]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/commitdiff
Merge /spare/repo/linux-2.6/
authorJeff Garzik <jgarzik@pobox.com>
Sat, 24 Sep 2005 04:26:49 +0000 (00:26 -0400)
committerJeff Garzik <jgarzik@pobox.com>
Sat, 24 Sep 2005 04:26:49 +0000 (00:26 -0400)
873 files changed:
CREDITS
Documentation/CodingStyle
Documentation/DocBook/kernel-hacking.tmpl
Documentation/cciss.txt
Documentation/dell_rbu.txt
Documentation/device-mapper/snapshot.txt [new file with mode: 0644]
Documentation/dontdiff
Documentation/feature-removal-schedule.txt
Documentation/filesystems/relayfs.txt
Documentation/ia64/mca.txt [new file with mode: 0644]
Documentation/kdump/kdump.txt
Documentation/oops-tracing.txt
Documentation/pm.txt
Documentation/sound/alsa/ALSA-Configuration.txt
Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl
Documentation/sparse.txt
Documentation/usb/URB.txt
MAINTAINERS
Makefile
README
arch/alpha/kernel/osf_sys.c
arch/alpha/kernel/process.c
arch/alpha/kernel/sys_dp264.c
arch/arm/boot/compressed/ofw-shark.c
arch/arm/common/locomo.c
arch/arm/configs/enp2611_defconfig
arch/arm/configs/ixdp2400_defconfig
arch/arm/configs/ixdp2401_defconfig
arch/arm/configs/ixdp2800_defconfig
arch/arm/configs/ixdp2801_defconfig
arch/arm/kernel/calls.S
arch/arm/kernel/entry-armv.S
arch/arm/kernel/entry-common.S
arch/arm/kernel/semaphore.c
arch/arm/kernel/traps.c
arch/arm/kernel/vmlinux.lds.S
arch/arm/mach-ixp4xx/ixdp425-setup.c
arch/arm/mach-pxa/Kconfig
arch/arm/mach-pxa/Makefile
arch/arm/mach-pxa/corgi.c
arch/arm/mach-pxa/corgi_lcd.c
arch/arm/mach-pxa/corgi_ssp.c
arch/arm/mach-pxa/lubbock.c
arch/arm/mach-pxa/poodle.c
arch/arm/mach-pxa/sharpsl.h [new file with mode: 0644]
arch/arm/mach-pxa/spitz.c [new file with mode: 0644]
arch/arm/mach-s3c2410/mach-anubis.c
arch/arm/mach-s3c2410/mach-bast.c
arch/arm/mach-s3c2410/mach-h1940.c
arch/arm/mach-s3c2410/mach-n30.c
arch/arm/mach-s3c2410/mach-nexcoder.c
arch/arm/mach-s3c2410/mach-otom.c
arch/arm/mach-s3c2410/mach-rx3715.c
arch/arm/mach-s3c2410/mach-smdk2410.c
arch/arm/mach-s3c2410/mach-smdk2440.c
arch/arm/mach-s3c2410/mach-vr1000.c
arch/arm/mach-sa1100/collie.c
arch/arm/mach-sa1100/generic.h
arch/arm/mm/fault.c
arch/arm/mm/proc-arm1020.S
arch/arm/mm/proc-arm1020e.S
arch/arm/mm/proc-arm1022.S
arch/arm/mm/proc-arm1026.S
arch/arm/mm/proc-arm6_7.S
arch/arm/mm/proc-arm720.S
arch/arm/mm/proc-arm920.S
arch/arm/mm/proc-arm922.S
arch/arm/mm/proc-arm925.S
arch/arm/mm/proc-arm926.S
arch/arm/mm/proc-sa110.S
arch/arm/mm/proc-sa1100.S
arch/arm/mm/proc-v6.S
arch/arm/mm/proc-xscale.S
arch/arm26/boot/compressed/hw-bse.c [deleted file]
arch/i386/Kconfig
arch/i386/kernel/acpi/earlyquirk.c
arch/i386/kernel/reboot.c
arch/i386/kernel/setup.c
arch/i386/kernel/smpboot.c
arch/i386/kernel/traps.c
arch/i386/lib/Makefile
arch/i386/lib/dec_and_lock.c [deleted file]
arch/ia64/Kconfig
arch/ia64/Makefile
arch/ia64/hp/sim/simscsi.c
arch/ia64/ia32/binfmt_elf32.c
arch/ia64/kernel/acpi.c
arch/ia64/kernel/asm-offsets.c
arch/ia64/kernel/entry.S
arch/ia64/kernel/mca_asm.S
arch/ia64/kernel/mca_drv.c
arch/ia64/kernel/mca_drv.h
arch/ia64/kernel/mca_drv_asm.S
arch/ia64/kernel/perfmon.c
arch/ia64/lib/Makefile
arch/ia64/lib/dec_and_lock.c [deleted file]
arch/m32r/Kconfig
arch/mips/Kconfig
arch/mips/kernel/sysirix.c
arch/mips/lib/Makefile
arch/mips/lib/dec_and_lock.c [deleted file]
arch/ppc/Kconfig
arch/ppc/kernel/Makefile
arch/ppc/kernel/perfmon.c
arch/ppc/kernel/temp.c
arch/ppc/kernel/time.c
arch/ppc/kernel/vmlinux.lds.S
arch/ppc/lib/Makefile
arch/ppc/lib/dec_and_lock.c [deleted file]
arch/ppc/platforms/chrp_time.c
arch/ppc/platforms/pmac_setup.c
arch/ppc/syslib/Makefile
arch/ppc/syslib/mpc8xx_devices.c [new file with mode: 0644]
arch/ppc/syslib/mpc8xx_sys.c [new file with mode: 0644]
arch/ppc/syslib/of_device.c
arch/ppc/syslib/open_pic2.c
arch/ppc/syslib/ppc85xx_setup.c
arch/ppc/syslib/prep_nvram.c
arch/ppc64/Kconfig
arch/ppc64/Makefile
arch/ppc64/kernel/asm-offsets.c
arch/ppc64/kernel/entry.S
arch/ppc64/kernel/head.S
arch/ppc64/kernel/of_device.c
arch/ppc64/kernel/pSeries_iommu.c
arch/ppc64/kernel/pSeries_setup.c
arch/ppc64/kernel/pci.c
arch/ppc64/kernel/pmac_setup.c
arch/ppc64/kernel/pmac_time.c
arch/ppc64/kernel/prom_init.c
arch/ppc64/kernel/ptrace.c
arch/ppc64/kernel/vdso.c
arch/ppc64/lib/Makefile
arch/ppc64/lib/dec_and_lock.c [deleted file]
arch/ppc64/mm/fault.c
arch/ppc64/mm/hash_native.c
arch/ppc64/mm/hugetlbpage.c
arch/s390/defconfig
arch/s390/kernel/Makefile
arch/s390/kernel/entry.S
arch/s390/kernel/entry64.S
arch/s390/kernel/reipl_diag.c [new file with mode: 0644]
arch/s390/kernel/setup.c
arch/s390/kernel/smp.c
arch/sparc64/Kconfig.debug
arch/sparc64/kernel/entry.S
arch/sparc64/kernel/ptrace.c
arch/sparc64/kernel/sparc64_ksyms.c
arch/sparc64/kernel/una_asm.S
arch/sparc64/kernel/unaligned.c
arch/sparc64/lib/Makefile
arch/sparc64/lib/dec_and_lock.S [deleted file]
arch/um/Kconfig.i386
arch/um/Makefile
arch/um/drivers/chan_kern.c
arch/um/drivers/mcast_user.c
arch/um/drivers/mconsole_kern.c
arch/um/drivers/mconsole_user.c
arch/um/drivers/pty.c
arch/um/drivers/ubd_user.c [deleted file]
arch/um/drivers/xterm.c
arch/um/include/common-offsets.h
arch/um/include/mconsole.h
arch/um/include/mem_user.h
arch/um/include/os.h
arch/um/include/user.h
arch/um/kernel/Makefile
arch/um/kernel/helper.c
arch/um/kernel/init_task.c
arch/um/kernel/mem.c
arch/um/kernel/mem_user.c [deleted file]
arch/um/kernel/process_kern.c
arch/um/kernel/sigio_user.c
arch/um/kernel/skas/include/mode_kern-skas.h
arch/um/kernel/skas/include/uaccess-skas.h
arch/um/kernel/skas/process_kern.c
arch/um/kernel/tempfile.c [deleted file]
arch/um/kernel/tlb.c
arch/um/kernel/trap_kern.c
arch/um/kernel/tt/include/mode_kern-tt.h
arch/um/kernel/tt/include/uaccess-tt.h
arch/um/kernel/tt/mem_user.c
arch/um/kernel/tt/process_kern.c
arch/um/kernel/tt/uaccess_user.c
arch/um/kernel/um_arch.c
arch/um/kernel/umid.c
arch/um/kernel/user_util.c
arch/um/os-Linux/Makefile
arch/um/os-Linux/aio.c
arch/um/os-Linux/drivers/tuntap_user.c
arch/um/os-Linux/elf_aux.c
arch/um/os-Linux/file.c
arch/um/os-Linux/mem.c [new file with mode: 0644]
arch/um/os-Linux/process.c
arch/um/os-Linux/start_up.c
arch/um/os-Linux/tt.c
arch/um/sys-i386/ldt.c
arch/x86_64/Kconfig
arch/x86_64/ia32/ia32_binfmt.c
arch/x86_64/ia32/syscall32.c
arch/x86_64/kernel/e820.c
arch/x86_64/kernel/io_apic.c
arch/x86_64/kernel/mce.c
arch/x86_64/kernel/nmi.c
arch/x86_64/kernel/setup.c
arch/x86_64/kernel/x8664_ksyms.c
arch/x86_64/lib/Makefile
arch/x86_64/lib/dec_and_lock.c [deleted file]
arch/xtensa/Kconfig
arch/xtensa/kernel/pci.c
arch/xtensa/kernel/platform.c
arch/xtensa/kernel/process.c
arch/xtensa/kernel/setup.c
arch/xtensa/kernel/signal.c
arch/xtensa/kernel/time.c
arch/xtensa/mm/init.c
drivers/acorn/char/pcf8583.c
drivers/base/attribute_container.c
drivers/base/class.c
drivers/base/dd.c
drivers/base/firmware_class.c
drivers/base/map.c
drivers/base/platform.c
drivers/block/cciss.c
drivers/block/cciss.h
drivers/block/cciss_cmd.h
drivers/block/cciss_scsi.c
drivers/block/ll_rw_blk.c
drivers/block/paride/pf.c
drivers/block/pktcdvd.c
drivers/block/scsi_ioctl.c
drivers/block/ub.c
drivers/bluetooth/hci_usb.c
drivers/bluetooth/hci_usb.h
drivers/char/agp/hp-agp.c
drivers/char/amiserial.c
drivers/char/epca.c
drivers/char/epca.h
drivers/char/hpet.c
drivers/char/hvc_console.c
drivers/char/ipmi/ipmi_msghandler.c
drivers/char/vt.c
drivers/char/watchdog/Kconfig
drivers/char/watchdog/Makefile
drivers/char/watchdog/i6300esb.c [new file with mode: 0644]
drivers/char/watchdog/ibmasr.c [new file with mode: 0644]
drivers/char/watchdog/mpcore_wdt.c
drivers/char/watchdog/mv64x60_wdt.c [new file with mode: 0644]
drivers/char/watchdog/pcwd_pci.c
drivers/char/watchdog/s3c2410_wdt.c
drivers/char/watchdog/sbc8360.c [new file with mode: 0644]
drivers/char/watchdog/w83977f_wdt.c [new file with mode: 0644]
drivers/firmware/dell_rbu.c
drivers/hwmon/Kconfig
drivers/hwmon/hdaps.c
drivers/i2c/busses/Kconfig
drivers/i2c/busses/Makefile
drivers/i2c/busses/i2c-keywest.c
drivers/i2c/busses/i2c-pmac-smu.c [new file with mode: 0644]
drivers/i2c/busses/i2c-pxa.c
drivers/ide/ide-iops.c
drivers/ide/ide-taskfile.c
drivers/ide/pci/cmd64x.c
drivers/ide/pci/hpt34x.c
drivers/infiniband/core/mad_rmpp.c
drivers/infiniband/core/user_mad.c
drivers/infiniband/hw/mthca/mthca_eq.c
drivers/infiniband/hw/mthca/mthca_qp.c
drivers/infiniband/hw/mthca/mthca_srq.c
drivers/infiniband/ulp/ipoib/ipoib.h
drivers/infiniband/ulp/ipoib/ipoib_ib.c
drivers/infiniband/ulp/ipoib/ipoib_main.c
drivers/infiniband/ulp/ipoib/ipoib_multicast.c
drivers/input/keyboard/Kconfig
drivers/input/keyboard/Makefile
drivers/input/keyboard/spitzkbd.c [new file with mode: 0644]
drivers/input/touchscreen/Kconfig
drivers/input/touchscreen/corgi_ts.c
drivers/isdn/hisax/hfc_pci.c
drivers/isdn/hisax/sedlbauer_cs.c
drivers/isdn/hisax/st5481.h
drivers/isdn/hisax/st5481_b.c
drivers/isdn/hisax/st5481_d.c
drivers/isdn/hisax/st5481_init.c
drivers/isdn/hisax/st5481_usb.c
drivers/isdn/sc/init.c
drivers/macintosh/smu.c
drivers/macintosh/therm_adt746x.c
drivers/macintosh/therm_pm72.c
drivers/macintosh/therm_windtunnel.c
drivers/md/raid6.h
drivers/md/raid6algos.c
drivers/md/raid6altivec.uc
drivers/md/raid6test/Makefile
drivers/media/radio/radio-aimslab.c
drivers/media/radio/radio-aztech.c
drivers/media/radio/radio-cadet.c
drivers/media/radio/radio-gemtek.c
drivers/media/radio/radio-rtrack2.c
drivers/media/radio/radio-sf16fmi.c
drivers/media/radio/radio-sf16fmr2.c
drivers/media/radio/radio-terratec.c
drivers/media/radio/radio-typhoon.c
drivers/media/radio/radio-zoltrix.c
drivers/media/video/bttv-driver.c
drivers/media/video/bttvp.h
drivers/media/video/cx88/cx88-dvb.c
drivers/message/fusion/Kconfig
drivers/message/fusion/Makefile
drivers/message/fusion/mptbase.c
drivers/message/fusion/mptbase.h
drivers/message/fusion/mptctl.c
drivers/message/fusion/mptfc.c
drivers/message/fusion/mptlan.c
drivers/message/fusion/mptsas.c [new file with mode: 0644]
drivers/message/fusion/mptscsih.c
drivers/message/fusion/mptscsih.h
drivers/message/fusion/mptspi.c
drivers/message/i2o/config-osm.c
drivers/mtd/devices/docecc.c
drivers/mtd/maps/sharpsl-flash.c
drivers/mtd/nand/sharpsl.c
drivers/net/8139cp.c
drivers/net/8390.c
drivers/net/Kconfig
drivers/net/arcnet/com90io.c
drivers/net/bonding/bond_main.c
drivers/net/e100.c
drivers/net/e1000/e1000_main.c
drivers/net/ixgb/ixgb_main.c
drivers/net/r8169.c
drivers/net/s2io.c
drivers/net/sk98lin/skge.c
drivers/net/skge.c
drivers/net/skge.h
drivers/net/spider_net.c
drivers/net/tg3.c
drivers/net/tulip/xircom_cb.c
drivers/net/wan/hdlc_cisco.c
drivers/net/wireless/airo.c
drivers/net/wireless/orinoco_cs.c
drivers/pci/hotplug.c
drivers/pci/hotplug/ibmphp_pci.c
drivers/pci/hotplug/pciehp_ctrl.c
drivers/pci/hotplug/rpadlpar_sysfs.c
drivers/pci/hotplug/sgi_hotplug.c
drivers/pci/hotplug/shpchp_ctrl.c
drivers/pci/pci-sysfs.c
drivers/pci/pci.c
drivers/pci/probe.c
drivers/pcmcia/pcmcia_ioctl.c
drivers/pcmcia/yenta_socket.c
drivers/s390/cio/blacklist.c
drivers/s390/cio/ccwgroup.c
drivers/s390/crypto/z90main.c
drivers/s390/net/ctcmain.c
drivers/s390/net/qeth.h
drivers/s390/net/qeth_main.c
drivers/s390/net/qeth_sys.c
drivers/s390/scsi/Makefile
drivers/s390/scsi/zfcp_aux.c
drivers/s390/scsi/zfcp_ccw.c
drivers/s390/scsi/zfcp_dbf.c [new file with mode: 0644]
drivers/s390/scsi/zfcp_def.h
drivers/s390/scsi/zfcp_erp.c
drivers/s390/scsi/zfcp_ext.h
drivers/s390/scsi/zfcp_fsf.c
drivers/s390/scsi/zfcp_fsf.h
drivers/s390/scsi/zfcp_qdio.c
drivers/s390/scsi/zfcp_scsi.c
drivers/s390/scsi/zfcp_sysfs_adapter.c
drivers/sbus/char/display7seg.c
drivers/scsi/aic7xxx/aic7xxx_osm.c
drivers/scsi/aic7xxx/aic7xxx_osm.h
drivers/scsi/aic7xxx/aic7xxx_osm_pci.c
drivers/scsi/ata_piix.c
drivers/scsi/atp870u.c
drivers/scsi/atp870u.h
drivers/scsi/fd_mcs.c
drivers/scsi/hosts.c
drivers/scsi/ibmmca.c
drivers/scsi/ibmvscsi/ibmvscsi.c
drivers/scsi/libata-core.c
drivers/scsi/mesh.c
drivers/scsi/qla2xxx/qla_init.c
drivers/scsi/sata_nv.c
drivers/scsi/sata_sis.c
drivers/scsi/scsi.c
drivers/scsi/scsi_devinfo.c
drivers/scsi/scsi_error.c
drivers/scsi/scsi_ioctl.c
drivers/scsi/scsi_lib.c
drivers/scsi/scsi_scan.c
drivers/scsi/scsi_sysfs.c
drivers/scsi/sd.c
drivers/scsi/sg.c
drivers/scsi/sr.c
drivers/scsi/st.c
drivers/serial/21285.c
drivers/serial/amba-pl010.c
drivers/serial/amba-pl011.c
drivers/serial/clps711x.c
drivers/serial/mpc52xx_uart.c
drivers/serial/pxa.c
drivers/serial/sa1100.c
drivers/serial/serial_lh7a40x.c
drivers/tc/zs.c
drivers/usb/core/message.c
drivers/usb/core/usb.c
drivers/usb/gadget/pxa2xx_udc.c
drivers/usb/gadget/pxa2xx_udc.h
drivers/usb/host/sl811-hcd.c
drivers/usb/net/pegasus.c
drivers/usb/serial/airprime.c
drivers/usb/serial/ftdi_sio.c
drivers/usb/serial/option.c
drivers/video/Kconfig
drivers/video/aty/xlinit.c
drivers/video/backlight/corgi_bl.c
drivers/video/console/fbcon.c
drivers/video/console/fbcon.h
drivers/video/console/font_10x18.c
drivers/video/console/font_6x11.c
drivers/video/console/font_7x14.c
drivers/video/console/font_8x16.c
drivers/video/console/font_8x8.c
drivers/video/console/font_acorn_8x8.c
drivers/video/console/font_mini_4x6.c
drivers/video/console/font_pearl_8x8.c
drivers/video/console/font_sun12x22.c
drivers/video/console/font_sun8x16.c
drivers/video/console/fonts.c
drivers/video/console/vgacon.c
drivers/video/fbcvt.c
drivers/video/imxfb.c
drivers/video/matrox/matroxfb_base.c
drivers/video/nvidia/nv_i2c.c
drivers/video/nvidia/nvidia.c
drivers/video/pm3fb.c
drivers/video/savage/savagefb-i2c.c
drivers/video/savage/savagefb.h
drivers/video/savage/savagefb_driver.c
fs/9p/conv.c
fs/9p/v9fs.c
fs/9p/vfs_inode.c
fs/9p/vfs_super.c
fs/aio.c
fs/cifs/cifsfs.c
fs/cifs/connect.c
fs/compat.c
fs/dcache.c
fs/eventpoll.c
fs/exec.c
fs/ext3/balloc.c
fs/ext3/resize.c
fs/ext3/super.c
fs/fat/file.c
fs/fat/inode.c
fs/file.c
fs/jfs/inode.c
fs/jfs/jfs_dmap.c
fs/jfs/jfs_txnmgr.c
fs/jfs/jfs_txnmgr.h
fs/locks.c
fs/namei.c
fs/nfs/read.c
fs/nfsd/nfs4proc.c
fs/nfsd/nfs4state.c
fs/ntfs/ChangeLog
fs/ntfs/aops.c
fs/ntfs/inode.c
fs/ntfs/malloc.h
fs/ntfs/runlist.c
fs/open.c
fs/proc/array.c
fs/proc/base.c
fs/reiserfs/file.c
fs/reiserfs/inode.c
include/asm-alpha/compiler.h
include/asm-alpha/futex.h
include/asm-alpha/pgtable.h
include/asm-arm/arch-aaec2000/memory.h
include/asm-arm/arch-iop3xx/memory.h
include/asm-arm/arch-ixp2000/ixp2000-regs.h
include/asm-arm/arch-ixp2000/platform.h
include/asm-arm/arch-lh7a40x/memory.h
include/asm-arm/arch-omap/memory.h
include/asm-arm/arch-pxa/akita.h [new file with mode: 0644]
include/asm-arm/arch-pxa/corgi.h
include/asm-arm/arch-pxa/memory.h
include/asm-arm/arch-pxa/poodle.h
include/asm-arm/arch-pxa/sharpsl.h [new file with mode: 0644]
include/asm-arm/arch-pxa/spitz.h [new file with mode: 0644]
include/asm-arm/arch-sa1100/memory.h
include/asm-arm/futex.h
include/asm-arm/hardware/arm_twd.h [new file with mode: 0644]
include/asm-arm/mach/arch.h
include/asm-arm/memory.h
include/asm-arm/pgtable.h
include/asm-arm/setup.h
include/asm-arm26/futex.h
include/asm-arm26/pgtable.h
include/asm-cris/futex.h
include/asm-frv/futex.h
include/asm-frv/pgtable.h
include/asm-h8300/futex.h
include/asm-h8300/pgtable.h
include/asm-i386/futex.h
include/asm-i386/pgtable.h
include/asm-ia64/futex.h
include/asm-ia64/mca.h
include/asm-ia64/pgtable.h
include/asm-ia64/ptrace.h
include/asm-ia64/thread_info.h
include/asm-m32r/futex.h
include/asm-m32r/pgtable.h
include/asm-m68k/futex.h
include/asm-m68k/pgtable.h
include/asm-m68knommu/futex.h
include/asm-m68knommu/pgtable.h
include/asm-mips/pgtable.h
include/asm-parisc/futex.h
include/asm-parisc/pgtable.h
include/asm-ppc/futex.h
include/asm-ppc/irq.h
include/asm-ppc/macio.h
include/asm-ppc/mpc8xx.h
include/asm-ppc/mv64x60.h
include/asm-ppc/of_device.h
include/asm-ppc/pgtable.h
include/asm-ppc/ppc_sys.h
include/asm-ppc/segment.h [deleted file]
include/asm-ppc/tlbflush.h
include/asm-ppc64/smu.h
include/asm-s390/futex.h
include/asm-sh/futex.h
include/asm-sh/pgtable.h
include/asm-sh64/futex.h
include/asm-sh64/pgtable.h
include/asm-sparc/futex.h
include/asm-sparc64/cacheflush.h
include/asm-sparc64/futex.h
include/asm-sparc64/ide.h
include/asm-sparc64/page.h
include/asm-sparc64/pgalloc.h
include/asm-sparc64/pgtable.h
include/asm-um/futex.h
include/asm-um/pgtable.h
include/asm-um/processor-generic.h
include/asm-um/system-i386.h
include/asm-v850/futex.h
include/asm-x86_64/desc.h
include/asm-x86_64/pgtable.h
include/asm-xtensa/atomic.h
include/asm-xtensa/bitops.h
include/asm-xtensa/hardirq.h
include/asm-xtensa/pgtable.h
include/asm-xtensa/semaphore.h
include/asm-xtensa/system.h
include/linux/audit.h
include/linux/byteorder/generic.h
include/linux/dccp.h
include/linux/device.h
include/linux/fb.h
include/linux/font.h
include/linux/i2c.h
include/linux/if_vlan.h
include/linux/joystick.h
include/linux/kernel.h
include/linux/libata.h
include/linux/mm.h
include/linux/netfilter_ipv4/ip_conntrack.h
include/linux/netfilter_ipv4/ip_conntrack_pptp.h [new file with mode: 0644]
include/linux/netfilter_ipv4/ip_conntrack_proto_gre.h [new file with mode: 0644]
include/linux/netfilter_ipv4/ip_conntrack_tuple.h
include/linux/netfilter_ipv4/ip_nat_pptp.h [new file with mode: 0644]
include/linux/netfilter_ipv6/ip6_tables.h
include/linux/netlink.h
include/linux/nfsd/xdr4.h
include/linux/pci_ids.h
include/linux/pktcdvd.h
include/linux/reboot.h
include/linux/sched.h
include/linux/security.h
include/linux/syscalls.h
include/linux/tfrc.h [new file with mode: 0644]
include/linux/videodev2.h
include/net/bluetooth/hci.h
include/net/ip_vs.h
include/rdma/ib_mad.h
include/scsi/scsi_host.h
include/scsi/scsi_transport_fc.h
include/sound/core.h
include/sound/cs46xx.h
include/sound/emu10k1.h
include/sound/pcm.h
include/sound/pcm_oss.h
include/sound/trident.h
include/sound/version.h
include/sound/ymfpci.h
include/video/pm3fb.h
include/video/w100fb.h
init/initramfs.c
kernel/audit.c
kernel/auditsc.c
kernel/exit.c
kernel/fork.c
kernel/module.c
kernel/power/Kconfig
kernel/power/disk.c
kernel/power/power.h
kernel/power/swsusp.c
kernel/printk.c
kernel/sched.c
kernel/signal.c
kernel/sys.c
kernel/timer.c
lib/dec_and_lock.c
mm/Kconfig
mm/mempolicy.c
mm/mmap.c
mm/mprotect.c
mm/page_alloc.c
mm/slab.c
mm/swapfile.c
mm/vmscan.c
net/8021q/vlan_dev.c
net/Kconfig
net/bluetooth/hci_event.c
net/bluetooth/rfcomm/sock.c
net/bridge/br_forward.c
net/bridge/br_netfilter.c
net/dccp/Makefile
net/dccp/ackvec.c [new file with mode: 0644]
net/dccp/ackvec.h [new file with mode: 0644]
net/dccp/ccid.h
net/dccp/ccids/ccid3.c
net/dccp/ccids/ccid3.h
net/dccp/dccp.h
net/dccp/input.c
net/dccp/ipv4.c
net/dccp/minisocks.c
net/dccp/options.c
net/dccp/output.c
net/dccp/proto.c
net/ipv4/fib_trie.c
net/ipv4/igmp.c
net/ipv4/ipvs/ip_vs_conn.c
net/ipv4/ipvs/ip_vs_core.c
net/ipv4/ipvs/ip_vs_sync.c
net/ipv4/netfilter/Kconfig
net/ipv4/netfilter/Makefile
net/ipv4/netfilter/ip_conntrack_amanda.c
net/ipv4/netfilter/ip_conntrack_core.c
net/ipv4/netfilter/ip_conntrack_ftp.c
net/ipv4/netfilter/ip_conntrack_helper_pptp.c [new file with mode: 0644]
net/ipv4/netfilter/ip_conntrack_irc.c
net/ipv4/netfilter/ip_conntrack_netbios_ns.c
net/ipv4/netfilter/ip_conntrack_netlink.c
net/ipv4/netfilter/ip_conntrack_proto_gre.c [new file with mode: 0644]
net/ipv4/netfilter/ip_conntrack_standalone.c
net/ipv4/netfilter/ip_conntrack_tftp.c
net/ipv4/netfilter/ip_nat_core.c
net/ipv4/netfilter/ip_nat_helper_pptp.c [new file with mode: 0644]
net/ipv4/netfilter/ip_nat_proto_gre.c [new file with mode: 0644]
net/ipv4/netfilter/ipt_CLUSTERIP.c
net/ipv4/netfilter/ipt_MASQUERADE.c
net/ipv4/netfilter/ipt_REDIRECT.c
net/ipv4/raw.c
net/ipv4/tcp_input.c
net/ipv4/tcp_minisocks.c
net/ipv4/tcp_output.c
net/ipv6/mcast.c
net/ipv6/netfilter/ip6_tables.c
net/ipv6/netfilter/ip6t_ah.c
net/ipv6/netfilter/ip6t_dst.c
net/ipv6/netfilter/ip6t_esp.c
net/ipv6/netfilter/ip6t_frag.c
net/ipv6/netfilter/ip6t_hbh.c
net/ipv6/netfilter/ip6t_rt.c
net/ipv6/raw.c
net/ipv6/udp.c
net/packet/af_packet.c
net/sctp/sm_statefuns.c
net/socket.c
net/sunrpc/svcsock.c
security/Kconfig
security/Makefile
security/inode.c [new file with mode: 0644]
security/seclvl.c
security/selinux/avc.c
security/selinux/hooks.c
security/selinux/ss/services.c
sound/arm/Kconfig
sound/arm/aaci.c
sound/arm/sa11xx-uda1341.c
sound/core/Kconfig
sound/core/control.c
sound/core/control_compat.c
sound/core/device.c
sound/core/hwdep.c
sound/core/info.c
sound/core/init.c
sound/core/memalloc.c
sound/core/memory.c
sound/core/oss/mixer_oss.c
sound/core/oss/pcm_oss.c
sound/core/oss/pcm_plugin.c
sound/core/pcm.c
sound/core/pcm_lib.c
sound/core/pcm_memory.c
sound/core/pcm_native.c
sound/core/rawmidi.c
sound/core/seq/instr/ainstr_gf1.c
sound/core/seq/instr/ainstr_iw.c
sound/core/seq/oss/seq_oss_init.c
sound/core/seq/oss/seq_oss_midi.c
sound/core/seq/oss/seq_oss_readq.c
sound/core/seq/oss/seq_oss_synth.c
sound/core/seq/oss/seq_oss_timer.c
sound/core/seq/oss/seq_oss_writeq.c
sound/core/seq/seq.c
sound/core/seq/seq_clientmgr.c
sound/core/seq/seq_device.c
sound/core/seq/seq_dummy.c
sound/core/seq/seq_fifo.c
sound/core/seq/seq_instr.c
sound/core/seq/seq_memory.c
sound/core/seq/seq_midi.c
sound/core/seq/seq_midi_event.c
sound/core/seq/seq_ports.c
sound/core/seq/seq_prioq.c
sound/core/seq/seq_queue.c
sound/core/seq/seq_system.c
sound/core/seq/seq_timer.c
sound/core/seq/seq_virmidi.c
sound/core/sound.c
sound/core/timer.c
sound/drivers/Kconfig
sound/drivers/dummy.c
sound/drivers/mpu401/mpu401.c
sound/drivers/mpu401/mpu401_uart.c
sound/drivers/mtpav.c
sound/drivers/opl3/opl3_lib.c
sound/drivers/opl3/opl3_oss.c
sound/drivers/opl4/opl4_lib.c
sound/drivers/serial-u16550.c
sound/drivers/virmidi.c
sound/drivers/vx/vx_core.c
sound/drivers/vx/vx_pcm.c
sound/i2c/cs8427.c
sound/i2c/i2c.c
sound/i2c/l3/uda1341.c
sound/i2c/other/ak4114.c
sound/i2c/other/ak4117.c
sound/i2c/tea6330t.c
sound/isa/Kconfig
sound/isa/ad1816a/ad1816a_lib.c
sound/isa/ad1848/ad1848.c
sound/isa/ad1848/ad1848_lib.c
sound/isa/cmi8330.c
sound/isa/cs423x/cs4231.c
sound/isa/cs423x/cs4231_lib.c
sound/isa/cs423x/cs4236.c
sound/isa/es1688/es1688.c
sound/isa/es1688/es1688_lib.c
sound/isa/es18xx.c
sound/isa/gus/gus_main.c
sound/isa/gus/gus_mem_proc.c
sound/isa/gus/gus_pcm.c
sound/isa/gus/gusclassic.c
sound/isa/gus/gusextreme.c
sound/isa/gus/gusmax.c
sound/isa/gus/interwave.c
sound/isa/opl3sa2.c
sound/isa/opti9xx/opti92x-ad1848.c
sound/isa/sb/emu8000.c
sound/isa/sb/emu8000_pcm.c
sound/isa/sb/sb16.c
sound/isa/sb/sb16_csp.c
sound/isa/sb/sb8.c
sound/isa/sb/sb_common.c
sound/isa/sgalaxy.c
sound/isa/sscape.c
sound/isa/wavefront/wavefront.c
sound/mips/Kconfig
sound/mips/au1x00.c
sound/oss/au1000.c
sound/oss/ite8172.c
sound/parisc/harmony.c
sound/pci/Kconfig
sound/pci/Makefile
sound/pci/ac97/ac97_codec.c
sound/pci/ac97/ac97_id.h
sound/pci/ac97/ac97_patch.c
sound/pci/ac97/ak4531_codec.c
sound/pci/ad1889.c [new file with mode: 0644]
sound/pci/ad1889.h [new file with mode: 0644]
sound/pci/ali5451/ali5451.c
sound/pci/als4000.c
sound/pci/atiixp.c
sound/pci/atiixp_modem.c
sound/pci/au88x0/au88x0.c
sound/pci/azt3328.c
sound/pci/bt87x.c
sound/pci/ca0106/ca0106_main.c
sound/pci/ca0106/ca0106_mixer.c
sound/pci/cmipci.c
sound/pci/cs4281.c
sound/pci/cs46xx/cs46xx.c
sound/pci/cs46xx/cs46xx_lib.c
sound/pci/emu10k1/emu10k1.c
sound/pci/emu10k1/emu10k1_main.c
sound/pci/emu10k1/emu10k1x.c
sound/pci/emu10k1/emufx.c
sound/pci/emu10k1/emupcm.c
sound/pci/emu10k1/p16v.c
sound/pci/ens1370.c
sound/pci/es1938.c
sound/pci/es1968.c
sound/pci/fm801.c
sound/pci/hda/hda_codec.c
sound/pci/hda/hda_codec.h
sound/pci/hda/hda_generic.c
sound/pci/hda/hda_intel.c
sound/pci/hda/hda_proc.c
sound/pci/hda/patch_analog.c
sound/pci/hda/patch_cmedia.c
sound/pci/hda/patch_realtek.c
sound/pci/hda/patch_si3054.c
sound/pci/hda/patch_sigmatel.c
sound/pci/ice1712/aureon.c
sound/pci/ice1712/ice1712.c
sound/pci/ice1712/ice1724.c
sound/pci/ice1712/juli.c
sound/pci/ice1712/phase.c
sound/pci/ice1712/pontis.c
sound/pci/intel8x0.c
sound/pci/intel8x0m.c
sound/pci/korg1212/korg1212.c
sound/pci/maestro3.c
sound/pci/mixart/mixart.c
sound/pci/nm256/nm256.c
sound/pci/rme32.c
sound/pci/rme96.c
sound/pci/rme9652/hdsp.c
sound/pci/rme9652/hdspm.c
sound/pci/rme9652/rme9652.c
sound/pci/sonicvibes.c
sound/pci/trident/trident.c
sound/pci/trident/trident_main.c
sound/pci/via82xx.c
sound/pci/via82xx_modem.c
sound/pci/vx222/vx222.c
sound/pci/ymfpci/ymfpci.c
sound/pci/ymfpci/ymfpci_main.c
sound/pcmcia/pdaudiocf/pdaudiocf_core.c
sound/ppc/Kconfig
sound/ppc/pmac.c
sound/ppc/powermac.c
sound/ppc/tumbler.c
sound/sparc/Kconfig
sound/sparc/amd7930.c
sound/sparc/cs4231.c
sound/sparc/dbri.c
sound/synth/emux/emux.c
sound/synth/emux/emux_seq.c
sound/synth/emux/soundfont.c
sound/synth/util_mem.c
sound/usb/usbaudio.c
sound/usb/usbmidi.c
sound/usb/usbmixer.c
sound/usb/usx2y/usbusx2yaudio.c

diff --git a/CREDITS b/CREDITS
index f553f8cfaa6266a54bc4081d448719d73abb5001..a347520bef2d63c1cd80dbf3cdd01d8f4184f26b 100644 (file)
--- 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
index 22e5f9036f3c193f88d14611b2e5fe669b2c9b9e..eb7db3c192273aa7b7b5d9244593c4add69bc863 100644 (file)
@@ -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.
index 6367bba32d22256dae461b2649c3f51367af93bc..582032eea87228352079b8b7002117151a79cc41 100644 (file)
@@ -1105,7 +1105,7 @@ static struct block_device_operations opt_fops = {
     </listitem>
     <listitem>
      <para>
-      Function names as strings (__func__).
+      Function names as strings (__FUNCTION__).
      </para>
     </listitem>
     <listitem>
index c8f9a73111da8371d5ff4b49b68116ffb3353e48..68a711fb82cf8d9d612363ff04bb71719ef6729f 100644 (file)
@@ -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:
 
index bcfa5c35036bf915a7a12cdca7db8713dafe36a6..95d7f62e4dbc07ecd90f101946378bc054ed17a4 100644 (file)
@@ -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/device-mapper/snapshot.txt b/Documentation/device-mapper/snapshot.txt
new file mode 100644 (file)
index 0000000..dca274f
--- /dev/null
@@ -0,0 +1,73 @@
+Device-mapper snapshot support
+==============================
+
+Device-mapper allows you, without massive data copying:
+
+*) To create snapshots of any block device i.e. mountable, saved states of
+the block device which are also writable without interfering with the
+original content;
+*) To create device "forks", i.e. multiple different versions of the
+same data stream.
+
+
+In both cases, dm copies only the chunks of data that get changed and
+uses a separate copy-on-write (COW) block device for storage.
+
+
+There are two dm targets available: snapshot and snapshot-origin.
+
+*) snapshot-origin <origin>
+
+which will normally have one or more snapshots based on it.
+You must create the snapshot-origin device before you can create snapshots.
+Reads will be mapped directly to the backing device. For each write, the
+original data will be saved in the <COW device> of each snapshot to keep
+its visible content unchanged, at least until the <COW device> fills up.
+
+
+*) snapshot <origin> <COW device> <persistent?> <chunksize>
+
+A snapshot is created of the <origin> block device. Changed chunks of
+<chunksize> sectors will be stored on the <COW device>.  Writes will
+only go to the <COW device>.  Reads will come from the <COW device> or
+from <origin> for unchanged data.  <COW device> will often be
+smaller than the origin and if it fills up the snapshot will become
+useless and be disabled, returning errors.  So it is important to monitor
+the amount of free space and expand the <COW device> before it fills up.
+
+<persistent?> is P (Persistent) or N (Not persistent - will not survive
+after reboot).
+
+
+How this is used by LVM2
+========================
+When you create the first LVM2 snapshot of a volume, four dm devices are used:
+
+1) a device containing the original mapping table of the source volume;
+2) a device used as the <COW device>;
+3) a "snapshot" device, combining #1 and #2, which is the visible snapshot
+   volume;
+4) the "original" volume (which uses the device number used by the original
+   source volume), whose table is replaced by a "snapshot-origin" mapping
+   from device #1.
+
+A fixed naming scheme is used, so with the following commands:
+
+lvcreate -L 1G -n base volumeGroup
+lvcreate -L 100M --snapshot -n snap volumeGroup/base
+
+we'll have this situation (with volumes in above order):
+
+# dmsetup table|grep volumeGroup
+
+volumeGroup-base-real: 0 2097152 linear 8:19 384
+volumeGroup-snap-cow: 0 204800 linear 8:19 2097536
+volumeGroup-snap: 0 2097152 snapshot 254:11 254:12 P 16
+volumeGroup-base: 0 2097152 snapshot-origin 254:11
+
+# ls -lL /dev/mapper/volumeGroup-*
+brw-------  1 root root 254, 11 29 ago 18:15 /dev/mapper/volumeGroup-base-real
+brw-------  1 root root 254, 12 29 ago 18:15 /dev/mapper/volumeGroup-snap-cow
+brw-------  1 root root 254, 13 29 ago 18:15 /dev/mapper/volumeGroup-snap
+brw-------  1 root root 254, 10 29 ago 18:14 /dev/mapper/volumeGroup-base
+
index 96bea278bbf61eb9ae6d6cb5657f8092b543a87e..24adfe9af3ca92a169b9f7a7fc368e9098dac487 100644 (file)
@@ -55,6 +55,7 @@ aic7*seq.h*
 aicasm
 aicdb.h*
 asm
+asm-offsets.*
 asm_offsets.*
 autoconf.h*
 bbootsect
index 784e08c1c80a308b9916a4a1f360380482761603..b67189a8d8d471789629ae23e4c1b6e9e2b713da 100644 (file)
@@ -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
index d24e1b0d4f39b581d75b4e4e8f33c1c437225bbe..d803abed29f01dcf2072486000750f88f0b564d5 100644 (file)
@@ -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 (file)
index 0000000..a71cc6a
--- /dev/null
@@ -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.
index 1f5f7d28c9e6bf54e2b95d97f9399aed324b177f..5f08f9ce60464bdb03e7dd6c82398c79c0bd2eba 100644 (file)
@@ -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
index da711028e5f712cde905b4129e6addfc96b7ac92..66eaaab7773d551691181070daead961fca33df2 100644 (file)
@@ -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.
index cc63ae18d147e031f69866c4aca8ebcdacfa5c5c..2ea1149bf6b044b7a77f5c70f7abe48863b60540 100644 (file)
@@ -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
index ebfcdf28485f28aa47ee6af8fd5f4f639aadda59..13cba955cb5af313a2c2cc0866666766ef56a40a 100644 (file)
@@ -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
index 0475478c2484c90c3b14b6c74a4a8efe8fa4941b..24e85520890b902a799def758cef191f78a30490 100644 (file)
           ....
 
           /* 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;
 
           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>
   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>
                   return -ENXIO;
           }
 
-          chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
+          chip = kzalloc(sizeof(*chip), GFP_KERNEL);
           if (chip == NULL) {
                   pci_disable_device(pci);
                   return -ENOMEM;
       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>
 
index 5df44dc894e594a7ef6344a05a0439fe7ebcce98..1829009db771042038f3e302a8c35dbcb07c1d14 100644 (file)
@@ -51,9 +51,9 @@ or you don't get any checking at all.
 Where to get sparse
 ~~~~~~~~~~~~~~~~~~~
 
-With BK, you can just get it from
+With git, you can just get it from
 
-        bk://sparse.bkbits.net/sparse
+        rsync://rsync.kernel.org/pub/scm/devel/sparse/sparse.git
 
 and DaveJ has tar-balls at
 
index d59b95cc6f1b0a1d1af69d02aa377537c37f9d40..a49e5f2c2b46e6a2f9947956d17d3a78e045e758 100644 (file)
@@ -1,5 +1,6 @@
 Revised: 2000-Dec-05.
 Again:   2002-Jul-06
+Again:   2005-Sep-19
 
     NOTE:
 
@@ -18,8 +19,8 @@ called USB Request Block, or URB for short.
   and deliver the data and status back. 
 
 - Execution of an URB is inherently an asynchronous operation, i.e. the 
-  usb_submit_urb(urb) call returns immediately after it has successfully queued 
-  the requested action. 
+  usb_submit_urb(urb) call returns immediately after it has successfully
+  queued the requested action.
 
 - Transfers for one URB can be canceled with usb_unlink_urb(urb) at any time. 
 
@@ -94,8 +95,9 @@ To free an URB, use
 
        void usb_free_urb(struct urb *urb)
 
-You may not free an urb that you've submitted, but which hasn't yet been
-returned to you in a completion callback.
+You may free an urb that you've submitted, but which hasn't yet been
+returned to you in a completion callback.  It will automatically be
+deallocated when it is no longer in use.
 
 
 1.4. What has to be filled in?
@@ -145,30 +147,36 @@ to get seamless ISO streaming.
 
 1.6. How to cancel an already running URB?
 
-For an URB which you've submitted, but which hasn't been returned to
-your driver by the host controller, call
+There are two ways to cancel an URB you've submitted but which hasn't
+been returned to your driver yet.  For an asynchronous cancel, call
 
        int usb_unlink_urb(struct urb *urb)
 
 It removes the urb from the internal list and frees all allocated
-HW descriptors. The status is changed to reflect unlinking. After 
-usb_unlink_urb() returns with that status code, you can free the URB
-with usb_free_urb().
+HW descriptors. The status is changed to reflect unlinking.  Note
+that the URB will not normally have finished when usb_unlink_urb()
+returns; you must still wait for the completion handler to be called.
 
-There is also an asynchronous unlink mode.  To use this, set the
-the URB_ASYNC_UNLINK flag in urb->transfer flags before calling
-usb_unlink_urb().  When using async unlinking, the URB will not
-normally be unlinked when usb_unlink_urb() returns.  Instead, wait
-for the completion handler to be called.
+To cancel an URB synchronously, call
+
+       void usb_kill_urb(struct urb *urb)
+
+It does everything usb_unlink_urb does, and in addition it waits
+until after the URB has been returned and the completion handler
+has finished.  It also marks the URB as temporarily unusable, so
+that if the completion handler or anyone else tries to resubmit it
+they will get a -EPERM error.  Thus you can be sure that when
+usb_kill_urb() returns, the URB is totally idle.
 
 
 1.7. What about the completion handler?
 
 The handler is of the following type:
 
-       typedef void (*usb_complete_t)(struct urb *);
+       typedef void (*usb_complete_t)(struct urb *, struct pt_regs *)
 
-i.e. it gets just the URB that caused the completion call.
+I.e., it gets the URB that caused the completion call, plus the
+register values at the time of the corresponding interrupt (if any).
 In the completion handler, you should have a look at urb->status to
 detect any USB errors. Since the context parameter is included in the URB,
 you can pass information to the completion handler. 
@@ -176,17 +184,11 @@ you can pass information to the completion handler.
 Note that even when an error (or unlink) is reported, data may have been
 transferred.  That's because USB transfers are packetized; it might take
 sixteen packets to transfer your 1KByte buffer, and ten of them might
-have transferred succesfully before the completion is called.
+have transferred succesfully before the completion was called.
 
 
 NOTE:  ***** WARNING *****
-Don't use urb->dev field in your completion handler; it's cleared
-as part of giving urbs back to drivers.  (Addressing an issue with
-ownership of periodic URBs, which was otherwise ambiguous.) Instead,
-use urb->context to hold all the data your driver needs.
-
-NOTE:  ***** WARNING *****
-Also, NEVER SLEEP IN A COMPLETION HANDLER.  These are normally called
+NEVER SLEEP IN A COMPLETION HANDLER.  These are normally called
 during hardware interrupt processing.  If you can, defer substantial
 work to a tasklet (bottom half) to keep system latencies low.  You'll
 probably need to use spinlocks to protect data structures you manipulate
@@ -229,24 +231,10 @@ ISO data with some other event stream.
 Interrupt transfers, like isochronous transfers, are periodic, and happen
 in intervals that are powers of two (1, 2, 4 etc) units.  Units are frames
 for full and low speed devices, and microframes for high speed ones.
-
-Currently, after you submit one interrupt URB, that urb is owned by the
-host controller driver until you cancel it with usb_unlink_urb().  You
-may unlink interrupt urbs in their completion handlers, if you need to.
-
-After a transfer completion is called, the URB is automagically resubmitted.
-THIS BEHAVIOR IS EXPECTED TO BE REMOVED!!
-
-Interrupt transfers may only send (or receive) the "maxpacket" value for
-the given interrupt endpoint; if you need more data, you will need to
-copy that data out of (or into) another buffer.  Similarly, you can't
-queue interrupt transfers.
-THESE RESTRICTIONS ARE EXPECTED TO BE REMOVED!!
-
-Note that this automagic resubmission model does make it awkward to use
-interrupt OUT transfers.  The portable solution involves unlinking those
-OUT urbs after the data is transferred, and perhaps submitting a final
-URB for a short packet.
-
 The usb_submit_urb() call modifies urb->interval to the implemented interval
 value that is less than or equal to the requested interval value.
+
+In Linux 2.6, unlike earlier versions, interrupt URBs are not automagically
+restarted when they complete.  They end when the completion handler is
+called, just like other URBs.  If you want an interrupt URB to be restarted,
+your completion handler must resubmit it.
index a67bf7d315d7ee14923789fc66eb08649178f4ce..7d1dd5bad39ad809034c7715b6a672d3483cd322 100644 (file)
@@ -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
@@ -1053,8 +1063,6 @@ M:        wli@holomorphy.com
 S:     Maintained
 
 I2C SUBSYSTEM
-P:     Greg Kroah-Hartman
-M:     greg@kroah.com
 P:     Jean Delvare
 M:     khali@linux-fr.org
 L:     lm-sensors@lm-sensors.org
@@ -1394,6 +1402,18 @@ L:       linux-kernel@vger.kernel.org
 L:     fastboot@osdl.org
 S:     Maintained
 
+KPROBES
+P:     Prasanna S Panchamukhi
+M:     prasanna@in.ibm.com
+P:     Ananth N Mavinakayanahalli
+M:     ananth@in.ibm.com
+P:     Anil S Keshavamurthy
+M:     anil.s.keshavamurthy@intel.com
+P:     David S. Miller
+M:     davem@davemloft.net
+L:     linux-kernel@vger.kernel.org
+S:     Maintained
+
 LANMEDIA WAN CARD DRIVER
 P:     Andrew Stanley-Jones
 M:     asj@lanmedia.com
@@ -2256,6 +2276,12 @@ M:       kristen.c.accardi@intel.com
 L:     pcihpd-discuss@lists.sourceforge.net
 S:     Maintained
 
+SKGE, SKY2 10/100/1000 GIGABIT ETHERNET DRIVERS
+P:     Stephen Hemminger
+M:     shemminger@osdl.org
+L:     netdev@vger.kernel.org
+S:     Maintained
+
 SPARC (sparc32):
 P:     William L. Irwin
 M:     wli@holomorphy.com
@@ -2268,12 +2294,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
index 4e0d7c68d2231fa1605378f8d637e19e347008b7..8cf6becf68dcf3352d0b1ebe8d87c1d1eb5df033 100644 (file)
--- 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/README b/README
index 76dd780d88edb6403ac7587229986788abd1a748..d1edcc7adabe4a1dfd8efbdb3d26777a8526b044 100644 (file)
--- a/README
+++ b/README
@@ -149,6 +149,9 @@ CONFIGURING the kernel:
        "make gconfig"     X windows (Gtk) based configuration tool.
        "make oldconfig"   Default all questions based on the contents of
                           your existing ./.config file.
+       "make silentoldconfig"
+                          Like above, but avoids cluttering the screen
+                          with questions already answered.
    
        NOTES on "make config":
        - having unnecessary drivers will make the kernel bigger, and can
@@ -169,9 +172,6 @@ CONFIGURING the kernel:
          should probably answer 'n' to the questions for
           "development", "experimental", or "debugging" features.
 
- - Check the top Makefile for further site-dependent configuration
-   (default SVGA mode etc). 
-
 COMPILING the kernel:
 
  - Make sure you have gcc 2.95.3 available.
@@ -199,6 +199,9 @@ COMPILING the kernel:
    are installing a new kernel with the same version number as your
    working kernel, make a backup of your modules directory before you
    do a "make modules_install".
+   Alternatively, before compiling, use the kernel config option
+   "LOCALVERSION" to append a unique suffix to the regular kernel version.
+   LOCALVERSION can be set in the "General Setup" menu.
 
  - In order to boot your new kernel, you'll need to copy the kernel
    image (e.g. .../linux/arch/i386/boot/bzImage after compilation)
index 0636116210d236e2ed0353c4296036e2edf793ec..01fe990d3e54b2c59d8c5fdfafbbea79a11ce1d7 100644 (file)
@@ -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;
 
        /*
index fa98dae3cd986dc323132a0ad2f0bd205ea7c9a4..eb20c3afff585b965a0bf3c2f1eace56b909aacb 100644 (file)
@@ -127,6 +127,10 @@ common_shutdown_1(void *generic_ptr)
        /* If booted from SRM, reset some of the original environment. */
        if (alpha_using_srm) {
 #ifdef CONFIG_DUMMY_CONSOLE
+               /* If we've gotten here after SysRq-b, leave interrupt
+                  context before taking over the console. */
+               if (in_interrupt())
+                       irq_exit();
                /* This has the effect of resetting the VGA video origin.  */
                take_over_console(&dummy_con, 0, MAX_NR_CONSOLES-1, 1);
 #endif
index 9e36b07fa940a09e197db647456ceffdb10d2698..d5da6b1b28eec6cd557942ff1684f371a9ccc22a 100644 (file)
@@ -394,6 +394,22 @@ clipper_init_irq(void)
  *  10  64 bit PCI option slot 3 (not bus 0)
  */
 
+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)
 {
@@ -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
index 7f6f5db0d0603275c668c0beebee4d5851e28ee0..465c54b6b128dceeed0608c40449aeebe8dcfbcc 100644 (file)
@@ -256,5 +256,5 @@ asmlinkage void ofw_init(ofw_handle_t o, int *nomr, int *pointer)
        temp[11]='\0';
        mem_len = OF_getproplen(o,phandle, temp);
        OF_getprop(o,phandle, temp, buffer, mem_len);
-       (unsigned char) pointer[32] = ((unsigned char *) buffer)[mem_len-2];
+       * ((unsigned char *) &pointer[32]) = ((unsigned char *) buffer)[mem_len-2];
 }
index 2786f7c34b3fc9e7627d613a00e63e9aaf40681d..a7bd857001522651709ff4fafd57c427ca036ad3 100644 (file)
@@ -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;
index f67ca01b4982f9e01e590468bae49bf0801bc756..30e6444f9aaab9238196b03a2d35fcf9438d45e0 100644 (file)
@@ -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
@@ -178,6 +177,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
index 5c6c928215d061911f00fea774b201b50341b453..678720fa2e2ecb84e101dc71a360cd23e6d344a4 100644 (file)
@@ -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
@@ -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
 #
@@ -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
index 6dc40f6be0eff06fd10163d5234193eb39e94b98..38c9a721d5c99ad7617926d670b194f86efff3d1 100644 (file)
@@ -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
@@ -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=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
index d2bb0b7153fea967629526fdd5a5cdc3f8cc1353..261e2343903b7b0f0bbb8ce6e424b164c27fa3eb 100644 (file)
@@ -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
@@ -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
 #
@@ -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
index 2d6f960e3395f6b0dde6c3bbf37cc5baf69b01cd..12ef23d1c016f63a57d70931ca60587b1fd71957 100644 (file)
@@ -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
@@ -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
 #
@@ -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
index 949ec4427f2165efdd2a7c04a66d391a76c7da6e..2ad4aa2a1536c1ca22e1843352cdd9d2ac9cfbb7 100644 (file)
@@ -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
index 7152bfbee581ea4fa83769bd323564a6249782f7..93b5e8e5292effd86be569c757670a190a38369e 100644 (file)
@@ -537,7 +537,7 @@ ENTRY(__switch_to)
 #ifdef CONFIG_CPU_MPCORE
        clrex
 #else
-       strex   r3, r4, [ip]                    @ Clear exclusive monitor
+       strex   r5, r4, [ip]                    @ Clear exclusive monitor
 #endif
 #endif
 #if defined(CONFIG_CPU_XSCALE) && !defined(CONFIG_IWMMXT)
index db302c6e53439ddd553d42992109deccc3105741..81d450ac3fab2e1351b15860d9e6bda727261198 100644 (file)
@@ -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.
index ac423e3e224be9d27b5a5dba934f0bb60450a82d..4c31f292305563bbf5199460a75df12f6475c5f9 100644 (file)
@@ -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\
index 4554c961251c5871e0a05a2c6a74d1f660d0af73..e7d22dbcb691e1e4444f94db0ab5da5b45b8731c 100644 (file)
@@ -624,6 +624,9 @@ void __attribute__((noreturn)) __bug(const char *file, int line, void *data)
                printk(" - extra data = %p", data);
        printk("\n");
        *(int *)0 = 0;
+
+       /* Avoid "noreturn function does return" */
+       for (;;);
 }
 EXPORT_SYMBOL(__bug);
 
index ad2d66c93a5c3edf15f7a854683c9d67bfd76241..08e58ecd44be78d342df2d8a3d4d896462012996 100644 (file)
@@ -23,20 +23,20 @@ SECTIONS
                        *(.init.text)
                        _einittext = .;
                __proc_info_begin = .;
-                       *(.proc.info)
+                       *(.proc.info.init)
                __proc_info_end = .;
                __arch_info_begin = .;
-                       *(.arch.info)
+                       *(.arch.info.init)
                __arch_info_end = .;
                __tagtable_begin = .;
-                       *(.taglist)
+                       *(.taglist.init)
                __tagtable_end = .;
                . = ALIGN(16);
                __setup_start = .;
                        *(.init.setup)
                __setup_end = .;
                __early_begin = .;
-                       *(__early_param)
+                       *(.early_param.init)
                __early_end = .;
                __initcall_start = .;
                        *(.initcall1.init)
index ae1fa099d5fa4c965a8f089d8708d1b00b466224..39b06ed806462b69a1afd5ac39c5e49430b1b844 100644 (file)
@@ -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
index 405a55f2287cc8b0b459f431effca8bc25d4ebdb..3e5f69bb5ac40764427b4d0d09ee1bedb040c1e9 100644 (file)
@@ -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
index 33dae99ec2d843290105013226519a47e3a50daf..f609a0f232cb6424918bda6f494e633b24f45382 100644 (file)
@@ -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
index 07b5dd453565402d9ec8c69b691681bae063be5a..be37586cb1b062ba5ec96502b223e6e97ab4d215 100644 (file)
@@ -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
index deac29c0029019136f87df697ac9d2e1f46334bb..c5efcd04fcbc8011c01961ca334a080dcf62005a 100644 (file)
@@ -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.
 #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
index 366a9bde3d8be08880231795926d834839d35ddc..0ef42828705526b5fc06823144791e3a93351fbb 100644 (file)
@@ -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
 #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);
        }
index 923f6eb774c0c80a7e54a5bc7b9cfc45730437f7..1f38033921e95c385446cbebf38b9a1d9fa4e4cd 100644 (file)
@@ -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,
 };
 
index 47cfb8bb8318abc4812f7ca56a6a339c0645a3da..f2563881001719306226374a976747a348d0ff11 100644 (file)
@@ -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 (file)
index 0000000..3977a77
--- /dev/null
@@ -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 (file)
index 0000000..568afe3
--- /dev/null
@@ -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
index f87aa0b669ad226084d33c00daef2acb36c95f4f..7c05f27fe1d63c564c1277f34fd2f1519bb61db3 100644 (file)
@@ -12,6 +12,7 @@
  *
  * Modifications:
  *     02-May-2005 BJD  Copied from mach-bast.c
+ *     20-Sep-2005 BJD  Added static to non-exported items
 */
 
 #include <linux/kernel.h>
@@ -232,7 +233,7 @@ static struct s3c24xx_board anubis_board __initdata = {
        .clocks_count  = ARRAY_SIZE(anubis_clocks)
 };
 
-void __init anubis_map_io(void)
+static void __init anubis_map_io(void)
 {
        /* initialise the clocks */
 
index 1a3367da640897e30acf33118d5fca4073a7fc1a..ed1f07d7252fe08e1ce6c57e66789a68a914c185 100644 (file)
@@ -31,6 +31,7 @@
  *     17-Jul-2005 BJD  Changed to platform device for SuperIO 16550s
  *     25-Jul-2005 BJD  Removed ASIX static mappings
  *     27-Jul-2005 BJD  Ensure maximum frequency of i2c bus
+ *     20-Sep-2005 BJD  Added static to non-exported items
 */
 
 #include <linux/kernel.h>
@@ -428,7 +429,7 @@ static struct s3c24xx_board bast_board __initdata = {
        .clocks_count  = ARRAY_SIZE(bast_clocks)
 };
 
-void __init bast_map_io(void)
+static void __init bast_map_io(void)
 {
        /* initialise the clocks */
 
index 6ff1889fbd21facb8b13b3bcf1a9eff3685509fe..fb3cb01266e513e27c5871d008eec550656fad73 100644 (file)
@@ -24,6 +24,7 @@
  *     10-Jan-2005 BJD  Removed include of s3c2410.h
  *     14-Jan-2005 BJD  Added clock init
  *     10-Mar-2005 LCVR Changed S3C2410_VA to S3C24XX_VA
+ *     20-Sep-2005 BJD  Added static to non-exported items
 */
 
 #include <linux/kernel.h>
@@ -147,7 +148,7 @@ static struct s3c24xx_board h1940_board __initdata = {
        .devices_count = ARRAY_SIZE(h1940_devices)
 };
 
-void __init h1940_map_io(void)
+static void __init h1940_map_io(void)
 {
        s3c24xx_init_io(h1940_iodesc, ARRAY_SIZE(h1940_iodesc));
        s3c24xx_init_clocks(0);
@@ -155,13 +156,13 @@ void __init h1940_map_io(void)
        s3c24xx_set_board(&h1940_board);
 }
 
-void __init h1940_init_irq(void)
+static void __init h1940_init_irq(void)
 {
        s3c24xx_init_irq();
 
 }
 
-void __init h1940_init(void)
+static void __init h1940_init(void)
 {
        set_s3c2410fb_info(&h1940_lcdcfg);
 }
index 66bf5bb2b3db2a2b18120379e098496a2700decc..5c0f2b091f95146d850d2ee4197f9b5b6d4dcbf1 100644 (file)
@@ -97,7 +97,7 @@ static struct s3c24xx_board n30_board __initdata = {
        .devices_count = ARRAY_SIZE(n30_devices)
 };
 
-void __init n30_map_io(void)
+static void __init n30_map_io(void)
 {
        s3c24xx_init_io(n30_iodesc, ARRAY_SIZE(n30_iodesc));
        s3c24xx_init_clocks(0);
@@ -105,14 +105,14 @@ void __init n30_map_io(void)
        s3c24xx_set_board(&n30_board);
 }
 
-void __init n30_init_irq(void)
+static void __init n30_init_irq(void)
 {
        s3c24xx_init_irq();
 }
 
 /* GPB3 is the line that controls the pull-up for the USB D+ line */
 
-void __init n30_init(void)
+static void __init n30_init(void)
 {
        s3c_device_i2c.dev.platform_data = &n30_i2ccfg;
 
index d24c242414ca22a03333425b9222620fe6fc84e0..c22f8216032d8d8a5e88c5d7e01bfc51bb580253 100644 (file)
@@ -136,7 +136,7 @@ static void __init nexcoder_sensorboard_init(void)
        s3c2410_gpio_cfgpin(S3C2410_GPF2, S3C2410_GPF2_OUTP); // CAM_GPIO6 => CAM_PWRDN
 }
 
-void __init nexcoder_map_io(void)
+static void __init nexcoder_map_io(void)
 {
        s3c24xx_init_io(nexcoder_iodesc, ARRAY_SIZE(nexcoder_iodesc));
        s3c24xx_init_clocks(0);
index d901ed492ff55b7f4090bb8d64ff5351a9c2797d..ad1459e402e286671dc3ded975a3416b24c6a69e 100644 (file)
@@ -105,7 +105,7 @@ static struct s3c24xx_board otom11_board __initdata = {
 };
 
 
-void __init otom11_map_io(void)
+static void __init otom11_map_io(void)
 {
        s3c24xx_init_io(otom11_iodesc, ARRAY_SIZE(otom11_iodesc));
        s3c24xx_init_clocks(0);
index a73d61c1de461f310533199af4783ece59aef4c6..22d9e070fd68f42e0e9275a1f97a0fdc258b96c0 100644 (file)
@@ -16,6 +16,7 @@
  *     14-Jan-2005 BJD  Added new clock init
  *     10-Mar-2005 LCVR Changed S3C2410_VA to S3C24XX_VA
  *     14-Mar-2005 BJD  Fixed __iomem warnings
+ *     20-Sep-2005 BJD  Added static to non-exported items
 */
 
 #include <linux/kernel.h>
@@ -108,7 +109,7 @@ static struct s3c24xx_board rx3715_board __initdata = {
        .devices_count = ARRAY_SIZE(rx3715_devices)
 };
 
-void __init rx3715_map_io(void)
+static void __init rx3715_map_io(void)
 {
        s3c24xx_init_io(rx3715_iodesc, ARRAY_SIZE(rx3715_iodesc));
        s3c24xx_init_clocks(16934000);
@@ -116,7 +117,7 @@ void __init rx3715_map_io(void)
        s3c24xx_set_board(&rx3715_board);
 }
 
-void __init rx3715_init_irq(void)
+static void __init rx3715_init_irq(void)
 {
        s3c24xx_init_irq();
 }
index 67e903a700d3c00cd0249344fc917fd0ed6f9ee9..2eda55a6b678bddd2b5fdb6f7c7f17db9bebeb86 100644 (file)
@@ -28,6 +28,7 @@
  * Ben Dooks <ben@simtec.co.uk>
  *
  * 10-Mar-2005 LCVR  Changed S3C2410_VA to S3C24XX_VA
+ * 20-Sep-2005 BJD  Added static to non-exported items
  *
  ***********************************************************************/
 
@@ -97,7 +98,7 @@ static struct s3c24xx_board smdk2410_board __initdata = {
        .devices_count = ARRAY_SIZE(smdk2410_devices)
 };
 
-void __init smdk2410_map_io(void)
+static void __init smdk2410_map_io(void)
 {
        s3c24xx_init_io(smdk2410_iodesc, ARRAY_SIZE(smdk2410_iodesc));
        s3c24xx_init_clocks(0);
@@ -105,7 +106,7 @@ void __init smdk2410_map_io(void)
        s3c24xx_set_board(&smdk2410_board);
 }
 
-void __init smdk2410_init_irq(void)
+static void __init smdk2410_init_irq(void)
 {
        s3c24xx_init_irq();
 }
index 357522106f68c44c935f727bfecd6c1cacc7aa01..722ef46b630ac12bbb40eb495baef8dfae10b208 100644 (file)
@@ -18,6 +18,7 @@
  *     22-Feb-2005 BJD   Updated for 2.6.11-rc5 relesa
  *     10-Mar-2005 LCVR  Replaced S3C2410_VA by S3C24XX_VA
  *     14-Mar-2005 BJD   void __iomem fixes
+ *     20-Sep-2005 BJD   Added static to non-exported items
 */
 
 #include <linux/kernel.h>
@@ -98,7 +99,7 @@ static struct s3c24xx_board smdk2440_board __initdata = {
        .devices_count = ARRAY_SIZE(smdk2440_devices)
 };
 
-void __init smdk2440_map_io(void)
+static void __init smdk2440_map_io(void)
 {
        s3c24xx_init_io(smdk2440_iodesc, ARRAY_SIZE(smdk2440_iodesc));
        s3c24xx_init_clocks(16934400);
@@ -106,7 +107,7 @@ void __init smdk2440_map_io(void)
        s3c24xx_set_board(&smdk2440_board);
 }
 
-void __init smdk2440_machine_init(void)
+static void __init smdk2440_machine_init(void)
 {
        /* Configure the LEDs (even if we have no LED support)*/
 
index 8f9ab2893df4b718bf29613b971ec79cc03ff117..663a7f98fc0b94d9ec349266c8cbf0b04c6d61dc 100644 (file)
@@ -28,6 +28,7 @@
  *     10-Mar-2005 LCVR Changed S3C2410_VA to S3C24XX_VA
  *     14-Mar-2006 BJD  void __iomem fixes
  *     22-Jun-2006 BJD  Added DM9000 platform information
+ *     20-Sep-2005 BJD  Added static to non-exported items
 */
 
 #include <linux/kernel.h>
@@ -347,7 +348,7 @@ static void vr1000_power_off(void)
        s3c2410_gpio_setpin(S3C2410_GPB9, 1);
 }
 
-void __init vr1000_map_io(void)
+static void __init vr1000_map_io(void)
 {
        /* initialise clock sources */
 
index 8cb69113a57c89beae576c7a7a7a4d54ddfb9346..25d6a4e27533f5088778b3ab2cbb6b3e62063336 100644 (file)
@@ -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 = {
index 279e3afa3c393bd8b25b4f01c47abd00ffb40d57..f085d68e568e4f049587ba5f741551e0ee2ee516 100644 (file)
@@ -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);
index 0b6c4db44e08275e4ef15ab74923a581f48dc645..4a884baf3b9c731c0f31e428c1595321f08dee4e 100644 (file)
@@ -233,7 +233,17 @@ do_page_fault(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
        if (in_interrupt() || !mm)
                goto no_context;
 
-       down_read(&mm->mmap_sem);
+       /*
+        * As per x86, we may deadlock here.  However, since the kernel only
+        * validly references user space from well defined areas of the code,
+        * we can bug out early if this is from code which shouldn't.
+        */
+       if (!down_read_trylock(&mm->mmap_sem)) {
+               if (!user_mode(regs) && !search_exception_tables(regs->ARM_pc))
+                       goto no_context;
+               down_read(&mm->mmap_sem);
+       }
+
        fault = __do_page_fault(mm, addr, fsr, tsk);
        up_read(&mm->mmap_sem);
 
index 1d739d282a453ac9e1f266e3b05eaa6df2f479af..82ec954e45b6b67951e4d0a8e4fe0a86ee314bba 100644 (file)
@@ -509,7 +509,7 @@ cpu_arm1020_name:
 
        .align
 
-       .section ".proc.info", #alloc, #execinstr
+       .section ".proc.info.init", #alloc, #execinstr
 
        .type   __arm1020_proc_info,#object
 __arm1020_proc_info:
index 9b725665b5c77dad5ef9de56300974704d5e78d6..7375fe930f7273520fe69c47f5141e6339e57f7d 100644 (file)
@@ -491,7 +491,7 @@ cpu_arm1020e_name:
 
        .align
 
-       .section ".proc.info", #alloc, #execinstr
+       .section ".proc.info.init", #alloc, #execinstr
 
        .type   __arm1020e_proc_info,#object
 __arm1020e_proc_info:
index 37b70fa21c767b671edc717a64f6e60f1567585a..6ca639094d6fc9f59aa3493180453062e9bbadb3 100644 (file)
@@ -473,7 +473,7 @@ cpu_arm1022_name:
 
        .align
 
-       .section ".proc.info", #alloc, #execinstr
+       .section ".proc.info.init", #alloc, #execinstr
 
        .type   __arm1022_proc_info,#object
 __arm1022_proc_info:
index 931b690d1be24979bc17561d54506e09071c5c1e..10317e4f55d2ae6101896d382c73dbc3bd25d412 100644 (file)
@@ -469,7 +469,7 @@ cpu_arm1026_name:
 
        .align
 
-       .section ".proc.info", #alloc, #execinstr
+       .section ".proc.info.init", #alloc, #execinstr
 
        .type   __arm1026_proc_info,#object
 __arm1026_proc_info:
index d0f1bbb48f6c2cb9fc9e04c46dccf0bc377f94e5..8e7e1e70ab05ce0329c5c09237925b4b2b888ef6 100644 (file)
@@ -332,7 +332,7 @@ cpu_arm710_name:
 
                .align
 
-               .section ".proc.info", #alloc, #execinstr
+               .section ".proc.info.init", #alloc, #execinstr
 
                .type   __arm6_proc_info, #object
 __arm6_proc_info:
index c69c9de32391742f037d556046a4d0026f5ad949..a13e0184d343dadb538cd535e6e50e37e220ebf2 100644 (file)
@@ -222,7 +222,7 @@ cpu_arm720_name:
  * See linux/include/asm-arm/procinfo.h for a definition of this structure.
  */
        
-               .section ".proc.info", #alloc, #execinstr
+               .section ".proc.info.init", #alloc, #execinstr
 
                .type   __arm710_proc_info, #object
 __arm710_proc_info:
index 0f490a0fcb71b4514b5957804cd58f0a426aed62..d16513899999299d8820471976e506cad2aeff4e 100644 (file)
@@ -452,7 +452,7 @@ cpu_arm920_name:
 
        .align
 
-       .section ".proc.info", #alloc, #execinstr
+       .section ".proc.info.init", #alloc, #execinstr
 
        .type   __arm920_proc_info,#object
 __arm920_proc_info:
index 62bc34a139ee799061a518f9113aac84675cd481..23b8ed97f4e3bc1fc36bf2d69d3339bdfdc49023 100644 (file)
@@ -456,7 +456,7 @@ cpu_arm922_name:
 
        .align
 
-       .section ".proc.info", #alloc, #execinstr
+       .section ".proc.info.init", #alloc, #execinstr
 
        .type   __arm922_proc_info,#object
 __arm922_proc_info:
index ee49aa2ca7818d5fafb062aee3ba0df36916f139..ee95c52db513b302b662388e0fc0fd4302e89fd5 100644 (file)
@@ -521,7 +521,7 @@ cpu_arm925_name:
 
        .align
 
-       .section ".proc.info", #alloc, #execinstr
+       .section ".proc.info.init", #alloc, #execinstr
 
        .type   __arm925_proc_info,#object
 __arm925_proc_info:
index bb95cc9fed03208f8472efafae396d6d68b28c76..7d042dc20c47a77855b258457478e1d0dceb8c96 100644 (file)
@@ -471,7 +471,7 @@ cpu_arm926_name:
 
        .align
 
-       .section ".proc.info", #alloc, #execinstr
+       .section ".proc.info.init", #alloc, #execinstr
 
        .type   __arm926_proc_info,#object
 __arm926_proc_info:
index 34f7e7d3f419c78c0aea1555cb6768fa51b6f566..bd330c4075a1d13c4ef25da370687d28c5fed1a8 100644 (file)
@@ -249,7 +249,7 @@ cpu_sa110_name:
 
        .align
 
-       .section ".proc.info", #alloc, #execinstr
+       .section ".proc.info.init", #alloc, #execinstr
 
        .type   __sa110_proc_info,#object
 __sa110_proc_info:
index ca14f80d5ab4b5b874bea29bef0be1359ceecdab..91b89124c0d7e0ec08328081381ed26b82fddfeb 100644 (file)
@@ -280,7 +280,7 @@ cpu_sa1110_name:
 
        .align
 
-       .section ".proc.info", #alloc, #execinstr
+       .section ".proc.info.init", #alloc, #execinstr
 
        .type   __sa1100_proc_info,#object
 __sa1100_proc_info:
index eb34823c9dbf6f37a4f522e128c89db02f23f3b5..caf3b19b167ffbfbc0d1676644974aadfd9e943a 100644 (file)
@@ -240,7 +240,7 @@ cpu_elf_name:
        .size   cpu_elf_name, . - cpu_elf_name
        .align
 
-       .section ".proc.info", #alloc, #execinstr
+       .section ".proc.info.init", #alloc, #execinstr
 
        /*
         * Match any ARMv6 processor core.
index b88de2700146e6cd494b774985eeca84df14c256..861b35947280fcc78897c01df1e3c9a8dc0da265 100644 (file)
@@ -578,7 +578,7 @@ cpu_pxa270_name:
 
        .align
 
-       .section ".proc.info", #alloc, #execinstr
+       .section ".proc.info.init", #alloc, #execinstr
 
        .type   __80200_proc_info,#object
 __80200_proc_info:
diff --git a/arch/arm26/boot/compressed/hw-bse.c b/arch/arm26/boot/compressed/hw-bse.c
deleted file mode 100644 (file)
index 3e8f07f..0000000
+++ /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;
-}
index b22f003eaa6d782c02523685501a22753c28a50e..d2703cda61ea36db794b75c0e8d6f01a6ca0e048 100644 (file)
@@ -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
index 1ae2aeeda18bddbbc23ec37702d2ed4878ee23d0..f1b9d2a46dab860c0cbf100e1bf6b9b0b220c024 100644 (file)
@@ -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;
 }
 
index 1cbb9c0f47040d9eb430e738f81871ff18aeacee..350ea6680f63782dcfb237480f83c42b9229005a 100644 (file)
@@ -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 
index dc39ca6a7eca82f546c649cb6b2e1b3c6a20b4a2..9b8c8a19824de64c9a308177e11f55df3974099c 100644 (file)
@@ -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
index c70cd2a083045ea7ff12069a1fce5e9444cd6257..5f0a95d76a4f16fa3c95ba57c131c6eb3c967046 100644 (file)
@@ -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:
index 09a58cb6daa7050e018496a127458241f2fa0e30..431a551e46ea5f191498eaa6fbe7a6fc7d7273fa 100644 (file)
@@ -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 */
                        /*
index 7b1932d20f967da2cf8e5af68285905ad01a8afc..914933e9ec3d29847e8a1b59b08902c87146e3cf 100644 (file)
@@ -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 (file)
index 8b81b25..0000000
+++ /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);
index ed25d66c8d50b2951eb3e1610a24f735c3e73957..945c15a0722b894eeac86f2778326313eadf4b5f 100644 (file)
@@ -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
index 70f8ed2748d1b41cc3f2ea1b9d44290ecd693c25..67932ad530822882047655b58f1d6ba0992bbc08 100644 (file)
@@ -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) $@
index 56405dbfd739ca71ca7ae327988f1066b416af3e..a18983a3c9347286670f47cfcc3267c521f3dc35 100644 (file)
@@ -233,6 +233,23 @@ simscsi_readwrite10 (struct scsi_cmnd *sc, int mode)
                simscsi_readwrite(sc, mode, offset, ((sc->cmnd[7] << 8) | sc->cmnd[8])*512);
 }
 
+static void simscsi_fillresult(struct scsi_cmnd *sc, char *buf, unsigned len)
+{
+
+       int scatterlen = sc->use_sg;
+       struct scatterlist *slp;
+
+       if (scatterlen == 0)
+               memcpy(sc->request_buffer, buf, len);
+       else for (slp = (struct scatterlist *)sc->buffer; scatterlen-- > 0 && len > 0; slp++) {
+               unsigned thislen = min(len, slp->length);
+
+               memcpy(page_address(slp->page) + slp->offset, buf, thislen);
+               slp++;
+               len -= thislen;
+       }
+}
+
 static int
 simscsi_queuecommand (struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *))
 {
@@ -240,6 +257,7 @@ simscsi_queuecommand (struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *))
        char fname[MAX_ROOT_LEN+16];
        size_t disk_size;
        char *buf;
+       char localbuf[36];
 #if DEBUG_SIMSCSI
        register long sp asm ("sp");
 
@@ -263,7 +281,7 @@ simscsi_queuecommand (struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *))
                                /* disk doesn't exist... */
                                break;
                        }
-                       buf = sc->request_buffer;
+                       buf = localbuf;
                        buf[0] = 0;     /* magnetic disk */
                        buf[1] = 0;     /* not a removable medium */
                        buf[2] = 2;     /* SCSI-2 compliant device */
@@ -273,6 +291,7 @@ simscsi_queuecommand (struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *))
                        buf[6] = 0;     /* reserved */
                        buf[7] = 0;     /* various flags */
                        memcpy(buf + 8, "HP      SIMULATED DISK  0.00",  28);
+                       simscsi_fillresult(sc, buf, 36);
                        sc->result = GOOD;
                        break;
 
@@ -304,16 +323,13 @@ simscsi_queuecommand (struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *))
                        simscsi_readwrite10(sc, SSC_WRITE);
                        break;
 
-
                      case READ_CAPACITY:
                        if (desc[target_id] < 0 || sc->request_bufflen < 8) {
                                break;
                        }
-                       buf = sc->request_buffer;
-
+                       buf = localbuf;
                        disk_size = simscsi_get_disk_size(desc[target_id]);
 
-                       /* pretend to be a 1GB disk (partition table contains real stuff): */
                        buf[0] = (disk_size >> 24) & 0xff;
                        buf[1] = (disk_size >> 16) & 0xff;
                        buf[2] = (disk_size >>  8) & 0xff;
@@ -323,13 +339,14 @@ simscsi_queuecommand (struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *))
                        buf[5] = 0;
                        buf[6] = 2;
                        buf[7] = 0;
+                       simscsi_fillresult(sc, buf, 8);
                        sc->result = GOOD;
                        break;
 
                      case MODE_SENSE:
                      case MODE_SENSE_10:
                        /* sd.c uses this to determine whether disk does write-caching. */
-                       memset(sc->request_buffer, 0, 128);
+                       simscsi_fillresult(sc, (char *)empty_zero_page, sc->request_bufflen);
                        sc->result = GOOD;
                        break;
 
index 31de70b7c67f63f95ba5c685b707f428d0fb1583..a7280d9f6c1634d80cdd7b1b48a90d6eb3a138f4 100644 (file)
@@ -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);
index 28a4529fdd60aed47c0cc2824ad381f763a73c2e..7e926471e4ec0905508c8b6083dcb6eda7e4abb7 100644 (file)
@@ -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 */
 
index f6a2342893418be2dd65fb55fc65798f58655bd8..77225659e9684c16e2628e0ce0f60df21e3d616d 100644 (file)
@@ -4,6 +4,7 @@
  * to extract and format the required data.
  */
 
+#define ASM_OFFSETS_C 1
 #include <linux/config.h>
 
 #include <linux/sched.h>
index ba0b6a1f429fc315c17e4a8ace1cf8c5de8e0913..0741b066b98fd92af00131bc170b47bbcf6264de 100644 (file)
@@ -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
index 499a065f4e6019544c957d72a8c5168fa6461803..db32fc1d39356321950de04b0a586df9ac5dff37 100644 (file)
@@ -489,24 +489,27 @@ ia64_state_save:
        ;;
        st8 [temp1]=r17,16      // pal_min_state
        st8 [temp2]=r6,16       // prev_IA64_KR_CURRENT
+       mov r6=IA64_KR(CURRENT_STACK)
+       ;;
+       st8 [temp1]=r6,16       // prev_IA64_KR_CURRENT_STACK
+       st8 [temp2]=r0,16       // prev_task, starts off as NULL
        mov r6=cr.ifa
        ;;
-       st8 [temp1]=r0,16       // prev_task, starts off as NULL
-       st8 [temp2]=r12,16      // cr.isr
+       st8 [temp1]=r12,16      // cr.isr
+       st8 [temp2]=r6,16       // cr.ifa
        mov r12=cr.itir
        ;;
-       st8 [temp1]=r6,16       // cr.ifa
-       st8 [temp2]=r12,16      // cr.itir
+       st8 [temp1]=r12,16      // cr.itir
+       st8 [temp2]=r11,16      // cr.iipa
        mov r12=cr.iim
        ;;
-       st8 [temp1]=r11,16      // cr.iipa
-       st8 [temp2]=r12,16      // cr.iim
-       mov r6=cr.iha
+       st8 [temp1]=r12,16      // cr.iim
 (p1)   mov r12=IA64_MCA_COLD_BOOT
 (p2)   mov r12=IA64_INIT_WARM_BOOT
+       mov r6=cr.iha
        ;;
-       st8 [temp1]=r6,16       // cr.iha
-       st8 [temp2]=r12         // os_status, default is cold boot
+       st8 [temp2]=r6,16       // cr.iha
+       st8 [temp1]=r12         // os_status, default is cold boot
        mov r6=IA64_MCA_SAME_CONTEXT
        ;;
        st8 [temp1]=r6          // context, default is same context
@@ -823,9 +826,12 @@ ia64_state_restore:
        ld8 r12=[temp1],16      // sal_ra
        ld8 r9=[temp2],16       // sal_gp
        ;;
-       ld8 r22=[temp1],24      // pal_min_state, virtual.  skip prev_task
+       ld8 r22=[temp1],16      // pal_min_state, virtual
        ld8 r21=[temp2],16      // prev_IA64_KR_CURRENT
        ;;
+       ld8 r16=[temp1],16      // prev_IA64_KR_CURRENT_STACK
+       ld8 r20=[temp2],16      // prev_task
+       ;;
        ld8 temp3=[temp1],16    // cr.isr
        ld8 temp4=[temp2],16    // cr.ifa
        ;;
@@ -846,6 +852,45 @@ ia64_state_restore:
        ld8 r8=[temp1]          // os_status
        ld8 r10=[temp2]         // context
 
+       /* Wire IA64_TR_CURRENT_STACK to the stack that we are resuming to.  To
+        * avoid any dependencies on the algorithm in ia64_switch_to(), just
+        * purge any existing CURRENT_STACK mapping and insert the new one.
+        *
+        * r16 contains prev_IA64_KR_CURRENT_STACK, r21 contains
+        * prev_IA64_KR_CURRENT, these values may have been changed by the C
+        * code.  Do not use r8, r9, r10, r22, they contain values ready for
+        * the return to SAL.
+        */
+
+       mov r15=IA64_KR(CURRENT_STACK)          // physical granule mapped by IA64_TR_CURRENT_STACK
+       ;;
+       shl r15=r15,IA64_GRANULE_SHIFT
+       ;;
+       dep r15=-1,r15,61,3                     // virtual granule
+       mov r18=IA64_GRANULE_SHIFT<<2           // for cr.itir.ps
+       ;;
+       ptr.d r15,r18
+       ;;
+       srlz.d
+
+       extr.u r19=r21,61,3                     // r21 = prev_IA64_KR_CURRENT
+       shl r20=r16,IA64_GRANULE_SHIFT          // r16 = prev_IA64_KR_CURRENT_STACK
+       movl r21=PAGE_KERNEL                    // page properties
+       ;;
+       mov IA64_KR(CURRENT_STACK)=r16
+       cmp.ne p6,p0=RGN_KERNEL,r19             // new stack is in the kernel region?
+       or r21=r20,r21                          // construct PA | page properties
+(p6)   br.spnt 1f                              // the dreaded cpu 0 idle task in region 5:(
+       ;;
+       mov cr.itir=r18
+       mov cr.ifa=r21
+       mov r20=IA64_TR_CURRENT_STACK
+       ;;
+       itr.d dtr[r20]=r21
+       ;;
+       srlz.d
+1:
+
        br.sptk b0
 
 //EndStub//////////////////////////////////////////////////////////////////////
@@ -982,6 +1027,7 @@ ia64_set_kernel_registers:
        add temp4=temp4, temp1  // &struct ia64_sal_os_state.os_gp
        add r12=temp1, temp3    // kernel stack pointer on MCA/INIT stack
        add r13=temp1, r3       // set current to start of MCA/INIT stack
+       add r20=temp1, r3       // physical start of MCA/INIT stack
        ;;
        ld8 r1=[temp4]          // OS GP from SAL OS state
        ;;
@@ -991,7 +1037,35 @@ ia64_set_kernel_registers:
        ;;
        mov IA64_KR(CURRENT)=r13
 
-       // FIXME: do I need to wire IA64_KR_CURRENT_STACK and IA64_TR_CURRENT_STACK?
+       /* Wire IA64_TR_CURRENT_STACK to the MCA/INIT handler stack.  To avoid
+        * any dependencies on the algorithm in ia64_switch_to(), just purge
+        * any existing CURRENT_STACK mapping and insert the new one.
+        */
+
+       mov r16=IA64_KR(CURRENT_STACK)          // physical granule mapped by IA64_TR_CURRENT_STACK
+       ;;
+       shl r16=r16,IA64_GRANULE_SHIFT
+       ;;
+       dep r16=-1,r16,61,3                     // virtual granule
+       mov r18=IA64_GRANULE_SHIFT<<2           // for cr.itir.ps
+       ;;
+       ptr.d r16,r18
+       ;;
+       srlz.d
+
+       shr.u r16=r20,IA64_GRANULE_SHIFT        // r20 = physical start of MCA/INIT stack
+       movl r21=PAGE_KERNEL                    // page properties
+       ;;
+       mov IA64_KR(CURRENT_STACK)=r16
+       or r21=r20,r21                          // construct PA | page properties
+       ;;
+       mov cr.itir=r18
+       mov cr.ifa=r13
+       mov r20=IA64_TR_CURRENT_STACK
+       ;;
+       itr.d dtr[r20]=r21
+       ;;
+       srlz.d
 
        br.sptk b0
 
index 6e683745af49d1ceb128fc99ec60b61ad76a61f6..f081c60ab20684234f3e815ef4e520cdd8d75de8 100644 (file)
@@ -56,8 +56,9 @@ static struct page *page_isolate[MAX_PAGE_ISOLATE];
 static int num_page_isolate = 0;
 
 typedef enum {
-       ISOLATE_NG = 0,
-       ISOLATE_OK = 1
+       ISOLATE_NG,
+       ISOLATE_OK,
+       ISOLATE_NONE
 } isolate_status_t;
 
 /*
@@ -74,7 +75,7 @@ static struct {
  * @paddr:     poisoned memory location
  *
  * Return value:
- *     ISOLATE_OK / ISOLATE_NG
+ *     one of isolate_status_t, ISOLATE_OK/NG/NONE.
  */
 
 static isolate_status_t
@@ -84,23 +85,26 @@ mca_page_isolate(unsigned long paddr)
        struct page *p;
 
        /* whether physical address is valid or not */
-       if ( !ia64_phys_addr_valid(paddr) ) 
-               return ISOLATE_NG;
+       if (!ia64_phys_addr_valid(paddr))
+               return ISOLATE_NONE;
+
+       if (!pfn_valid(paddr))
+               return ISOLATE_NONE;
 
        /* 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 */
@@ -122,10 +126,15 @@ mca_handler_bh(unsigned long paddr)
                current->pid, current->comm);
 
        spin_lock(&mca_bh_lock);
-       if (mca_page_isolate(paddr) == ISOLATE_OK) {
+       switch (mca_page_isolate(paddr)) {
+       case ISOLATE_OK:
                printk(KERN_DEBUG "Page isolation: ( %lx ) success.\n", paddr);
-       } else {
+               break;
+       case ISOLATE_NG:
                printk(KERN_DEBUG "Page isolation: ( %lx ) failure.\n", paddr);
+               break;
+       default:
+               break;
        }
        spin_unlock(&mca_bh_lock);
 
@@ -139,10 +148,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 +173,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 +181,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 +223,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 +270,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 +312,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 +327,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 +337,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 +402,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 +476,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 +508,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 +524,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 +538,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 +577,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 +588,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 +619,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 +630,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 +644,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;
index 0227b761f2c4bdfe9dc30db25abce03fa4f0724a..e2f6fa1e0ef6908121cea86108fbcaffe5498707 100644 (file)
@@ -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;              |
index 2d7e0217638d29866d13070f4ca4a516e450eaef..3f298ee4d00cbd828a0f53a69ded4cd18363428d 100644 (file)
 #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)
index 1650353e3f77ef40cdf5ab96e4642e67eb8b4190..d71731ee5b61fc8ce322458d3ca4dc9012b48335 100644 (file)
@@ -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);
 
index 799407e7726f2a9c54f301ce50f71c253f514174..cb1af597370bc8a2b2dc05e940baac84e2936b2d 100644 (file)
@@ -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 (file)
index c7ce92f..0000000
+++ /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);
index 1ef3987ebc6ac28e31cd1242e9c6e07b34b8ebb2..4d100f3886e1e7ab687a027937fbc555d3f9af9e 100644 (file)
@@ -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---
index 0eb71ac303af2c51bb6cf8ba1db5ed9899f647de..4cd724c05700674d18e884deec66a3f0756189c4 100644 (file)
@@ -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.
 #
index 4de155699c4fa2d748267365c923b6a1eaf2a58a..7ae4af476974cc0583a10086679ae233e4736c47 100644 (file)
@@ -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:
index 21b92b9dd0133af3c59e3031efd6ad9de27fa67a..03730341290916a58edaf43de4f0d86a93d272df 100644 (file)
@@ -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 (file)
index fd82c84..0000000
+++ /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);
index 347ea284140b28be32262dbb0427af539845940b..776941c756729510a48f9c4473df0f5315495315 100644 (file)
@@ -26,10 +26,6 @@ config GENERIC_CALIBRATE_DELAY
        bool
        default y
 
-config HAVE_DEC_LOCK
-       bool
-       default y
-
 config PPC
        bool
        default y
index 1fb92f16acd61efba7b3a1c641c13e485523b6d7..b1457a8a9c0f0eff8cf3cf130396076438d8d7e5 100644 (file)
@@ -15,9 +15,8 @@ extra-y                               += vmlinux.lds
 obj-y                          := entry.o traps.o irq.o idle.o time.o misc.o \
                                        process.o signal.o ptrace.o align.o \
                                        semaphore.o syscalls.o setup.o \
-                                       cputable.o ppc_htab.o
+                                       cputable.o ppc_htab.o perfmon.o
 obj-$(CONFIG_6xx)              += l2cr.o cpu_setup_6xx.o
-obj-$(CONFIG_E500)             += perfmon.o
 obj-$(CONFIG_SOFTWARE_SUSPEND) += swsusp.o
 obj-$(CONFIG_POWER4)           += cpu_setup_power4.o
 obj-$(CONFIG_MODULES)          += module.o ppc_ksyms.o
index fa1dad96b8309f1b44a4a40aef2748a36b4cf3e0..04c18788e85ff088c453985ac9b3aa86d231a318 100644 (file)
@@ -45,7 +45,7 @@ static void dummy_perf(struct pt_regs *regs)
        mtpmr(PMRN_PMGC0, pmgc0);
 }
 
-#else
+#elif CONFIG_6xx
 /* Ensure exceptions are disabled */
 
 static void dummy_perf(struct pt_regs *regs)
@@ -55,6 +55,10 @@ static void dummy_perf(struct pt_regs *regs)
        mmcr0 &= ~MMCR0_PMXE;
        mtspr(SPRN_MMCR0, mmcr0);
 }
+#else
+static void dummy_perf(struct pt_regs *regs)
+{
+}
 #endif
 
 void (*perf_irq)(struct pt_regs *) = dummy_perf;
index fe8bb634ead0a1e404edfff77c50260c887442a7..26bd8ea35a4e915e10264202cc12a6937f8c4cbf 100644 (file)
@@ -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>
index a3c5281a5d2d8c05e328a6fc5c83f10b9981193c..22d7fd1e0aea7e4e86851db796699ffa3c8f9bee 100644 (file)
@@ -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>
index 9353584fb7103c77cc866b417eecb12fa729c968..17d2db7e537df7eef854d6500bfc7b13ee84ed45 100644 (file)
@@ -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)
   }
 }
index f1e1fb4144f034a9be9197cffab83570efa9790d..50358e4ea1590e39889f90a01069a356f4ad5be0 100644 (file)
@@ -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 (file)
index b18f0d9..0000000
+++ /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);
index 4864a7de3daa9ac1373f9a2cf1fe4c288dcbac4d..6037ce7796f5e2e1864749b40636b6e759746b75 100644 (file)
@@ -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>
index b392b9a1598704af7e80e5749fed05cd625738fc..4c56a4734aec53333b0f328c31c98e765097b99d 100644 (file)
@@ -719,7 +719,8 @@ pmac_declare_of_platform_devices(void)
        if (np) {
                for (np = np->child; np != NULL; np = np->sibling)
                        if (strncmp(np->name, "i2c", 3) == 0) {
-                               of_platform_device_create(np, "uni-n-i2c");
+                               of_platform_device_create(np, "uni-n-i2c",
+                                                         NULL);
                                break;
                        }
        }
@@ -727,17 +728,18 @@ pmac_declare_of_platform_devices(void)
        if (np) {
                for (np = np->child; np != NULL; np = np->sibling)
                        if (strncmp(np->name, "i2c", 3) == 0) {
-                               of_platform_device_create(np, "u3-i2c");
+                               of_platform_device_create(np, "u3-i2c",
+                                                         NULL);
                                break;
                        }
        }
 
        np = find_devices("valkyrie");
        if (np)
-               of_platform_device_create(np, "valkyrie");
+               of_platform_device_create(np, "valkyrie", NULL);
        np = find_devices("platinum");
        if (np)
-               of_platform_device_create(np, "platinum");
+               of_platform_device_create(np, "platinum", NULL);
 
        return 0;
 }
index 8b9b226005d125c0e130d8fb9f29a59cbf414a1a..b8d08f33f7ee6c1d2309c8aa92f96f37a434c9a3 100644 (file)
@@ -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 (file)
index 0000000..2b5f0e7
--- /dev/null
@@ -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 (file)
index 0000000..a532ccc
--- /dev/null
@@ -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,
+       },
+};
index da8a0f2128dccc23bc06cc8b3f8a93809384e7ec..93c7231ea709295313de744788bdfa3d085134e9 100644 (file)
@@ -234,7 +234,9 @@ void of_device_unregister(struct of_device *ofdev)
        device_unregister(&ofdev->dev);
 }
 
-struct of_device* of_platform_device_create(struct device_node *np, const char *bus_id)
+struct of_device* of_platform_device_create(struct device_node *np,
+                                           const char *bus_id,
+                                           struct device *parent)
 {
        struct of_device *dev;
        u32 *reg;
@@ -247,7 +249,7 @@ struct of_device* of_platform_device_create(struct device_node *np, const char *
        dev->node = of_node_get(np);
        dev->dma_mask = 0xffffffffUL;
        dev->dev.dma_mask = &dev->dma_mask;
-       dev->dev.parent = NULL;
+       dev->dev.parent = parent;
        dev->dev.bus = &of_platform_bus_type;
        dev->dev.release = of_release_dev;
 
index 2e0ea92144f6b3f15a759dc9f9983f0b49f711b7..9a7e8748e2b2460353adc9d3f2974f81aa3e083d 100644 (file)
@@ -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;
index b7242f1bd931048977e2a99951c8ca68a5780502..832b8bf99ae71f890ba592797948cfe806e040ee 100644 (file)
@@ -184,8 +184,8 @@ mpc85xx_setup_pci1(struct pci_controller *hose)
        pci->powar1 = 0x80044000 |
           (__ilog2(MPC85XX_PCI1_UPPER_MEM - MPC85XX_PCI1_LOWER_MEM + 1) - 1);
 
-       /* Setup outboud IO windows @ MPC85XX_PCI1_IO_BASE */
-       pci->potar2 = 0x00000000;
+       /* Setup outbound IO windows @ MPC85XX_PCI1_IO_BASE */
+       pci->potar2 = (MPC85XX_PCI1_LOWER_IO >> 12) & 0x000fffff;
        pci->potear2 = 0x00000000;
        pci->powbar2 = (MPC85XX_PCI1_IO_BASE >> 12) & 0x000fffff;
        /* Enable, IO R/W */
@@ -235,8 +235,8 @@ mpc85xx_setup_pci2(struct pci_controller *hose)
        pci->powar1 = 0x80044000 |
           (__ilog2(MPC85XX_PCI2_UPPER_MEM - MPC85XX_PCI2_LOWER_MEM + 1) - 1);
 
-       /* Setup outboud IO windows @ MPC85XX_PCI2_IO_BASE */
-       pci->potar2 = 0x00000000;
+       /* Setup outbound IO windows @ MPC85XX_PCI2_IO_BASE */
+       pci->potar2 = (MPC85XX_PCI2_LOWER_IO >> 12) & 0x000fffff;;
        pci->potear2 = 0x00000000;
        pci->powbar2 = (MPC85XX_PCI2_IO_BASE >> 12) & 0x000fffff;
        /* Enable, IO R/W */
index 2bcf8a16d1c936180acae6965438678ef417a17d..8599850ca772f5d8a7cfef073a98875c5afae220 100644 (file)
@@ -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>
index deca68ad644ae41681537867c7e8accdb6d2a18b..c658650af429672267409508b02b38754c11a40f 100644 (file)
@@ -28,10 +28,6 @@ config GENERIC_ISA_DMA
        bool
        default y
 
-config HAVE_DEC_LOCK
-       bool
-       default y
-
 config EARLY_PRINTK
        bool
        default y
index 17d2c1eac3b8567e8cd711f3dd72a0c1bf037a82..521c2a5a286268e1538885b858f57a66177f4440 100644 (file)
@@ -107,7 +107,7 @@ install: vmlinux
        $(Q)$(MAKE) $(build)=$(boot) BOOTIMAGE=$(BOOTIMAGE) $@
 
 defaultimage-$(CONFIG_PPC_PSERIES) := zImage
-defaultimage-$(CONFIG_PPC_PMAC) := vmlinux
+defaultimage-$(CONFIG_PPC_PMAC) := zImage.vmode
 defaultimage-$(CONFIG_PPC_MAPLE) := zImage
 defaultimage-$(CONFIG_PPC_ISERIES) := vmlinux
 KBUILD_IMAGE := $(defaultimage-y)
index 17e35d0fed09ff87d7eeb0d49e30b02d8e9f139d..1ff4fa05a97329f1a7c5217a7e8737f6f49421e5 100644 (file)
@@ -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));
index d133a49cdf8972270fcd1f668f1d43cbea1a6766..e8c0bbf4d000353c176b55d4da7c36b628b19b65 100644 (file)
@@ -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
index 58c314738c9987f441ef29a273c551436db1650e..72c61041151a28ee23220035c5c68eea524bc4fd 100644 (file)
@@ -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 */
index da580812ddfeeb6305b8604c03ae6867ade531af..9f200f0f2ad54ae4eaac0fa7a7bc173d20200b87 100644 (file)
@@ -233,7 +233,9 @@ void of_device_unregister(struct of_device *ofdev)
        device_unregister(&ofdev->dev);
 }
 
-struct of_device* of_platform_device_create(struct device_node *np, const char *bus_id)
+struct of_device* of_platform_device_create(struct device_node *np,
+                                           const char *bus_id,
+                                           struct device *parent)
 {
        struct of_device *dev;
 
@@ -245,7 +247,7 @@ struct of_device* of_platform_device_create(struct device_node *np, const char *
        dev->node = np;
        dev->dma_mask = 0xffffffffUL;
        dev->dev.dma_mask = &dev->dma_mask;
-       dev->dev.parent = NULL;
+       dev->dev.parent = parent;
        dev->dev.bus = &of_platform_bus_type;
        dev->dev.release = of_release_dev;
 
@@ -259,6 +261,7 @@ struct of_device* of_platform_device_create(struct device_node *np, const char *
        return dev;
 }
 
+
 EXPORT_SYMBOL(of_match_device);
 EXPORT_SYMBOL(of_platform_bus_type);
 EXPORT_SYMBOL(of_register_driver);
index f0fd7fbd6531cd01fb8984d2c81e82a25825b484..d17f0108a03200c0437146f199acaab21ca6f678 100644 (file)
@@ -265,8 +265,10 @@ static void iommu_table_setparms(struct pci_controller *phb,
        tbl->it_offset = phb->dma_window_base_cur >> PAGE_SHIFT;
        
        /* Test if we are going over 2GB of DMA space */
-       if (phb->dma_window_base_cur + phb->dma_window_size > (1L << 31))
+       if (phb->dma_window_base_cur + phb->dma_window_size > 0x80000000ul) {
+               udbg_printf("PCI_DMA: Unexpected number of IOAs under this PHB.\n");
                panic("PCI_DMA: Unexpected number of IOAs under this PHB.\n"); 
+       }
        
        phb->dma_window_base_cur += phb->dma_window_size;
 
@@ -310,92 +312,85 @@ static void iommu_table_setparms_lpar(struct pci_controller *phb,
 
 static void iommu_bus_setup_pSeries(struct pci_bus *bus)
 {
-       struct device_node *dn, *pdn;
-       struct pci_dn *pci;
+       struct device_node *dn;
        struct iommu_table *tbl;
+       struct device_node *isa_dn, *isa_dn_orig;
+       struct device_node *tmp;
+       struct pci_dn *pci;
+       int children;
 
        DBG("iommu_bus_setup_pSeries, bus %p, bus->self %p\n", bus, bus->self);
 
-       /* For each (root) bus, we carve up the available DMA space in 256MB
-        * pieces. Since each piece is used by one (sub) bus/device, that would
-        * give a maximum of 7 devices per PHB. In most cases, this is plenty.
-        *
-        * The exception is on Python PHBs (pre-POWER4). Here we don't have EADS
-        * bridges below the PHB to allocate the sectioned tables to, so instead
-        * we allocate a 1GB table at the PHB level.
+       dn = pci_bus_to_OF_node(bus);
+       pci = PCI_DN(dn);
+
+       if (bus->self) {
+               /* This is not a root bus, any setup will be done for the
+                * device-side of the bridge in iommu_dev_setup_pSeries().
+                */
+               return;
+       }
+
+       /* Check if the ISA bus on the system is under
+        * this PHB.
         */
+       isa_dn = isa_dn_orig = of_find_node_by_type(NULL, "isa");
 
-       dn = pci_bus_to_OF_node(bus);
-       pci = dn->data;
-
-       if (!bus->self) {
-               /* Root bus */
-               if (is_python(dn)) {
-                       unsigned int *iohole;
-
-                       DBG("Python root bus %s\n", bus->name);
-
-                       iohole = (unsigned int *)get_property(dn, "io-hole", 0);
-
-                       if (iohole) {
-                               /* On first bus we need to leave room for the
-                                * ISA address space. Just skip the first 256MB
-                                * alltogether. This leaves 768MB for the window.
-                                */
-                               DBG("PHB has io-hole, reserving 256MB\n");
-                               pci->phb->dma_window_size = 3 << 28;
-                               pci->phb->dma_window_base_cur = 1 << 28;
-                       } else {
-                               /* 1GB window by default */
-                               pci->phb->dma_window_size = 1 << 30;
-                               pci->phb->dma_window_base_cur = 0;
-                       }
-
-                       tbl = kmalloc(sizeof(struct iommu_table), GFP_KERNEL);
-
-                       iommu_table_setparms(pci->phb, dn, tbl);
-                       pci->iommu_table = iommu_init_table(tbl);
-               } else {
-                       /* Do a 128MB table at root. This is used for the IDE
-                        * controller on some SMP-mode POWER4 machines. It
-                        * doesn't hurt to allocate it on other machines
-                        * -- it'll just be unused since new tables are
-                        * allocated on the EADS level.
-                        *
-                        * Allocate at offset 128MB to avoid having to deal
-                        * with ISA holes; 128MB table for IDE is plenty.
-                        */
-                       pci->phb->dma_window_size = 1 << 27;
-                       pci->phb->dma_window_base_cur = 1 << 27;
-
-                       tbl = kmalloc(sizeof(struct iommu_table), GFP_KERNEL);
-
-                       iommu_table_setparms(pci->phb, dn, tbl);
-                       pci->iommu_table = iommu_init_table(tbl);
-
-                       /* All child buses have 256MB tables */
-                       pci->phb->dma_window_size = 1 << 28;
-               }
-       } else {
-               pdn = pci_bus_to_OF_node(bus->parent);
+       while (isa_dn && isa_dn != dn)
+               isa_dn = isa_dn->parent;
+
+       if (isa_dn_orig)
+               of_node_put(isa_dn_orig);
 
-               if (!bus->parent->self && !is_python(pdn)) {
-                       struct iommu_table *tbl;
-                       /* First child and not python means this is the EADS
-                        * level. Allocate new table for this slot with 256MB
-                        * window.
-                        */
+       /* Count number of direct PCI children of the PHB.
+        * All PCI device nodes have class-code property, so it's
+        * an easy way to find them.
+        */
+       for (children = 0, tmp = dn->child; tmp; tmp = tmp->sibling)
+               if (get_property(tmp, "class-code", NULL))
+                       children++;
 
-                       tbl = kmalloc(sizeof(struct iommu_table), GFP_KERNEL);
+       DBG("Children: %d\n", children);
 
-                       iommu_table_setparms(pci->phb, dn, tbl);
+       /* Calculate amount of DMA window per slot. Each window must be
+        * a power of two (due to pci_alloc_consistent requirements).
+        *
+        * Keep 256MB aside for PHBs with ISA.
+        */
 
-                       pci->iommu_table = iommu_init_table(tbl);
-               } else {
-                       /* Lower than first child or under python, use parent table */
-                       pci->iommu_table = PCI_DN(pdn)->iommu_table;
-               }
+       if (!isa_dn) {
+               /* No ISA/IDE - just set window size and return */
+               pci->phb->dma_window_size = 0x80000000ul; /* To be divided */
+
+               while (pci->phb->dma_window_size * children > 0x80000000ul)
+                       pci->phb->dma_window_size >>= 1;
+               DBG("No ISA/IDE, window size is 0x%lx\n",
+                       pci->phb->dma_window_size);
+               pci->phb->dma_window_base_cur = 0;
+
+               return;
        }
+
+       /* If we have ISA, then we probably have an IDE
+        * controller too. Allocate a 128MB table but
+        * skip the first 128MB to avoid stepping on ISA
+        * space.
+        */
+       pci->phb->dma_window_size = 0x8000000ul;
+       pci->phb->dma_window_base_cur = 0x8000000ul;
+
+       tbl = kmalloc(sizeof(struct iommu_table), GFP_KERNEL);
+
+       iommu_table_setparms(pci->phb, dn, tbl);
+       pci->iommu_table = iommu_init_table(tbl);
+
+       /* Divide the rest (1.75GB) among the children */
+       pci->phb->dma_window_size = 0x80000000ul;
+       while (pci->phb->dma_window_size * children > 0x70000000ul)
+               pci->phb->dma_window_size >>= 1;
+
+       DBG("ISA/IDE, window size is 0x%lx\n", pci->phb->dma_window_size);
+
 }
 
 
@@ -446,21 +441,36 @@ static void iommu_bus_setup_pSeriesLP(struct pci_bus *bus)
 static void iommu_dev_setup_pSeries(struct pci_dev *dev)
 {
        struct device_node *dn, *mydn;
+       struct iommu_table *tbl;
+
+       DBG("iommu_dev_setup_pSeries, dev %p (%s)\n", dev, pci_name(dev));
 
-       DBG("iommu_dev_setup_pSeries, dev %p (%s)\n", dev, dev->pretty_name);
-       /* Now copy the iommu_table ptr from the bus device down to the
-        * pci device_node.  This means get_iommu_table() won't need to search
-        * up the device tree to find it.
-        */
        mydn = dn = pci_device_to_OF_node(dev);
 
+       /* If we're the direct child of a root bus, then we need to allocate
+        * an iommu table ourselves. The bus setup code should have setup
+        * the window sizes already.
+        */
+       if (!dev->bus->self) {
+               DBG(" --> first child, no bridge. Allocating iommu table.\n");
+               tbl = kmalloc(sizeof(struct iommu_table), GFP_KERNEL);
+               iommu_table_setparms(PCI_DN(dn)->phb, dn, tbl);
+               PCI_DN(mydn)->iommu_table = iommu_init_table(tbl);
+
+               return;
+       }
+
+       /* If this device is further down the bus tree, search upwards until
+        * an already allocated iommu table is found and use that.
+        */
+
        while (dn && dn->data && PCI_DN(dn)->iommu_table == NULL)
                dn = dn->parent;
 
        if (dn && dn->data) {
                PCI_DN(mydn)->iommu_table = PCI_DN(dn)->iommu_table;
        } else {
-               DBG("iommu_dev_setup_pSeries, dev %p (%s) has no iommu table\n", dev, dev->pretty_name);
+               DBG("iommu_dev_setup_pSeries, dev %p (%s) has no iommu table\n", dev, pci_name(dev));
        }
 }
 
@@ -494,7 +504,7 @@ static void iommu_dev_setup_pSeriesLP(struct pci_dev *dev)
        int *dma_window = NULL;
        struct pci_dn *pci;
 
-       DBG("iommu_dev_setup_pSeriesLP, dev %p (%s)\n", dev, dev->pretty_name);
+       DBG("iommu_dev_setup_pSeriesLP, dev %p (%s)\n", dev, pci_name(dev));
 
        /* dev setup for LPAR is a little tricky, since the device tree might
         * contain the dma-window properties per-device and not neccesarily
@@ -516,9 +526,8 @@ static void iommu_dev_setup_pSeriesLP(struct pci_dev *dev)
         * slots on POWER4 machines.
         */
        if (dma_window == NULL || pdn->parent == NULL) {
-               /* Fall back to regular (non-LPAR) dev setup */
-               DBG("No dma window for device, falling back to regular setup\n");
-               iommu_dev_setup_pSeries(dev);
+               DBG("No dma window for device, linking to parent\n");
+               PCI_DN(dn)->iommu_table = PCI_DN(pdn)->iommu_table;
                return;
        } else {
                DBG("Found DMA window, allocating table\n");
index bfadccc7b8be78e4683fcb0bac7f1fd5189ab3ab..3009701eb90d89b7dfe708ee499e97a6f61ab85d 100644 (file)
@@ -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;
index 861138ad092c597efcaee48d9d6496e9f41a7057..ff4be1da69d5b11e19a93add1b33154c5a3c212a 100644 (file)
@@ -246,11 +246,14 @@ static unsigned int pci_parse_of_flags(u32 addr0)
        unsigned int flags = 0;
 
        if (addr0 & 0x02000000) {
-               flags |= IORESOURCE_MEM;
+               flags = IORESOURCE_MEM | PCI_BASE_ADDRESS_SPACE_MEMORY;
+               flags |= (addr0 >> 22) & PCI_BASE_ADDRESS_MEM_TYPE_64;
+               flags |= (addr0 >> 28) & PCI_BASE_ADDRESS_MEM_TYPE_1M;
                if (addr0 & 0x40000000)
-                       flags |= IORESOURCE_PREFETCH;
+                       flags |= IORESOURCE_PREFETCH
+                                | PCI_BASE_ADDRESS_MEM_PREFETCH;
        } else if (addr0 & 0x01000000)
-               flags |= IORESOURCE_IO;
+               flags = IORESOURCE_IO | PCI_BASE_ADDRESS_SPACE_IO;
        return flags;
 }
 
index 325426c7bed00f5348ac0fc2dcdb64949a3ff716..25755252067aa052f05a6bd847804365a9cb6886 100644 (file)
@@ -434,15 +434,23 @@ static int pmac_check_legacy_ioport(unsigned int baseport)
 
 static int __init pmac_declare_of_platform_devices(void)
 {
-       struct device_node *np;
+       struct device_node *np, *npp;
 
-       np = find_devices("u3");
-       if (np) {
-               for (np = np->child; np != NULL; np = np->sibling)
+       npp = of_find_node_by_name(NULL, "u3");
+       if (npp) {
+               for (np = NULL; (np = of_get_next_child(npp, np)) != NULL;) {
                        if (strncmp(np->name, "i2c", 3) == 0) {
-                               of_platform_device_create(np, "u3-i2c");
+                               of_platform_device_create(np, "u3-i2c", NULL);
+                               of_node_put(np);
                                break;
                        }
+               }
+               of_node_put(npp);
+       }
+        npp = of_find_node_by_type(NULL, "smu");
+        if (npp) {
+               of_platform_device_create(npp, "smu", NULL);
+               of_node_put(npp);
        }
 
        return 0;
index 3059edb09cc8c9e8dc79540b9cb6a04be8f40922..41bbb8c59697388b8bf33ddb588eb324bbf7741e 100644 (file)
@@ -84,7 +84,7 @@ void __pmac pmac_get_rtc_time(struct rtc_time *tm)
 
 #ifdef CONFIG_PMAC_SMU
        case SYS_CTRLER_SMU:
-               smu_get_rtc_time(tm);
+               smu_get_rtc_time(tm, 1);
                break;
 #endif /* CONFIG_PMAC_SMU */
        default:
@@ -128,7 +128,7 @@ int __pmac pmac_set_rtc_time(struct rtc_time *tm)
 
 #ifdef CONFIG_PMAC_SMU
        case SYS_CTRLER_SMU:
-               return smu_set_rtc_time(tm);
+               return smu_set_rtc_time(tm, 1);
 #endif /* CONFIG_PMAC_SMU */
        default:
                return -ENODEV;
index 9979919cdf9297c1481091151caca0a401ea6a94..f252670874a4b0d027b7fa736e8d0876f12475de 100644 (file)
@@ -1711,6 +1711,7 @@ static void __init flatten_device_tree(void)
        unsigned long offset = reloc_offset();
        unsigned long mem_start, mem_end, room;
        struct boot_param_header *hdr;
+       struct prom_t *_prom = PTRRELOC(&prom);
        char *namep;
        u64 *rsvmap;
 
@@ -1765,6 +1766,7 @@ static void __init flatten_device_tree(void)
        RELOC(dt_struct_end) = PAGE_ALIGN(mem_start);
 
        /* Finish header */
+       hdr->boot_cpuid_phys = _prom->cpu;
        hdr->magic = OF_DT_HEADER;
        hdr->totalsize = RELOC(dt_struct_end) - RELOC(dt_header_start);
        hdr->off_dt_struct = RELOC(dt_struct_start) - RELOC(dt_header_start);
@@ -1854,7 +1856,6 @@ static void __init prom_find_boot_cpu(void)
 
        cpu_pkg = call_prom("instance-to-package", 1, 1, prom_cpu);
 
-       prom_setprop(cpu_pkg, "linux,boot-cpu", NULL, 0);
        prom_getprop(cpu_pkg, "reg", &getprop_rval, sizeof(getprop_rval));
        _prom->cpu = getprop_rval;
 
index 85ed3188a91d0a7ef7c3799c8cf9a7992f411ac1..b1c044ca57568d3aee5b4cc60286c8e22d6dbbb3 100644 (file)
@@ -219,6 +219,7 @@ int sys_ptrace(long request, long pid, long addr, long data)
 
        case PTRACE_SET_DEBUGREG:
                ret = ptrace_set_debugreg(child, addr, data);
+               break;
 
        case PTRACE_DETACH:
                ret = ptrace_detach(child, data);
index 4777676365fe2a60917683cfa713b0f0b5728289..efa985f05aca2ebfe45be32ff4cd1e6b339ce1d8 100644 (file)
@@ -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);
 
index 76fbfa9f706fb4c220036244b882290c56be22a6..0b6e967de948dc1038805dfa92face96fce4630b 100644 (file)
@@ -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 (file)
index 7b9d4da..0000000
+++ /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);
index 7fbc68bbb7391cef88ee614d2ec54f291f54c7dc..be3f25cf3e9fbb96cc987c2dd5b9494213a64678 100644 (file)
@@ -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
index 7626bb59954d43e6fa6b7437aff89c68cf2fe5b2..eb1bbb5b6c160bcf3b4e2e1a8f630951c3209be8 100644 (file)
@@ -343,9 +343,7 @@ static void native_flush_hash_range(unsigned long context,
        hpte_t *hptep;
        unsigned long hpte_v;
        struct ppc64_tlb_batch *batch = &__get_cpu_var(ppc64_tlb_batch);
-
-       /* XXX fix for large ptes */
-       unsigned long large = 0;
+       unsigned long large;
 
        local_irq_save(flags);
 
@@ -358,6 +356,7 @@ static void native_flush_hash_range(unsigned long context,
 
                va = (vsid << 28) | (batch->addr[i] & 0x0fffffff);
                batch->vaddr[j] = va;
+               large = pte_huge(batch->pte[i]);
                if (large)
                        vpn = va >> HPAGE_SHIFT;
                else
index 338771ec70d7622775190417f69085496ac2e209..0ea0994ed974e0185bad810cc1757cc4f20f5063 100644 (file)
@@ -710,10 +710,13 @@ repeat:
                        hpte_group = ((~hash & htab_hash_mask) *
                                      HPTES_PER_GROUP) & ~0x7UL; 
                        slot = ppc_md.hpte_insert(hpte_group, va, prpn,
-                                                 HPTE_V_LARGE, rflags);
+                                                 HPTE_V_LARGE |
+                                                 HPTE_V_SECONDARY,
+                                                 rflags);
                        if (slot == -1) {
                                if (mftb() & 0x1)
-                                       hpte_group = ((hash & htab_hash_mask) * HPTES_PER_GROUP) & ~0x7UL;
+                                       hpte_group = ((hash & htab_hash_mask) *
+                                                     HPTES_PER_GROUP)&~0x7UL;
 
                                ppc_md.hpte_remove(hpte_group);
                                goto repeat;
index 0865251a3f4418bc514fd3a0b3d01e71526e49f2..45d44c6bb39d3982d4de5b7e003f2da8ecbbaae1 100644 (file)
@@ -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
@@ -164,6 +167,11 @@ CONFIG_IPV6=y
 # CONFIG_IPV6_TUNNEL is not set
 # CONFIG_NETFILTER is not set
 
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
+
 #
 # SCTP Configuration (EXPERIMENTAL)
 #
@@ -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
 
@@ -383,6 +394,10 @@ CONFIG_BONDING=m
 CONFIG_EQUALIZER=m
 CONFIG_TUN=m
 
+#
+# PHY device support
+#
+
 #
 # Ethernet (10 or 100Mbit)
 #
@@ -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
index ab1e49d2e5185dad2116aa8ff8afacf5e6f2cf2e..8584dd8232181a5cec925779ad799688dbccfc82 100644 (file)
@@ -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 
index 58fc7fbcb40e17d6150f171125e47bafde4f0591..9b30f4cf32c4736806791f0904231705f1fc9353 100644 (file)
@@ -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
index d0c9ffaa25db7b02c0bb77c76097e2cdceee852c..7b9b4a2ba1d7c3ee58c6b16aba372c278d52addb 100644 (file)
@@ -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 (file)
index 0000000..83cb42b
--- /dev/null
@@ -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" );
+}
index 5ba5a5485da9021c0cfc9ec3e63c6a1ecb9ea78c..5204778b8e5e7b8921949c8cfb8689316943ee6d 100644 (file)
@@ -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;
 }
 
index 85222fee43611293bdd8271f760f030535ed286f..e13c87b446b2e58051797dbe88b25d930fa5376a 100644 (file)
@@ -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
index cd8d39fb954d3412ccbe1ff2bc267aeedb112f30..af0e9411b83e62fbbb6539eadc0bd2cdcdc34f13 100644 (file)
@@ -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
index 3e0badb820c5798996c296b913130cb7e5ac9d0a..b48349527853eff14a0eaab5befc217f66273a0a 100644 (file)
  * executing (see inherit_locked_prom_mappings() rant).
  */
 sparc64_vpte_nucleus:
-       /* Load 0xf0000000, which is LOW_OBP_ADDRESS.  */
-       mov             0xf, %g5
-       sllx            %g5, 28, %g5
-
-       /* Is addr >= LOW_OBP_ADDRESS?  */
+       /* Note that kvmap below has verified that the address is
+        * in the range MODULES_VADDR --> VMALLOC_END already.  So
+        * here we need only check if it is an OBP address or not.
+        */
+       sethi           %hi(LOW_OBP_ADDRESS), %g5
        cmp             %g4, %g5
        blu,pn          %xcc, sparc64_vpte_patchme1
         mov            0x1, %g5
-
-       /* Load 0x100000000, which is HI_OBP_ADDRESS.  */
        sllx            %g5, 32, %g5
-
-       /* Is addr < HI_OBP_ADDRESS?  */
        cmp             %g4, %g5
        blu,pn          %xcc, obp_iaddr_patch
         nop
@@ -156,26 +152,29 @@ obp_daddr_patch:
  * rather, use information saved during inherit_prom_mappings() using 8k
  * pagesize.
  */
+       .align          32
 kvmap:
-       /* Load 0xf0000000, which is LOW_OBP_ADDRESS.  */
-       mov             0xf, %g5
-       sllx            %g5, 28, %g5
+       sethi           %hi(MODULES_VADDR), %g5
+       cmp             %g4, %g5
+       blu,pn          %xcc, longpath
+        mov            (VMALLOC_END >> 24), %g5
+       sllx            %g5, 24, %g5
+       cmp             %g4, %g5
+       bgeu,pn         %xcc, longpath
+        nop
 
-       /* Is addr >= LOW_OBP_ADDRESS?  */
+kvmap_check_obp:
+       sethi           %hi(LOW_OBP_ADDRESS), %g5
        cmp             %g4, %g5
-       blu,pn          %xcc, vmalloc_addr
+       blu,pn          %xcc, kvmap_vmalloc_addr
         mov            0x1, %g5
-
-       /* Load 0x100000000, which is HI_OBP_ADDRESS.  */
        sllx            %g5, 32, %g5
-
-       /* Is addr < HI_OBP_ADDRESS?  */
        cmp             %g4, %g5
        blu,pn          %xcc, obp_daddr_patch
         nop
 
-vmalloc_addr:
-       /* If we get here, a vmalloc addr accessed, load kernel VPTE.  */
+kvmap_vmalloc_addr:
+       /* If we get here, a vmalloc addr was accessed, load kernel VPTE.  */
        ldxa            [%g3 + %g6] ASI_N, %g5
        brgez,pn        %g5, longpath
         nop
index 23ad839d113fcef60137ac27d4f72799684c6029..5efbff90d66862054ce827bb3c327bd636d280bc 100644 (file)
@@ -30,6 +30,7 @@
 #include <asm/psrcompat.h>
 #include <asm/visasm.h>
 #include <asm/spitfire.h>
+#include <asm/page.h>
 
 /* Returning from ptrace is a bit tricky because the syscall return
  * low level code assumes any value returned which is negative and
@@ -128,20 +129,20 @@ void flush_ptrace_access(struct vm_area_struct *vma, struct page *page,
         * is mapped to in the user's address space, we can skip the
         * D-cache flush.
         */
-       if ((uaddr ^ kaddr) & (1UL << 13)) {
+       if ((uaddr ^ (unsigned long) kaddr) & (1UL << 13)) {
                unsigned long start = __pa(kaddr);
                unsigned long end = start + len;
 
                if (tlb_type == spitfire) {
                        for (; start < end; start += 32)
-                               spitfire_put_dcache_tag(va & 0x3fe0, 0x0);
+                               spitfire_put_dcache_tag(start & 0x3fe0, 0x0);
                } else {
                        for (; start < end; start += 32)
                                __asm__ __volatile__(
                                        "stxa %%g0, [%0] %1\n\t"
                                        "membar #Sync"
                                        : /* no outputs */
-                                       : "r" (va),
+                                       : "r" (start),
                                        "i" (ASI_DCACHE_INVALIDATE));
                }
        }
index cbb5e59824e569f68757dc220baed881159b9b54..fb7a5370dbfcf7c0a8d9c2fda0a70fc736ad30a4 100644 (file)
@@ -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);
index cbb40585253c279f0cdc83eaf337c3170b5e2089..da48400bcc95a8b43a7dcef27f63e62998b0489f 100644 (file)
@@ -17,7 +17,7 @@ kernel_unaligned_trap_fault:
 __do_int_store:
        rd      %asi, %o4
        wr      %o3, 0, %asi
-       ldx     [%o2], %g3
+       mov     %o2, %g3
        cmp     %o1, 2
        be,pn   %icc, 2f
         cmp    %o1, 4
index da9739f0d43723cbee80f87cf9f491bff1ea11f3..42718f6a7d3671ea349c3918f2355c11809c272c 100644 (file)
@@ -184,13 +184,14 @@ extern void do_int_load(unsigned long *dest_reg, int size,
                        unsigned long *saddr, int is_signed, int asi);
        
 extern void __do_int_store(unsigned long *dst_addr, int size,
-                          unsigned long *src_val, int asi);
+                          unsigned long src_val, int asi);
 
 static inline void do_int_store(int reg_num, int size, unsigned long *dst_addr,
-                               struct pt_regs *regs, int asi)
+                               struct pt_regs *regs, int asi, int orig_asi)
 {
        unsigned long zero = 0;
-       unsigned long *src_val = &zero;
+       unsigned long *src_val_p = &zero;
+       unsigned long src_val;
 
        if (size == 16) {
                size = 8;
@@ -198,7 +199,25 @@ static inline void do_int_store(int reg_num, int size, unsigned long *dst_addr,
                        (unsigned)fetch_reg(reg_num, regs) : 0)) << 32) |
                        (unsigned)fetch_reg(reg_num + 1, regs);
        } else if (reg_num) {
-               src_val = fetch_reg_addr(reg_num, regs);
+               src_val_p = fetch_reg_addr(reg_num, regs);
+       }
+       src_val = *src_val_p;
+       if (unlikely(asi != orig_asi)) {
+               switch (size) {
+               case 2:
+                       src_val = swab16(src_val);
+                       break;
+               case 4:
+                       src_val = swab32(src_val);
+                       break;
+               case 8:
+                       src_val = swab64(src_val);
+                       break;
+               case 16:
+               default:
+                       BUG();
+                       break;
+               };
        }
        __do_int_store(dst_addr, size, src_val, asi);
 }
@@ -276,6 +295,7 @@ asmlinkage void kernel_unaligned_trap(struct pt_regs *regs, unsigned int insn, u
                kernel_mna_trap_fault();
        } else {
                unsigned long addr;
+               int orig_asi, asi;
 
                addr = compute_effective_address(regs, insn,
                                                 ((insn >> 25) & 0x1f));
@@ -285,18 +305,48 @@ asmlinkage void kernel_unaligned_trap(struct pt_regs *regs, unsigned int insn, u
                       regs->tpc, dirstrings[dir], addr, size,
                       regs->u_regs[UREG_RETPC]);
 #endif
+               orig_asi = asi = decode_asi(insn, regs);
+               switch (asi) {
+               case ASI_NL:
+               case ASI_AIUPL:
+               case ASI_AIUSL:
+               case ASI_PL:
+               case ASI_SL:
+               case ASI_PNFL:
+               case ASI_SNFL:
+                       asi &= ~0x08;
+                       break;
+               };
                switch (dir) {
                case load:
                        do_int_load(fetch_reg_addr(((insn>>25)&0x1f), regs),
                                    size, (unsigned long *) addr,
-                                   decode_signedness(insn),
-                                   decode_asi(insn, regs));
+                                   decode_signedness(insn), asi);
+                       if (unlikely(asi != orig_asi)) {
+                               unsigned long val_in = *(unsigned long *) addr;
+                               switch (size) {
+                               case 2:
+                                       val_in = swab16(val_in);
+                                       break;
+                               case 4:
+                                       val_in = swab32(val_in);
+                                       break;
+                               case 8:
+                                       val_in = swab64(val_in);
+                                       break;
+                               case 16:
+                               default:
+                                       BUG();
+                                       break;
+                               };
+                               *(unsigned long *) addr = val_in;
+                       }
                        break;
 
                case store:
                        do_int_store(((insn>>25)&0x1f), size,
                                     (unsigned long *) addr, regs,
-                                    decode_asi(insn, regs));
+                                    asi, orig_asi);
                        break;
 
                default:
index d968aebe83b282319fefb194dd942b3614a67764..c295806500f78d66168f7efb003f31489f97b52e 100644 (file)
@@ -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 (file)
index 8ee288d..0000000
+++ /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
index 8ad156a00499acf682a808e37d5120337f15c5b2..5d92cacd56c6a71cddf0c88026d7788fedbd3e39 100644 (file)
@@ -42,3 +42,7 @@ config ARCH_HAS_SC_SIGNALS
 config ARCH_REUSE_HOST_VSYSCALL_AREA
        bool
        default y
+
+config X86_CMPXCHG
+       bool
+       default y
index ce987266dac6206afbdaf85c974080578075f911..5b5af95721ab16f4cee63ae8ac0c988a91aa45e0 100644 (file)
@@ -53,9 +53,13 @@ SYS_DIR              := $(ARCH_DIR)/include/sysdep-$(SUBARCH)
 
 # -Dvmap=kernel_vmap affects everything, and prevents anything from
 # referencing the libpcap.o symbol so named.
+#
+# Same things for in6addr_loopback - found in libc.
 
 CFLAGS += $(CFLAGS-y) -D__arch_um__ -DSUBARCH=\"$(SUBARCH)\" \
-       $(ARCH_INCLUDE) $(MODE_INCLUDE) -Dvmap=kernel_vmap
+       $(ARCH_INCLUDE) $(MODE_INCLUDE) -Dvmap=kernel_vmap \
+       -Din6addr_loopback=kernel_in6addr_loopback
+
 AFLAGS += $(ARCH_INCLUDE)
 
 USER_CFLAGS := $(patsubst -I%,,$(CFLAGS))
index 14a12d6b3df6e89c695860170ce10145d1556f0d..16e7dc89f61d78e2508b71a3c6cb2bb046c09785 100644 (file)
 #include "line.h"
 #include "os.h"
 
-#ifdef CONFIG_NOCONFIG_CHAN
+/* XXX: could well be moved to somewhere else, if needed. */
+static int my_printf(const char * fmt, ...)
+       __attribute__ ((format (printf, 1, 2)));
+
+static int my_printf(const char * fmt, ...)
+{
+       /* Yes, can be called on atomic context.*/
+       char *buf = kmalloc(4096, GFP_ATOMIC);
+       va_list args;
+       int r;
+
+       if (!buf) {
+               /* We print directly fmt.
+                * Yes, yes, yes, feel free to complain. */
+               r = strlen(fmt);
+       } else {
+               va_start(args, fmt);
+               r = vsprintf(buf, fmt, args);
+               va_end(args);
+               fmt = buf;
+       }
 
-/* The printk's here are wrong because we are complaining that there is no
- * output device, but printk is printing to that output device.  The user will
- * never see the error.  printf would be better, except it can't run on a
- * kernel stack because it will overflow it.
- * Use printk for now since that will avoid crashing.
- */
+       if (r)
+               r = os_write_file(1, fmt, r);
+       return r;
+
+}
+
+#ifdef CONFIG_NOCONFIG_CHAN
+/* Despite its name, there's no added trailing newline. */
+static int my_puts(const char * buf)
+{
+       return os_write_file(1, buf, strlen(buf));
+}
 
 static void *not_configged_init(char *str, int device, struct chan_opts *opts)
 {
-       printk(KERN_ERR "Using a channel type which is configured out of "
+       my_puts("Using a channel type which is configured out of "
               "UML\n");
        return(NULL);
 }
@@ -38,27 +64,27 @@ static void *not_configged_init(char *str, int device, struct chan_opts *opts)
 static int not_configged_open(int input, int output, int primary, void *data,
                              char **dev_out)
 {
-       printk(KERN_ERR "Using a channel type which is configured out of "
+       my_puts("Using a channel type which is configured out of "
               "UML\n");
        return(-ENODEV);
 }
 
 static void not_configged_close(int fd, void *data)
 {
-       printk(KERN_ERR "Using a channel type which is configured out of "
+       my_puts("Using a channel type which is configured out of "
               "UML\n");
 }
 
 static int not_configged_read(int fd, char *c_out, void *data)
 {
-       printk(KERN_ERR "Using a channel type which is configured out of "
+       my_puts("Using a channel type which is configured out of "
               "UML\n");
        return(-EIO);
 }
 
 static int not_configged_write(int fd, const char *buf, int len, void *data)
 {
-       printk(KERN_ERR "Using a channel type which is configured out of "
+       my_puts("Using a channel type which is configured out of "
               "UML\n");
        return(-EIO);
 }
@@ -66,7 +92,7 @@ static int not_configged_write(int fd, const char *buf, int len, void *data)
 static int not_configged_console_write(int fd, const char *buf, int len,
                                       void *data)
 {
-       printk(KERN_ERR "Using a channel type which is configured out of "
+       my_puts("Using a channel type which is configured out of "
               "UML\n");
        return(-EIO);
 }
@@ -74,14 +100,14 @@ static int not_configged_console_write(int fd, const char *buf, int len,
 static int not_configged_window_size(int fd, void *data, unsigned short *rows,
                                     unsigned short *cols)
 {
-       printk(KERN_ERR "Using a channel type which is configured out of "
+       my_puts("Using a channel type which is configured out of "
               "UML\n");
        return(-ENODEV);
 }
 
 static void not_configged_free(void *data)
 {
-       printf(KERN_ERR "Using a channel type which is configured out of "
+       my_puts("Using a channel type which is configured out of "
               "UML\n");
 }
 
@@ -457,7 +483,7 @@ static struct chan *parse_chan(char *str, int pri, int device,
                }
        }
        if(ops == NULL){
-               printk(KERN_ERR "parse_chan couldn't parse \"%s\"\n", 
+               my_printf("parse_chan couldn't parse \"%s\"\n",
                       str);
                return(NULL);
        }
@@ -465,7 +491,7 @@ static struct chan *parse_chan(char *str, int pri, int device,
        data = (*ops->init)(str, device, opts);
        if(data == NULL) return(NULL);
 
-       chan = kmalloc(sizeof(*chan), GFP_KERNEL);
+       chan = kmalloc(sizeof(*chan), GFP_ATOMIC);
        if(chan == NULL) return(NULL);
        *chan = ((struct chan) { .list          = LIST_HEAD_INIT(chan->list),
                                 .primary       = 1,
index 7a0d115b29d09e8b9361668e424c208c0f1a6e5b..5db136e2651cc20a7883ad6ce3048423bbfaa8dd 100644 (file)
@@ -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;
 }
 
index c190c24141972399fa2ec328181f002939c60d36..12c95368124afa58940bba1326ecc4cc1352c4c7 100644 (file)
@@ -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.
  */
index fe5afb13252c8221fc1e4f1c256d6f012b480000..04383f98f4d5ff9258109941ac19cfe387907778 100644 (file)
@@ -23,13 +23,14 @@ static struct mconsole_command commands[] = {
        { "reboot", mconsole_reboot, MCONSOLE_PROC },
        { "config", mconsole_config, MCONSOLE_PROC },
        { "remove", mconsole_remove, MCONSOLE_PROC },
-       { "sysrq", mconsole_sysrq, MCONSOLE_INTR },
+       { "sysrq", mconsole_sysrq, MCONSOLE_PROC },
        { "help", mconsole_help, MCONSOLE_INTR },
        { "cad", mconsole_cad, MCONSOLE_INTR },
        { "stop", mconsole_stop, MCONSOLE_PROC },
        { "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);
 }
index ed84d01df6cc94f9a828415d01fbe0ab099a26cc..0306a1b215b7d8016f04bd3eca2dba996ee53dfa 100644 (file)
@@ -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 (file)
index b94d2bc..0000000
+++ /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:
- */
index 93dc1911363ff3f7d3fd2a782fcf295fb1f0b80f..90e0e5ff451e1cc2f21909ff90b6a40575172baa 100644 (file)
@@ -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);
 
index 0aa620970adb5a4e930f139a649ed3874742e3d6..782ac3a3baf98bd82fc16f9c176a64d323d553aa 100644 (file)
@@ -12,4 +12,6 @@ DEFINE_STR(UM_KERN_WARNING, KERN_WARNING);
 DEFINE_STR(UM_KERN_NOTICE, KERN_NOTICE);
 DEFINE_STR(UM_KERN_INFO, KERN_INFO);
 DEFINE_STR(UM_KERN_DEBUG, KERN_DEBUG);
-DEFINE(HOST_ELF_CLASS, ELF_CLASS);
+DEFINE(UM_ELF_CLASS, ELF_CLASS);
+DEFINE(UM_ELFCLASS32, ELFCLASS32);
+DEFINE(UM_ELFCLASS64, ELFCLASS64);
index cfa368e045a548b76aa2bd05677effbf584d07f7..b1b512f47035ecfc8ace712bd1ec0d7e37957809 100644 (file)
@@ -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, 
index d6404bb646625e2728b457c69ce25f84cb8e346a..9fef4123a65a72af9baada02ecd1cb775d571d8b 100644 (file)
@@ -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:
- */
index 4c362458052cb3acf0d8a80256122e122b226f01..583329d0a539a012196b2fe0e72e68926865d127 100644 (file)
@@ -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 *));
index 57ee9e26122843869bb185432ef8bb3260ac739a..0f865ef46918190d528f556506ca9439d75da175 100644 (file)
@@ -14,7 +14,9 @@ extern void *um_kmalloc_atomic(int size);
 extern void kfree(void *ptr);
 extern int in_aton(char *str);
 extern int open_gdb_chan(void);
-extern int strlcpy(char *, const char *, int);
+/* These use size_t, however unsigned long is correct on both i386 and x86_64. */
+extern unsigned long strlcpy(char *, const char *, unsigned long);
+extern unsigned long strlcat(char *, const char *, unsigned long);
 extern void *um_vmalloc(int size);
 extern void vfree(void *ptr);
 
index 614b8ebeb0ed026a7ee41060eb2f5fd42a3b06c2..1a0001b3850caf86c00ef2c61f0258ed67666c5c 100644 (file)
@@ -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
 
index f83e1e8e2392f06b4f99384c4345421f617bb260..33fb0bd3b11a13af3f0db7ddf272af3aa4f3e871 100644 (file)
@@ -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);
 }
index cd7c85be0a1b7c8a0c3bc405ec5f8af25a1cf113..49ed5ddf070478ed21025f32db09dba081c9ad35 100644 (file)
@@ -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);
 }
 
 /*
index 64fa062cc1192bd60178d035cfe2e9bad80d67a3..ea008b031a8f50203fa928bb88b40198322fe76e 100644 (file)
@@ -1,4 +1,4 @@
-/* 
+/*
  * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com)
  * Licensed under the GPL
  */
 #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 (file)
index 4a663fd..0000000
+++ /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:
- */
index c23d8a08d0ff5403df391fbdd04ca86baa89a391..ea65db679e9cc59d11a1985a0c935deebdf06fd1 100644 (file)
@@ -82,7 +82,8 @@ unsigned long alloc_stack(int order, int atomic)
        unsigned long page;
        int flags = GFP_KERNEL;
 
-       if(atomic) flags |= GFP_ATOMIC;
+       if (atomic)
+               flags = GFP_ATOMIC;
        page = __get_free_pages(flags, order);
        if(page == 0)
                return(0);
@@ -113,8 +114,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)
index e89218958f38c4bbe9bd1473363a862235ad4fcd..a52751108aa125c3299926efdb8d8aad53496a72 100644 (file)
@@ -340,7 +340,7 @@ static int setup_initial_poll(int fd)
 {
        struct pollfd *p;
 
-       p = um_kmalloc(sizeof(struct pollfd));
+       p = um_kmalloc_atomic(sizeof(struct pollfd));
        if(p == NULL){
                printk("setup_initial_poll : failed to allocate poll\n");
                return(-1);
index e48490028111ba7d260707c273242e4579cac349..c97a80dfe37052bb5bf8f51378ae0f809d29b15e 100644 (file)
@@ -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,
index 6ee3f3902e6894298acb82bc5042207a778f9ca2..7da0c2def0ef1c6ca8c2034619ad3ba2777a1b55 100644 (file)
          ((unsigned long) (addr) + (size) <= FIXADDR_USER_END) && \
          ((unsigned long) (addr) + (size) >= (unsigned long)(addr))))
 
-static inline int verify_area_skas(int type, const void __user * addr,
-                                   unsigned long size)
-{
-       return(access_ok_skas(type, addr, size) ? 0 : -EFAULT);
-}
-
 extern int copy_from_user_skas(void *to, const void __user *from, int n);
 extern int copy_to_user_skas(void __user *to, const void *from, int n);
 extern int strncpy_from_user_skas(char *dst, const char __user *src, int count);
index 3d1b227226e653d6ded1b4b8005c6d20a388530d..efe92e8aa2a9e37ffba7974d1dd6ee842928e131 100644 (file)
@@ -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 (file)
index b1674bc..0000000
+++ /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:
- */
index 80ed6188e8a21a511ce60216ffe7e53cb3f8786c..f5b0636f9ad73fcdb3aa5bea335a3bac344c8eb8 100644 (file)
@@ -193,12 +193,12 @@ void fix_range_common(struct mm_struct *mm, unsigned long start_addr,
                 r = pte_read(*npte);
                 w = pte_write(*npte);
                 x = pte_exec(*npte);
-                if(!pte_dirty(*npte))
-                        w = 0;
-                if(!pte_young(*npte)){
-                        r = 0;
-                        w = 0;
-                }
+               if (!pte_young(*npte)) {
+                       r = 0;
+                       w = 0;
+               } else if (!pte_dirty(*npte)) {
+                       w = 0;
+               }
                 if(force || pte_newpage(*npte)){
                         if(pte_present(*npte))
                          ret = add_mmap(addr,
@@ -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;
         }
index 87cc6fd76cedecd10ac110db2b2f60cd0b109fcc..d297429ac3605613511356fd355bf596b683c2f5 100644 (file)
@@ -18,6 +18,7 @@
 #include "asm/a.out.h"
 #include "asm/current.h"
 #include "asm/irq.h"
+#include "sysdep/sigcontext.h"
 #include "user_util.h"
 #include "kern_util.h"
 #include "kern.h"
@@ -39,6 +40,12 @@ int handle_page_fault(unsigned long address, unsigned long ip,
        int err = -EFAULT;
 
        *code_out = SEGV_MAPERR;
+
+       /* If the fault was during atomic operation, don't take the fault, just
+        * fail. */
+       if (in_atomic())
+               goto out_nosemaphore;
+
        down_read(&mm->mmap_sem);
        vma = find_vma(mm, address);
        if(!vma) 
@@ -89,6 +96,7 @@ survive:
        flush_tlb_page(vma, address);
 out:
        up_read(&mm->mmap_sem);
+out_nosemaphore:
        return(err);
 
 /*
@@ -125,7 +133,15 @@ unsigned long segv(struct faultinfo fi, unsigned long ip, int is_user, void *sc)
         }
        else if(current->mm == NULL)
                panic("Segfault with no mm");
-       err = handle_page_fault(address, ip, is_write, is_user, &si.si_code);
+
+       if (SEGV_IS_FIXABLE(&fi))
+               err = handle_page_fault(address, ip, is_write, is_user, &si.si_code);
+       else {
+               err = -EFAULT;
+               /* A thread accessed NULL, we get a fault, but CR2 is invalid.
+                * This code is used in __do_copy_from_user() of TT mode. */
+               address = 0;
+       }
 
        catcher = current->thread.fault_catcher;
        if(!err)
index e0ca0e0b251644f9a9fd30af8d2a5f7299077e9e..2a35b15c5fef4f19633f76d1af397d56f4c93beb 100644 (file)
@@ -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);
index aa6db384af803bca44237567536c371afb9e4bfd..dc2ebfa8c54fb621c6d790659417f4f68c010d26 100644 (file)
@@ -33,12 +33,6 @@ extern unsigned long uml_physmem;
          (((unsigned long) (addr) <= ((unsigned long) (addr) + (size))) && \
           (under_task_size(addr, size) || is_stack(addr, size))))
 
-static inline int verify_area_tt(int type, const void __user * addr,
-                                 unsigned long size)
-{
-       return(access_ok_tt(type, addr, size) ? 0 : -EFAULT);
-}
-
 extern unsigned long get_fault_addr(void);
 
 extern int __do_copy_from_user(void *to, const void *from, int n,
index 3085267459b16fbc565e4304a0524bdbf5e59e2c..03e589895388198ce2f15f02ab7bffe798e7a66b 100644 (file)
@@ -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)
 {
index a189a2b92935973123f8a855ca75832e4651e78c..cfaa373a6e77df4190a2721b467a29fd94c5f4c3 100644 (file)
 #include "mem_user.h"
 #include "tlb.h"
 #include "mode.h"
+#include "mode_kern.h"
 #include "init.h"
 #include "tt.h"
 
-void *switch_to_tt(void *prev, void *next, void *last)
+void switch_to_tt(void *prev, void *next)
 {
        struct task_struct *from, *to, *prev_sched;
        unsigned long flags;
@@ -36,8 +37,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 +52,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 +83,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)
index f01475512ecb248e0c9cf776dd2d26aaf5078a15..8c220f054b611a3349114e69eb8fe8cb188e39ab 100644 (file)
@@ -22,8 +22,15 @@ int __do_copy_from_user(void *to, const void *from, int n,
                               __do_copy, &faulted);
        TASK_REGS(get_current())->tt = save;
 
-       if(!faulted) return(0);
-       else return(n - (fault - (unsigned long) from));
+       if(!faulted)
+               return 0;
+       else if (fault)
+               return n - (fault - (unsigned long) from);
+       else
+               /* In case of a general protection fault, we don't have the
+                * fault address, so NULL is used instead. Pretend we didn't
+                * copy anything. */
+               return n;
 }
 
 static void __do_strncpy(void *dst, const void *src, int count)
index 09f6f7ce4695f73c10a1507acfb122b854cf2fe5..f0a275947d34b18dea67b432c1543c054738d35f 100644 (file)
@@ -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
index 186c2888501699f99d9f6bdb94faeb4fbb417b12..0b21d59ba0cdcdf3555e2f57fa2f8bd2a254c6b0 100644 (file)
@@ -31,6 +31,8 @@ static char *uml_dir = UML_DIR;
 /* Changed by set_umid */
 static int umid_is_random = 1;
 static int umid_inited = 0;
+/* Have we created the files? Should we remove them? */
+static int umid_owned = 0;
 
 static int make_umid(int (*printer)(const char *fmt, ...));
 
@@ -82,20 +84,21 @@ int __init umid_file_name(char *name, char *buf, int len)
 
 extern int tracing_pid;
 
-static int __init create_pid_file(void)
+static void __init create_pid_file(void)
 {
        char file[strlen(uml_dir) + UMID_LEN + sizeof("/pid\0")];
        char pid[sizeof("nnnnn\0")];
        int fd, n;
 
-       if(umid_file_name("pid", file, sizeof(file))) return 0;
+       if(umid_file_name("pid", file, sizeof(file)))
+               return;
 
        fd = os_open_file(file, of_create(of_excl(of_rdwr(OPENFLAGS()))), 
                          0644);
        if(fd < 0){
                printf("Open of machine pid file \"%s\" failed: %s\n",
                       file, strerror(-fd));
-               return 0;
+               return;
        }
 
        sprintf(pid, "%d\n", os_getpid());
@@ -103,7 +106,6 @@ static int __init create_pid_file(void)
        if(n != strlen(pid))
                printf("Write of pid file failed - err = %d\n", -n);
        os_close_file(fd);
-       return 0;
 }
 
 static int actually_do_remove(char *dir)
@@ -147,7 +149,8 @@ static int actually_do_remove(char *dir)
 void remove_umid_dir(void)
 {
        char dir[strlen(uml_dir) + UMID_LEN + 1];
-       if(!umid_inited) return;
+       if (!umid_owned)
+               return;
 
        sprintf(dir, "%s%s", uml_dir, umid);
        actually_do_remove(dir);
@@ -155,11 +158,12 @@ void remove_umid_dir(void)
 
 char *get_umid(int only_if_set)
 {
-       if(only_if_set && umid_is_random) return(NULL);
-       return(umid);
+       if(only_if_set && umid_is_random)
+               return NULL;
+       return umid;
 }
 
-int not_dead_yet(char *dir)
+static int not_dead_yet(char *dir)
 {
        char file[strlen(uml_dir) + UMID_LEN + sizeof("/pid\0")];
        char pid[sizeof("nnnnn\0")], *end;
@@ -193,7 +197,8 @@ int not_dead_yet(char *dir)
                   (p == CHOOSE_MODE(tracing_pid, os_getpid())))
                        dead = 1;
        }
-       if(!dead) return(1);
+       if(!dead)
+               return(1);
        return(actually_do_remove(dir));
 }
 
@@ -232,16 +237,13 @@ static int __init make_uml_dir(void)
                strlcpy(dir, home, sizeof(dir));
                uml_dir++;
        }
+       strlcat(dir, uml_dir, sizeof(dir));
        len = strlen(dir);
-       strncat(dir, uml_dir, sizeof(dir) - len);
-       len = strlen(dir);
-       if((len > 0) && (len < sizeof(dir) - 1) && (dir[len - 1] != '/')){
-               dir[len] = '/';
-               dir[len + 1] = '\0';
-       }
+       if (len > 0 && dir[len - 1] != '/')
+               strlcat(dir, "/", sizeof(dir));
 
        uml_dir = malloc(strlen(dir) + 1);
-       if(uml_dir == NULL){
+       if (uml_dir == NULL) {
                printf("make_uml_dir : malloc failed, errno = %d\n", errno);
                exit(1);
        }
@@ -286,6 +288,7 @@ static int __init make_umid(int (*printer)(const char *fmt, ...))
                if(errno == EEXIST){
                        if(not_dead_yet(tmp)){
                                (*printer)("umid '%s' is in use\n", umid);
+                               umid_owned = 0;
                                return(-1);
                        }
                        err = mkdir(tmp, 0777);
@@ -296,7 +299,8 @@ static int __init make_umid(int (*printer)(const char *fmt, ...))
                return(-1);
        }
 
-       return(0);
+       umid_owned = 1;
+       return 0;
 }
 
 __uml_setup("uml_dir=", set_uml_dir,
@@ -309,7 +313,8 @@ static int __init make_umid_setup(void)
        /* one function with the ordering we need ... */
        make_uml_dir();
        make_umid(printf);
-       return create_pid_file();
+       create_pid_file();
+       return 0;
 }
 __uml_postsetup(make_umid_setup);
 
index 954ff67cc8b3ec9f701fea22eb9182f07869edcd..41d17c71511c51cf01077d51d2c6637863892c59 100644 (file)
@@ -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) */
@@ -132,6 +128,12 @@ void setup_machinename(char *machine_out)
        struct utsname host;
 
        uname(&host);
+#if defined(UML_CONFIG_UML_X86) && !defined(UML_CONFIG_64BIT)
+       if (!strcmp(host.machine, "x86_64")) {
+               strcpy(machine_out, "i686");
+               return;
+       }
+#endif
        strcpy(machine_out, host.machine);
 }
 
index 7a1662419c0c6d703e3f8d2f96d877aa379d643d..d15ec2af6a224cda56b45d66cd8bf048c1c04d90 100644 (file)
@@ -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
index b04897cd995d02d021ec82864f24ad82d6de6b25..f6e64026f9952b90d1af98625b152ef394c454e9 100644 (file)
@@ -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,8 @@ static int aio_thread(void *arg)
                                "errno = %d\n", errno);
                 }
                 else {
-                       aio = (struct aio_context *) event.data;
+                       /* This is safe as we've just a pointer here. */
+                       aio = (struct aio_context *) (long) event.data;
                        if(update_aio(aio, event.res)){
                                do_aio(ctx, aio);
                                continue;
@@ -313,15 +316,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;
 
index 4b83c6c3f48d25c5b3084b19c6a330063f2eef02..4ba9b17adf13cac85f62dfc224218bbeb9b354d7 100644 (file)
@@ -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 {
index 1399520a85889d79c37862f160233946939cbf22..ab33cb3c74ec26e5ba282067cb701a741cfab5ca 100644 (file)
@@ -14,7 +14,8 @@
 #include "mem_user.h"
 #include <kernel-offsets.h>
 
-#if HOST_ELF_CLASS == ELFCLASS32
+/* Use the one from the kernel - the host may miss it, if having old headers. */
+#if UM_ELF_CLASS == UM_ELFCLASS32
 typedef Elf32_auxv_t elf_auxv_t;
 #else
 typedef Elf64_auxv_t elf_auxv_t;
@@ -54,7 +55,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;
index fd45bb2609079a3bd3f13339ec8154d6a168ef69..f55773c819e64fa6be68fe1d319326b11958c195 100644 (file)
@@ -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 (file)
index 0000000..8e71eda
--- /dev/null
@@ -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);
+}
index d32413e4b4ce21faa2f3b61dbb690b6fecd90d87..d9c52387c4a16c4dea868f0de58201092d0c967f 100644 (file)
@@ -3,6 +3,7 @@
  * Licensed under the GPL
  */
 
+#include <unistd.h>
 #include <stdio.h>
 #include <errno.h>
 #include <signal.h>
index 040cc1472bc77d4ad44ca7022c253bdda9fbe4ef..6af83171ca4eaf2b6ad8e170602d1372d0498906 100644 (file)
@@ -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);
+}
+
index 5b047ab8416a12df3aea79f06755fce966481e05..a6db8877931a8cbc06a39911e35d61059c58c61f 100644 (file)
 #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...)
index bd3c34aa52e5d3d52542d61ca6ef8ab26c9b17e3..36b5c2c13289fd900e96f48d87c667f552b49721 100644 (file)
@@ -83,6 +83,7 @@ int sys_modify_ldt(int func, void __user *ptr, unsigned long bytecount)
                        goto out;
                }
                p = buf;
+               break;
        default:
                res = -ENOSYS;
                goto out;
index e63323e03ea9f17f8bec6c0d6aa9d2c94cad0be9..21afa69a086d6826c41b6d26650486a941377b34 100644 (file)
@@ -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
@@ -313,7 +308,7 @@ config HPET_TIMER
          present.  The HPET provides a stable time base on SMP
          systems, unlike the TSC, but it is more expensive to access,
          as it is off-chip.  You can find the HPET spec at
-         <http://www.intel.com/labs/platcomp/hpet/hpetspec.htm>.
+         <http://www.intel.com/hardwaredesign/hpetspec.htm>.
 
 config X86_PM_TIMER
        bool "PM timer"
index c8131f342cfc6de02b41e447b66bdaaee5e83b5b..d9161e395978ca6d423d44b87845290781acb6c8 100644 (file)
@@ -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));
 
index adbc5f8089e9a209707087ca86048c8358caa93e..3a01329473ab42642210804fc586122d433007f8 100644 (file)
@@ -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;
index eb7929eea7b33c4743b533a0d39bf8c22c42707c..ab3f87aaff70ab81e4c14f9beacc6341d52579b8 100644 (file)
@@ -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.
index 522944a000ad9c8755ad529ba0c74bff3353c897..c8eee20cd5197cbb4b81a4cd7f0441685090a583 100644 (file)
@@ -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? */
index 969365c0771b242f5b64071e294bba4cd114fca9..08203b07f4bd6d6c5aa26ddc9cedda58a29fda7f 100644 (file)
@@ -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 */
index 4388b8a5bae761fd04a7ab70af00d5a0b8b04043..39d445e16f2254441b29dcfb6a5a37de5439ca8a 100644 (file)
@@ -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));
        }
 }
 
index 351d8d64c2fbf45cff433c18fe38cba1156f2b7f..238f73e1a834cc9b2fcb57b175416d091e6968f6 100644 (file)
@@ -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);
index 68ec03070e5adbe82925dba26772a688cecd1b9b..fd99ddd009bc8834163335a1f779aedfcbaa3cb8 100644 (file)
@@ -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);
 
index 6b26a1c1e9fff91a2cd6cb2b285677d7f637774b..bba5db6cebd69aef528dcba68b60d0b4d5bd1581 100644 (file)
@@ -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 (file)
index ab43394..0000000
+++ /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;
-}
index 2b6257bec4c3b898056bb6a9b9d2541f48d6c58d..7e841aa2a4aa1259ea9e7367d40f84fd617a5822 100644 (file)
@@ -26,10 +26,6 @@ config RWSEM_XCHGADD_ALGORITHM
        bool
        default y
 
-config HAVE_DEC_LOCK
-       bool
-       default y
-
 config GENERIC_HARDIRQS
        bool
        default y
index 09887c96e9a1c035980801ca48596a738cef53a8..de19501aa809afc4784bcfc9affba6e6b3c313a2 100644 (file)
@@ -402,8 +402,8 @@ int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
        __pci_mmap_set_flags(dev, vma, mmap_state);
        __pci_mmap_set_pgprot(dev, vma, mmap_state, write_combine);
 
-       ret = io_remap_page_range(vma, vma->vm_start, vma->vm_pgoff<<PAGE_SHIFT,
-                              vma->vm_end - vma->vm_start, vma->vm_page_prot);
+       ret = io_remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
+                                vma->vm_end - vma->vm_start,vma->vm_page_prot);
 
        return ret;
 }
index cf1362784443cdcc9baf239875a82924c63ea5bd..03674daabc66b25ea73ccbd204fc928cbef1d797 100644 (file)
@@ -39,7 +39,7 @@ _F(int,  pcibios_fixup, (void), { return 0; });
 _F(int, get_rtc_time, (time_t* t), { return 0; });
 _F(int, set_rtc_time, (time_t t), { return 0; });
 
-#if CONFIG_XTENSA_CALIBRATE_CCOUNT
+#ifdef CONFIG_XTENSA_CALIBRATE_CCOUNT
 _F(void, calibrate_ccount, (void),
 {
   printk ("ERROR: Cannot calibrate cpu frequency! Assuming 100MHz.\n");
index c83bb0d41787b0789f2a4717dd810958b1e43848..08ef6d82ee5144d1e30d98195a9d91de57af5806 100644 (file)
@@ -457,7 +457,7 @@ int
 dump_task_fpu(struct pt_regs *regs, struct task_struct *task, elf_fpregset_t *r)
 {
 /* see asm/coprocessor.h for this magic number 16 */
-#if TOTAL_CPEXTRA_SIZE > 16
+#if XTENSA_CP_EXTRA_SIZE > 16
        do_save_fpregs (r, regs, task);
 
        /*  For now, bit 16 means some extra state may be present:  */
index 1f5bf5d624e4e4a208c8950f1c6a1b856d252278..513ed8d67766932305ca6cdef97f59fc8724f034 100644 (file)
@@ -304,7 +304,7 @@ void __init setup_arch(char **cmdline_p)
 # endif
 #endif
 
-#if CONFIG_PCI
+#ifdef CONFIG_PCI
        platform_pcibios_init();
 #endif
 }
index dc42cede939462986a0acba34e756ee0614d4e3a..e252b61e45a5b36ff6d1ddadbe1aeb172dc3a359 100644 (file)
@@ -182,7 +182,7 @@ restore_cpextra (struct _cpstate *buf)
 
        struct task_struct *tsk = current;
        release_all_cp(tsk);
-       return __copy_from_user(tsk->thread.cpextra, buf, TOTAL_CPEXTRA_SIZE);
+       return __copy_from_user(tsk->thread.cpextra, buf, XTENSA_CP_EXTRA_SIZE);
 #endif
        return 0;
 }
index 1ac7d5ce7456659ecf771df51580aacdb8282454..8e423d1335cee107ad8918710f5bbe3386fc440b 100644 (file)
@@ -68,7 +68,7 @@ void __init time_init(void)
         * speed for the CALIBRATE.
         */
 
-#if CONFIG_XTENSA_CALIBRATE_CCOUNT
+#ifdef CONFIG_XTENSA_CALIBRATE_CCOUNT
        printk("Calibrating CPU frequency ");
        platform_calibrate_ccount();
        printk("%d.%02d MHz\n", (int)ccount_per_jiffy/(1000000/HZ),
index 56aace84aaebda34a4719cd1c1d10956f38d24e1..5a91d6c9e66db45402c50ec487b127fd6901931c 100644 (file)
@@ -239,7 +239,7 @@ void __init mem_init(void)
        high_memory = (void *) __va(max_mapnr << PAGE_SHIFT);
        highmemsize = 0;
 
-#if CONFIG_HIGHMEM
+#ifdef CONFIG_HIGHMEM
 #error HIGHGMEM not implemented in init.c
 #endif
 
index 141b4c237a509dc9dab28fb105644b6ec5529859..2b850e5860a04fda9f6c99919f30a66cba66f815 100644 (file)
@@ -23,12 +23,13 @@ static struct i2c_driver pcf8583_driver;
 
 static unsigned short ignore[] = { I2C_CLIENT_END };
 static unsigned short normal_addr[] = { 0x50, I2C_CLIENT_END };
+static unsigned short *forces[] = { NULL };
 
 static struct i2c_client_address_data addr_data = {
        .normal_i2c             = normal_addr,
        .probe                  = ignore,
        .ignore                 = ignore,
-       .force                  = ignore,
+       .forces                 = forces,
 };
 
 #define DAT(x) ((unsigned int)(x->dev.driver_data))
index 373e7b728fa70746bb13907e07114ee0293fd4f6..6b2eb6f39b4dea6ec809acb715cf1c2ab1fc0b45 100644 (file)
@@ -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);
index d164c32a97ad4e90426a4f1e8a244b8d5f7d93d3..ce23dc8c18c590fe11b4eeff4ae6d933fb894731 100644 (file)
@@ -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;
@@ -671,6 +669,7 @@ void class_device_destroy(struct class *cls, dev_t devt)
 int class_device_rename(struct class_device *class_dev, char *new_name)
 {
        int error = 0;
+       char *old_class_name = NULL, *new_class_name = NULL;
 
        class_dev = class_device_get(class_dev);
        if (!class_dev)
@@ -679,12 +678,24 @@ int class_device_rename(struct class_device *class_dev, char *new_name)
        pr_debug("CLASS: renaming '%s' to '%s'\n", class_dev->class_id,
                 new_name);
 
+       if (class_dev->dev)
+               old_class_name = make_class_name(class_dev);
+
        strlcpy(class_dev->class_id, new_name, KOBJ_NAME_LEN);
 
        error = kobject_rename(&class_dev->kobj, new_name);
 
+       if (class_dev->dev) {
+               new_class_name = make_class_name(class_dev);
+               sysfs_create_link(&class_dev->dev->kobj, &class_dev->kobj,
+                                 new_class_name);
+               sysfs_remove_link(&class_dev->dev->kobj, old_class_name);
+       }
        class_device_put(class_dev);
 
+       kfree(old_class_name);
+       kfree(new_class_name);
+
        return error;
 }
 
index d5bbce38282fd233f06ef77891257a399be2471e..3565e9795301d6d90a72ce2e433313a635df5c1c 100644 (file)
@@ -40,6 +40,9 @@
  */
 void device_bind_driver(struct device * dev)
 {
+       if (klist_node_attached(&dev->knode_driver))
+               return;
+
        pr_debug("bound device '%s' to driver '%s'\n",
                 dev->bus_id, dev->driver->name);
        klist_add_tail(&dev->knode_driver, &dev->driver->klist_devices);
index 5bfa2e9a7c2678efade79213aa5bd203054613b8..4acb2c5733c3b46710d6321b886d16b8704f1d1c 100644 (file)
@@ -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);
index 2f455d86793c8bde34098fae2deb80a17e54238d..b449dae6f0d30fcb8385ce68c1f9bdfd34f6ff64 100644 (file)
@@ -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;
index 3a5f4c991797a02eb0de0ecaac726076d88281f9..361e204209ebb3c8324599aecf0716766d1b20c1 100644 (file)
@@ -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;
index 28f2c177a54167a0ce7d3bd9e3f1dbe7ac1d7995..486b6e1c7dfb96aaa1a8e98e06169d7ce7164f27 100644 (file)
 #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,8 @@ 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 || 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 +828,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 +1175,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 +1727,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 +1804,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 +2010,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 +2264,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 +2343,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 +2361,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 +2383,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 +2803,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 +2820,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 +2905,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;
 
@@ -2807,6 +2988,7 @@ static int __devinit cciss_init_one(struct pci_dev *pdev,
        hba[i]->access.set_intr_mask(hba[i], CCISS_INTR_ON);
 
        cciss_procinit(i);
+       hba[i]->busy_initializing = 0;
 
        for(j=0; j < NWD; j++) { /* mfm */
                drive_info_struct *drv = &(hba[i]->drv[j]);
@@ -2869,6 +3051,7 @@ clean2:
 clean1:
        release_io_mem(hba[i]);
        free_hba(i);
+       hba[i]->busy_initializing = 0;
        return(-1);
 }
 
@@ -2913,9 +3096,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 +3148,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);
index 566587d0a5003726dc75e5fe7ea67ad639581c54..ef277baee9fdc565834a04dda71f1da3014bba72 100644 (file)
@@ -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 */
index a88a88817623fb34b230141eba5f0ae7d068c95b..53fea549ba8b23a6714cfd8a33fc55705893986e 100644 (file)
@@ -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
index f16e3caed58a36129ff7046531607ea6cfb07fa3..e183a3ef7839fdabd5dfc8a2ec9d1f1fa11d94db 100644 (file)
@@ -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;
index 483d71b10cf9307364f86cfcd244da6c2850ef96..baedac522945a45ca7c886de93c6f1f9d6739765 100644 (file)
@@ -2373,44 +2373,6 @@ int blkdev_issue_flush(struct block_device *bdev, sector_t *error_sector)
 
 EXPORT_SYMBOL(blkdev_issue_flush);
 
-/**
- * blkdev_scsi_issue_flush_fn - issue flush for SCSI devices
- * @q:         device queue
- * @disk:      gendisk
- * @error_sector:      error offset
- *
- * Description:
- *    Devices understanding the SCSI command set, can use this function as
- *    a helper for issuing a cache flush. Note: driver is required to store
- *    the error offset (in case of error flushing) in ->sector of struct
- *    request.
- */
-int blkdev_scsi_issue_flush_fn(request_queue_t *q, struct gendisk *disk,
-                              sector_t *error_sector)
-{
-       struct request *rq = blk_get_request(q, WRITE, __GFP_WAIT);
-       int ret;
-
-       rq->flags |= REQ_BLOCK_PC | REQ_SOFTBARRIER;
-       rq->sector = 0;
-       memset(rq->cmd, 0, sizeof(rq->cmd));
-       rq->cmd[0] = 0x35;
-       rq->cmd_len = 12;
-       rq->data = NULL;
-       rq->data_len = 0;
-       rq->timeout = 60 * HZ;
-
-       ret = blk_execute_rq(q, disk, rq, 0);
-
-       if (ret && error_sector)
-               *error_sector = rq->sector;
-
-       blk_put_request(rq);
-       return ret;
-}
-
-EXPORT_SYMBOL(blkdev_scsi_issue_flush_fn);
-
 static void drive_stat_acct(struct request *rq, int nr_sectors, int new_io)
 {
        int rw = rq_data_dir(rq);
index 711d2f314ac32736c01fcdd63647d18f2d0eecb7..94af920465b588392c262fe6fe88fc35730601f1 100644 (file)
@@ -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);
index 7b838342f0a353939324c228212074b15ea48c76..7e22a58926b8ed790636c62f1a036a4799391ee3 100644 (file)
@@ -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)
index 856c2278e9d0b74ea1a8a168be4743f859505a99..079ec344eb4768677248b39a7a474c0b2c00a8d1 100644 (file)
@@ -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),
index aa0bf7ee008d923d2f8264f5683313c871dac92b..ed4d5006fe622441a2aeeb87e48f49e27c26f169 100644 (file)
@@ -172,7 +172,7 @@ struct bulk_cs_wrap {
  */
 struct ub_dev;
 
-#define UB_MAX_REQ_SG  4
+#define UB_MAX_REQ_SG  9       /* cdrecord requires 32KB and maybe a header */
 #define UB_MAX_SECTORS 64
 
 /*
@@ -387,7 +387,7 @@ struct ub_dev {
        struct bulk_cs_wrap work_bcs;
        struct usb_ctrlrequest work_cr;
 
-       int sg_stat[UB_MAX_REQ_SG+1];
+       int sg_stat[6];
        struct ub_scsi_trace tr;
 };
 
@@ -525,12 +525,13 @@ static ssize_t ub_diag_show(struct device *dev, struct device_attribute *attr,
            "qlen %d qmax %d\n",
            sc->cmd_queue.qlen, sc->cmd_queue.qmax);
        cnt += sprintf(page + cnt,
-           "sg %d %d %d %d %d\n",
+           "sg %d %d %d %d %d .. %d\n",
            sc->sg_stat[0],
            sc->sg_stat[1],
            sc->sg_stat[2],
            sc->sg_stat[3],
-           sc->sg_stat[4]);
+           sc->sg_stat[4],
+           sc->sg_stat[5]);
 
        list_for_each (p, &sc->luns) {
                lun = list_entry(p, struct ub_lun, link);
@@ -835,7 +836,7 @@ static int ub_cmd_build_block(struct ub_dev *sc, struct ub_lun *lun,
                return -1;
        }
        cmd->nsg = n_elem;
-       sc->sg_stat[n_elem]++;
+       sc->sg_stat[n_elem < 5 ? n_elem : 5]++;
 
        /*
         * build the command
@@ -891,7 +892,7 @@ static int ub_cmd_build_packet(struct ub_dev *sc, struct ub_lun *lun,
                return -1;
        }
        cmd->nsg = n_elem;
-       sc->sg_stat[n_elem]++;
+       sc->sg_stat[n_elem < 5 ? n_elem : 5]++;
 
        memcpy(&cmd->cdb, rq->cmd, rq->cmd_len);
        cmd->cdb_len = rq->cmd_len;
@@ -1010,7 +1011,6 @@ static int ub_scsi_cmd_start(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
        sc->last_pipe = sc->send_bulk_pipe;
        usb_fill_bulk_urb(&sc->work_urb, sc->dev, sc->send_bulk_pipe,
            bcb, US_BULK_CB_WRAP_LEN, ub_urb_complete, sc);
-       sc->work_urb.transfer_flags = 0;
 
        /* Fill what we shouldn't be filling, because usb-storage did so. */
        sc->work_urb.actual_length = 0;
@@ -1019,7 +1019,6 @@ static int ub_scsi_cmd_start(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
 
        if ((rc = usb_submit_urb(&sc->work_urb, GFP_ATOMIC)) != 0) {
                /* XXX Clear stalls */
-               printk("ub: cmd #%d start failed (%d)\n", cmd->tag, rc); /* P3 */
                ub_complete(&sc->work_done);
                return rc;
        }
@@ -1190,11 +1189,9 @@ static void ub_scsi_urb_compl(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
                        return;
                }
                if (urb->status != 0) {
-                       printk("ub: cmd #%d cmd status (%d)\n", cmd->tag, urb->status); /* P3 */
                        goto Bad_End;
                }
                if (urb->actual_length != US_BULK_CB_WRAP_LEN) {
-                       printk("ub: cmd #%d xferred %d\n", cmd->tag, urb->actual_length); /* P3 */
                        /* XXX Must do reset here to unconfuse the device */
                        goto Bad_End;
                }
@@ -1395,14 +1392,12 @@ static void ub_data_start(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
        usb_fill_bulk_urb(&sc->work_urb, sc->dev, pipe,
            page_address(sg->page) + sg->offset, sg->length,
            ub_urb_complete, sc);
-       sc->work_urb.transfer_flags = 0;
        sc->work_urb.actual_length = 0;
        sc->work_urb.error_count = 0;
        sc->work_urb.status = 0;
 
        if ((rc = usb_submit_urb(&sc->work_urb, GFP_ATOMIC)) != 0) {
                /* XXX Clear stalls */
-               printk("ub: data #%d submit failed (%d)\n", cmd->tag, rc); /* P3 */
                ub_complete(&sc->work_done);
                ub_state_done(sc, cmd, rc);
                return;
@@ -1442,7 +1437,6 @@ static int __ub_state_stat(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
        sc->last_pipe = sc->recv_bulk_pipe;
        usb_fill_bulk_urb(&sc->work_urb, sc->dev, sc->recv_bulk_pipe,
            &sc->work_bcs, US_BULK_CS_WRAP_LEN, ub_urb_complete, sc);
-       sc->work_urb.transfer_flags = 0;
        sc->work_urb.actual_length = 0;
        sc->work_urb.error_count = 0;
        sc->work_urb.status = 0;
@@ -1563,7 +1557,6 @@ static int ub_submit_clear_stall(struct ub_dev *sc, struct ub_scsi_cmd *cmd,
 
        usb_fill_control_urb(&sc->work_urb, sc->dev, sc->send_ctrl_pipe,
            (unsigned char*) cr, NULL, 0, ub_urb_complete, sc);
-       sc->work_urb.transfer_flags = 0;
        sc->work_urb.actual_length = 0;
        sc->work_urb.error_count = 0;
        sc->work_urb.status = 0;
@@ -2000,17 +1993,16 @@ static int ub_sync_getmaxlun(struct ub_dev *sc)
 
        usb_fill_control_urb(&sc->work_urb, sc->dev, sc->recv_ctrl_pipe,
            (unsigned char*) cr, p, 1, ub_probe_urb_complete, &compl);
-       sc->work_urb.transfer_flags = 0;
        sc->work_urb.actual_length = 0;
        sc->work_urb.error_count = 0;
        sc->work_urb.status = 0;
 
        if ((rc = usb_submit_urb(&sc->work_urb, GFP_KERNEL)) != 0) {
                if (rc == -EPIPE) {
-                       printk("%s: Stall at GetMaxLUN, using 1 LUN\n",
+                       printk("%s: Stall submitting GetMaxLUN, using 1 LUN\n",
                             sc->name); /* P3 */
                } else {
-                       printk(KERN_WARNING
+                       printk(KERN_NOTICE
                             "%s: Unable to submit GetMaxLUN (%d)\n",
                             sc->name, rc);
                }
@@ -2028,6 +2020,18 @@ static int ub_sync_getmaxlun(struct ub_dev *sc)
        del_timer_sync(&timer);
        usb_kill_urb(&sc->work_urb);
 
+       if ((rc = sc->work_urb.status) < 0) {
+               if (rc == -EPIPE) {
+                       printk("%s: Stall at GetMaxLUN, using 1 LUN\n",
+                            sc->name); /* P3 */
+               } else {
+                       printk(KERN_NOTICE
+                            "%s: Error at GetMaxLUN (%d)\n",
+                            sc->name, rc);
+               }
+               goto err_io;
+       }
+
        if (sc->work_urb.actual_length != 1) {
                printk("%s: GetMaxLUN returned %d bytes\n", sc->name,
                    sc->work_urb.actual_length); /* P3 */
@@ -2048,6 +2052,7 @@ static int ub_sync_getmaxlun(struct ub_dev *sc)
        kfree(p);
        return nluns;
 
+err_io:
 err_submit:
        kfree(p);
 err_alloc:
@@ -2080,7 +2085,6 @@ static int ub_probe_clear_stall(struct ub_dev *sc, int stalled_pipe)
 
        usb_fill_control_urb(&sc->work_urb, sc->dev, sc->send_ctrl_pipe,
            (unsigned char*) cr, NULL, 0, ub_probe_urb_complete, &compl);
-       sc->work_urb.transfer_flags = 0;
        sc->work_urb.actual_length = 0;
        sc->work_urb.error_count = 0;
        sc->work_urb.status = 0;
@@ -2213,8 +2217,10 @@ static int ub_probe(struct usb_interface *intf,
         * This is needed to clear toggles. It is a problem only if we do
         * `rmmod ub && modprobe ub` without disconnects, but we like that.
         */
+#if 0 /* iPod Mini fails if we do this (big white iPod works) */
        ub_probe_clear_stall(sc, sc->recv_bulk_pipe);
        ub_probe_clear_stall(sc, sc->send_bulk_pipe);
+#endif
 
        /*
         * The way this is used by the startup code is a little specific.
@@ -2241,10 +2247,10 @@ static int ub_probe(struct usb_interface *intf,
        for (i = 0; i < 3; i++) {
                if ((rc = ub_sync_getmaxlun(sc)) < 0) {
                        /* 
-                        * Some devices (i.e. Iomega Zip100) need this --
-                        * apparently the bulk pipes get STALLed when the
-                        * GetMaxLUN request is processed.
-                        * XXX I have a ZIP-100, verify it does this.
+                        * This segment is taken from usb-storage. They say
+                        * that ZIP-100 needs this, but my own ZIP-100 works
+                        * fine without this.
+                        * Still, it does not seem to hurt anything.
                         */
                        if (rc == -EPIPE) {
                                ub_probe_clear_stall(sc, sc->recv_bulk_pipe);
@@ -2313,7 +2319,7 @@ static int ub_probe_lun(struct ub_dev *sc, int lnum)
        disk->first_minor = lun->id * UB_MINORS_PER_MAJOR;
        disk->fops = &ub_bd_fops;
        disk->private_data = lun;
-       disk->driverfs_dev = &sc->intf->dev;    /* XXX Many to one ok? */
+       disk->driverfs_dev = &sc->intf->dev;
 
        rc = -ENOMEM;
        if ((q = blk_init_queue(ub_request_fn, &sc->lock)) == NULL)
@@ -2466,9 +2472,6 @@ static int __init ub_init(void)
 {
        int rc;
 
-       /* P3 */ printk("ub: sizeof ub_scsi_cmd %zu ub_dev %zu ub_lun %zu\n",
-                       sizeof(struct ub_scsi_cmd), sizeof(struct ub_dev), sizeof(struct ub_lun));
-
        if ((rc = register_blkdev(UB_MAJOR, DRV_NAME)) != 0)
                goto err_regblkdev;
        devfs_mk_dir(DEVFS_NAME);
index 67d96b5cbb96535568bb26f28595d75e1b869e6d..57c48bbf6fe6766117b5362c7c8aebd38a09b3a2 100644 (file)
 #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");
 
index 29936b43d4f861e84e4799eccf92d10e45fe936b..37100a6ea1a895a0b7a020550d590aef5bdff382 100644 (file)
 #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
 
index 99762b6c19aea2fdc82119d44f28dde30479f969..de5d6d212674808ad1a437ec510a86f894b00e2a 100644 (file)
@@ -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);
index 2a36561eec68dab6efc8e690167df7a78668f1eb..a124f8c5d062dd65b29775881f9b9c55a0d95a14 100644 (file)
@@ -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);
index 58d3738a2b7fd4eab9d51cd783fba8bf98ceb562..407708a001e421ea0322ee908074a09381e2125a 100644 (file)
@@ -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;
index 20eeb5a70e1ad841c9b73490df25d82d6c7f8786..456d6c8f94a8c6ae1644a698cd087c95617fb3b0 100644 (file)
@@ -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) ;
index de0379b6d502cd4f2e512565bf6da5c04439780e..c055bb630ffcda9e882923c2256cb6137dfb491d 100644 (file)
@@ -273,7 +273,6 @@ static int hpet_mmap(struct file *file, struct vm_area_struct *vma)
 
        vma->vm_flags |= VM_IO;
        vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
-       addr = __pa(addr);
 
        if (io_remap_pfn_range(vma, vma->vm_start, addr >> PAGE_SHIFT,
                                        PAGE_SIZE, vma->vm_page_prot)) {
index cddb789902db3c8766cdc3c604ced656f31cf09b..f921776346779aa8516d7ce861e6c44c6cc50165 100644 (file)
@@ -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);
index 463351d4f9423c388d424231326b8bbe23a60cd0..32fa82c78c73c16336a8527b7b9b4acceffa581a 100644 (file)
@@ -2620,7 +2620,7 @@ void ipmi_smi_msg_received(ipmi_smi_t          intf,
        spin_lock_irqsave(&(intf->waiting_msgs_lock), flags);
        if (!list_empty(&(intf->waiting_msgs))) {
                list_add_tail(&(msg->link), &(intf->waiting_msgs));
-               spin_unlock(&(intf->waiting_msgs_lock));
+               spin_unlock_irqrestore(&(intf->waiting_msgs_lock), flags);
                goto out_unlock;
        }
        spin_unlock_irqrestore(&(intf->waiting_msgs_lock), flags);
@@ -2629,9 +2629,9 @@ void ipmi_smi_msg_received(ipmi_smi_t          intf,
        if (rv > 0) {
                /* Could not handle the message now, just add it to a
                    list to handle later. */
-               spin_lock(&(intf->waiting_msgs_lock));
+               spin_lock_irqsave(&(intf->waiting_msgs_lock), flags);
                list_add_tail(&(msg->link), &(intf->waiting_msgs));
-               spin_unlock(&(intf->waiting_msgs_lock));
+               spin_unlock_irqrestore(&(intf->waiting_msgs_lock), flags);
        } else if (rv == 0) {
                ipmi_free_smi_msg(msg);
        }
index 1e33cb032e073ba40a0c9e5b14ed705f777c9c82..e91268e86833bf8322d883e10d69c6bd3ec80089 100644 (file)
@@ -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);
index fa789ea36bbe3169490c02204e9e6209cd860eb9..344001b45af94b3caa8ac0cf83979e224bb61e96 100644 (file)
@@ -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
 #
index bc6f5fe88c8c24f200c13a0caf38fc3c02d6344a..cfd0a39877102224f901856f805562ed4feb1b33 100644 (file)
@@ -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 (file)
index 0000000..93785f1
--- /dev/null
@@ -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 (file)
index 0000000..294c474
--- /dev/null
@@ -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);
index c694eee1fb246cfb6f472488341a7e302d48c2f2..75ca84ed4adf5ea728bfa3c05d23bcdaae4fc72c 100644 (file)
@@ -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 (file)
index 0000000..1436aea
--- /dev/null
@@ -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);
index 2b13afb09c5dfc4d601e65256ccf20bacc0641b2..5a80adbf8032565aec110a5f050d30612af62497 100644 (file)
  *     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;
                        }
 
index 8b292bf343c4169d57ee694fbc14f38d9c659695..3625b2601b4257603b6e0b365a012cdc06fbe2a5 100644 (file)
@@ -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 (file)
index 0000000..c6cbf80
--- /dev/null
@@ -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 (file)
index 0000000..a7ff64c
--- /dev/null
@@ -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);
index 3b865f34a0955c58577dd2539029f331cb497e93..b667823982581db99206b15cd6a4fefdb8660ed2 100644 (file)
@@ -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;
 
index 7e72e922b41c2ca603c8bcde49aa549005d52dbf..db358cfa7cbfca99191be097977e3476e68b6335 100644 (file)
@@ -418,12 +418,11 @@ config SENSORS_HDAPS
        help
          This driver provides support for the IBM Hard Drive Active Protection
          System (hdaps), which provides an accelerometer and other misc. data.
-         Supported laptops include the IBM ThinkPad T41, T42, T43, and R51.
-         The accelerometer data is readable via sysfs.
+         ThinkPads starting with the R50, T41, and X40 are supported.  The
+         accelerometer data is readable via sysfs.
 
-         This driver also provides an input class device, allowing the
-         laptop to act as a pinball machine-esque mouse.  This is off by
-         default but enabled via sysfs or the module parameter "mousedev".
+         This driver also provides an absolute input class device, allowing
+         the laptop to act as a pinball machine-esque joystick.
 
          Say Y here if you have an applicable laptop and want to experience
          the awesome power of hdaps.
index eaebfc14c933c1f84783fcdbf401bd5bc4b2a453..7f0107613827bcacc209fbb4f806dba28cdad747 100644 (file)
@@ -4,11 +4,11 @@
  * Copyright (C) 2005 Robert Love <rml@novell.com>
  * Copyright (C) 2005 Jesper Juhl <jesper.juhl@gmail.com>
  *
- * The HardDisk Active Protection System (hdaps) is present in the IBM ThinkPad
- * T41, T42, T43, R51, and X40, at least.  It provides a basic two-axis
+ * The HardDisk Active Protection System (hdaps) is present in IBM ThinkPads
+ * starting with the R40, T41, and X40.  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.
  *
 #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 */
 #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,
 };
@@ -615,24 +487,19 @@ static struct attribute_group hdaps_attribute_group = {
 
 /* Module stuff */
 
-/*
- * XXX: We should be able to return nonzero and halt the detection process.
- * But there is a bug in dmi_check_system() where a nonzero return from the
- * first match will result in a return of failure from dmi_check_system().
- * I fixed this; the patch is in 2.6-mm.  Once in Linus's tree we can make
- * hdaps_dmi_match_invert() return hdaps_dmi_match(), which in turn returns 1.
- */
+/* hdaps_dmi_match - found a match.  return one, short-circuiting the hunt. */
 static int hdaps_dmi_match(struct dmi_system_id *id)
 {
        printk(KERN_INFO "hdaps: %s detected.\n", id->ident);
-       return 0;
+       return 1;
 }
 
+/* hdaps_dmi_match_invert - found an inverted match. */
 static int hdaps_dmi_match_invert(struct dmi_system_id *id)
 {
        hdaps_invert = 1;
        printk(KERN_INFO "hdaps: inverting axis readings.\n");
-       return 0;
+       return hdaps_dmi_match(id);
 }
 
 #define HDAPS_DMI_MATCH_NORMAL(model)  {               \
@@ -662,12 +529,15 @@ static int __init hdaps_init(void)
                HDAPS_DMI_MATCH_INVERT("ThinkPad R50p"),
                HDAPS_DMI_MATCH_NORMAL("ThinkPad R50"),
                HDAPS_DMI_MATCH_NORMAL("ThinkPad R51"),
+               HDAPS_DMI_MATCH_NORMAL("ThinkPad R52"),
                HDAPS_DMI_MATCH_INVERT("ThinkPad T41p"),
                HDAPS_DMI_MATCH_NORMAL("ThinkPad T41"),
                HDAPS_DMI_MATCH_INVERT("ThinkPad T42p"),
                HDAPS_DMI_MATCH_NORMAL("ThinkPad T42"),
                HDAPS_DMI_MATCH_NORMAL("ThinkPad T43"),
                HDAPS_DMI_MATCH_NORMAL("ThinkPad X40"),
+               HDAPS_DMI_MATCH_NORMAL("ThinkPad X41 Tablet"),
+               HDAPS_DMI_MATCH_NORMAL("ThinkPad X41"),
                { .ident = NULL }
        };
 
@@ -696,8 +566,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 +595,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 +608,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");
 
index 8334496a7e0aee02b42ca7b4953a165d2efb91e1..3badfec75b1c8b081530f05f74cce287a73f4111 100644 (file)
@@ -245,6 +245,18 @@ config I2C_KEYWEST
          This support is also available as a module.  If so, the module 
          will be called i2c-keywest.
 
+config I2C_PMAC_SMU
+       tristate "Powermac SMU I2C interface"
+       depends on I2C && PMAC_SMU
+       help
+         This supports the use of the I2C interface in the SMU
+         chip on recent Apple machines like the iMac G5.  It is used
+         among others by the thermal control driver for those machines.
+         Say Y if you have such a machine.
+
+         This support is also available as a module.  If so, the module
+         will be called i2c-pmac-smu.
+
 config I2C_MPC
        tristate "MPC107/824x/85xx/52xx"
        depends on I2C && PPC32
index 980b3e98367040acf2df92baede7212012add7a7..f1df00f66c6cde856f188126fa1e4ab3a4ea2a5d 100644 (file)
@@ -20,6 +20,7 @@ obj-$(CONFIG_I2C_ITE)         += i2c-ite.o
 obj-$(CONFIG_I2C_IXP2000)      += i2c-ixp2000.o
 obj-$(CONFIG_I2C_IXP4XX)       += i2c-ixp4xx.o
 obj-$(CONFIG_I2C_KEYWEST)      += i2c-keywest.o
+obj-$(CONFIG_I2C_PMAC_SMU)     += i2c-pmac-smu.o
 obj-$(CONFIG_I2C_MPC)          += i2c-mpc.o
 obj-$(CONFIG_I2C_MV64XXX)      += i2c-mv64xxx.o
 obj-$(CONFIG_I2C_NFORCE2)      += i2c-nforce2.o
index 37b49c2daf5f824a5057ff713effce45149f7116..eff5896ce865572baab25f49802077f78f6f8ea7 100644 (file)
@@ -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-pmac-smu.c b/drivers/i2c/busses/i2c-pmac-smu.c
new file mode 100644 (file)
index 0000000..8a9f564
--- /dev/null
@@ -0,0 +1,316 @@
+/*
+    i2c Support for Apple SMU Controller
+
+    Copyright (c) 2005 Benjamin Herrenschmidt, IBM Corp.
+                       <benh@kernel.crashing.org>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/i2c.h>
+#include <linux/init.h>
+#include <linux/completion.h>
+#include <linux/device.h>
+#include <asm/prom.h>
+#include <asm/of_device.h>
+#include <asm/smu.h>
+
+static int probe;
+
+MODULE_AUTHOR("Benjamin Herrenschmidt <benh@kernel.crashing.org>");
+MODULE_DESCRIPTION("I2C driver for Apple's SMU");
+MODULE_LICENSE("GPL");
+module_param(probe, bool, 0);
+
+
+/* Physical interface */
+struct smu_iface
+{
+       struct i2c_adapter      adapter;
+       struct completion       complete;
+       u32                     busid;
+};
+
+static void smu_i2c_done(struct smu_i2c_cmd *cmd, void *misc)
+{
+       struct smu_iface        *iface = misc;
+       complete(&iface->complete);
+}
+
+/*
+ * SMBUS-type transfer entrypoint
+ */
+static s32 smu_smbus_xfer(     struct i2c_adapter*     adap,
+                               u16                     addr,
+                               unsigned short          flags,
+                               char                    read_write,
+                               u8                      command,
+                               int                     size,
+                               union i2c_smbus_data*   data)
+{
+       struct smu_iface        *iface = i2c_get_adapdata(adap);
+       struct smu_i2c_cmd      cmd;
+       int                     rc = 0;
+       int                     read = (read_write == I2C_SMBUS_READ);
+
+       cmd.info.bus = iface->busid;
+       cmd.info.devaddr = (addr << 1) | (read ? 0x01 : 0x00);
+
+       /* Prepare datas & select mode */
+       switch (size) {
+        case I2C_SMBUS_QUICK:
+               cmd.info.type = SMU_I2C_TRANSFER_SIMPLE;
+               cmd.info.datalen = 0;
+               break;
+        case I2C_SMBUS_BYTE:
+               cmd.info.type = SMU_I2C_TRANSFER_SIMPLE;
+               cmd.info.datalen = 1;
+               if (!read)
+                       cmd.info.data[0] = data->byte;
+               break;
+        case I2C_SMBUS_BYTE_DATA:
+               cmd.info.type = SMU_I2C_TRANSFER_STDSUB;
+               cmd.info.datalen = 1;
+               cmd.info.sublen = 1;
+               cmd.info.subaddr[0] = command;
+               cmd.info.subaddr[1] = 0;
+               cmd.info.subaddr[2] = 0;
+               if (!read)
+                       cmd.info.data[0] = data->byte;
+               break;
+        case I2C_SMBUS_WORD_DATA:
+               cmd.info.type = SMU_I2C_TRANSFER_STDSUB;
+               cmd.info.datalen = 2;
+               cmd.info.sublen = 1;
+               cmd.info.subaddr[0] = command;
+               cmd.info.subaddr[1] = 0;
+               cmd.info.subaddr[2] = 0;
+               if (!read) {
+                       cmd.info.data[0] = data->byte & 0xff;
+                       cmd.info.data[1] = (data->byte >> 8) & 0xff;
+               }
+               break;
+       /* Note that these are broken vs. the expected smbus API where
+        * on reads, the lenght is actually returned from the function,
+        * but I think the current API makes no sense and I don't want
+        * any driver that I haven't verified for correctness to go
+        * anywhere near a pmac i2c bus anyway ...
+        */
+        case I2C_SMBUS_BLOCK_DATA:
+               cmd.info.type = SMU_I2C_TRANSFER_STDSUB;
+               cmd.info.datalen = data->block[0] + 1;
+               if (cmd.info.datalen > 6)
+                       return -EINVAL;
+               if (!read)
+                       memcpy(cmd.info.data, data->block, cmd.info.datalen);
+               cmd.info.sublen = 1;
+               cmd.info.subaddr[0] = command;
+               cmd.info.subaddr[1] = 0;
+               cmd.info.subaddr[2] = 0;
+               break;
+       case I2C_SMBUS_I2C_BLOCK_DATA:
+               cmd.info.type = SMU_I2C_TRANSFER_STDSUB;
+               cmd.info.datalen = data->block[0];
+               if (cmd.info.datalen > 7)
+                       return -EINVAL;
+               if (!read)
+                       memcpy(cmd.info.data, &data->block[1],
+                              cmd.info.datalen);
+               cmd.info.sublen = 1;
+               cmd.info.subaddr[0] = command;
+               cmd.info.subaddr[1] = 0;
+               cmd.info.subaddr[2] = 0;
+               break;
+
+        default:
+               return -EINVAL;
+       }
+
+       /* Turn a standardsub read into a combined mode access */
+       if (read_write == I2C_SMBUS_READ &&
+           cmd.info.type == SMU_I2C_TRANSFER_STDSUB)
+               cmd.info.type = SMU_I2C_TRANSFER_COMBINED;
+
+       /* Finish filling command and submit it */
+       cmd.done = smu_i2c_done;
+       cmd.misc = iface;
+       rc = smu_queue_i2c(&cmd);
+       if (rc < 0)
+               return rc;
+       wait_for_completion(&iface->complete);
+       rc = cmd.status;
+
+       if (!read || rc < 0)
+               return rc;
+
+       switch (size) {
+        case I2C_SMBUS_BYTE:
+        case I2C_SMBUS_BYTE_DATA:
+               data->byte = cmd.info.data[0];
+               break;
+        case I2C_SMBUS_WORD_DATA:
+               data->word = ((u16)cmd.info.data[1]) << 8;
+               data->word |= cmd.info.data[0];
+               break;
+       /* Note that these are broken vs. the expected smbus API where
+        * on reads, the lenght is actually returned from the function,
+        * but I think the current API makes no sense and I don't want
+        * any driver that I haven't verified for correctness to go
+        * anywhere near a pmac i2c bus anyway ...
+        */
+        case I2C_SMBUS_BLOCK_DATA:
+       case I2C_SMBUS_I2C_BLOCK_DATA:
+               memcpy(&data->block[0], cmd.info.data, cmd.info.datalen);
+               break;
+       }
+
+       return rc;
+}
+
+static u32
+smu_smbus_func(struct i2c_adapter * adapter)
+{
+       return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
+              I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA |
+              I2C_FUNC_SMBUS_BLOCK_DATA;
+}
+
+/* For now, we only handle combined mode (smbus) */
+static struct i2c_algorithm smu_algorithm = {
+       .smbus_xfer     = smu_smbus_xfer,
+       .functionality  = smu_smbus_func,
+};
+
+static int create_iface(struct device_node *np, struct device *dev)
+{
+       struct smu_iface* iface;
+       u32 *reg, busid;
+       int rc;
+
+       reg = (u32 *)get_property(np, "reg", NULL);
+       if (reg == NULL) {
+               printk(KERN_ERR "i2c-pmac-smu: can't find bus number !\n");
+               return -ENXIO;
+       }
+       busid = *reg;
+
+       iface = kmalloc(sizeof(struct smu_iface), GFP_KERNEL);
+       if (iface == NULL) {
+               printk(KERN_ERR "i2c-pmac-smu: can't allocate inteface !\n");
+               return -ENOMEM;
+       }
+       memset(iface, 0, sizeof(struct smu_iface));
+       init_completion(&iface->complete);
+       iface->busid = busid;
+
+       dev_set_drvdata(dev, iface);
+
+       sprintf(iface->adapter.name, "smu-i2c-%02x", busid);
+       iface->adapter.algo = &smu_algorithm;
+       iface->adapter.algo_data = NULL;
+       iface->adapter.client_register = NULL;
+       iface->adapter.client_unregister = NULL;
+       i2c_set_adapdata(&iface->adapter, iface);
+       iface->adapter.dev.parent = dev;
+
+       rc = i2c_add_adapter(&iface->adapter);
+       if (rc) {
+               printk(KERN_ERR "i2c-pamc-smu.c: Adapter %s registration "
+                      "failed\n", iface->adapter.name);
+               i2c_set_adapdata(&iface->adapter, NULL);
+       }
+
+       if (probe) {
+               unsigned char addr;
+               printk("Probe: ");
+               for (addr = 0x00; addr <= 0x7f; addr++) {
+                       if (i2c_smbus_xfer(&iface->adapter,addr,
+                                          0,0,0,I2C_SMBUS_QUICK,NULL) >= 0)
+                               printk("%02x ", addr);
+               }
+               printk("\n");
+       }
+
+       printk(KERN_INFO "SMU i2c bus %x registered\n", busid);
+
+       return 0;
+}
+
+static int dispose_iface(struct device *dev)
+{
+       struct smu_iface *iface = dev_get_drvdata(dev);
+       int rc;
+
+       rc = i2c_del_adapter(&iface->adapter);
+       i2c_set_adapdata(&iface->adapter, NULL);
+       /* We aren't that prepared to deal with this... */
+       if (rc)
+               printk("i2c-pmac-smu.c: Failed to remove bus %s !\n",
+                      iface->adapter.name);
+       dev_set_drvdata(dev, NULL);
+       kfree(iface);
+
+       return 0;
+}
+
+
+static int create_iface_of_platform(struct of_device* dev,
+                                   const struct of_device_id *match)
+{
+       return create_iface(dev->node, &dev->dev);
+}
+
+
+static int dispose_iface_of_platform(struct of_device* dev)
+{
+       return dispose_iface(&dev->dev);
+}
+
+
+static struct of_device_id i2c_smu_match[] =
+{
+       {
+               .compatible     = "smu-i2c",
+       },
+       {},
+};
+static struct of_platform_driver i2c_smu_of_platform_driver =
+{
+       .name           = "i2c-smu",
+       .match_table    = i2c_smu_match,
+       .probe          = create_iface_of_platform,
+       .remove         = dispose_iface_of_platform
+};
+
+
+static int __init i2c_pmac_smu_init(void)
+{
+       of_register_driver(&i2c_smu_of_platform_driver);
+       return 0;
+}
+
+
+static void __exit i2c_pmac_smu_cleanup(void)
+{
+       of_unregister_driver(&i2c_smu_of_platform_driver);
+}
+
+module_init(i2c_pmac_smu_init);
+module_exit(i2c_pmac_smu_cleanup);
index fdf53ce0424840757743501f9bca3b054d191a61..44b595d90a4a19cd8554ba9a04ebfbc4af9455c2 100644 (file)
@@ -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,
        },
 };
index b443b04a4c5a7c1de5263dc4c2120655d88b38c4..0b0aa4f516280bc522769f5761e18cb8dc4e5259 100644 (file)
@@ -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);
index d04f62ab5de1991939a07f965c92bf6142370924..ace8edad6e9620ac685dc0e038a89c6e1d0ef546 100644 (file)
@@ -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);
 }
 
index 3de9ab897e421aff8eb235023ee115189678cf19..3d9c7afc86950ad1660852bba5eb680199cde1b2 100644 (file)
@@ -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
index bbde462799843802ccfe66936ef7271618c765ce..be334da7a7549b4fb44f82e59000450875c1abfb 100644 (file)
@@ -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);
index 2bd8b1cc57c4c925fe8db42ecfb6c8a82797dc14..e23836d0e21be53b6ff0df319c08b9c899af72ca 100644 (file)
@@ -412,8 +412,8 @@ static inline int get_mad_len(struct mad_rmpp_recv *rmpp_recv)
 
        hdr_size = data_offset(rmpp_mad->mad_hdr.mgmt_class);
        data_size = sizeof(struct ib_rmpp_mad) - hdr_size;
-       pad = data_size - be32_to_cpu(rmpp_mad->rmpp_hdr.paylen_newwin);
-       if (pad > data_size || pad < 0)
+       pad = IB_MGMT_RMPP_DATA - be32_to_cpu(rmpp_mad->rmpp_hdr.paylen_newwin);
+       if (pad > IB_MGMT_RMPP_DATA || pad < 0)
                pad = 0;
 
        return hdr_size + rmpp_recv->seg_num * data_size - pad;
@@ -583,6 +583,7 @@ static int send_next_seg(struct ib_mad_send_wr_private *mad_send_wr)
 {
        struct ib_rmpp_mad *rmpp_mad;
        int timeout;
+       u32 paylen;
 
        rmpp_mad = (struct ib_rmpp_mad *)mad_send_wr->send_wr.wr.ud.mad_hdr;
        ib_set_rmpp_flags(&rmpp_mad->rmpp_hdr, IB_MGMT_RMPP_FLAG_ACTIVE);
@@ -590,11 +591,9 @@ static int send_next_seg(struct ib_mad_send_wr_private *mad_send_wr)
 
        if (mad_send_wr->seg_num == 1) {
                rmpp_mad->rmpp_hdr.rmpp_rtime_flags |= IB_MGMT_RMPP_FLAG_FIRST;
-               rmpp_mad->rmpp_hdr.paylen_newwin =
-                       cpu_to_be32(mad_send_wr->total_seg *
-                                   (sizeof(struct ib_rmpp_mad) -
-                                      offsetof(struct ib_rmpp_mad, data)) -
-                                   mad_send_wr->pad);
+               paylen = mad_send_wr->total_seg * IB_MGMT_RMPP_DATA -
+                        mad_send_wr->pad;
+               rmpp_mad->rmpp_hdr.paylen_newwin = cpu_to_be32(paylen);
                mad_send_wr->sg_list[0].length = sizeof(struct ib_rmpp_mad);
        } else {
                mad_send_wr->send_wr.num_sge = 2;
@@ -608,10 +607,8 @@ static int send_next_seg(struct ib_mad_send_wr_private *mad_send_wr)
 
        if (mad_send_wr->seg_num == mad_send_wr->total_seg) {
                rmpp_mad->rmpp_hdr.rmpp_rtime_flags |= IB_MGMT_RMPP_FLAG_LAST;
-               rmpp_mad->rmpp_hdr.paylen_newwin =
-                       cpu_to_be32(sizeof(struct ib_rmpp_mad) -
-                                   offsetof(struct ib_rmpp_mad, data) -
-                                   mad_send_wr->pad);
+               paylen = IB_MGMT_RMPP_DATA - mad_send_wr->pad;
+               rmpp_mad->rmpp_hdr.paylen_newwin = cpu_to_be32(paylen);
        }
 
        /* 2 seconds for an ACK until we can find the packet lifetime */
index 7c2f03057ddb1f6ed411d3509c68ba768e4bf0ad..a64d6b4dcc165851f41631d0938ab9d57eceaeac 100644 (file)
@@ -334,10 +334,11 @@ static ssize_t ib_umad_write(struct file *filp, const char __user *buf,
                        ret = -EINVAL;
                        goto err_ah;
                }
-               /* Validate that management class can support RMPP */
+
+               /* Validate that the management class can support RMPP */
                if (rmpp_mad->mad_hdr.mgmt_class == IB_MGMT_CLASS_SUBN_ADM) {
                        hdr_len = offsetof(struct ib_sa_mad, data);
-                       data_len = length;
+                       data_len = length - hdr_len;
                } else if ((rmpp_mad->mad_hdr.mgmt_class >= IB_MGMT_CLASS_VENDOR_RANGE2_START) &&
                            (rmpp_mad->mad_hdr.mgmt_class <= IB_MGMT_CLASS_VENDOR_RANGE2_END)) {
                                hdr_len = offsetof(struct ib_vendor_mad, data);
index 18f0981eb0c15e977c587ccf052d590f51f1ed85..78152a8ad17d82561f650c14040c7145fc2685db 100644 (file)
@@ -476,12 +476,8 @@ static int __devinit mthca_create_eq(struct mthca_dev *dev,
        int i;
        u8 status;
 
-       /* Make sure EQ size is aligned to a power of 2 size. */
-       for (i = 1; i < nent; i <<= 1)
-               ; /* nothing */
-       nent = i;
-
-       eq->dev = dev;
+       eq->dev  = dev;
+       eq->nent = roundup_pow_of_two(max(nent, 2));
 
        eq->page_list = kmalloc(npages * sizeof *eq->page_list,
                                GFP_KERNEL);
@@ -512,7 +508,7 @@ static int __devinit mthca_create_eq(struct mthca_dev *dev,
                memset(eq->page_list[i].buf, 0, PAGE_SIZE);
        }
 
-       for (i = 0; i < nent; ++i)
+       for (i = 0; i < eq->nent; ++i)
                set_eqe_hw(get_eqe(eq, i));
 
        eq->eqn = mthca_alloc(&dev->eq_table.alloc);
@@ -528,8 +524,6 @@ static int __devinit mthca_create_eq(struct mthca_dev *dev,
        if (err)
                goto err_out_free_eq;
 
-       eq->nent = nent;
-
        memset(eq_context, 0, sizeof *eq_context);
        eq_context->flags           = cpu_to_be32(MTHCA_EQ_STATUS_OK   |
                                                  MTHCA_EQ_OWNER_HW    |
@@ -538,7 +532,7 @@ static int __devinit mthca_create_eq(struct mthca_dev *dev,
        if (mthca_is_memfree(dev))
                eq_context->flags  |= cpu_to_be32(MTHCA_EQ_STATE_ARBEL);
 
-       eq_context->logsize_usrpage = cpu_to_be32((ffs(nent) - 1) << 24);
+       eq_context->logsize_usrpage = cpu_to_be32((ffs(eq->nent) - 1) << 24);
        if (mthca_is_memfree(dev)) {
                eq_context->arbel_pd = cpu_to_be32(dev->driver_pd.pd_num);
        } else {
@@ -569,7 +563,7 @@ static int __devinit mthca_create_eq(struct mthca_dev *dev,
        dev->eq_table.arm_mask |= eq->eqn_mask;
 
        mthca_dbg(dev, "Allocated EQ %d with %d entries\n",
-                 eq->eqn, nent);
+                 eq->eqn, eq->nent);
 
        return err;
 
index bcef06bf15e724c47aaedd013168be2bf9fe7d63..5fa00669f9b8c43d59e9dd70fe1469d707ceb600 100644 (file)
@@ -227,7 +227,6 @@ static void mthca_wq_init(struct mthca_wq *wq)
        wq->last_comp = wq->max - 1;
        wq->head      = 0;
        wq->tail      = 0;
-       wq->last      = NULL;
 }
 
 void mthca_qp_event(struct mthca_dev *dev, u32 qpn,
@@ -687,7 +686,7 @@ int mthca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask)
        }
 
        if (attr_mask & IB_QP_TIMEOUT) {
-               qp_context->pri_path.ackto = attr->timeout;
+               qp_context->pri_path.ackto = attr->timeout << 3;
                qp_param->opt_param_mask |= cpu_to_be32(MTHCA_QP_OPTPAR_ACK_TIMEOUT);
        }
 
@@ -1103,6 +1102,9 @@ static int mthca_alloc_qp_common(struct mthca_dev *dev,
                }
        }
 
+       qp->sq.last = get_send_wqe(qp, qp->sq.max - 1);
+       qp->rq.last = get_recv_wqe(qp, qp->rq.max - 1);
+
        return 0;
 }
 
@@ -1583,15 +1585,13 @@ int mthca_tavor_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
                        goto out;
                }
 
-               if (prev_wqe) {
-                       ((struct mthca_next_seg *) prev_wqe)->nda_op =
-                               cpu_to_be32(((ind << qp->sq.wqe_shift) +
-                                            qp->send_wqe_offset) |
-                                           mthca_opcode[wr->opcode]);
-                       wmb();
-                       ((struct mthca_next_seg *) prev_wqe)->ee_nds =
-                               cpu_to_be32((size0 ? 0 : MTHCA_NEXT_DBD) | size);
-               }
+               ((struct mthca_next_seg *) prev_wqe)->nda_op =
+                       cpu_to_be32(((ind << qp->sq.wqe_shift) +
+                                    qp->send_wqe_offset) |
+                                   mthca_opcode[wr->opcode]);
+               wmb();
+               ((struct mthca_next_seg *) prev_wqe)->ee_nds =
+                       cpu_to_be32((size0 ? 0 : MTHCA_NEXT_DBD) | size);
 
                if (!size0) {
                        size0 = size;
@@ -1688,13 +1688,11 @@ int mthca_tavor_post_receive(struct ib_qp *ibqp, struct ib_recv_wr *wr,
 
                qp->wrid[ind] = wr->wr_id;
 
-               if (likely(prev_wqe)) {
-                       ((struct mthca_next_seg *) prev_wqe)->nda_op =
-                               cpu_to_be32((ind << qp->rq.wqe_shift) | 1);
-                       wmb();
-                       ((struct mthca_next_seg *) prev_wqe)->ee_nds =
-                               cpu_to_be32(MTHCA_NEXT_DBD | size);
-               }
+               ((struct mthca_next_seg *) prev_wqe)->nda_op =
+                       cpu_to_be32((ind << qp->rq.wqe_shift) | 1);
+               wmb();
+               ((struct mthca_next_seg *) prev_wqe)->ee_nds =
+                       cpu_to_be32(MTHCA_NEXT_DBD | size);
 
                if (!size0)
                        size0 = size;
@@ -1905,15 +1903,13 @@ int mthca_arbel_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
                        goto out;
                }
 
-               if (likely(prev_wqe)) {
-                       ((struct mthca_next_seg *) prev_wqe)->nda_op =
-                               cpu_to_be32(((ind << qp->sq.wqe_shift) +
-                                            qp->send_wqe_offset) |
-                                           mthca_opcode[wr->opcode]);
-                       wmb();
-                       ((struct mthca_next_seg *) prev_wqe)->ee_nds =
-                               cpu_to_be32(MTHCA_NEXT_DBD | size);
-               }
+               ((struct mthca_next_seg *) prev_wqe)->nda_op =
+                       cpu_to_be32(((ind << qp->sq.wqe_shift) +
+                                    qp->send_wqe_offset) |
+                                   mthca_opcode[wr->opcode]);
+               wmb();
+               ((struct mthca_next_seg *) prev_wqe)->ee_nds =
+                       cpu_to_be32(MTHCA_NEXT_DBD | size);
 
                if (!size0) {
                        size0 = size;
@@ -2127,5 +2123,6 @@ void __devexit mthca_cleanup_qp_table(struct mthca_dev *dev)
        for (i = 0; i < 2; ++i)
                mthca_CONF_SPECIAL_QP(dev, i, 0, &status);
 
+       mthca_array_cleanup(&dev->qp_table.qp, dev->limits.num_qps);
        mthca_alloc_cleanup(&dev->qp_table.alloc);
 }
index 75cd2d84ef12ac82f9fb598ec2e4dff191a766fa..18998d48c53ec39fc3c21fba93a9903b71853f79 100644 (file)
@@ -172,6 +172,8 @@ static int mthca_alloc_srq_buf(struct mthca_dev *dev, struct mthca_pd *pd,
                        scatter->lkey = cpu_to_be32(MTHCA_INVAL_LKEY);
        }
 
+       srq->last = get_wqe(srq, srq->max - 1);
+
        return 0;
 }
 
@@ -189,7 +191,6 @@ int mthca_alloc_srq(struct mthca_dev *dev, struct mthca_pd *pd,
 
        srq->max      = attr->max_wr;
        srq->max_gs   = attr->max_sge;
-       srq->last     = NULL;
        srq->counter  = 0;
 
        if (mthca_is_memfree(dev))
@@ -409,7 +410,7 @@ int mthca_tavor_post_srq_recv(struct ib_srq *ibsrq, struct ib_recv_wr *wr,
                        mthca_err(dev, "SRQ %06x full\n", srq->srqn);
                        err = -ENOMEM;
                        *bad_wr = wr;
-                       return nreq;
+                       break;
                }
 
                wqe       = get_wqe(srq, ind);
@@ -427,7 +428,7 @@ int mthca_tavor_post_srq_recv(struct ib_srq *ibsrq, struct ib_recv_wr *wr,
                        err = -EINVAL;
                        *bad_wr = wr;
                        srq->last = prev_wqe;
-                       return nreq;
+                       break;
                }
 
                for (i = 0; i < wr->num_sge; ++i) {
@@ -446,20 +447,16 @@ int mthca_tavor_post_srq_recv(struct ib_srq *ibsrq, struct ib_recv_wr *wr,
                        ((struct mthca_data_seg *) wqe)->addr = 0;
                }
 
-               if (likely(prev_wqe)) {
-                       ((struct mthca_next_seg *) prev_wqe)->nda_op =
-                               cpu_to_be32((ind << srq->wqe_shift) | 1);
-                       wmb();
-                       ((struct mthca_next_seg *) prev_wqe)->ee_nds =
-                               cpu_to_be32(MTHCA_NEXT_DBD);
-               }
+               ((struct mthca_next_seg *) prev_wqe)->nda_op =
+                       cpu_to_be32((ind << srq->wqe_shift) | 1);
+               wmb();
+               ((struct mthca_next_seg *) prev_wqe)->ee_nds =
+                       cpu_to_be32(MTHCA_NEXT_DBD);
 
                srq->wrid[ind]  = wr->wr_id;
                srq->first_free = next_ind;
        }
 
-       return nreq;
-
        if (likely(nreq)) {
                __be32 doorbell[2];
 
@@ -503,7 +500,7 @@ int mthca_arbel_post_srq_recv(struct ib_srq *ibsrq, struct ib_recv_wr *wr,
                        mthca_err(dev, "SRQ %06x full\n", srq->srqn);
                        err = -ENOMEM;
                        *bad_wr = wr;
-                       return nreq;
+                       break;
                }
 
                wqe       = get_wqe(srq, ind);
@@ -519,7 +516,7 @@ int mthca_arbel_post_srq_recv(struct ib_srq *ibsrq, struct ib_recv_wr *wr,
                if (unlikely(wr->num_sge > srq->max_gs)) {
                        err = -EINVAL;
                        *bad_wr = wr;
-                       return nreq;
+                       break;
                }
 
                for (i = 0; i < wr->num_sge; ++i) {
index bea960b8191feffff376dd7b64a26c2d9586d6f6..4ea1c1ca85bc965fa330d6b1a9e24161457fa817 100644 (file)
@@ -257,7 +257,7 @@ void ipoib_mcast_send(struct net_device *dev, union ib_gid *mgid,
 
 void ipoib_mcast_restart_task(void *dev_ptr);
 int ipoib_mcast_start_thread(struct net_device *dev);
-int ipoib_mcast_stop_thread(struct net_device *dev);
+int ipoib_mcast_stop_thread(struct net_device *dev, int flush);
 
 void ipoib_mcast_dev_down(struct net_device *dev);
 void ipoib_mcast_dev_flush(struct net_device *dev);
index ef0e3894863c023c08082c4c201da070fb393871..f7440096b5ed0355a41252c50c93f5290b1810df 100644 (file)
@@ -432,7 +432,7 @@ int ipoib_ib_dev_down(struct net_device *dev)
                flush_workqueue(ipoib_workqueue);
        }
 
-       ipoib_mcast_stop_thread(dev);
+       ipoib_mcast_stop_thread(dev, 1);
 
        /*
         * Flush the multicast groups first so we stop any multicast joins. The
@@ -599,7 +599,7 @@ void ipoib_ib_dev_cleanup(struct net_device *dev)
 
        ipoib_dbg(priv, "cleaning up ib_dev\n");
 
-       ipoib_mcast_stop_thread(dev);
+       ipoib_mcast_stop_thread(dev, 1);
 
        /* Delete the broadcast address and the local address */
        ipoib_mcast_dev_down(dev);
index 49d120d2b92c5308e5dda9fe802a4ae9667b26ac..704f48e0b6a738dc7a9c2e3ae41751dafc1c205a 100644 (file)
@@ -1005,6 +1005,7 @@ debug_failed:
 
 register_failed:
        ib_unregister_event_handler(&priv->event_handler);
+       flush_scheduled_work();
 
 event_failed:
        ipoib_dev_cleanup(priv->dev);
@@ -1057,6 +1058,7 @@ static void ipoib_remove_one(struct ib_device *device)
 
        list_for_each_entry_safe(priv, tmp, dev_list, list) {
                ib_unregister_event_handler(&priv->event_handler);
+               flush_scheduled_work();
 
                unregister_netdev(priv->dev);
                ipoib_dev_cleanup(priv->dev);
index aca7aea18a69006ed0b403a439611c66dd0f9781..36ce29836bf2fd218e6d37e0cb2e580e5fa94085 100644 (file)
@@ -145,7 +145,7 @@ static struct ipoib_mcast *ipoib_mcast_alloc(struct net_device *dev,
 
        mcast->dev = dev;
        mcast->created = jiffies;
-       mcast->backoff = HZ;
+       mcast->backoff = 1;
        mcast->logcount = 0;
 
        INIT_LIST_HEAD(&mcast->list);
@@ -396,7 +396,7 @@ static void ipoib_mcast_join_complete(int status,
                        IPOIB_GID_ARG(mcast->mcmember.mgid), status);
 
        if (!status && !ipoib_mcast_join_finish(mcast, mcmember)) {
-               mcast->backoff = HZ;
+               mcast->backoff = 1;
                down(&mcast_mutex);
                if (test_bit(IPOIB_MCAST_RUN, &priv->flags))
                        queue_work(ipoib_workqueue, &priv->mcast_task);
@@ -496,7 +496,7 @@ static void ipoib_mcast_join(struct net_device *dev, struct ipoib_mcast *mcast,
                if (test_bit(IPOIB_MCAST_RUN, &priv->flags))
                        queue_delayed_work(ipoib_workqueue,
                                           &priv->mcast_task,
-                                          mcast->backoff);
+                                          mcast->backoff * HZ);
                up(&mcast_mutex);
        } else
                mcast->query_id = ret;
@@ -598,7 +598,7 @@ int ipoib_mcast_start_thread(struct net_device *dev)
        return 0;
 }
 
-int ipoib_mcast_stop_thread(struct net_device *dev)
+int ipoib_mcast_stop_thread(struct net_device *dev, int flush)
 {
        struct ipoib_dev_priv *priv = netdev_priv(dev);
        struct ipoib_mcast *mcast;
@@ -610,7 +610,8 @@ int ipoib_mcast_stop_thread(struct net_device *dev)
        cancel_delayed_work(&priv->mcast_task);
        up(&mcast_mutex);
 
-       flush_workqueue(ipoib_workqueue);
+       if (flush)
+               flush_workqueue(ipoib_workqueue);
 
        if (priv->broadcast && priv->broadcast->query) {
                ib_sa_cancel_query(priv->broadcast->query_id, priv->broadcast->query);
@@ -832,7 +833,7 @@ void ipoib_mcast_restart_task(void *dev_ptr)
 
        ipoib_dbg_mcast(priv, "restarting multicast task\n");
 
-       ipoib_mcast_stop_thread(dev);
+       ipoib_mcast_stop_thread(dev, 0);
 
        spin_lock_irqsave(&priv->lock, flags);
 
index e55dee3907756425059612c4fe049ecc177d58b3..444f7756fee65fece09ab6ad7204e4205a132c5d 100644 (file)
@@ -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
index b02eeceea3c32a0b683e703f2d8aa8591b205151..9ce0b87f2facb9fc06fde3ffd497d52b88c0b72c 100644 (file)
@@ -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 (file)
index 0000000..1714045
--- /dev/null
@@ -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");
index 0489af5a80c95bcdf67c2c87e3159bed004eec55..21d55ed4b88a69e08881a4b03f1ef9dbf20548d2 100644 (file)
@@ -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"
index 5d19261b884fe8f09ebe48432589011080942e41..4c7fbe55036540463974608157de2f4f11143931 100644 (file)
@@ -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;
index 8337b0f26cc40183e0846c683bbd43797f4a97bf..4866fc32d8d9f1697806ccd938b9edf2d13692eb 100644 (file)
@@ -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},
 };
 
index c6b5bf7d2acaf32544f6a502de70693f9cd0fb3a..dc334aab433e730a5f04ffde750cf17a7ba25c7d 100644 (file)
@@ -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),
index 0fda5c89429b4a73180a7c1bfbcfaa79a779e8ee..9ffaae7c657a1e09510698229adf285588d8ab91 100644 (file)
@@ -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)
 
index 2fcd093921d8c3337934918a3989880e5a2b82ef..657817a591fe03af6364a68adef40732731a7bea 100644 (file)
@@ -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;
                }
        }
 
index 071b1d31999f75c27c03740861c7cb0ea008cf14..941f7022ada1c52f7b32eac2326b0dd11a966f57 100644 (file)
@@ -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;
 
index 7aa810d5d333c9ccc9420531fc9076d988272054..2cf5d1a6df6c321fe334ca1c4c05e56df75ab2de 100644 (file)
@@ -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);
 
index ab62223297a56d8cdd2a097341ccd49ade474f42..89fbeb58485de92d158631bf69822d314176a9c4 100644 (file)
@@ -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;
                }
        }
 
index 40b0df04ed9f1620e2d36e8336bb243fda21ce88..1ebed041672d0c3876c892c515e218997a58f38a 100644 (file)
@@ -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) {
index fb535737d17d114244481fea4ba7421a768ce1ed..a85ac18dd21d13971738fbb45a93415384ed194f 100644 (file)
@@ -8,21 +8,15 @@
  */
 
 /*
- * For now, this driver includes:
- * - RTC get & set
- * - reboot & shutdown commands
- * all synchronous with IRQ disabled (ugh)
- *
  * TODO:
- *   rework in a way the PMU driver works, that is asynchronous
- *   with a queue of commands. I'll do that as soon as I have an
- *   SMU based machine at hand. Some more cleanup is needed too,
- *   like maybe fitting it into a platform device, etc...
- *   Also check what's up with cache coherency, and if we really
- *   can't do better than flushing the cache, maybe build a table
- *   of command len/reply len like the PMU driver to only flush
- *   what is actually necessary.
- *   --BenH.
+ *  - maybe add timeout to commands ?
+ *  - blocking version of time functions
+ *  - polling version of i2c commands (including timer that works with
+ *    interrutps off)
+ *  - maybe avoid some data copies with i2c by directly using the smu cmd
+ *    buffer and a lower level internal interface
+ *  - understand SMU -> CPU events and implement reception of them via
+ *    the userland interface
  */
 
 #include <linux/config.h>
 #include <linux/jiffies.h>
 #include <linux/interrupt.h>
 #include <linux/rtc.h>
+#include <linux/completion.h>
+#include <linux/miscdevice.h>
+#include <linux/delay.h>
+#include <linux/sysdev.h>
+#include <linux/poll.h>
 
 #include <asm/byteorder.h>
 #include <asm/io.h>
 #include <asm/smu.h>
 #include <asm/sections.h>
 #include <asm/abs_addr.h>
+#include <asm/uaccess.h>
+#include <asm/of_device.h>
+
+#define VERSION "0.6"
+#define AUTHOR  "(c) 2005 Benjamin Herrenschmidt, IBM Corp."
 
-#define DEBUG_SMU 1
+#undef DEBUG_SMU
 
 #ifdef DEBUG_SMU
 #define DPRINTK(fmt, args...) do { printk(KERN_DEBUG fmt , ##args); } while (0)
 /*
  * This is the command buffer passed to the SMU hardware
  */
+#define SMU_MAX_DATA   254
+
 struct smu_cmd_buf {
        u8 cmd;
        u8 length;
-       u8 data[0x0FFE];
+       u8 data[SMU_MAX_DATA];
 };
 
 struct smu_device {
        spinlock_t              lock;
        struct device_node      *of_node;
-       int                     db_ack;         /* doorbell ack GPIO */
-       int                     db_req;         /* doorbell req GPIO */
+       struct of_device        *of_dev;
+       int                     doorbell;       /* doorbell gpio */
        u32 __iomem             *db_buf;        /* doorbell buffer */
+       int                     db_irq;
+       int                     msg;
+       int                     msg_irq;
        struct smu_cmd_buf      *cmd_buf;       /* command buffer virtual */
        u32                     cmd_buf_abs;    /* command buffer absolute */
+       struct list_head        cmd_list;
+       struct smu_cmd          *cmd_cur;       /* pending command */
+       struct list_head        cmd_i2c_list;
+       struct smu_i2c_cmd      *cmd_i2c_cur;   /* pending i2c command */
+       struct timer_list       i2c_timer;
 };
 
 /*
@@ -79,113 +93,243 @@ struct smu_device {
  */
 static struct smu_device       *smu;
 
+
 /*
- * SMU low level communication stuff
+ * SMU driver low level stuff
  */
-static inline int smu_cmd_stat(struct smu_cmd_buf *cmd_buf, u8 cmd_ack)
-{
-       rmb();
-       return cmd_buf->cmd == cmd_ack && cmd_buf->length != 0;
-}
 
-static inline u8 smu_save_ack_cmd(struct smu_cmd_buf *cmd_buf)
+static void smu_start_cmd(void)
 {
-       return (~cmd_buf->cmd) & 0xff;
-}
+       unsigned long faddr, fend;
+       struct smu_cmd *cmd;
 
-static void smu_send_cmd(struct smu_device *dev)
-{
-       /* SMU command buf is currently cacheable, we need a physical
-        * address. This isn't exactly a DMA mapping here, I suspect
+       if (list_empty(&smu->cmd_list))
+               return;
+
+       /* Fetch first command in queue */
+       cmd = list_entry(smu->cmd_list.next, struct smu_cmd, link);
+       smu->cmd_cur = cmd;
+       list_del(&cmd->link);
+
+       DPRINTK("SMU: starting cmd %x, %d bytes data\n", cmd->cmd,
+               cmd->data_len);
+       DPRINTK("SMU: data buffer: %02x %02x %02x %02x ...\n",
+               ((u8 *)cmd->data_buf)[0], ((u8 *)cmd->data_buf)[1],
+               ((u8 *)cmd->data_buf)[2], ((u8 *)cmd->data_buf)[3]);
+
+       /* Fill the SMU command buffer */
+       smu->cmd_buf->cmd = cmd->cmd;
+       smu->cmd_buf->length = cmd->data_len;
+       memcpy(smu->cmd_buf->data, cmd->data_buf, cmd->data_len);
+
+       /* Flush command and data to RAM */
+       faddr = (unsigned long)smu->cmd_buf;
+       fend = faddr + smu->cmd_buf->length + 2;
+       flush_inval_dcache_range(faddr, fend);
+
+       /* This isn't exactly a DMA mapping here, I suspect
         * the SMU is actually communicating with us via i2c to the
         * northbridge or the CPU to access RAM.
         */
-       writel(dev->cmd_buf_abs, dev->db_buf);
+       writel(smu->cmd_buf_abs, smu->db_buf);
 
        /* Ring the SMU doorbell */
-       pmac_do_feature_call(PMAC_FTR_WRITE_GPIO, NULL, dev->db_req, 4);
-       pmac_do_feature_call(PMAC_FTR_READ_GPIO, NULL, dev->db_req, 4);
+       pmac_do_feature_call(PMAC_FTR_WRITE_GPIO, NULL, smu->doorbell, 4);
 }
 
-static int smu_cmd_done(struct smu_device *dev)
+
+static irqreturn_t smu_db_intr(int irq, void *arg, struct pt_regs *regs)
 {
-       unsigned long wait = 0;
-       int gpio;
+       unsigned long flags;
+       struct smu_cmd *cmd;
+       void (*done)(struct smu_cmd *cmd, void *misc) = NULL;
+       void *misc = NULL;
+       u8 gpio;
+       int rc = 0;
 
-       /* Check the SMU doorbell */
-       do  {
-               gpio = pmac_do_feature_call(PMAC_FTR_READ_GPIO,
-                                           NULL, dev->db_ack);
-               if ((gpio & 7) == 7)
-                       return 0;
-               udelay(100);
-       } while(++wait < 10000);
+       /* SMU completed the command, well, we hope, let's make sure
+        * of it
+        */
+       spin_lock_irqsave(&smu->lock, flags);
 
-       printk(KERN_ERR "SMU timeout !\n");
-       return -ENXIO;
+       gpio = pmac_do_feature_call(PMAC_FTR_READ_GPIO, NULL, smu->doorbell);
+       if ((gpio & 7) != 7)
+               return IRQ_HANDLED;
+
+       cmd = smu->cmd_cur;
+       smu->cmd_cur = NULL;
+       if (cmd == NULL)
+               goto bail;
+
+       if (rc == 0) {
+               unsigned long faddr;
+               int reply_len;
+               u8 ack;
+
+               /* CPU might have brought back the cache line, so we need
+                * to flush again before peeking at the SMU response. We
+                * flush the entire buffer for now as we haven't read the
+                * reply lenght (it's only 2 cache lines anyway)
+                */
+               faddr = (unsigned long)smu->cmd_buf;
+               flush_inval_dcache_range(faddr, faddr + 256);
+
+               /* Now check ack */
+               ack = (~cmd->cmd) & 0xff;
+               if (ack != smu->cmd_buf->cmd) {
+                       DPRINTK("SMU: incorrect ack, want %x got %x\n",
+                               ack, smu->cmd_buf->cmd);
+                       rc = -EIO;
+               }
+               reply_len = rc == 0 ? smu->cmd_buf->length : 0;
+               DPRINTK("SMU: reply len: %d\n", reply_len);
+               if (reply_len > cmd->reply_len) {
+                       printk(KERN_WARNING "SMU: reply buffer too small,"
+                              "got %d bytes for a %d bytes buffer\n",
+                              reply_len, cmd->reply_len);
+                       reply_len = cmd->reply_len;
+               }
+               cmd->reply_len = reply_len;
+               if (cmd->reply_buf && reply_len)
+                       memcpy(cmd->reply_buf, smu->cmd_buf->data, reply_len);
+       }
+
+       /* Now complete the command. Write status last in order as we lost
+        * ownership of the command structure as soon as it's no longer -1
+        */
+       done = cmd->done;
+       misc = cmd->misc;
+       mb();
+       cmd->status = rc;
+ bail:
+       /* Start next command if any */
+       smu_start_cmd();
+       spin_unlock_irqrestore(&smu->lock, flags);
+
+       /* Call command completion handler if any */
+       if (done)
+               done(cmd, misc);
+
+       /* It's an edge interrupt, nothing to do */
+       return IRQ_HANDLED;
 }
 
-static int smu_do_cmd(struct smu_device *dev)
+
+static irqreturn_t smu_msg_intr(int irq, void *arg, struct pt_regs *regs)
 {
-       int rc;
-       u8 cmd_ack;
+       /* I don't quite know what to do with this one, we seem to never
+        * receive it, so I suspect we have to arm it someway in the SMU
+        * to start getting events that way.
+        */
+
+       printk(KERN_INFO "SMU: message interrupt !\n");
 
-       DPRINTK("SMU do_cmd %02x len=%d %02x\n",
-               dev->cmd_buf->cmd, dev->cmd_buf->length,
-               dev->cmd_buf->data[0]);
+       /* It's an edge interrupt, nothing to do */
+       return IRQ_HANDLED;
+}
 
-       cmd_ack = smu_save_ack_cmd(dev->cmd_buf);
 
-       /* Clear cmd_buf cache lines */
-       flush_inval_dcache_range((unsigned long)dev->cmd_buf,
-                                ((unsigned long)dev->cmd_buf) +
-                                sizeof(struct smu_cmd_buf));
-       smu_send_cmd(dev);
-       rc = smu_cmd_done(dev);
-       if (rc == 0)
-               rc = smu_cmd_stat(dev->cmd_buf, cmd_ack) ? 0 : -1;
+/*
+ * Queued command management.
+ *
+ */
 
-       DPRINTK("SMU do_cmd %02x len=%d %02x => %d (%02x)\n",
-               dev->cmd_buf->cmd, dev->cmd_buf->length,
-               dev->cmd_buf->data[0], rc, cmd_ack);
+int smu_queue_cmd(struct smu_cmd *cmd)
+{
+       unsigned long flags;
 
-       return rc;
+       if (smu == NULL)
+               return -ENODEV;
+       if (cmd->data_len > SMU_MAX_DATA ||
+           cmd->reply_len > SMU_MAX_DATA)
+               return -EINVAL;
+
+       cmd->status = 1;
+       spin_lock_irqsave(&smu->lock, flags);
+       list_add_tail(&cmd->link, &smu->cmd_list);
+       if (smu->cmd_cur == NULL)
+               smu_start_cmd();
+       spin_unlock_irqrestore(&smu->lock, flags);
+
+       return 0;
 }
+EXPORT_SYMBOL(smu_queue_cmd);
 
-/* RTC low level commands */
-static inline int bcd2hex (int n)
+
+int smu_queue_simple(struct smu_simple_cmd *scmd, u8 command,
+                    unsigned int data_len,
+                    void (*done)(struct smu_cmd *cmd, void *misc),
+                    void *misc, ...)
 {
-       return (((n & 0xf0) >> 4) * 10) + (n & 0xf);
+       struct smu_cmd *cmd = &scmd->cmd;
+       va_list list;
+       int i;
+
+       if (data_len > sizeof(scmd->buffer))
+               return -EINVAL;
+
+       memset(scmd, 0, sizeof(*scmd));
+       cmd->cmd = command;
+       cmd->data_len = data_len;
+       cmd->data_buf = scmd->buffer;
+       cmd->reply_len = sizeof(scmd->buffer);
+       cmd->reply_buf = scmd->buffer;
+       cmd->done = done;
+       cmd->misc = misc;
+
+       va_start(list, misc);
+       for (i = 0; i < data_len; ++i)
+               scmd->buffer[i] = (u8)va_arg(list, int);
+       va_end(list);
+
+       return smu_queue_cmd(cmd);
 }
+EXPORT_SYMBOL(smu_queue_simple);
 
-static inline int hex2bcd (int n)
+
+void smu_poll(void)
 {
-       return ((n / 10) << 4) + (n % 10);
+       u8 gpio;
+
+       if (smu == NULL)
+               return;
+
+       gpio = pmac_do_feature_call(PMAC_FTR_READ_GPIO, NULL, smu->doorbell);
+       if ((gpio & 7) == 7)
+               smu_db_intr(smu->db_irq, smu, NULL);
 }
+EXPORT_SYMBOL(smu_poll);
+
 
-#if 0
-static inline void smu_fill_set_pwrup_timer_cmd(struct smu_cmd_buf *cmd_buf)
+void smu_done_complete(struct smu_cmd *cmd, void *misc)
 {
-       cmd_buf->cmd = 0x8e;
-       cmd_buf->length = 8;
-       cmd_buf->data[0] = 0x00;
-       memset(cmd_buf->data + 1, 0, 7);
+       struct completion *comp = misc;
+
+       complete(comp);
 }
+EXPORT_SYMBOL(smu_done_complete);
+
 
-static inline void smu_fill_get_pwrup_timer_cmd(struct smu_cmd_buf *cmd_buf)
+void smu_spinwait_cmd(struct smu_cmd *cmd)
 {
-       cmd_buf->cmd = 0x8e;
-       cmd_buf->length = 1;
-       cmd_buf->data[0] = 0x01;
+       while(cmd->status == 1)
+               smu_poll();
+}
+EXPORT_SYMBOL(smu_spinwait_cmd);
+
+
+/* RTC low level commands */
+static inline int bcd2hex (int n)
+{
+       return (((n & 0xf0) >> 4) * 10) + (n & 0xf);
 }
 
-static inline void smu_fill_dis_pwrup_timer_cmd(struct smu_cmd_buf *cmd_buf)
+
+static inline int hex2bcd (int n)
 {
-       cmd_buf->cmd = 0x8e;
-       cmd_buf->length = 1;
-       cmd_buf->data[0] = 0x02;
+       return ((n / 10) << 4) + (n % 10);
 }
-#endif
+
 
 static inline void smu_fill_set_rtc_cmd(struct smu_cmd_buf *cmd_buf,
                                        struct rtc_time *time)
@@ -202,100 +346,96 @@ static inline void smu_fill_set_rtc_cmd(struct smu_cmd_buf *cmd_buf,
        cmd_buf->data[7] = hex2bcd(time->tm_year - 100);
 }
 
-static inline void smu_fill_get_rtc_cmd(struct smu_cmd_buf *cmd_buf)
-{
-       cmd_buf->cmd = 0x8e;
-       cmd_buf->length = 1;
-       cmd_buf->data[0] = 0x81;
-}
 
-static void smu_parse_get_rtc_reply(struct smu_cmd_buf *cmd_buf,
-                                   struct rtc_time *time)
+int smu_get_rtc_time(struct rtc_time *time, int spinwait)
 {
-       time->tm_sec = bcd2hex(cmd_buf->data[0]);
-       time->tm_min = bcd2hex(cmd_buf->data[1]);
-       time->tm_hour = bcd2hex(cmd_buf->data[2]);
-       time->tm_wday = bcd2hex(cmd_buf->data[3]);
-       time->tm_mday = bcd2hex(cmd_buf->data[4]);
-       time->tm_mon = bcd2hex(cmd_buf->data[5]) - 1;
-       time->tm_year = bcd2hex(cmd_buf->data[6]) + 100;
-}
-
-int smu_get_rtc_time(struct rtc_time *time)
-{
-       unsigned long flags;
+       struct smu_simple_cmd cmd;
        int rc;
 
        if (smu == NULL)
                return -ENODEV;
 
        memset(time, 0, sizeof(struct rtc_time));
-       spin_lock_irqsave(&smu->lock, flags);
-       smu_fill_get_rtc_cmd(smu->cmd_buf);
-       rc = smu_do_cmd(smu);
-       if (rc == 0)
-               smu_parse_get_rtc_reply(smu->cmd_buf, time);
-       spin_unlock_irqrestore(&smu->lock, flags);
+       rc = smu_queue_simple(&cmd, SMU_CMD_RTC_COMMAND, 1, NULL, NULL,
+                             SMU_CMD_RTC_GET_DATETIME);
+       if (rc)
+               return rc;
+       smu_spinwait_simple(&cmd);
 
-       return rc;
+       time->tm_sec = bcd2hex(cmd.buffer[0]);
+       time->tm_min = bcd2hex(cmd.buffer[1]);
+       time->tm_hour = bcd2hex(cmd.buffer[2]);
+       time->tm_wday = bcd2hex(cmd.buffer[3]);
+       time->tm_mday = bcd2hex(cmd.buffer[4]);
+       time->tm_mon = bcd2hex(cmd.buffer[5]) - 1;
+       time->tm_year = bcd2hex(cmd.buffer[6]) + 100;
+
+       return 0;
 }
 
-int smu_set_rtc_time(struct rtc_time *time)
+
+int smu_set_rtc_time(struct rtc_time *time, int spinwait)
 {
-       unsigned long flags;
+       struct smu_simple_cmd cmd;
        int rc;
 
        if (smu == NULL)
                return -ENODEV;
 
-       spin_lock_irqsave(&smu->lock, flags);
-       smu_fill_set_rtc_cmd(smu->cmd_buf, time);
-       rc = smu_do_cmd(smu);
-       spin_unlock_irqrestore(&smu->lock, flags);
+       rc = smu_queue_simple(&cmd, SMU_CMD_RTC_COMMAND, 8, NULL, NULL,
+                             SMU_CMD_RTC_SET_DATETIME,
+                             hex2bcd(time->tm_sec),
+                             hex2bcd(time->tm_min),
+                             hex2bcd(time->tm_hour),
+                             time->tm_wday,
+                             hex2bcd(time->tm_mday),
+                             hex2bcd(time->tm_mon) + 1,
+                             hex2bcd(time->tm_year - 100));
+       if (rc)
+               return rc;
+       smu_spinwait_simple(&cmd);
 
-       return rc;
+       return 0;
 }
 
+
 void smu_shutdown(void)
 {
-       const unsigned char *command = "SHUTDOWN";
-       unsigned long flags;
+       struct smu_simple_cmd cmd;
 
        if (smu == NULL)
                return;
 
-       spin_lock_irqsave(&smu->lock, flags);
-       smu->cmd_buf->cmd = 0xaa;
-       smu->cmd_buf->length = strlen(command);
-       strcpy(smu->cmd_buf->data, command);
-       smu_do_cmd(smu);
+       if (smu_queue_simple(&cmd, SMU_CMD_POWER_COMMAND, 9, NULL, NULL,
+                            'S', 'H', 'U', 'T', 'D', 'O', 'W', 'N', 0))
+               return;
+       smu_spinwait_simple(&cmd);
        for (;;)
                ;
-       spin_unlock_irqrestore(&smu->lock, flags);
 }
 
+
 void smu_restart(void)
 {
-       const unsigned char *command = "RESTART";
-       unsigned long flags;
+       struct smu_simple_cmd cmd;
 
        if (smu == NULL)
                return;
 
-       spin_lock_irqsave(&smu->lock, flags);
-       smu->cmd_buf->cmd = 0xaa;
-       smu->cmd_buf->length = strlen(command);
-       strcpy(smu->cmd_buf->data, command);
-       smu_do_cmd(smu);
+       if (smu_queue_simple(&cmd, SMU_CMD_POWER_COMMAND, 8, NULL, NULL,
+                            'R', 'E', 'S', 'T', 'A', 'R', 'T', 0))
+               return;
+       smu_spinwait_simple(&cmd);
        for (;;)
                ;
-       spin_unlock_irqrestore(&smu->lock, flags);
 }
 
+
 int smu_present(void)
 {
        return smu != NULL;
 }
+EXPORT_SYMBOL(smu_present);
 
 
 int smu_init (void)
@@ -307,6 +447,8 @@ int smu_init (void)
         if (np == NULL)
                return -ENODEV;
 
+       printk(KERN_INFO "SMU driver %s %s\n", VERSION, AUTHOR);
+
        if (smu_cmdbuf_abs == 0) {
                printk(KERN_ERR "SMU: Command buffer not allocated !\n");
                return -EINVAL;
@@ -318,7 +460,13 @@ int smu_init (void)
        memset(smu, 0, sizeof(*smu));
 
        spin_lock_init(&smu->lock);
+       INIT_LIST_HEAD(&smu->cmd_list);
+       INIT_LIST_HEAD(&smu->cmd_i2c_list);
        smu->of_node = np;
+       smu->db_irq = NO_IRQ;
+       smu->msg_irq = NO_IRQ;
+       init_timer(&smu->i2c_timer);
+
        /* smu_cmdbuf_abs is in the low 2G of RAM, can be converted to a
         * 32 bits value safely
         */
@@ -331,8 +479,8 @@ int smu_init (void)
                goto fail;
        }
        data = (u32 *)get_property(np, "reg", NULL);
-       of_node_put(np);
        if (data == NULL) {
+               of_node_put(np);
                printk(KERN_ERR "SMU: Can't find doorbell GPIO address !\n");
                goto fail;
        }
@@ -341,8 +489,31 @@ int smu_init (void)
         * and ack. GPIOs are at 0x50, best would be to find that out
         * in the device-tree though.
         */
-       smu->db_req = 0x50 + *data;
-       smu->db_ack = 0x50 + *data;
+       smu->doorbell = *data;
+       if (smu->doorbell < 0x50)
+               smu->doorbell += 0x50;
+       if (np->n_intrs > 0)
+               smu->db_irq = np->intrs[0].line;
+
+       of_node_put(np);
+
+       /* Now look for the smu-interrupt GPIO */
+       do {
+               np = of_find_node_by_name(NULL, "smu-interrupt");
+               if (np == NULL)
+                       break;
+               data = (u32 *)get_property(np, "reg", NULL);
+               if (data == NULL) {
+                       of_node_put(np);
+                       break;
+               }
+               smu->msg = *data;
+               if (smu->msg < 0x50)
+                       smu->msg += 0x50;
+               if (np->n_intrs > 0)
+                       smu->msg_irq = np->intrs[0].line;
+               of_node_put(np);
+       } while(0);
 
        /* Doorbell buffer is currently hard-coded, I didn't find a proper
         * device-tree entry giving the address. Best would probably to use
@@ -362,3 +533,584 @@ int smu_init (void)
        return -ENXIO;
 
 }
+
+
+static int smu_late_init(void)
+{
+       if (!smu)
+               return 0;
+
+       /*
+        * Try to request the interrupts
+        */
+
+       if (smu->db_irq != NO_IRQ) {
+               if (request_irq(smu->db_irq, smu_db_intr,
+                               SA_SHIRQ, "SMU doorbell", smu) < 0) {
+                       printk(KERN_WARNING "SMU: can't "
+                              "request interrupt %d\n",
+                              smu->db_irq);
+                       smu->db_irq = NO_IRQ;
+               }
+       }
+
+       if (smu->msg_irq != NO_IRQ) {
+               if (request_irq(smu->msg_irq, smu_msg_intr,
+                               SA_SHIRQ, "SMU message", smu) < 0) {
+                       printk(KERN_WARNING "SMU: can't "
+                              "request interrupt %d\n",
+                              smu->msg_irq);
+                       smu->msg_irq = NO_IRQ;
+               }
+       }
+
+       return 0;
+}
+arch_initcall(smu_late_init);
+
+/*
+ * sysfs visibility
+ */
+
+static void smu_expose_childs(void *unused)
+{
+       struct device_node *np;
+
+       for (np = NULL; (np = of_get_next_child(smu->of_node, np)) != NULL;) {
+               if (device_is_compatible(np, "smu-i2c")) {
+                       char name[32];
+                       u32 *reg = (u32 *)get_property(np, "reg", NULL);
+
+                       if (reg == NULL)
+                               continue;
+                       sprintf(name, "smu-i2c-%02x", *reg);
+                       of_platform_device_create(np, name, &smu->of_dev->dev);
+               }
+       }
+
+}
+
+static DECLARE_WORK(smu_expose_childs_work, smu_expose_childs, NULL);
+
+static int smu_platform_probe(struct of_device* dev,
+                             const struct of_device_id *match)
+{
+       if (!smu)
+               return -ENODEV;
+       smu->of_dev = dev;
+
+       /*
+        * Ok, we are matched, now expose all i2c busses. We have to defer
+        * that unfortunately or it would deadlock inside the device model
+        */
+       schedule_work(&smu_expose_childs_work);
+
+       return 0;
+}
+
+static struct of_device_id smu_platform_match[] =
+{
+       {
+               .type           = "smu",
+       },
+       {},
+};
+
+static struct of_platform_driver smu_of_platform_driver =
+{
+       .name           = "smu",
+       .match_table    = smu_platform_match,
+       .probe          = smu_platform_probe,
+};
+
+static int __init smu_init_sysfs(void)
+{
+       int rc;
+
+       /*
+        * Due to sysfs bogosity, a sysdev is not a real device, so
+        * we should in fact create both if we want sysdev semantics
+        * for power management.
+        * For now, we don't power manage machines with an SMU chip,
+        * I'm a bit too far from figuring out how that works with those
+        * new chipsets, but that will come back and bite us
+        */
+       rc = of_register_driver(&smu_of_platform_driver);
+       return 0;
+}
+
+device_initcall(smu_init_sysfs);
+
+struct of_device *smu_get_ofdev(void)
+{
+       if (!smu)
+               return NULL;
+       return smu->of_dev;
+}
+
+EXPORT_SYMBOL_GPL(smu_get_ofdev);
+
+/*
+ * i2c interface
+ */
+
+static void smu_i2c_complete_command(struct smu_i2c_cmd *cmd, int fail)
+{
+       void (*done)(struct smu_i2c_cmd *cmd, void *misc) = cmd->done;
+       void *misc = cmd->misc;
+       unsigned long flags;
+
+       /* Check for read case */
+       if (!fail && cmd->read) {
+               if (cmd->pdata[0] < 1)
+                       fail = 1;
+               else
+                       memcpy(cmd->info.data, &cmd->pdata[1],
+                              cmd->info.datalen);
+       }
+
+       DPRINTK("SMU: completing, success: %d\n", !fail);
+
+       /* Update status and mark no pending i2c command with lock
+        * held so nobody comes in while we dequeue an eventual
+        * pending next i2c command
+        */
+       spin_lock_irqsave(&smu->lock, flags);
+       smu->cmd_i2c_cur = NULL;
+       wmb();
+       cmd->status = fail ? -EIO : 0;
+
+       /* Is there another i2c command waiting ? */
+       if (!list_empty(&smu->cmd_i2c_list)) {
+               struct smu_i2c_cmd *newcmd;
+
+               /* Fetch it, new current, remove from list */
+               newcmd = list_entry(smu->cmd_i2c_list.next,
+                                   struct smu_i2c_cmd, link);
+               smu->cmd_i2c_cur = newcmd;
+               list_del(&cmd->link);
+
+               /* Queue with low level smu */
+               list_add_tail(&cmd->scmd.link, &smu->cmd_list);
+               if (smu->cmd_cur == NULL)
+                       smu_start_cmd();
+       }
+       spin_unlock_irqrestore(&smu->lock, flags);
+
+       /* Call command completion handler if any */
+       if (done)
+               done(cmd, misc);
+
+}
+
+
+static void smu_i2c_retry(unsigned long data)
+{
+       struct smu_i2c_cmd      *cmd = (struct smu_i2c_cmd *)data;
+
+       DPRINTK("SMU: i2c failure, requeuing...\n");
+
+       /* requeue command simply by resetting reply_len */
+       cmd->pdata[0] = 0xff;
+       cmd->scmd.reply_len = 0x10;
+       smu_queue_cmd(&cmd->scmd);
+}
+
+
+static void smu_i2c_low_completion(struct smu_cmd *scmd, void *misc)
+{
+       struct smu_i2c_cmd      *cmd = misc;
+       int                     fail = 0;
+
+       DPRINTK("SMU: i2c compl. stage=%d status=%x pdata[0]=%x rlen: %x\n",
+               cmd->stage, scmd->status, cmd->pdata[0], scmd->reply_len);
+
+       /* Check for possible status */
+       if (scmd->status < 0)
+               fail = 1;
+       else if (cmd->read) {
+               if (cmd->stage == 0)
+                       fail = cmd->pdata[0] != 0;
+               else
+                       fail = cmd->pdata[0] >= 0x80;
+       } else {
+               fail = cmd->pdata[0] != 0;
+       }
+
+       /* Handle failures by requeuing command, after 5ms interval
+        */
+       if (fail && --cmd->retries > 0) {
+               DPRINTK("SMU: i2c failure, starting timer...\n");
+               smu->i2c_timer.function = smu_i2c_retry;
+               smu->i2c_timer.data = (unsigned long)cmd;
+               smu->i2c_timer.expires = jiffies + msecs_to_jiffies(5);
+               add_timer(&smu->i2c_timer);
+               return;
+       }
+
+       /* If failure or stage 1, command is complete */
+       if (fail || cmd->stage != 0) {
+               smu_i2c_complete_command(cmd, fail);
+               return;
+       }
+
+       DPRINTK("SMU: going to stage 1\n");
+
+       /* Ok, initial command complete, now poll status */
+       scmd->reply_buf = cmd->pdata;
+       scmd->reply_len = 0x10;
+       scmd->data_buf = cmd->pdata;
+       scmd->data_len = 1;
+       cmd->pdata[0] = 0;
+       cmd->stage = 1;
+       cmd->retries = 20;
+       smu_queue_cmd(scmd);
+}
+
+
+int smu_queue_i2c(struct smu_i2c_cmd *cmd)
+{
+       unsigned long flags;
+
+       if (smu == NULL)
+               return -ENODEV;
+
+       /* Fill most fields of scmd */
+       cmd->scmd.cmd = SMU_CMD_I2C_COMMAND;
+       cmd->scmd.done = smu_i2c_low_completion;
+       cmd->scmd.misc = cmd;
+       cmd->scmd.reply_buf = cmd->pdata;
+       cmd->scmd.reply_len = 0x10;
+       cmd->scmd.data_buf = (u8 *)(char *)&cmd->info;
+       cmd->scmd.status = 1;
+       cmd->stage = 0;
+       cmd->pdata[0] = 0xff;
+       cmd->retries = 20;
+       cmd->status = 1;
+
+       /* Check transfer type, sanitize some "info" fields
+        * based on transfer type and do more checking
+        */
+       cmd->info.caddr = cmd->info.devaddr;
+       cmd->read = cmd->info.devaddr & 0x01;
+       switch(cmd->info.type) {
+       case SMU_I2C_TRANSFER_SIMPLE:
+               memset(&cmd->info.sublen, 0, 4);
+               break;
+       case SMU_I2C_TRANSFER_COMBINED:
+               cmd->info.devaddr &= 0xfe;
+       case SMU_I2C_TRANSFER_STDSUB:
+               if (cmd->info.sublen > 3)
+                       return -EINVAL;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       /* Finish setting up command based on transfer direction
+        */
+       if (cmd->read) {
+               if (cmd->info.datalen > SMU_I2C_READ_MAX)
+                       return -EINVAL;
+               memset(cmd->info.data, 0xff, cmd->info.datalen);
+               cmd->scmd.data_len = 9;
+       } else {
+               if (cmd->info.datalen > SMU_I2C_WRITE_MAX)
+                       return -EINVAL;
+               cmd->scmd.data_len = 9 + cmd->info.datalen;
+       }
+
+       DPRINTK("SMU: i2c enqueuing command\n");
+       DPRINTK("SMU:   %s, len=%d bus=%x addr=%x sub0=%x type=%x\n",
+               cmd->read ? "read" : "write", cmd->info.datalen,
+               cmd->info.bus, cmd->info.caddr,
+               cmd->info.subaddr[0], cmd->info.type);
+
+
+       /* Enqueue command in i2c list, and if empty, enqueue also in
+        * main command list
+        */
+       spin_lock_irqsave(&smu->lock, flags);
+       if (smu->cmd_i2c_cur == NULL) {
+               smu->cmd_i2c_cur = cmd;
+               list_add_tail(&cmd->scmd.link, &smu->cmd_list);
+               if (smu->cmd_cur == NULL)
+                       smu_start_cmd();
+       } else
+               list_add_tail(&cmd->link, &smu->cmd_i2c_list);
+       spin_unlock_irqrestore(&smu->lock, flags);
+
+       return 0;
+}
+
+
+
+/*
+ * Userland driver interface
+ */
+
+
+static LIST_HEAD(smu_clist);
+static DEFINE_SPINLOCK(smu_clist_lock);
+
+enum smu_file_mode {
+       smu_file_commands,
+       smu_file_events,
+       smu_file_closing
+};
+
+struct smu_private
+{
+       struct list_head        list;
+       enum smu_file_mode      mode;
+       int                     busy;
+       struct smu_cmd          cmd;
+       spinlock_t              lock;
+       wait_queue_head_t       wait;
+       u8                      buffer[SMU_MAX_DATA];
+};
+
+
+static int smu_open(struct inode *inode, struct file *file)
+{
+       struct smu_private *pp;
+       unsigned long flags;
+
+       pp = kmalloc(sizeof(struct smu_private), GFP_KERNEL);
+       if (pp == 0)
+               return -ENOMEM;
+       memset(pp, 0, sizeof(struct smu_private));
+       spin_lock_init(&pp->lock);
+       pp->mode = smu_file_commands;
+       init_waitqueue_head(&pp->wait);
+
+       spin_lock_irqsave(&smu_clist_lock, flags);
+       list_add(&pp->list, &smu_clist);
+       spin_unlock_irqrestore(&smu_clist_lock, flags);
+       file->private_data = pp;
+
+       return 0;
+}
+
+
+static void smu_user_cmd_done(struct smu_cmd *cmd, void *misc)
+{
+       struct smu_private *pp = misc;
+
+       wake_up_all(&pp->wait);
+}
+
+
+static ssize_t smu_write(struct file *file, const char __user *buf,
+                        size_t count, loff_t *ppos)
+{
+       struct smu_private *pp = file->private_data;
+       unsigned long flags;
+       struct smu_user_cmd_hdr hdr;
+       int rc = 0;
+
+       if (pp->busy)
+               return -EBUSY;
+       else if (copy_from_user(&hdr, buf, sizeof(hdr)))
+               return -EFAULT;
+       else if (hdr.cmdtype == SMU_CMDTYPE_WANTS_EVENTS) {
+               pp->mode = smu_file_events;
+               return 0;
+       } else if (hdr.cmdtype != SMU_CMDTYPE_SMU)
+               return -EINVAL;
+       else if (pp->mode != smu_file_commands)
+               return -EBADFD;
+       else if (hdr.data_len > SMU_MAX_DATA)
+               return -EINVAL;
+
+       spin_lock_irqsave(&pp->lock, flags);
+       if (pp->busy) {
+               spin_unlock_irqrestore(&pp->lock, flags);
+               return -EBUSY;
+       }
+       pp->busy = 1;
+       pp->cmd.status = 1;
+       spin_unlock_irqrestore(&pp->lock, flags);
+
+       if (copy_from_user(pp->buffer, buf + sizeof(hdr), hdr.data_len)) {
+               pp->busy = 0;
+               return -EFAULT;
+       }
+
+       pp->cmd.cmd = hdr.cmd;
+       pp->cmd.data_len = hdr.data_len;
+       pp->cmd.reply_len = SMU_MAX_DATA;
+       pp->cmd.data_buf = pp->buffer;
+       pp->cmd.reply_buf = pp->buffer;
+       pp->cmd.done = smu_user_cmd_done;
+       pp->cmd.misc = pp;
+       rc = smu_queue_cmd(&pp->cmd);
+       if (rc < 0)
+               return rc;
+       return count;
+}
+
+
+static ssize_t smu_read_command(struct file *file, struct smu_private *pp,
+                               char __user *buf, size_t count)
+{
+       DECLARE_WAITQUEUE(wait, current);
+       struct smu_user_reply_hdr hdr;
+       unsigned long flags;
+       int size, rc = 0;
+
+       if (!pp->busy)
+               return 0;
+       if (count < sizeof(struct smu_user_reply_hdr))
+               return -EOVERFLOW;
+       spin_lock_irqsave(&pp->lock, flags);
+       if (pp->cmd.status == 1) {
+               if (file->f_flags & O_NONBLOCK)
+                       return -EAGAIN;
+               add_wait_queue(&pp->wait, &wait);
+               for (;;) {
+                       set_current_state(TASK_INTERRUPTIBLE);
+                       rc = 0;
+                       if (pp->cmd.status != 1)
+                               break;
+                       rc = -ERESTARTSYS;
+                       if (signal_pending(current))
+                               break;
+                       spin_unlock_irqrestore(&pp->lock, flags);
+                       schedule();
+                       spin_lock_irqsave(&pp->lock, flags);
+               }
+               set_current_state(TASK_RUNNING);
+               remove_wait_queue(&pp->wait, &wait);
+       }
+       spin_unlock_irqrestore(&pp->lock, flags);
+       if (rc)
+               return rc;
+       if (pp->cmd.status != 0)
+               pp->cmd.reply_len = 0;
+       size = sizeof(hdr) + pp->cmd.reply_len;
+       if (count < size)
+               size = count;
+       rc = size;
+       hdr.status = pp->cmd.status;
+       hdr.reply_len = pp->cmd.reply_len;
+       if (copy_to_user(buf, &hdr, sizeof(hdr)))
+               return -EFAULT;
+       size -= sizeof(hdr);
+       if (size && copy_to_user(buf + sizeof(hdr), pp->buffer, size))
+               return -EFAULT;
+       pp->busy = 0;
+
+       return rc;
+}
+
+
+static ssize_t smu_read_events(struct file *file, struct smu_private *pp,
+                              char __user *buf, size_t count)
+{
+       /* Not implemented */
+       msleep_interruptible(1000);
+       return 0;
+}
+
+
+static ssize_t smu_read(struct file *file, char __user *buf,
+                       size_t count, loff_t *ppos)
+{
+       struct smu_private *pp = file->private_data;
+
+       if (pp->mode == smu_file_commands)
+               return smu_read_command(file, pp, buf, count);
+       if (pp->mode == smu_file_events)
+               return smu_read_events(file, pp, buf, count);
+
+       return -EBADFD;
+}
+
+static unsigned int smu_fpoll(struct file *file, poll_table *wait)
+{
+       struct smu_private *pp = file->private_data;
+       unsigned int mask = 0;
+       unsigned long flags;
+
+       if (pp == 0)
+               return 0;
+
+       if (pp->mode == smu_file_commands) {
+               poll_wait(file, &pp->wait, wait);
+
+               spin_lock_irqsave(&pp->lock, flags);
+               if (pp->busy && pp->cmd.status != 1)
+                       mask |= POLLIN;
+               spin_unlock_irqrestore(&pp->lock, flags);
+       } if (pp->mode == smu_file_events) {
+               /* Not yet implemented */
+       }
+       return mask;
+}
+
+static int smu_release(struct inode *inode, struct file *file)
+{
+       struct smu_private *pp = file->private_data;
+       unsigned long flags;
+       unsigned int busy;
+
+       if (pp == 0)
+               return 0;
+
+       file->private_data = NULL;
+
+       /* Mark file as closing to avoid races with new request */
+       spin_lock_irqsave(&pp->lock, flags);
+       pp->mode = smu_file_closing;
+       busy = pp->busy;
+
+       /* Wait for any pending request to complete */
+       if (busy && pp->cmd.status == 1) {
+               DECLARE_WAITQUEUE(wait, current);
+
+               add_wait_queue(&pp->wait, &wait);
+               for (;;) {
+                       set_current_state(TASK_UNINTERRUPTIBLE);
+                       if (pp->cmd.status != 1)
+                               break;
+                       spin_lock_irqsave(&pp->lock, flags);
+                       schedule();
+                       spin_unlock_irqrestore(&pp->lock, flags);
+               }
+               set_current_state(TASK_RUNNING);
+               remove_wait_queue(&pp->wait, &wait);
+       }
+       spin_unlock_irqrestore(&pp->lock, flags);
+
+       spin_lock_irqsave(&smu_clist_lock, flags);
+       list_del(&pp->list);
+       spin_unlock_irqrestore(&smu_clist_lock, flags);
+       kfree(pp);
+
+       return 0;
+}
+
+
+static struct file_operations smu_device_fops __pmacdata = {
+       .llseek         = no_llseek,
+       .read           = smu_read,
+       .write          = smu_write,
+       .poll           = smu_fpoll,
+       .open           = smu_open,
+       .release        = smu_release,
+};
+
+static struct miscdevice pmu_device __pmacdata = {
+       MISC_DYNAMIC_MINOR, "smu", &smu_device_fops
+};
+
+static int smu_device_init(void)
+{
+       if (!smu)
+               return -ENODEV;
+       if (misc_register(&pmu_device) < 0)
+               printk(KERN_ERR "via-pmu: cannot register misc device.\n");
+       return 0;
+}
+device_initcall(smu_device_init);
index c9ca1118e449207c2dca58a742b0ddd204a556d7..f38696622eb4a201667649accdd2a69074d13ee6 100644 (file)
@@ -599,7 +599,7 @@ thermostat_init(void)
                sensor_location[2] = "?";
        }
 
-       of_dev = of_platform_device_create(np, "temperatures");
+       of_dev = of_platform_device_create(np, "temperatures", NULL);
        
        if (of_dev == NULL) {
                printk(KERN_ERR "Can't register temperatures device !\n");
index 703e3197331471dada2210e3c2ff9ddd471e2278..cc507ceef15388175917ef3852c504731dd66c24 100644 (file)
@@ -2051,7 +2051,7 @@ static int __init therm_pm72_init(void)
                            return -ENODEV;
                }
        }
-       of_dev = of_platform_device_create(np, "temperature");
+       of_dev = of_platform_device_create(np, "temperature", NULL);
        if (of_dev == NULL) {
                printk(KERN_ERR "Can't register FCU platform device !\n");
                return -ENODEV;
index cbb72eb0426d493c9691f1deadb66915037df54b..6aaa1df1a64ed458fb54d2804ce8d6e58b9a08bd 100644 (file)
@@ -504,7 +504,7 @@ g4fan_init( void )
        }
        if( !(np=of_find_node_by_name(NULL, "fan")) )
                return -ENODEV;
-       x.of_dev = of_platform_device_create( np, "temperature" );
+       x.of_dev = of_platform_device_create(np, "temperature", NULL);
        of_node_put( np );
 
        if( !x.of_dev ) {
index f80ee6350edf1dce079af9e680ec12740229b3f2..31cbee71365f4d5ad969e4558b32147020b81173 100644 (file)
@@ -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__ */
 
index acf386fc4b4fdaae903ee07a59b31fd2c80714a8..51c63c0cf1c9a8a52d680149d630c9c88613e5c6 100644 (file)
@@ -19,6 +19,7 @@
 #include "raid6.h"
 #ifndef __KERNEL__
 #include <sys/mman.h>
+#include <stdio.h>
 #endif
 
 struct raid6_calls raid6_call;
index 1de8f030eee0e2318093d898884a9f537dbdbc12..b9afd35b8812cf46c1994a37b99f4e8935680614 100644 (file)
 #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
 
index 557806728609d82e60754faa9e26e62fbaafa59a..78e0396adf2ac28ab8cc23f0427303b10d2207b2 100644 (file)
@@ -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 *~
index 8b4ad70dd1b2f30e197564a90df10cef1252a3fc..877c770558e9c407350da4ea90d92b2e875cefd2 100644 (file)
@@ -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            */
index 013c835ed910d6c9a7d69783a96eb030f7221341..5319a9c9a9796bbf4e0d769a3e120cd98d5dc952 100644 (file)
@@ -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            */
index 53d399b6652b87fb75406dff045b5f429233d6af..022913da8c5994dbfd0468b7fa51ff62b8f2cdcc 100644 (file)
@@ -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            */
index 202bfe6819b887297c06492442de0dd4edacc8f6..6418f03b9ce4b74b1711e03a718efe952028bd06 100644 (file)
@@ -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            */
index c00245d4d24900a59d90eb1e3ab54aaa51eca2b2..b2256d675b4434f8f8553b13d4892089a6edff6e 100644 (file)
@@ -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            */
index 3a464a09221f959c7287ecd8847301c3e24dd798..6f03ce4dd7b0e4fb076c72dcfe9cdec20b122c8f 100644 (file)
@@ -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>
index 0732efda6a9831da4f6862acdacf5b3befcd2dad..71971e9bb3422c36acb8280becdfbf03a9c37944 100644 (file)
@@ -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            */
index 248d67fde037268df3d735f435ee561a00bce9f5..b03573c6840e56e632bd52f60aa90aabc45abc81 100644 (file)
@@ -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            */
index d7da901ebe90617f019360a93bc10dd3cbb587bf..f304f3c147637c92a7956f88c7fc548429f3338a 100644 (file)
@@ -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              */
index 342f92df4aba7b924e151dba2c2369a187204371..4c6d6fb49034e04a04d1c2d220e574b5aed1d434 100644 (file)
@@ -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              */
index a564321db2f02039c9e7d6804a2c4d204d2b19c4..c062a017491e4bb08bf8c853d265b349ed464c59 100644 (file)
@@ -763,21 +763,21 @@ static void set_pll(struct bttv *btv)
                 /* no PLL needed */
                 if (btv->pll.pll_current == 0)
                         return;
-               vprintk(KERN_INFO "bttv%d: PLL can sleep, using XTAL (%d).\n",
-                       btv->c.nr,btv->pll.pll_ifreq);
+               bttv_printk(KERN_INFO "bttv%d: PLL can sleep, using XTAL (%d).\n",
+                           btv->c.nr,btv->pll.pll_ifreq);
                 btwrite(0x00,BT848_TGCTRL);
                 btwrite(0x00,BT848_PLL_XCI);
                 btv->pll.pll_current = 0;
                 return;
         }
 
-       vprintk(KERN_INFO "bttv%d: PLL: %d => %d ",btv->c.nr,
-               btv->pll.pll_ifreq, btv->pll.pll_ofreq);
+       bttv_printk(KERN_INFO "bttv%d: PLL: %d => %d ",btv->c.nr,
+                   btv->pll.pll_ifreq, btv->pll.pll_ofreq);
        set_pll_freq(btv, btv->pll.pll_ifreq, btv->pll.pll_ofreq);
 
         for (i=0; i<10; i++) {
                /*  Let other people run while the PLL stabilizes */
-               vprintk(".");
+               bttv_printk(".");
                msleep(10);
 
                 if (btread(BT848_DSTATUS) & BT848_DSTATUS_PLOCK) {
@@ -785,12 +785,12 @@ static void set_pll(struct bttv *btv)
                 } else {
                         btwrite(0x08,BT848_TGCTRL);
                         btv->pll.pll_current = btv->pll.pll_ofreq;
-                       vprintk(" ok\n");
+                       bttv_printk(" ok\n");
                         return;
                 }
         }
         btv->pll.pll_current = -1;
-       vprintk("failed\n");
+       bttv_printk("failed\n");
         return;
 }
 
index 9b0b7ca035f8a1f99d2be789bfb16255829b9d20..7a312f79340aa3786ef721e4c1bae0f7d00883e9 100644 (file)
@@ -221,7 +221,7 @@ extern void bttv_gpio_tracking(struct bttv *btv, char *comment);
 extern int init_bttv_i2c(struct bttv *btv);
 extern int fini_bttv_i2c(struct bttv *btv);
 
-#define vprintk  if (bttv_verbose) printk
+#define bttv_printk if (bttv_verbose) printk
 #define dprintk  if (bttv_debug >= 1) printk
 #define d2printk if (bttv_debug >= 2) printk
 
index c9106b1d79dff67c83cdc442cdc01d02b6616ec1..4334744652de0b22c23122fa311190ff217e02e1 100644 (file)
@@ -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);
 }
index 33f209a39cb62263d9f93d5600cdd197d301d77f..1883d22cffeb100a73bf3ea1479722aad93f0b98 100644 (file)
@@ -35,6 +35,23 @@ config FUSION_FC
          LSIFC929X
          LSIFC929XL
 
+config FUSION_SAS
+       tristate "Fusion MPT ScsiHost drivers for SAS"
+       depends on PCI && SCSI
+       select FUSION
+       select SCSI_SAS_ATTRS
+       ---help---
+         SCSI HOST support for a SAS host adapters.
+
+         List of supported controllers:
+
+         LSISAS1064
+         LSISAS1066
+         LSISAS1068
+         LSISAS1064E
+         LSISAS1066E
+         LSISAS1068E
+
 config FUSION_MAX_SGE
        int "Maximum number of scatter gather entries (16 - 128)"
        depends on FUSION
index 1d2f9db813c15ff9bc7d8b867a4b46fdb0f5c8c4..8a2e2657f4c28c0c304cbe1859861c3f2190d5f8 100644 (file)
@@ -34,5 +34,6 @@
 
 obj-$(CONFIG_FUSION_SPI)       += mptbase.o mptscsih.o mptspi.o
 obj-$(CONFIG_FUSION_FC)                += mptbase.o mptscsih.o mptfc.o
+obj-$(CONFIG_FUSION_SAS)       += mptbase.o mptscsih.o mptsas.o
 obj-$(CONFIG_FUSION_CTL)       += mptctl.o
 obj-$(CONFIG_FUSION_LAN)       += mptlan.o
index f517d0692d5faa08d960276d55dbc998d51b5945..790a2932ded99673bae69d0ab7cd16e99e2454b9 100644 (file)
@@ -135,13 +135,12 @@ static void       mpt_adapter_dispose(MPT_ADAPTER *ioc);
 
 static void    MptDisplayIocCapabilities(MPT_ADAPTER *ioc);
 static int     MakeIocReady(MPT_ADAPTER *ioc, int force, int sleepFlag);
-//static u32   mpt_GetIocState(MPT_ADAPTER *ioc, int cooked);
 static int     GetIocFacts(MPT_ADAPTER *ioc, int sleepFlag, int reason);
 static int     GetPortFacts(MPT_ADAPTER *ioc, int portnum, int sleepFlag);
 static int     SendIocInit(MPT_ADAPTER *ioc, int sleepFlag);
 static int     SendPortEnable(MPT_ADAPTER *ioc, int portnum, int sleepFlag);
 static int     mpt_do_upload(MPT_ADAPTER *ioc, int sleepFlag);
-static int     mpt_downloadboot(MPT_ADAPTER *ioc, int sleepFlag);
+static int     mpt_downloadboot(MPT_ADAPTER *ioc, MpiFwHeader_t *pFwHeader, int sleepFlag);
 static int     mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag);
 static int     KickStart(MPT_ADAPTER *ioc, int ignore, int sleepFlag);
 static int     SendIocReset(MPT_ADAPTER *ioc, u8 reset_type, int sleepFlag);
@@ -152,6 +151,7 @@ static int  WaitForDoorbellReply(MPT_ADAPTER *ioc, int howlong, int sleepFlag);
 static int     GetLanConfigPages(MPT_ADAPTER *ioc);
 static int     GetFcPortPage0(MPT_ADAPTER *ioc, int portnum);
 static int     GetIoUnitPage2(MPT_ADAPTER *ioc);
+int            mptbase_sas_persist_operation(MPT_ADAPTER *ioc, u8 persist_opcode);
 static int     mpt_GetScsiPortSettings(MPT_ADAPTER *ioc, int portnum);
 static int     mpt_readScsiDevicePageHeaders(MPT_ADAPTER *ioc, int portnum);
 static void    mpt_read_ioc_pg_1(MPT_ADAPTER *ioc);
@@ -159,6 +159,8 @@ static void         mpt_read_ioc_pg_4(MPT_ADAPTER *ioc);
 static void    mpt_timer_expired(unsigned long data);
 static int     SendEventNotification(MPT_ADAPTER *ioc, u8 EvSwitch);
 static int     SendEventAck(MPT_ADAPTER *ioc, EventNotificationReply_t *evnp);
+static int     mpt_host_page_access_control(MPT_ADAPTER *ioc, u8 access_control_value, int sleepFlag);
+static int     mpt_host_page_alloc(MPT_ADAPTER *ioc, pIOCInit_t ioc_init);
 
 #ifdef CONFIG_PROC_FS
 static int     procmpt_summary_read(char *buf, char **start, off_t offset,
@@ -175,6 +177,7 @@ static int  ProcessEventNotification(MPT_ADAPTER *ioc, EventNotificationReply_t *
 static void    mpt_sp_ioc_info(MPT_ADAPTER *ioc, u32 ioc_status, MPT_FRAME_HDR *mf);
 static void    mpt_fc_log_info(MPT_ADAPTER *ioc, u32 log_info);
 static void    mpt_sp_log_info(MPT_ADAPTER *ioc, u32 log_info);
+static void    mpt_sas_log_info(MPT_ADAPTER *ioc, u32 log_info);
 
 /* module entry point */
 static int  __init    fusion_init  (void);
@@ -206,6 +209,144 @@ pci_enable_io_access(struct pci_dev *pdev)
        pci_write_config_word(pdev, PCI_COMMAND, command_reg);
 }
 
+/*
+ *  Process turbo (context) reply...
+ */
+static void
+mpt_turbo_reply(MPT_ADAPTER *ioc, u32 pa)
+{
+       MPT_FRAME_HDR *mf = NULL;
+       MPT_FRAME_HDR *mr = NULL;
+       int req_idx = 0;
+       int cb_idx;
+
+       dmfprintk((MYIOC_s_INFO_FMT "Got TURBO reply req_idx=%08x\n",
+                               ioc->name, pa));
+
+       switch (pa >> MPI_CONTEXT_REPLY_TYPE_SHIFT) {
+       case MPI_CONTEXT_REPLY_TYPE_SCSI_INIT:
+               req_idx = pa & 0x0000FFFF;
+               cb_idx = (pa & 0x00FF0000) >> 16;
+               mf = MPT_INDEX_2_MFPTR(ioc, req_idx);
+               break;
+       case MPI_CONTEXT_REPLY_TYPE_LAN:
+               cb_idx = mpt_lan_index;
+               /*
+                *  Blind set of mf to NULL here was fatal
+                *  after lan_reply says "freeme"
+                *  Fix sort of combined with an optimization here;
+                *  added explicit check for case where lan_reply
+                *  was just returning 1 and doing nothing else.
+                *  For this case skip the callback, but set up
+                *  proper mf value first here:-)
+                */
+               if ((pa & 0x58000000) == 0x58000000) {
+                       req_idx = pa & 0x0000FFFF;
+                       mf = MPT_INDEX_2_MFPTR(ioc, req_idx);
+                       mpt_free_msg_frame(ioc, mf);
+                       mb();
+                       return;
+                       break;
+               }
+               mr = (MPT_FRAME_HDR *) CAST_U32_TO_PTR(pa);
+               break;
+       case MPI_CONTEXT_REPLY_TYPE_SCSI_TARGET:
+               cb_idx = mpt_stm_index;
+               mr = (MPT_FRAME_HDR *) CAST_U32_TO_PTR(pa);
+               break;
+       default:
+               cb_idx = 0;
+               BUG();
+       }
+
+       /*  Check for (valid) IO callback!  */
+       if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS ||
+                       MptCallbacks[cb_idx] == NULL) {
+               printk(MYIOC_s_WARN_FMT "%s: Invalid cb_idx (%d)!\n",
+                               __FUNCTION__, ioc->name, cb_idx);
+               goto out;
+       }
+
+       if (MptCallbacks[cb_idx](ioc, mf, mr))
+               mpt_free_msg_frame(ioc, mf);
+ out:
+       mb();
+}
+
+static void
+mpt_reply(MPT_ADAPTER *ioc, u32 pa)
+{
+       MPT_FRAME_HDR   *mf;
+       MPT_FRAME_HDR   *mr;
+       int              req_idx;
+       int              cb_idx;
+       int              freeme;
+
+       u32 reply_dma_low;
+       u16 ioc_stat;
+
+       /* non-TURBO reply!  Hmmm, something may be up...
+        *  Newest turbo reply mechanism; get address
+        *  via left shift 1 (get rid of MPI_ADDRESS_REPLY_A_BIT)!
+        */
+
+       /* Map DMA address of reply header to cpu address.
+        * pa is 32 bits - but the dma address may be 32 or 64 bits
+        * get offset based only only the low addresses
+        */
+
+       reply_dma_low = (pa <<= 1);
+       mr = (MPT_FRAME_HDR *)((u8 *)ioc->reply_frames +
+                        (reply_dma_low - ioc->reply_frames_low_dma));
+
+       req_idx = le16_to_cpu(mr->u.frame.hwhdr.msgctxu.fld.req_idx);
+       cb_idx = mr->u.frame.hwhdr.msgctxu.fld.cb_idx;
+       mf = MPT_INDEX_2_MFPTR(ioc, req_idx);
+
+       dmfprintk((MYIOC_s_INFO_FMT "Got non-TURBO reply=%p req_idx=%x cb_idx=%x Function=%x\n",
+                       ioc->name, mr, req_idx, cb_idx, mr->u.hdr.Function));
+       DBG_DUMP_REPLY_FRAME(mr)
+
+        /*  Check/log IOC log info
+        */
+       ioc_stat = le16_to_cpu(mr->u.reply.IOCStatus);
+       if (ioc_stat & MPI_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE) {
+               u32      log_info = le32_to_cpu(mr->u.reply.IOCLogInfo);
+               if (ioc->bus_type == FC)
+                       mpt_fc_log_info(ioc, log_info);
+               else if (ioc->bus_type == SCSI)
+                       mpt_sp_log_info(ioc, log_info);
+               else if (ioc->bus_type == SAS)
+                       mpt_sas_log_info(ioc, log_info);
+       }
+       if (ioc_stat & MPI_IOCSTATUS_MASK) {
+               if (ioc->bus_type == SCSI &&
+                   cb_idx != mpt_stm_index &&
+                   cb_idx != mpt_lan_index)
+                       mpt_sp_ioc_info(ioc, (u32)ioc_stat, mf);
+       }
+
+
+       /*  Check for (valid) IO callback!  */
+       if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS ||
+                       MptCallbacks[cb_idx] == NULL) {
+               printk(MYIOC_s_WARN_FMT "%s: Invalid cb_idx (%d)!\n",
+                               __FUNCTION__, ioc->name, cb_idx);
+               freeme = 0;
+               goto out;
+       }
+
+       freeme = MptCallbacks[cb_idx](ioc, mf, mr);
+
+ out:
+       /*  Flush (non-TURBO) reply with a WRITE!  */
+       CHIPREG_WRITE32(&ioc->chip->ReplyFifo, pa);
+
+       if (freeme)
+               mpt_free_msg_frame(ioc, mf);
+       mb();
+}
+
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /*
  *     mpt_interrupt - MPT adapter (IOC) specific interrupt handler.
@@ -227,164 +368,21 @@ pci_enable_io_access(struct pci_dev *pdev)
 static irqreturn_t
 mpt_interrupt(int irq, void *bus_id, struct pt_regs *r)
 {
-       MPT_ADAPTER     *ioc;
-       MPT_FRAME_HDR   *mf;
-       MPT_FRAME_HDR   *mr;
-       u32              pa;
-       int              req_idx;
-       int              cb_idx;
-       int              type;
-       int              freeme;
-
-       ioc = (MPT_ADAPTER *)bus_id;
+       MPT_ADAPTER *ioc = bus_id;
+       u32 pa;
 
        /*
         *  Drain the reply FIFO!
-        *
-        * NOTES: I've seen up to 10 replies processed in this loop, so far...
-        * Update: I've seen up to 9182 replies processed in this loop! ??
-        * Update: Limit ourselves to processing max of N replies
-        *      (bottom of loop).
         */
        while (1) {
-
-               if ((pa = CHIPREG_READ32_dmasync(&ioc->chip->ReplyFifo)) == 0xFFFFFFFF)
+               pa = CHIPREG_READ32_dmasync(&ioc->chip->ReplyFifo);
+               if (pa == 0xFFFFFFFF)
                        return IRQ_HANDLED;
-
-               cb_idx = 0;
-               freeme = 0;
-
-               /*
-                *  Check for non-TURBO reply!
-                */
-               if (pa & MPI_ADDRESS_REPLY_A_BIT) {
-                       u32 reply_dma_low;
-                       u16 ioc_stat;
-
-                       /* non-TURBO reply!  Hmmm, something may be up...
-                        *  Newest turbo reply mechanism; get address
-                        *  via left shift 1 (get rid of MPI_ADDRESS_REPLY_A_BIT)!
-                        */
-
-                       /* Map DMA address of reply header to cpu address.
-                        * pa is 32 bits - but the dma address may be 32 or 64 bits
-                        * get offset based only only the low addresses
-                        */
-                       reply_dma_low = (pa = (pa << 1));
-                       mr = (MPT_FRAME_HDR *)((u8 *)ioc->reply_frames +
-                                        (reply_dma_low - ioc->reply_frames_low_dma));
-
-                       req_idx = le16_to_cpu(mr->u.frame.hwhdr.msgctxu.fld.req_idx);
-                       cb_idx = mr->u.frame.hwhdr.msgctxu.fld.cb_idx;
-                       mf = MPT_INDEX_2_MFPTR(ioc, req_idx);
-
-                       dmfprintk((MYIOC_s_INFO_FMT "Got non-TURBO reply=%p req_idx=%x cb_idx=%x Function=%x\n",
-                                       ioc->name, mr, req_idx, cb_idx, mr->u.hdr.Function));
-                       DBG_DUMP_REPLY_FRAME(mr)
-
-                        /*  Check/log IOC log info
-                        */
-                       ioc_stat = le16_to_cpu(mr->u.reply.IOCStatus);
-                       if (ioc_stat & MPI_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE) {
-                               u32      log_info = le32_to_cpu(mr->u.reply.IOCLogInfo);
-                               if (ioc->bus_type == FC)
-                                       mpt_fc_log_info(ioc, log_info);
-                               else if (ioc->bus_type == SCSI)
-                                       mpt_sp_log_info(ioc, log_info);
-                       }
-                       if (ioc_stat & MPI_IOCSTATUS_MASK) {
-                               if (ioc->bus_type == SCSI)
-                                       mpt_sp_ioc_info(ioc, (u32)ioc_stat, mf);
-                       }
-               } else {
-                       /*
-                        *  Process turbo (context) reply...
-                        */
-                       dmfprintk((MYIOC_s_INFO_FMT "Got TURBO reply req_idx=%08x\n", ioc->name, pa));
-                       type = (pa >> MPI_CONTEXT_REPLY_TYPE_SHIFT);
-                       if (type == MPI_CONTEXT_REPLY_TYPE_SCSI_TARGET) {
-                               cb_idx = mpt_stm_index;
-                               mf = NULL;
-                               mr = (MPT_FRAME_HDR *) CAST_U32_TO_PTR(pa);
-                       } else if (type == MPI_CONTEXT_REPLY_TYPE_LAN) {
-                               cb_idx = mpt_lan_index;
-                                /*  Blind set of mf to NULL here was fatal
-                                *  after lan_reply says "freeme"
-                                *  Fix sort of combined with an optimization here;
-                                *  added explicit check for case where lan_reply
-                                *  was just returning 1 and doing nothing else.
-                                *  For this case skip the callback, but set up
-                                *  proper mf value first here:-)
-                                */
-                               if ((pa & 0x58000000) == 0x58000000) {
-                                       req_idx = pa & 0x0000FFFF;
-                                       mf = MPT_INDEX_2_MFPTR(ioc, req_idx);
-                                       freeme = 1;
-                                       /*
-                                        *  IMPORTANT!  Invalidate the callback!
-                                        */
-                                       cb_idx = 0;
-                               } else {
-                                       mf = NULL;
-                               }
-                               mr = (MPT_FRAME_HDR *) CAST_U32_TO_PTR(pa);
-                       } else {
-                               req_idx = pa & 0x0000FFFF;
-                               cb_idx = (pa & 0x00FF0000) >> 16;
-                               mf = MPT_INDEX_2_MFPTR(ioc, req_idx);
-                               mr = NULL;
-                       }
-                       pa = 0;                                 /* No reply flush! */
-               }
-
-#ifdef MPT_DEBUG_IRQ
-               if (ioc->bus_type == SCSI) {
-                       /* Verify mf, mr are reasonable.
-                        */
-                       if ((mf) && ((mf >= MPT_INDEX_2_MFPTR(ioc, ioc->req_depth))
-                               || (mf < ioc->req_frames)) ) {
-                               printk(MYIOC_s_WARN_FMT
-                                       "mpt_interrupt: Invalid mf (%p)!\n", ioc->name, (void *)mf);
-                               cb_idx = 0;
-                               pa = 0;
-                               freeme = 0;
-                       }
-                       if ((pa) && (mr) && ((mr >= MPT_INDEX_2_RFPTR(ioc, ioc->req_depth))
-                               || (mr < ioc->reply_frames)) ) {
-                               printk(MYIOC_s_WARN_FMT
-                                       "mpt_interrupt: Invalid rf (%p)!\n", ioc->name, (void *)mr);
-                               cb_idx = 0;
-                               pa = 0;
-                               freeme = 0;
-                       }
-                       if (cb_idx > (MPT_MAX_PROTOCOL_DRIVERS-1)) {
-                               printk(MYIOC_s_WARN_FMT
-                                       "mpt_interrupt: Invalid cb_idx (%d)!\n", ioc->name, cb_idx);
-                               cb_idx = 0;
-                               pa = 0;
-                               freeme = 0;
-                       }
-               }
-#endif
-
-               /*  Check for (valid) IO callback!  */
-               if (cb_idx) {
-                       /*  Do the callback!  */
-                       freeme = (*(MptCallbacks[cb_idx]))(ioc, mf, mr);
-               }
-
-               if (pa) {
-                       /*  Flush (non-TURBO) reply with a WRITE!  */
-                       CHIPREG_WRITE32(&ioc->chip->ReplyFifo, pa);
-               }
-
-               if (freeme) {
-                       /*  Put Request back on FreeQ!  */
-                       mpt_free_msg_frame(ioc, mf);
-               }
-
-               mb();
-       }       /* drain reply FIFO */
+               else if (pa & MPI_ADDRESS_REPLY_A_BIT)
+                       mpt_reply(ioc, pa);
+               else
+                       mpt_turbo_reply(ioc, pa);
+       }
 
        return IRQ_HANDLED;
 }
@@ -509,6 +507,14 @@ mpt_base_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *reply)
                        pCfg->wait_done = 1;
                        wake_up(&mpt_waitq);
                }
+       } else if (func == MPI_FUNCTION_SAS_IO_UNIT_CONTROL) {
+               /* we should be always getting a reply frame */
+               memcpy(ioc->persist_reply_frame, reply,
+                   min(MPT_DEFAULT_FRAME_SIZE,
+                   4*reply->u.reply.MsgLength));
+               del_timer(&ioc->persist_timer);
+               ioc->persist_wait_done = 1;
+               wake_up(&mpt_waitq);
        } else {
                printk(MYIOC_s_ERR_FMT "Unexpected msg function (=%02Xh) reply received!\n",
                                ioc->name, func);
@@ -750,6 +756,7 @@ mpt_get_msg_frame(int handle, MPT_ADAPTER *ioc)
                mf = list_entry(ioc->FreeQ.next, MPT_FRAME_HDR,
                                u.frame.linkage.list);
                list_del(&mf->u.frame.linkage.list);
+               mf->u.frame.linkage.arg1 = 0;
                mf->u.frame.hwhdr.msgctxu.fld.cb_idx = handle;  /* byte */
                req_offset = (u8 *)mf - (u8 *)ioc->req_frames;
                                                                /* u16! */
@@ -845,6 +852,7 @@ mpt_free_msg_frame(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf)
 
        /*  Put Request back on FreeQ!  */
        spin_lock_irqsave(&ioc->FreeQlock, flags);
+       mf->u.frame.linkage.arg1 = 0xdeadbeaf; /* signature to know if this mf is freed */
        list_add_tail(&mf->u.frame.linkage.list, &ioc->FreeQ);
 #ifdef MFCNT
        ioc->mfcnt--;
@@ -971,10 +979,121 @@ mpt_send_handshake_request(int handle, MPT_ADAPTER *ioc, int reqBytes, u32 *req,
 
        /* Make sure there are no doorbells */
        CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
-       
+
        return r;
 }
 
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/**
+ * mpt_host_page_access_control - provides mechanism for the host
+ * driver to control the IOC's Host Page Buffer access.
+ * @ioc: Pointer to MPT adapter structure
+ * @access_control_value: define bits below
+ *
+ * Access Control Value - bits[15:12]
+ * 0h Reserved
+ * 1h Enable Access { MPI_DB_HPBAC_ENABLE_ACCESS }
+ * 2h Disable Access { MPI_DB_HPBAC_DISABLE_ACCESS }
+ * 3h Free Buffer { MPI_DB_HPBAC_FREE_BUFFER }
+ *
+ * Returns 0 for success, non-zero for failure.
+ */
+
+static int
+mpt_host_page_access_control(MPT_ADAPTER *ioc, u8 access_control_value, int sleepFlag)
+{
+       int      r = 0;
+
+       /* return if in use */
+       if (CHIPREG_READ32(&ioc->chip->Doorbell)
+           & MPI_DOORBELL_ACTIVE)
+           return -1;
+
+       CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
+
+       CHIPREG_WRITE32(&ioc->chip->Doorbell,
+               ((MPI_FUNCTION_HOST_PAGEBUF_ACCESS_CONTROL
+                <<MPI_DOORBELL_FUNCTION_SHIFT) |
+                (access_control_value<<12)));
+
+       /* Wait for IOC to clear Doorbell Status bit */
+       if ((r = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0) {
+               return -2;
+       }else
+               return 0;
+}
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/**
+ *     mpt_host_page_alloc - allocate system memory for the fw
+ *     If we already allocated memory in past, then resend the same pointer.
+ *     ioc@: Pointer to pointer to IOC adapter
+ *     ioc_init@: Pointer to ioc init config page
+ *
+ *     Returns 0 for success, non-zero for failure.
+ */
+static int
+mpt_host_page_alloc(MPT_ADAPTER *ioc, pIOCInit_t ioc_init)
+{
+       char    *psge;
+       int     flags_length;
+       u32     host_page_buffer_sz=0;
+
+       if(!ioc->HostPageBuffer) {
+
+               host_page_buffer_sz =
+                   le32_to_cpu(ioc->facts.HostPageBufferSGE.FlagsLength) & 0xFFFFFF;
+
+               if(!host_page_buffer_sz)
+                       return 0; /* fw doesn't need any host buffers */
+
+               /* spin till we get enough memory */
+               while(host_page_buffer_sz > 0) {
+
+                       if((ioc->HostPageBuffer = pci_alloc_consistent(
+                           ioc->pcidev,
+                           host_page_buffer_sz,
+                           &ioc->HostPageBuffer_dma)) != NULL) {
+
+                               dinitprintk((MYIOC_s_INFO_FMT
+                                   "host_page_buffer @ %p, dma @ %x, sz=%d bytes\n",
+                                   ioc->name,
+                                   ioc->HostPageBuffer,
+                                   ioc->HostPageBuffer_dma,
+                                   host_page_buffer_sz));
+                               ioc->alloc_total += host_page_buffer_sz;
+                               ioc->HostPageBuffer_sz = host_page_buffer_sz;
+                               break;
+                       }
+
+                       host_page_buffer_sz -= (4*1024);
+               }
+       }
+
+       if(!ioc->HostPageBuffer) {
+               printk(MYIOC_s_ERR_FMT
+                   "Failed to alloc memory for host_page_buffer!\n",
+                   ioc->name);
+               return -999;
+       }
+
+       psge = (char *)&ioc_init->HostPageBufferSGE;
+       flags_length = MPI_SGE_FLAGS_SIMPLE_ELEMENT |
+           MPI_SGE_FLAGS_SYSTEM_ADDRESS |
+           MPI_SGE_FLAGS_32_BIT_ADDRESSING |
+           MPI_SGE_FLAGS_HOST_TO_IOC |
+           MPI_SGE_FLAGS_END_OF_BUFFER;
+       if (sizeof(dma_addr_t) == sizeof(u64)) {
+           flags_length |= MPI_SGE_FLAGS_64_BIT_ADDRESSING;
+       }
+       flags_length = flags_length << MPI_SGE_FLAGS_SHIFT;
+       flags_length |= ioc->HostPageBuffer_sz;
+       mpt_add_sge(psge, flags_length, ioc->HostPageBuffer_dma);
+       ioc->facts.HostPageBufferSGE = ioc_init->HostPageBufferSGE;
+
+return 0;
+}
+
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /**
  *     mpt_verify_adapter - Given a unique IOC identifier, set pointer to
@@ -1084,7 +1203,7 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id)
 
        /* Initilize SCSI Config Data structure
         */
-       memset(&ioc->spi_data, 0, sizeof(ScsiCfgData));
+       memset(&ioc->spi_data, 0, sizeof(SpiCfgData));
 
        /* Initialize the running configQ head.
         */
@@ -1213,6 +1332,33 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id)
                ioc->prod_name = "LSI53C1035";
                ioc->bus_type = SCSI;
        }
+       else if (pdev->device == MPI_MANUFACTPAGE_DEVID_SAS1064) {
+               ioc->prod_name = "LSISAS1064";
+               ioc->bus_type = SAS;
+               ioc->errata_flag_1064 = 1;
+       }
+       else if (pdev->device == MPI_MANUFACTPAGE_DEVID_SAS1066) {
+               ioc->prod_name = "LSISAS1066";
+               ioc->bus_type = SAS;
+               ioc->errata_flag_1064 = 1;
+       }
+       else if (pdev->device == MPI_MANUFACTPAGE_DEVID_SAS1068) {
+               ioc->prod_name = "LSISAS1068";
+               ioc->bus_type = SAS;
+               ioc->errata_flag_1064 = 1;
+       }
+       else if (pdev->device == MPI_MANUFACTPAGE_DEVID_SAS1064E) {
+               ioc->prod_name = "LSISAS1064E";
+               ioc->bus_type = SAS;
+       }
+       else if (pdev->device == MPI_MANUFACTPAGE_DEVID_SAS1066E) {
+               ioc->prod_name = "LSISAS1066E";
+               ioc->bus_type = SAS;
+       }
+       else if (pdev->device == MPI_MANUFACTPAGE_DEVID_SAS1068E) {
+               ioc->prod_name = "LSISAS1068E";
+               ioc->bus_type = SAS;
+       }
 
        if (ioc->errata_flag_1064)
                pci_disable_io_access(pdev);
@@ -1604,8 +1750,23 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag)
                         */
                        if (ret == 0) {
                                rc = mpt_do_upload(ioc, sleepFlag);
-                               if (rc != 0)
+                               if (rc == 0) {
+                                       if (ioc->alt_ioc && ioc->alt_ioc->cached_fw) {
+                                               /*
+                                                * Maintain only one pointer to FW memory
+                                                * so there will not be two attempt to
+                                                * downloadboot onboard dual function
+                                                * chips (mpt_adapter_disable,
+                                                * mpt_diag_reset)
+                                                */
+                                               ioc->cached_fw = NULL;
+                                               ddlprintk((MYIOC_s_INFO_FMT ": mpt_upload:  alt_%s has cached_fw=%p \n",
+                                                       ioc->name, ioc->alt_ioc->name, ioc->alt_ioc->cached_fw));
+                                       }
+                               } else {
                                        printk(KERN_WARNING MYNAM ": firmware upload failure!\n");
+                                       ret = -5;
+                               }
                        }
                }
        }
@@ -1640,7 +1801,22 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag)
         *      and we try GetLanConfigPages again...
         */
        if ((ret == 0) && (reason == MPT_HOSTEVENT_IOC_BRINGUP)) {
-               if (ioc->bus_type == FC) {
+               if (ioc->bus_type == SAS) {
+
+                       /* clear persistency table */
+                       if(ioc->facts.IOCExceptions &
+                           MPI_IOCFACTS_EXCEPT_PERSISTENT_TABLE_FULL) {
+                               ret = mptbase_sas_persist_operation(ioc,
+                                   MPI_SAS_OP_CLEAR_NOT_PRESENT);
+                               if(ret != 0)
+                                       return -1;
+                       }
+
+                       /* Find IM volumes
+                        */
+                       mpt_findImVolumes(ioc);
+
+               } else if (ioc->bus_type == FC) {
                        /*
                         *  Pre-fetch FC port WWN and stuff...
                         *  (FCPortPage0_t stuff)
@@ -1783,7 +1959,7 @@ mpt_adapter_disable(MPT_ADAPTER *ioc)
 
        if (ioc->cached_fw != NULL) {
                ddlprintk((KERN_INFO MYNAM ": mpt_adapter_disable: Pushing FW onto adapter\n"));
-               if ((ret = mpt_downloadboot(ioc, NO_SLEEP)) < 0) {
+               if ((ret = mpt_downloadboot(ioc, (MpiFwHeader_t *)ioc->cached_fw, NO_SLEEP)) < 0) {
                        printk(KERN_WARNING MYNAM
                                ": firmware downloadboot failure (%d)!\n", ret);
                }
@@ -1831,9 +2007,9 @@ mpt_adapter_disable(MPT_ADAPTER *ioc)
        }
 
        kfree(ioc->spi_data.nvram);
-       kfree(ioc->spi_data.pIocPg3);
+       kfree(ioc->raid_data.pIocPg3);
        ioc->spi_data.nvram = NULL;
-       ioc->spi_data.pIocPg3 = NULL;
+       ioc->raid_data.pIocPg3 = NULL;
 
        if (ioc->spi_data.pIocPg4 != NULL) {
                sz = ioc->spi_data.IocPg4Sz;
@@ -1852,6 +2028,23 @@ mpt_adapter_disable(MPT_ADAPTER *ioc)
 
        kfree(ioc->ChainToChain);
        ioc->ChainToChain = NULL;
+
+       if (ioc->HostPageBuffer != NULL) {
+               if((ret = mpt_host_page_access_control(ioc,
+                   MPI_DB_HPBAC_FREE_BUFFER, NO_SLEEP)) != 0) {
+                       printk(KERN_ERR MYNAM
+                          ": %s: host page buffers free failed (%d)!\n",
+                           __FUNCTION__, ret);
+               }
+               dexitprintk((KERN_INFO MYNAM ": %s HostPageBuffer free  @ %p, sz=%d bytes\n",
+                       ioc->name, ioc->HostPageBuffer, ioc->HostPageBuffer_sz));
+               pci_free_consistent(ioc->pcidev, ioc->HostPageBuffer_sz,
+                               ioc->HostPageBuffer,
+                               ioc->HostPageBuffer_dma);
+               ioc->HostPageBuffer = NULL;
+               ioc->HostPageBuffer_sz = 0;
+               ioc->alloc_total -= ioc->HostPageBuffer_sz;
+       }
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
@@ -2034,7 +2227,7 @@ MakeIocReady(MPT_ADAPTER *ioc, int force, int sleepFlag)
         *  Loop here waiting for IOC to come READY.
         */
        ii = 0;
-       cntdn = ((sleepFlag == CAN_SLEEP) ? HZ : 1000) * 15;    /* 15 seconds */
+       cntdn = ((sleepFlag == CAN_SLEEP) ? HZ : 1000) * 5;     /* 5 seconds */
 
        while ((ioc_state = mpt_GetIocState(ioc, 1)) != MPI_IOC_STATE_READY) {
                if (ioc_state == MPI_IOC_STATE_OPERATIONAL) {
@@ -2212,6 +2405,7 @@ GetIocFacts(MPT_ADAPTER *ioc, int sleepFlag, int reason)
                                le32_to_cpu(facts->CurrentSenseBufferHighAddr);
                facts->CurReplyFrameSize =
                                le16_to_cpu(facts->CurReplyFrameSize);
+               facts->IOCCapabilities = le32_to_cpu(facts->IOCCapabilities);
 
                /*
                 * Handle NEW (!) IOCFactsReply fields in MPI-1.01.xx
@@ -2383,13 +2577,25 @@ SendIocInit(MPT_ADAPTER *ioc, int sleepFlag)
        ddlprintk((MYIOC_s_INFO_FMT "upload_fw %d facts.Flags=%x\n",
                   ioc->name, ioc->upload_fw, ioc->facts.Flags));
 
-       if (ioc->bus_type == FC)
+       if(ioc->bus_type == SAS)
+               ioc_init.MaxDevices = ioc->facts.MaxDevices;
+       else if(ioc->bus_type == FC)
                ioc_init.MaxDevices = MPT_MAX_FC_DEVICES;
        else
                ioc_init.MaxDevices = MPT_MAX_SCSI_DEVICES;
-       
        ioc_init.MaxBuses = MPT_MAX_BUS;
-
+       dinitprintk((MYIOC_s_INFO_FMT "facts.MsgVersion=%x\n",
+                  ioc->name, ioc->facts.MsgVersion));
+       if (ioc->facts.MsgVersion >= MPI_VERSION_01_05) {
+               // set MsgVersion and HeaderVersion host driver was built with
+               ioc_init.MsgVersion = cpu_to_le16(MPI_VERSION);
+               ioc_init.HeaderVersion = cpu_to_le16(MPI_HEADER_VERSION);
+
+               if (ioc->facts.Flags & MPI_IOCFACTS_FLAGS_HOST_PAGE_BUFFER_PERSISTENT) {
+                       ioc_init.HostPageBufferSGE = ioc->facts.HostPageBufferSGE;
+               } else if(mpt_host_page_alloc(ioc, &ioc_init))
+                       return -99;
+       }
        ioc_init.ReplyFrameSize = cpu_to_le16(ioc->reply_sz);   /* in BYTES */
 
        if (sizeof(dma_addr_t) == sizeof(u64)) {
@@ -2403,17 +2609,21 @@ SendIocInit(MPT_ADAPTER *ioc, int sleepFlag)
                ioc_init.HostMfaHighAddr = cpu_to_le32(0);
                ioc_init.SenseBufferHighAddr = cpu_to_le32(0);
        }
-               
+
        ioc->facts.CurrentHostMfaHighAddr = ioc_init.HostMfaHighAddr;
        ioc->facts.CurrentSenseBufferHighAddr = ioc_init.SenseBufferHighAddr;
+       ioc->facts.MaxDevices = ioc_init.MaxDevices;
+       ioc->facts.MaxBuses = ioc_init.MaxBuses;
 
        dhsprintk((MYIOC_s_INFO_FMT "Sending IOCInit (req @ %p)\n",
                        ioc->name, &ioc_init));
 
        r = mpt_handshake_req_reply_wait(ioc, sizeof(IOCInit_t), (u32*)&ioc_init,
                                sizeof(MPIDefaultReply_t), (u16*)&init_reply, 10 /*seconds*/, sleepFlag);
-       if (r != 0)
+       if (r != 0) {
+               printk(MYIOC_s_ERR_FMT "Sending IOCInit failed(%d)!\n",ioc->name, r);
                return r;
+       }
 
        /* No need to byte swap the multibyte fields in the reply
         * since we don't even look at it's contents.
@@ -2472,7 +2682,7 @@ SendPortEnable(MPT_ADAPTER *ioc, int portnum, int sleepFlag)
 {
        PortEnable_t             port_enable;
        MPIDefaultReply_t        reply_buf;
-       int      ii;
+       int      rc;
        int      req_sz;
        int      reply_sz;
 
@@ -2494,22 +2704,15 @@ SendPortEnable(MPT_ADAPTER *ioc, int portnum, int sleepFlag)
 
        /* RAID FW may take a long time to enable
         */
-       if (ioc->bus_type == FC) {
-               ii = mpt_handshake_req_reply_wait(ioc, req_sz, (u32*)&port_enable,
-                               reply_sz, (u16*)&reply_buf, 65 /*seconds*/, sleepFlag);
-       } else {
-               ii = mpt_handshake_req_reply_wait(ioc, req_sz, (u32*)&port_enable,
+       if ( (ioc->facts.ProductID & MPI_FW_HEADER_PID_PROD_MASK)
+                       > MPI_FW_HEADER_PID_PROD_TARGET_SCSI ) {
+               rc = mpt_handshake_req_reply_wait(ioc, req_sz, (u32*)&port_enable,
                                reply_sz, (u16*)&reply_buf, 300 /*seconds*/, sleepFlag);
+       } else {
+               rc = mpt_handshake_req_reply_wait(ioc, req_sz, (u32*)&port_enable,
+                               reply_sz, (u16*)&reply_buf, 30 /*seconds*/, sleepFlag);
        }
-
-       if (ii != 0)
-               return ii;
-
-       /* We do not even look at the reply, so we need not
-        * swap the multi-byte fields.
-        */
-
-       return 0;
+       return rc;
 }
 
 /*
@@ -2666,9 +2869,8 @@ mpt_do_upload(MPT_ADAPTER *ioc, int sleepFlag)
  *             <0 for fw upload failure.
  */
 static int
-mpt_downloadboot(MPT_ADAPTER *ioc, int sleepFlag)
+mpt_downloadboot(MPT_ADAPTER *ioc, MpiFwHeader_t *pFwHeader, int sleepFlag)
 {
-       MpiFwHeader_t           *pFwHeader;
        MpiExtImageHeader_t     *pExtImage;
        u32                      fwSize;
        u32                      diag0val;
@@ -2679,18 +2881,8 @@ mpt_downloadboot(MPT_ADAPTER *ioc, int sleepFlag)
        u32                      load_addr;
        u32                      ioc_state=0;
 
-       ddlprintk((MYIOC_s_INFO_FMT "downloadboot: fw size 0x%x, ioc FW Ptr %p\n",
-                               ioc->name, ioc->facts.FWImageSize, ioc->cached_fw));
-
-       if ( ioc->facts.FWImageSize == 0 )
-               return -1;
-
-       if (ioc->cached_fw == NULL)
-               return -2;
-
-       /* prevent a second downloadboot and memory free with alt_ioc */
-       if (ioc->alt_ioc && ioc->alt_ioc->cached_fw)
-               ioc->alt_ioc->cached_fw = NULL;
+       ddlprintk((MYIOC_s_INFO_FMT "downloadboot: fw size 0x%x (%d), FW Ptr %p\n",
+                               ioc->name, pFwHeader->ImageSize, pFwHeader->ImageSize, pFwHeader));
 
        CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF);
        CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_1ST_KEY_VALUE);
@@ -2718,16 +2910,17 @@ mpt_downloadboot(MPT_ADAPTER *ioc, int sleepFlag)
                                ioc->name, count));
                        break;
                }
-               /* wait 1 sec */
+               /* wait .1 sec */
                if (sleepFlag == CAN_SLEEP) {
-                       msleep_interruptible (1000);
+                       msleep_interruptible (100);
                } else {
-                       mdelay (1000);
+                       mdelay (100);
                }
        }
 
        if ( count == 30 ) {
-               ddlprintk((MYIOC_s_INFO_FMT "downloadboot failed! Unable to RESET_ADAPTER diag0val=%x\n",
+               ddlprintk((MYIOC_s_INFO_FMT "downloadboot failed! "
+               "Unable to get MPI_DIAG_DRWE mode, diag0val=%x\n",
                ioc->name, diag0val));
                return -3;
        }
@@ -2742,7 +2935,6 @@ mpt_downloadboot(MPT_ADAPTER *ioc, int sleepFlag)
        /* Set the DiagRwEn and Disable ARM bits */
        CHIPREG_WRITE32(&ioc->chip->Diagnostic, (MPI_DIAG_RW_ENABLE | MPI_DIAG_DISABLE_ARM));
 
-       pFwHeader = (MpiFwHeader_t *) ioc->cached_fw;
        fwSize = (pFwHeader->ImageSize + 3)/4;
        ptrFw = (u32 *) pFwHeader;
 
@@ -2792,19 +2984,38 @@ mpt_downloadboot(MPT_ADAPTER *ioc, int sleepFlag)
        /* Clear the internal flash bad bit - autoincrementing register,
         * so must do two writes.
         */
-       CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, 0x3F000000);
-       diagRwData = CHIPREG_PIO_READ32(&ioc->pio_chip->DiagRwData);
-       diagRwData |= 0x4000000;
-       CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, 0x3F000000);
-       CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, diagRwData);
+       if (ioc->bus_type == SCSI) {
+               /*
+                * 1030 and 1035 H/W errata, workaround to access
+                * the ClearFlashBadSignatureBit
+                */
+               CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, 0x3F000000);
+               diagRwData = CHIPREG_PIO_READ32(&ioc->pio_chip->DiagRwData);
+               diagRwData |= 0x40000000;
+               CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, 0x3F000000);
+               CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, diagRwData);
+
+       } else /* if((ioc->bus_type == SAS) || (ioc->bus_type == FC)) */ {
+               diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
+               CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val |
+                   MPI_DIAG_CLEAR_FLASH_BAD_SIG);
+
+               /* wait 1 msec */
+               if (sleepFlag == CAN_SLEEP) {
+                       msleep_interruptible (1);
+               } else {
+                       mdelay (1);
+               }
+       }
 
        if (ioc->errata_flag_1064)
                pci_disable_io_access(ioc->pcidev);
 
        diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
-       ddlprintk((MYIOC_s_INFO_FMT "downloadboot diag0val=%x, turning off PREVENT_IOC_BOOT, DISABLE_ARM\n",
+       ddlprintk((MYIOC_s_INFO_FMT "downloadboot diag0val=%x, "
+               "turning off PREVENT_IOC_BOOT, DISABLE_ARM, RW_ENABLE\n",
                ioc->name, diag0val));
-       diag0val &= ~(MPI_DIAG_PREVENT_IOC_BOOT | MPI_DIAG_DISABLE_ARM);
+       diag0val &= ~(MPI_DIAG_PREVENT_IOC_BOOT | MPI_DIAG_DISABLE_ARM | MPI_DIAG_RW_ENABLE);
        ddlprintk((MYIOC_s_INFO_FMT "downloadboot now diag0val=%x\n",
                ioc->name, diag0val));
        CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val);
@@ -2812,10 +3023,23 @@ mpt_downloadboot(MPT_ADAPTER *ioc, int sleepFlag)
        /* Write 0xFF to reset the sequencer */
        CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF);
 
+       if (ioc->bus_type == SAS) {
+               ioc_state = mpt_GetIocState(ioc, 0);
+               if ( (GetIocFacts(ioc, sleepFlag,
+                               MPT_HOSTEVENT_IOC_BRINGUP)) != 0 ) {
+                       ddlprintk((MYIOC_s_INFO_FMT "GetIocFacts failed: IocState=%x\n",
+                                       ioc->name, ioc_state));
+                       return -EFAULT;
+               }
+       }
+
        for (count=0; count<HZ*20; count++) {
                if ((ioc_state = mpt_GetIocState(ioc, 0)) & MPI_IOC_STATE_READY) {
                        ddlprintk((MYIOC_s_INFO_FMT "downloadboot successful! (count=%d) IocState=%x\n",
                                        ioc->name, count, ioc_state));
+                       if (ioc->bus_type == SAS) {
+                               return 0;
+                       }
                        if ((SendIocInit(ioc, sleepFlag)) != 0) {
                                ddlprintk((MYIOC_s_INFO_FMT "downloadboot: SendIocInit failed\n",
                                        ioc->name));
@@ -3049,12 +3273,13 @@ mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag)
 
                                /* wait 1 sec */
                                if (sleepFlag == CAN_SLEEP) {
-                                       ssleep(1);
+                                       msleep_interruptible (1000);
                                } else {
                                        mdelay (1000);
                                }
                        }
-                       if ((count = mpt_downloadboot(ioc, sleepFlag)) < 0) {
+                       if ((count = mpt_downloadboot(ioc,
+                               (MpiFwHeader_t *)ioc->cached_fw, sleepFlag)) < 0) {
                                printk(KERN_WARNING MYNAM
                                        ": firmware downloadboot failure (%d)!\n", count);
                        }
@@ -3637,7 +3862,7 @@ WaitForDoorbellAck(MPT_ADAPTER *ioc, int howlong, int sleepFlag)
        int count = 0;
        u32 intstat=0;
 
-       cntdn = ((sleepFlag == CAN_SLEEP) ? HZ : 1000) * howlong;
+       cntdn = 1000 * howlong;
 
        if (sleepFlag == CAN_SLEEP) {
                while (--cntdn) {
@@ -3687,7 +3912,7 @@ WaitForDoorbellInt(MPT_ADAPTER *ioc, int howlong, int sleepFlag)
        int count = 0;
        u32 intstat=0;
 
-       cntdn = ((sleepFlag == CAN_SLEEP) ? HZ : 1000) * howlong;
+       cntdn = 1000 * howlong;
        if (sleepFlag == CAN_SLEEP) {
                while (--cntdn) {
                        intstat = CHIPREG_READ32(&ioc->chip->IntStatus);
@@ -3999,6 +4224,85 @@ GetFcPortPage0(MPT_ADAPTER *ioc, int portnum)
        return rc;
 }
 
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/*
+ *     mptbase_sas_persist_operation - Perform operation on SAS Persitent Table
+ *     @ioc: Pointer to MPT_ADAPTER structure
+ *     @sas_address: 64bit SAS Address for operation.
+ *     @target_id: specified target for operation
+ *     @bus: specified bus for operation
+ *     @persist_opcode: see below
+ *
+ *     MPI_SAS_OP_CLEAR_NOT_PRESENT - Free all persist TargetID mappings for
+ *             devices not currently present.
+ *     MPI_SAS_OP_CLEAR_ALL_PERSISTENT - Clear al persist TargetID mappings
+ *
+ *     NOTE: Don't use not this function during interrupt time.
+ *
+ *     Returns: 0 for success, non-zero error
+ */
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+int
+mptbase_sas_persist_operation(MPT_ADAPTER *ioc, u8 persist_opcode)
+{
+       SasIoUnitControlRequest_t       *sasIoUnitCntrReq;
+       SasIoUnitControlReply_t         *sasIoUnitCntrReply;
+       MPT_FRAME_HDR                   *mf = NULL;
+       MPIHeader_t                     *mpi_hdr;
+
+
+       /* insure garbage is not sent to fw */
+       switch(persist_opcode) {
+
+       case MPI_SAS_OP_CLEAR_NOT_PRESENT:
+       case MPI_SAS_OP_CLEAR_ALL_PERSISTENT:
+               break;
+
+       default:
+               return -1;
+               break;
+       }
+
+       printk("%s: persist_opcode=%x\n",__FUNCTION__, persist_opcode);
+
+       /* Get a MF for this command.
+        */
+       if ((mf = mpt_get_msg_frame(mpt_base_index, ioc)) == NULL) {
+               printk("%s: no msg frames!\n",__FUNCTION__);
+               return -1;
+        }
+
+       mpi_hdr = (MPIHeader_t *) mf;
+       sasIoUnitCntrReq = (SasIoUnitControlRequest_t *)mf;
+       memset(sasIoUnitCntrReq,0,sizeof(SasIoUnitControlRequest_t));
+       sasIoUnitCntrReq->Function = MPI_FUNCTION_SAS_IO_UNIT_CONTROL;
+       sasIoUnitCntrReq->MsgContext = mpi_hdr->MsgContext;
+       sasIoUnitCntrReq->Operation = persist_opcode;
+
+       init_timer(&ioc->persist_timer);
+       ioc->persist_timer.data = (unsigned long) ioc;
+       ioc->persist_timer.function = mpt_timer_expired;
+       ioc->persist_timer.expires = jiffies + HZ*10 /* 10 sec */;
+       ioc->persist_wait_done=0;
+       add_timer(&ioc->persist_timer);
+       mpt_put_msg_frame(mpt_base_index, ioc, mf);
+       wait_event(mpt_waitq, ioc->persist_wait_done);
+
+       sasIoUnitCntrReply =
+           (SasIoUnitControlReply_t *)ioc->persist_reply_frame;
+       if (le16_to_cpu(sasIoUnitCntrReply->IOCStatus) != MPI_IOCSTATUS_SUCCESS) {
+               printk("%s: IOCStatus=0x%X IOCLogInfo=0x%X\n",
+                   __FUNCTION__,
+                   sasIoUnitCntrReply->IOCStatus,
+                   sasIoUnitCntrReply->IOCLogInfo);
+               return -1;
+       }
+
+       printk("%s: success\n",__FUNCTION__);
+       return 0;
+}
+
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /*
  *     GetIoUnitPage2 - Retrieve BIOS version and boot order information.
@@ -4340,10 +4644,10 @@ mpt_findImVolumes(MPT_ADAPTER *ioc)
        if (mpt_config(ioc, &cfg) != 0)
                goto done_and_free;
 
-       if ( (mem = (u8 *)ioc->spi_data.pIocPg2) == NULL ) {
+       if ( (mem = (u8 *)ioc->raid_data.pIocPg2) == NULL ) {
                mem = kmalloc(iocpage2sz, GFP_ATOMIC);
                if (mem) {
-                       ioc->spi_data.pIocPg2 = (IOCPage2_t *) mem;
+                       ioc->raid_data.pIocPg2 = (IOCPage2_t *) mem;
                } else {
                        goto done_and_free;
                }
@@ -4360,7 +4664,7 @@ mpt_findImVolumes(MPT_ADAPTER *ioc)
                /* At least 1 RAID Volume
                 */
                pIocRv = pIoc2->RaidVolume;
-               ioc->spi_data.isRaid = 0;
+               ioc->raid_data.isRaid = 0;
                for (jj = 0; jj < nVols; jj++, pIocRv++) {
                        vid = pIocRv->VolumeID;
                        vbus = pIocRv->VolumeBus;
@@ -4369,7 +4673,7 @@ mpt_findImVolumes(MPT_ADAPTER *ioc)
                        /* find the match
                         */
                        if (vbus == 0) {
-                               ioc->spi_data.isRaid |= (1 << vid);
+                               ioc->raid_data.isRaid |= (1 << vid);
                        } else {
                                /* Error! Always bus 0
                                 */
@@ -4404,8 +4708,8 @@ mpt_read_ioc_pg_3(MPT_ADAPTER *ioc)
 
        /* Free the old page
         */
-       kfree(ioc->spi_data.pIocPg3);
-       ioc->spi_data.pIocPg3 = NULL;
+       kfree(ioc->raid_data.pIocPg3);
+       ioc->raid_data.pIocPg3 = NULL;
 
        /* There is at least one physical disk.
         * Read and save IOC Page 3
@@ -4442,7 +4746,7 @@ mpt_read_ioc_pg_3(MPT_ADAPTER *ioc)
                mem = kmalloc(iocpage3sz, GFP_ATOMIC);
                if (mem) {
                        memcpy(mem, (u8 *)pIoc3, iocpage3sz);
-                       ioc->spi_data.pIocPg3 = (IOCPage3_t *) mem;
+                       ioc->raid_data.pIocPg3 = (IOCPage3_t *) mem;
                }
        }
 
@@ -5366,8 +5670,8 @@ mpt_HardResetHandler(MPT_ADAPTER *ioc, int sleepFlag)
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-static char *
-EventDescriptionStr(u8 event, u32 evData0)
+static void
+EventDescriptionStr(u8 event, u32 evData0, char *evStr)
 {
        char *ds;
 
@@ -5420,8 +5724,95 @@ EventDescriptionStr(u8 event, u32 evData0)
                        ds = "Events(OFF) Change";
                break;
        case MPI_EVENT_INTEGRATED_RAID:
-               ds = "Integrated Raid";
+       {
+               u8 ReasonCode = (u8)(evData0 >> 16);
+               switch (ReasonCode) {
+               case MPI_EVENT_RAID_RC_VOLUME_CREATED :
+                       ds = "Integrated Raid: Volume Created";
+                       break;
+               case MPI_EVENT_RAID_RC_VOLUME_DELETED :
+                       ds = "Integrated Raid: Volume Deleted";
+                       break;
+               case MPI_EVENT_RAID_RC_VOLUME_SETTINGS_CHANGED :
+                       ds = "Integrated Raid: Volume Settings Changed";
+                       break;
+               case MPI_EVENT_RAID_RC_VOLUME_STATUS_CHANGED :
+                       ds = "Integrated Raid: Volume Status Changed";
+                       break;
+               case MPI_EVENT_RAID_RC_VOLUME_PHYSDISK_CHANGED :
+                       ds = "Integrated Raid: Volume Physdisk Changed";
+                       break;
+               case MPI_EVENT_RAID_RC_PHYSDISK_CREATED :
+                       ds = "Integrated Raid: Physdisk Created";
+                       break;
+               case MPI_EVENT_RAID_RC_PHYSDISK_DELETED :
+                       ds = "Integrated Raid: Physdisk Deleted";
+                       break;
+               case MPI_EVENT_RAID_RC_PHYSDISK_SETTINGS_CHANGED :
+                       ds = "Integrated Raid: Physdisk Settings Changed";
+                       break;
+               case MPI_EVENT_RAID_RC_PHYSDISK_STATUS_CHANGED :
+                       ds = "Integrated Raid: Physdisk Status Changed";
+                       break;
+               case MPI_EVENT_RAID_RC_DOMAIN_VAL_NEEDED :
+                       ds = "Integrated Raid: Domain Validation Needed";
+                       break;
+               case MPI_EVENT_RAID_RC_SMART_DATA :
+                       ds = "Integrated Raid; Smart Data";
+                       break;
+               case MPI_EVENT_RAID_RC_REPLACE_ACTION_STARTED :
+                       ds = "Integrated Raid: Replace Action Started";
+                       break;
+               default:
+                       ds = "Integrated Raid";
+               break;
+               }
+               break;
+       }
+       case MPI_EVENT_SCSI_DEVICE_STATUS_CHANGE:
+               ds = "SCSI Device Status Change";
+               break;
+       case MPI_EVENT_SAS_DEVICE_STATUS_CHANGE:
+       {
+               u8 ReasonCode = (u8)(evData0 >> 16);
+               switch (ReasonCode) {
+               case MPI_EVENT_SAS_DEV_STAT_RC_ADDED:
+                       ds = "SAS Device Status Change: Added";
+                       break;
+               case MPI_EVENT_SAS_DEV_STAT_RC_NOT_RESPONDING:
+                       ds = "SAS Device Status Change: Deleted";
+                       break;
+               case MPI_EVENT_SAS_DEV_STAT_RC_SMART_DATA:
+                       ds = "SAS Device Status Change: SMART Data";
+                       break;
+               case MPI_EVENT_SAS_DEV_STAT_RC_NO_PERSIST_ADDED:
+                       ds = "SAS Device Status Change: No Persistancy Added";
+                       break;
+               default:
+                       ds = "SAS Device Status Change: Unknown";
+               break;
+               }
+               break;
+       }
+       case MPI_EVENT_ON_BUS_TIMER_EXPIRED:
+               ds = "Bus Timer Expired";
+               break;
+       case MPI_EVENT_QUEUE_FULL:
+               ds = "Queue Full";
+               break;
+       case MPI_EVENT_SAS_SES:
+               ds = "SAS SES Event";
+               break;
+       case MPI_EVENT_PERSISTENT_TABLE_FULL:
+               ds = "Persistent Table Full";
+               break;
+       case MPI_EVENT_SAS_PHY_LINK_STATUS:
+               ds = "SAS PHY Link Status";
+               break;
+       case MPI_EVENT_SAS_DISCOVERY_ERROR:
+               ds = "SAS Discovery Error";
                break;
+
        /*
         *  MPT base "custom" events may be added here...
         */
@@ -5429,7 +5820,7 @@ EventDescriptionStr(u8 event, u32 evData0)
                ds = "Unknown";
                break;
        }
-       return ds;
+       strcpy(evStr,ds);
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
@@ -5451,7 +5842,7 @@ ProcessEventNotification(MPT_ADAPTER *ioc, EventNotificationReply_t *pEventReply
        int ii;
        int r = 0;
        int handlers = 0;
-       char *evStr;
+       char evStr[100];
        u8 event;
 
        /*
@@ -5464,7 +5855,7 @@ ProcessEventNotification(MPT_ADAPTER *ioc, EventNotificationReply_t *pEventReply
                evData0 = le32_to_cpu(pEventReply->Data[0]);
        }
 
-       evStr = EventDescriptionStr(event, evData0);
+       EventDescriptionStr(event, evData0, evStr);
        devtprintk((MYIOC_s_INFO_FMT "MPT event (%s=%02Xh) detected!\n",
                        ioc->name,
                        evStr,
@@ -5481,20 +5872,6 @@ ProcessEventNotification(MPT_ADAPTER *ioc, EventNotificationReply_t *pEventReply
         *  Do general / base driver event processing
         */
        switch(event) {
-       case MPI_EVENT_NONE:                    /* 00 */
-       case MPI_EVENT_LOG_DATA:                /* 01 */
-       case MPI_EVENT_STATE_CHANGE:            /* 02 */
-       case MPI_EVENT_UNIT_ATTENTION:          /* 03 */
-       case MPI_EVENT_IOC_BUS_RESET:           /* 04 */
-       case MPI_EVENT_EXT_BUS_RESET:           /* 05 */
-       case MPI_EVENT_RESCAN:                  /* 06 */
-       case MPI_EVENT_LINK_STATUS_CHANGE:      /* 07 */
-       case MPI_EVENT_LOOP_STATE_CHANGE:       /* 08 */
-       case MPI_EVENT_LOGOUT:                  /* 09 */
-       case MPI_EVENT_INTEGRATED_RAID:         /* 0B */
-       case MPI_EVENT_SCSI_DEVICE_STATUS_CHANGE:       /* 0C */
-       default:
-               break;
        case MPI_EVENT_EVENT_CHANGE:            /* 0A */
                if (evDataLen) {
                        u8 evState = evData0 & 0xFF;
@@ -5507,6 +5884,8 @@ ProcessEventNotification(MPT_ADAPTER *ioc, EventNotificationReply_t *pEventReply
                        }
                }
                break;
+       default:
+               break;
        }
 
        /*
@@ -5653,6 +6032,111 @@ mpt_sp_log_info(MPT_ADAPTER *ioc, u32 log_info)
        printk(MYIOC_s_INFO_FMT "LogInfo(0x%08x): F/W: %s\n", ioc->name, log_info, desc);
 }
 
+/* strings for sas loginfo */
+       static char *originator_str[] = {
+               "IOP",                                          /* 00h */
+               "PL",                                           /* 01h */
+               "IR"                                            /* 02h */
+       };
+       static char *iop_code_str[] = {
+               NULL,                                           /* 00h */
+               "Invalid SAS Address",                          /* 01h */
+               NULL,                                           /* 02h */
+               "Invalid Page",                                 /* 03h */
+               NULL,                                           /* 04h */
+               "Task Terminated"                               /* 05h */
+       };
+       static char *pl_code_str[] = {
+               NULL,                                           /* 00h */
+               "Open Failure",                                 /* 01h */
+               "Invalid Scatter Gather List",                  /* 02h */
+               "Wrong Relative Offset or Frame Length",        /* 03h */
+               "Frame Transfer Error",                         /* 04h */
+               "Transmit Frame Connected Low",                 /* 05h */
+               "SATA Non-NCQ RW Error Bit Set",                /* 06h */
+               "SATA Read Log Receive Data Error",             /* 07h */
+               "SATA NCQ Fail All Commands After Error",       /* 08h */
+               "SATA Error in Receive Set Device Bit FIS",     /* 09h */
+               "Receive Frame Invalid Message",                /* 0Ah */
+               "Receive Context Message Valid Error",          /* 0Bh */
+               "Receive Frame Current Frame Error",            /* 0Ch */
+               "SATA Link Down",                               /* 0Dh */
+               "Discovery SATA Init W IOS",                    /* 0Eh */
+               "Config Invalid Page",                          /* 0Fh */
+               "Discovery SATA Init Timeout",                  /* 10h */
+               "Reset",                                        /* 11h */
+               "Abort",                                        /* 12h */
+               "IO Not Yet Executed",                          /* 13h */
+               "IO Executed",                                  /* 14h */
+               NULL,                                           /* 15h */
+               NULL,                                           /* 16h */
+               NULL,                                           /* 17h */
+               NULL,                                           /* 18h */
+               NULL,                                           /* 19h */
+               NULL,                                           /* 1Ah */
+               NULL,                                           /* 1Bh */
+               NULL,                                           /* 1Ch */
+               NULL,                                           /* 1Dh */
+               NULL,                                           /* 1Eh */
+               NULL,                                           /* 1Fh */
+               "Enclosure Management"                          /* 20h */
+       };
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/*
+ *     mpt_sas_log_info - Log information returned from SAS IOC.
+ *     @ioc: Pointer to MPT_ADAPTER structure
+ *     @log_info: U32 LogInfo reply word from the IOC
+ *
+ *     Refer to lsi/mpi_log_sas.h.
+ */
+static void
+mpt_sas_log_info(MPT_ADAPTER *ioc, u32 log_info)
+{
+union loginfo_type {
+       u32     loginfo;
+       struct {
+               u32     subcode:16;
+               u32     code:8;
+               u32     originator:4;
+               u32     bus_type:4;
+       }dw;
+};
+       union loginfo_type sas_loginfo;
+       char *code_desc = NULL;
+
+       sas_loginfo.loginfo = log_info;
+       if ((sas_loginfo.dw.bus_type != 3 /*SAS*/) &&
+           (sas_loginfo.dw.originator < sizeof(originator_str)/sizeof(char*)))
+               return;
+       if ((sas_loginfo.dw.originator == 0 /*IOP*/) &&
+           (sas_loginfo.dw.code < sizeof(iop_code_str)/sizeof(char*))) {
+               code_desc = iop_code_str[sas_loginfo.dw.code];
+       }else if ((sas_loginfo.dw.originator == 1 /*PL*/) &&
+           (sas_loginfo.dw.code < sizeof(pl_code_str)/sizeof(char*) )) {
+               code_desc = pl_code_str[sas_loginfo.dw.code];
+       }
+
+       if (code_desc != NULL)
+               printk(MYIOC_s_INFO_FMT
+                       "LogInfo(0x%08x): Originator={%s}, Code={%s},"
+                       " SubCode(0x%04x)\n",
+                       ioc->name,
+                       log_info,
+                       originator_str[sas_loginfo.dw.originator],
+                       code_desc,
+                       sas_loginfo.dw.subcode);
+       else
+               printk(MYIOC_s_INFO_FMT
+                       "LogInfo(0x%08x): Originator={%s}, Code=(0x%02x),"
+                       " SubCode(0x%04x)\n",
+                       ioc->name,
+                       log_info,
+                       originator_str[sas_loginfo.dw.originator],
+                       sas_loginfo.dw.code,
+                       sas_loginfo.dw.subcode);
+}
+
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /*
  *     mpt_sp_ioc_info - IOC information returned from SCSI Parallel IOC.
@@ -5814,6 +6298,7 @@ EXPORT_SYMBOL(mpt_findImVolumes);
 EXPORT_SYMBOL(mpt_read_ioc_pg_3);
 EXPORT_SYMBOL(mpt_alloc_fw_memory);
 EXPORT_SYMBOL(mpt_free_fw_memory);
+EXPORT_SYMBOL(mptbase_sas_persist_operation);
 
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
index f4827d92373119987376a1d2387189872c6d0a93..75105277e22f1606113a73c160775e3ec9444e88 100644 (file)
@@ -65,6 +65,7 @@
 #include "lsi/mpi_fc.h"                /* Fibre Channel (lowlevel) support */
 #include "lsi/mpi_targ.h"      /* SCSI/FCP Target protcol support */
 #include "lsi/mpi_tool.h"      /* Tools support */
+#include "lsi/mpi_sas.h"       /* SAS support */
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 
@@ -76,8 +77,8 @@
 #define COPYRIGHT      "Copyright (c) 1999-2005 " MODULEAUTHOR
 #endif
 
-#define MPT_LINUX_VERSION_COMMON       "3.03.02"
-#define MPT_LINUX_PACKAGE_NAME         "@(#)mptlinux-3.03.02"
+#define MPT_LINUX_VERSION_COMMON       "3.03.03"
+#define MPT_LINUX_PACKAGE_NAME         "@(#)mptlinux-3.03.03"
 #define WHAT_MAGIC_STRING              "@" "(" "#" ")"
 
 #define show_mptmod_ver(s,ver)  \
@@ -423,7 +424,7 @@ typedef struct _MPT_IOCTL {
 /*
  *  Event Structure and define
  */
-#define MPTCTL_EVENT_LOG_SIZE          (0x0000000A)
+#define MPTCTL_EVENT_LOG_SIZE          (0x000000032)
 typedef struct _mpt_ioctl_events {
        u32     event;          /* Specified by define above */
        u32     eventContext;   /* Index or counter */
@@ -451,16 +452,13 @@ typedef struct _mpt_ioctl_events {
 #define MPT_SCSICFG_ALL_IDS            0x02    /* WriteSDP1 to all IDS */
 /* #define MPT_SCSICFG_BLK_NEGO                0x10       WriteSDP1 with WDTR and SDTR disabled */
 
-typedef        struct _ScsiCfgData {
+typedef        struct _SpiCfgData {
        u32              PortFlags;
        int             *nvram;                 /* table of device NVRAM values */
-       IOCPage2_t      *pIocPg2;               /* table of Raid Volumes */
-       IOCPage3_t      *pIocPg3;               /* table of physical disks */
        IOCPage4_t      *pIocPg4;               /* SEP devices addressing */
        dma_addr_t       IocPg4_dma;            /* Phys Addr of IOCPage4 data */
        int              IocPg4Sz;              /* IOCPage4 size */
        u8               dvStatus[MPT_MAX_SCSI_DEVICES];
-       int              isRaid;                /* bit field, 1 if RAID */
        u8               minSyncFactor;         /* 0xFF if async */
        u8               maxSyncOffset;         /* 0 if async */
        u8               maxBusWidth;           /* 0 if narrow, 1 if wide */
@@ -472,10 +470,28 @@ typedef   struct _ScsiCfgData {
        u8               dvScheduled;           /* 1 if scheduled */
        u8               forceDv;               /* 1 to force DV scheduling */
        u8               noQas;                 /* Disable QAS for this adapter */
-       u8               Saf_Te;                /* 1 to force all Processors as SAF-TE if Inquiry data length is too short to check for SAF-TE */
+       u8               Saf_Te;                /* 1 to force all Processors as
+                                                * SAF-TE if Inquiry data length
+                                                * is too short to check for SAF-TE
+                                                */
        u8               mpt_dv;                /* command line option: enhanced=1, basic=0 */
+       u8               bus_reset;             /* 1 to allow bus reset */
        u8               rsvd[1];
-} ScsiCfgData;
+}SpiCfgData;
+
+typedef        struct _SasCfgData {
+       u8               ptClear;               /* 1 to automatically clear the
+                                                * persistent table.
+                                                * 0 to disable
+                                                * automatic clearing.
+                                                */
+}SasCfgData;
+
+typedef        struct _RaidCfgData {
+       IOCPage2_t      *pIocPg2;               /* table of Raid Volumes */
+       IOCPage3_t      *pIocPg3;               /* table of physical disks */
+       int              isRaid;                /* bit field, 1 if RAID */
+}RaidCfgData;
 
 /*
  *  Adapter Structure - pci_dev specific. Maximum: MPT_MAX_ADAPTERS
@@ -530,11 +546,16 @@ typedef struct _MPT_ADAPTER
        u8                      *sense_buf_pool;
        dma_addr_t               sense_buf_pool_dma;
        u32                      sense_buf_low_dma;
+       u8                      *HostPageBuffer; /* SAS - host page buffer support */
+       u32                     HostPageBuffer_sz;
+       dma_addr_t              HostPageBuffer_dma;
        int                      mtrr_reg;
        struct pci_dev          *pcidev;        /* struct pci_dev pointer */
        u8                      __iomem *memmap;        /* mmap address */
        struct Scsi_Host        *sh;            /* Scsi Host pointer */
-       ScsiCfgData             spi_data;       /* Scsi config. data */
+       SpiCfgData              spi_data;       /* Scsi config. data */
+       RaidCfgData             raid_data;      /* Raid config. data */
+       SasCfgData              sas_data;       /* Sas config. data */
        MPT_IOCTL               *ioctl;         /* ioctl data pointer */
        struct proc_dir_entry   *ioc_dentry;
        struct _MPT_ADAPTER     *alt_ioc;       /* ptr to 929 bound adapter port */
@@ -554,31 +575,35 @@ typedef struct _MPT_ADAPTER
 #else
        u32                      mfcnt;
 #endif
-       u32                      NB_for_64_byte_frame;       
+       u32                      NB_for_64_byte_frame;
        u32                      hs_req[MPT_MAX_FRAME_SIZE/sizeof(u32)];
        u16                      hs_reply[MPT_MAX_FRAME_SIZE/sizeof(u16)];
        IOCFactsReply_t          facts;
        PortFactsReply_t         pfacts[2];
        FCPortPage0_t            fc_port_page0[2];
+       struct timer_list        persist_timer; /* persist table timer */
+       int                      persist_wait_done; /* persist completion flag */
+       u8                       persist_reply_frame[MPT_DEFAULT_FRAME_SIZE]; /* persist reply */
        LANPage0_t               lan_cnfg_page0;
        LANPage1_t               lan_cnfg_page1;
-       /*  
+       /*
         * Description: errata_flag_1064
         * If a PCIX read occurs within 1 or 2 cycles after the chip receives
         * a split completion for a read data, an internal address pointer incorrectly
         * increments by 32 bytes
         */
-       int                      errata_flag_1064;      
+       int                      errata_flag_1064;
        u8                       FirstWhoInit;
        u8                       upload_fw;     /* If set, do a fw upload */
        u8                       reload_fw;     /* Force a FW Reload on next reset */
-       u8                       NBShiftFactor;  /* NB Shift Factor based on Block Size (Facts)  */     
+       u8                       NBShiftFactor;  /* NB Shift Factor based on Block Size (Facts)  */
        u8                       pad1[4];
        int                      DoneCtx;
        int                      TaskCtx;
        int                      InternalCtx;
-       struct list_head         list; 
+       struct list_head         list;
        struct net_device       *netdev;
+       struct list_head         sas_topology;
 } MPT_ADAPTER;
 
 /*
@@ -964,6 +989,7 @@ extern void  mpt_alloc_fw_memory(MPT_ADAPTER *ioc, int size);
 extern void     mpt_free_fw_memory(MPT_ADAPTER *ioc);
 extern int      mpt_findImVolumes(MPT_ADAPTER *ioc);
 extern int      mpt_read_ioc_pg_3(MPT_ADAPTER *ioc);
+extern int      mptbase_sas_persist_operation(MPT_ADAPTER *ioc, u8 persist_opcode);
 
 /*
  *  Public data decl's...
index 7577c2417e2e124ca9109640a86cbe7fc4e9ddf7..cb2d59d5f5af76e395a8714bbe2e4e831557cfae 100644 (file)
@@ -1326,7 +1326,7 @@ mptctl_gettargetinfo (unsigned long arg)
                 */
                if (hd && hd->Targets) {
                        mpt_findImVolumes(ioc);
-                       pIoc2 = ioc->spi_data.pIocPg2;
+                       pIoc2 = ioc->raid_data.pIocPg2;
                        for ( id = 0; id <= max_id; ) {
                                if ( pIoc2 && pIoc2->NumActiveVolumes ) {
                                        if ( id == pIoc2->RaidVolume[0].VolumeID ) {
@@ -1348,7 +1348,7 @@ mptctl_gettargetinfo (unsigned long arg)
                                                --maxWordsLeft;
                                                goto next_id;
                                        } else {
-                                               pIoc3 = ioc->spi_data.pIocPg3;
+                                               pIoc3 = ioc->raid_data.pIocPg3;
                                                for ( jj = 0; jj < pIoc3->NumPhysDisks; jj++ ) {
                                                        if ( pIoc3->PhysDisk[jj].PhysDiskID == id )
                                                                goto next_id;
index 13771abea13f28f075bab7e338f787221bcbc9fd..a628be9bbbadd0070326e5af78f9dadfb2f6934a 100644 (file)
@@ -189,7 +189,7 @@ mptfc_probe(struct pci_dev *pdev, const struct pci_device_id *id)
                printk(MYIOC_s_WARN_FMT
                        "Skipping ioc=%p because SCSI Initiator mode is NOT enabled!\n",
                        ioc->name, ioc);
-               return -ENODEV;
+               return 0;
        }
 
        sh = scsi_host_alloc(&mptfc_driver_template, sizeof(MPT_SCSI_HOST));
index 52794be5a95c87a1b0d7f1d5b937e85266bbe97e..ed3c891e388f9ee3c73184dc0b445202bb208ab8 100644 (file)
@@ -312,7 +312,12 @@ static int
 mpt_lan_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
 {
        struct net_device *dev = ioc->netdev;
-       struct mpt_lan_priv *priv = netdev_priv(dev);
+       struct mpt_lan_priv *priv;
+
+       if (dev == NULL)
+               return(1);
+       else
+               priv = netdev_priv(dev);
 
        dlprintk((KERN_INFO MYNAM ": IOC %s_reset routed to LAN driver!\n",
                        reset_phase==MPT_IOC_SETUP_RESET ? "setup" : (
diff --git a/drivers/message/fusion/mptsas.c b/drivers/message/fusion/mptsas.c
new file mode 100644 (file)
index 0000000..429820e
--- /dev/null
@@ -0,0 +1,1235 @@
+/*
+ *  linux/drivers/message/fusion/mptsas.c
+ *      For use with LSI Logic PCI chip/adapter(s)
+ *      running LSI Logic Fusion MPT (Message Passing Technology) firmware.
+ *
+ *  Copyright (c) 1999-2005 LSI Logic Corporation
+ *  (mailto:mpt_linux_developer@lsil.com)
+ *  Copyright (c) 2005 Dell
+ */
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/*
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; version 2 of the License.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    NO WARRANTY
+    THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
+    CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
+    LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
+    MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
+    solely responsible for determining the appropriateness of using and
+    distributing the Program and assumes all risks associated with its
+    exercise of rights under this Agreement, including but not limited to
+    the risks and costs of program errors, damage to or loss of data,
+    programs or equipment, and unavailability or interruption of operations.
+
+    DISCLAIMER OF LIABILITY
+    NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
+    DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+    DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), 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 OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
+    HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/workqueue.h>
+
+#include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_device.h>
+#include <scsi/scsi_host.h>
+#include <scsi/scsi_transport_sas.h>
+
+#include "mptbase.h"
+#include "mptscsih.h"
+
+
+#define my_NAME                "Fusion MPT SAS Host driver"
+#define my_VERSION     MPT_LINUX_VERSION_COMMON
+#define MYNAM          "mptsas"
+
+MODULE_AUTHOR(MODULEAUTHOR);
+MODULE_DESCRIPTION(my_NAME);
+MODULE_LICENSE("GPL");
+
+static int mpt_pq_filter;
+module_param(mpt_pq_filter, int, 0);
+MODULE_PARM_DESC(mpt_pq_filter,
+               "Enable peripheral qualifier filter: enable=1  "
+               "(default=0)");
+
+static int mpt_pt_clear;
+module_param(mpt_pt_clear, int, 0);
+MODULE_PARM_DESC(mpt_pt_clear,
+               "Clear persistency table: enable=1  "
+               "(default=MPTSCSIH_PT_CLEAR=0)");
+
+static int     mptsasDoneCtx = -1;
+static int     mptsasTaskCtx = -1;
+static int     mptsasInternalCtx = -1; /* Used only for internal commands */
+
+
+/*
+ * SAS topology structures
+ *
+ * The MPT Fusion firmware interface spreads information about the
+ * SAS topology over many manufacture pages, thus we need some data
+ * structure to collect it and process it for the SAS transport class.
+ */
+
+struct mptsas_devinfo {
+       u16     handle;         /* unique id to address this device */
+       u8      phy_id;         /* phy number of parent device */
+       u8      port_id;        /* sas physical port this device
+                                  is assoc'd with */
+       u8      target;         /* logical target id of this device */
+       u8      bus;            /* logical bus number of this device */
+       u64     sas_address;    /* WWN of this device,
+                                  SATA is assigned by HBA,expander */
+       u32     device_info;    /* bitfield detailed info about this device */
+};
+
+struct mptsas_phyinfo {
+       u8      phy_id;                 /* phy index */
+       u8      port_id;                /* port number this phy is part of */
+       u8      negotiated_link_rate;   /* nego'd link rate for this phy */
+       u8      hw_link_rate;           /* hardware max/min phys link rate */
+       u8      programmed_link_rate;   /* programmed max/min phy link rate */
+       struct mptsas_devinfo identify; /* point to phy device info */
+       struct mptsas_devinfo attached; /* point to attached device info */
+       struct sas_rphy *rphy;
+};
+
+struct mptsas_portinfo {
+       struct list_head list;
+       u16             handle;         /* unique id to address this */
+       u8              num_phys;       /* number of phys */
+       struct mptsas_phyinfo *phy_info;
+};
+
+/*
+ * This is pretty ugly.  We will be able to seriously clean it up
+ * once the DV code in mptscsih goes away and we can properly
+ * implement ->target_alloc.
+ */
+static int
+mptsas_slave_alloc(struct scsi_device *device)
+{
+       struct Scsi_Host        *host = device->host;
+       MPT_SCSI_HOST           *hd = (MPT_SCSI_HOST *)host->hostdata;
+       struct sas_rphy         *rphy;
+       struct mptsas_portinfo  *p;
+       VirtDevice              *vdev;
+       uint                    target = device->id;
+       int i;
+
+       if ((vdev = hd->Targets[target]) != NULL)
+               goto out;
+
+       vdev = kmalloc(sizeof(VirtDevice), GFP_KERNEL);
+       if (!vdev) {
+               printk(MYIOC_s_ERR_FMT "slave_alloc kmalloc(%zd) FAILED!\n",
+                               hd->ioc->name, sizeof(VirtDevice));
+               return -ENOMEM;
+       }
+
+       memset(vdev, 0, sizeof(VirtDevice));
+       vdev->tflags = MPT_TARGET_FLAGS_Q_YES|MPT_TARGET_FLAGS_VALID_INQUIRY;
+       vdev->ioc_id = hd->ioc->id;
+
+       rphy = dev_to_rphy(device->sdev_target->dev.parent);
+       list_for_each_entry(p, &hd->ioc->sas_topology, list) {
+               for (i = 0; i < p->num_phys; i++) {
+                       if (p->phy_info[i].attached.sas_address ==
+                                       rphy->identify.sas_address) {
+                               vdev->target_id =
+                                       p->phy_info[i].attached.target;
+                               vdev->bus_id = p->phy_info[i].attached.bus;
+                               hd->Targets[device->id] = vdev;
+                               goto out;
+                       }
+               }
+       }
+
+       printk("No matching SAS device found!!\n");
+       kfree(vdev);
+       return -ENODEV;
+
+ out:
+       vdev->num_luns++;
+       device->hostdata = vdev;
+       return 0;
+}
+
+static struct scsi_host_template mptsas_driver_template = {
+       .proc_name                      = "mptsas",
+       .proc_info                      = mptscsih_proc_info,
+       .name                           = "MPT SPI Host",
+       .info                           = mptscsih_info,
+       .queuecommand                   = mptscsih_qcmd,
+       .slave_alloc                    = mptsas_slave_alloc,
+       .slave_configure                = mptscsih_slave_configure,
+       .slave_destroy                  = mptscsih_slave_destroy,
+       .change_queue_depth             = mptscsih_change_queue_depth,
+       .eh_abort_handler               = mptscsih_abort,
+       .eh_device_reset_handler        = mptscsih_dev_reset,
+       .eh_bus_reset_handler           = mptscsih_bus_reset,
+       .eh_host_reset_handler          = mptscsih_host_reset,
+       .bios_param                     = mptscsih_bios_param,
+       .can_queue                      = MPT_FC_CAN_QUEUE,
+       .this_id                        = -1,
+       .sg_tablesize                   = MPT_SCSI_SG_DEPTH,
+       .max_sectors                    = 8192,
+       .cmd_per_lun                    = 7,
+       .use_clustering                 = ENABLE_CLUSTERING,
+};
+
+static struct sas_function_template mptsas_transport_functions = {
+};
+
+static struct scsi_transport_template *mptsas_transport_template;
+
+#ifdef SASDEBUG
+static void mptsas_print_phy_data(MPI_SAS_IO_UNIT0_PHY_DATA *phy_data)
+{
+       printk("---- IO UNIT PAGE 0 ------------\n");
+       printk("Handle=0x%X\n",
+               le16_to_cpu(phy_data->AttachedDeviceHandle));
+       printk("Controller Handle=0x%X\n",
+               le16_to_cpu(phy_data->ControllerDevHandle));
+       printk("Port=0x%X\n", phy_data->Port);
+       printk("Port Flags=0x%X\n", phy_data->PortFlags);
+       printk("PHY Flags=0x%X\n", phy_data->PhyFlags);
+       printk("Negotiated Link Rate=0x%X\n", phy_data->NegotiatedLinkRate);
+       printk("Controller PHY Device Info=0x%X\n",
+               le32_to_cpu(phy_data->ControllerPhyDeviceInfo));
+       printk("DiscoveryStatus=0x%X\n",
+               le32_to_cpu(phy_data->DiscoveryStatus));
+       printk("\n");
+}
+
+static void mptsas_print_phy_pg0(SasPhyPage0_t *pg0)
+{
+       __le64 sas_address;
+
+       memcpy(&sas_address, &pg0->SASAddress, sizeof(__le64));
+
+       printk("---- SAS PHY PAGE 0 ------------\n");
+       printk("Attached Device Handle=0x%X\n",
+                       le16_to_cpu(pg0->AttachedDevHandle));
+       printk("SAS Address=0x%llX\n",
+                       (unsigned long long)le64_to_cpu(sas_address));
+       printk("Attached PHY Identifier=0x%X\n", pg0->AttachedPhyIdentifier);
+       printk("Attached Device Info=0x%X\n",
+                       le32_to_cpu(pg0->AttachedDeviceInfo));
+       printk("Programmed Link Rate=0x%X\n", pg0->ProgrammedLinkRate);
+       printk("Change Count=0x%X\n", pg0->ChangeCount);
+       printk("PHY Info=0x%X\n", le32_to_cpu(pg0->PhyInfo));
+       printk("\n");
+}
+
+static void mptsas_print_device_pg0(SasDevicePage0_t *pg0)
+{
+       __le64 sas_address;
+
+       memcpy(&sas_address, &pg0->SASAddress, sizeof(__le64));
+
+       printk("---- SAS DEVICE PAGE 0 ---------\n");
+       printk("Handle=0x%X\n" ,le16_to_cpu(pg0->DevHandle));
+       printk("Enclosure Handle=0x%X\n", le16_to_cpu(pg0->EnclosureHandle));
+       printk("Slot=0x%X\n", le16_to_cpu(pg0->Slot));
+       printk("SAS Address=0x%llX\n", le64_to_cpu(sas_address));
+       printk("Target ID=0x%X\n", pg0->TargetID);
+       printk("Bus=0x%X\n", pg0->Bus);
+       printk("PhyNum=0x%X\n", pg0->PhyNum);
+       printk("AccessStatus=0x%X\n", le16_to_cpu(pg0->AccessStatus));
+       printk("Device Info=0x%X\n", le32_to_cpu(pg0->DeviceInfo));
+       printk("Flags=0x%X\n", le16_to_cpu(pg0->Flags));
+       printk("Physical Port=0x%X\n", pg0->PhysicalPort);
+       printk("\n");
+}
+
+static void mptsas_print_expander_pg1(SasExpanderPage1_t *pg1)
+{
+       printk("---- SAS EXPANDER PAGE 1 ------------\n");
+
+       printk("Physical Port=0x%X\n", pg1->PhysicalPort);
+       printk("PHY Identifier=0x%X\n", pg1->Phy);
+       printk("Negotiated Link Rate=0x%X\n", pg1->NegotiatedLinkRate);
+       printk("Programmed Link Rate=0x%X\n", pg1->ProgrammedLinkRate);
+       printk("Hardware Link Rate=0x%X\n", pg1->HwLinkRate);
+       printk("Owner Device Handle=0x%X\n",
+                       le16_to_cpu(pg1->OwnerDevHandle));
+       printk("Attached Device Handle=0x%X\n",
+                       le16_to_cpu(pg1->AttachedDevHandle));
+}
+#else
+#define mptsas_print_phy_data(phy_data)                do { } while (0)
+#define mptsas_print_phy_pg0(pg0)              do { } while (0)
+#define mptsas_print_device_pg0(pg0)           do { } while (0)
+#define mptsas_print_expander_pg1(pg1)         do { } while (0)
+#endif
+
+static int
+mptsas_sas_io_unit_pg0(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info)
+{
+       ConfigExtendedPageHeader_t hdr;
+       CONFIGPARMS cfg;
+       SasIOUnitPage0_t *buffer;
+       dma_addr_t dma_handle;
+       int error, i;
+
+       hdr.PageVersion = MPI_SASIOUNITPAGE0_PAGEVERSION;
+       hdr.ExtPageLength = 0;
+       hdr.PageNumber = 0;
+       hdr.Reserved1 = 0;
+       hdr.Reserved2 = 0;
+       hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
+       hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_IO_UNIT;
+
+       cfg.cfghdr.ehdr = &hdr;
+       cfg.physAddr = -1;
+       cfg.pageAddr = 0;
+       cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
+       cfg.dir = 0;    /* read */
+       cfg.timeout = 10;
+
+       error = mpt_config(ioc, &cfg);
+       if (error)
+               goto out;
+       if (!hdr.ExtPageLength) {
+               error = -ENXIO;
+               goto out;
+       }
+
+       buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
+                                           &dma_handle);
+       if (!buffer) {
+               error = -ENOMEM;
+               goto out;
+       }
+
+       cfg.physAddr = dma_handle;
+       cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
+
+       error = mpt_config(ioc, &cfg);
+       if (error)
+               goto out_free_consistent;
+
+       port_info->num_phys = buffer->NumPhys;
+       port_info->phy_info = kcalloc(port_info->num_phys,
+               sizeof(struct mptsas_phyinfo),GFP_KERNEL);
+       if (!port_info->phy_info) {
+               error = -ENOMEM;
+               goto out_free_consistent;
+       }
+
+       for (i = 0; i < port_info->num_phys; i++) {
+               mptsas_print_phy_data(&buffer->PhyData[i]);
+               port_info->phy_info[i].phy_id = i;
+               port_info->phy_info[i].port_id =
+                   buffer->PhyData[i].Port;
+               port_info->phy_info[i].negotiated_link_rate =
+                   buffer->PhyData[i].NegotiatedLinkRate;
+       }
+
+ out_free_consistent:
+       pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
+                           buffer, dma_handle);
+ out:
+       return error;
+}
+
+static int
+mptsas_sas_phy_pg0(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info,
+               u32 form, u32 form_specific)
+{
+       ConfigExtendedPageHeader_t hdr;
+       CONFIGPARMS cfg;
+       SasPhyPage0_t *buffer;
+       dma_addr_t dma_handle;
+       int error;
+
+       hdr.PageVersion = MPI_SASPHY0_PAGEVERSION;
+       hdr.ExtPageLength = 0;
+       hdr.PageNumber = 0;
+       hdr.Reserved1 = 0;
+       hdr.Reserved2 = 0;
+       hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
+       hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_PHY;
+
+       cfg.cfghdr.ehdr = &hdr;
+       cfg.dir = 0;    /* read */
+       cfg.timeout = 10;
+
+       /* Get Phy Pg 0 for each Phy. */
+       cfg.physAddr = -1;
+       cfg.pageAddr = form + form_specific;
+       cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
+
+       error = mpt_config(ioc, &cfg);
+       if (error)
+               goto out;
+
+       if (!hdr.ExtPageLength) {
+               error = -ENXIO;
+               goto out;
+       }
+
+       buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
+                                     &dma_handle);
+       if (!buffer) {
+               error = -ENOMEM;
+               goto out;
+       }
+
+       cfg.physAddr = dma_handle;
+       cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
+
+       error = mpt_config(ioc, &cfg);
+       if (error)
+               goto out_free_consistent;
+
+       mptsas_print_phy_pg0(buffer);
+
+       phy_info->hw_link_rate = buffer->HwLinkRate;
+       phy_info->programmed_link_rate = buffer->ProgrammedLinkRate;
+       phy_info->identify.handle = le16_to_cpu(buffer->OwnerDevHandle);
+       phy_info->attached.handle = le16_to_cpu(buffer->AttachedDevHandle);
+
+ out_free_consistent:
+       pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
+                           buffer, dma_handle);
+ out:
+       return error;
+}
+
+static int
+mptsas_sas_device_pg0(MPT_ADAPTER *ioc, struct mptsas_devinfo *device_info,
+               u32 form, u32 form_specific)
+{
+       ConfigExtendedPageHeader_t hdr;
+       CONFIGPARMS cfg;
+       SasDevicePage0_t *buffer;
+       dma_addr_t dma_handle;
+       __le64 sas_address;
+       int error;
+
+       hdr.PageVersion = MPI_SASDEVICE0_PAGEVERSION;
+       hdr.ExtPageLength = 0;
+       hdr.PageNumber = 0;
+       hdr.Reserved1 = 0;
+       hdr.Reserved2 = 0;
+       hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
+       hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_DEVICE;
+
+       cfg.cfghdr.ehdr = &hdr;
+       cfg.pageAddr = form + form_specific;
+       cfg.physAddr = -1;
+       cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
+       cfg.dir = 0;    /* read */
+       cfg.timeout = 10;
+
+       error = mpt_config(ioc, &cfg);
+       if (error)
+               goto out;
+       if (!hdr.ExtPageLength) {
+               error = -ENXIO;
+               goto out;
+       }
+
+       buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
+                                     &dma_handle);
+       if (!buffer) {
+               error = -ENOMEM;
+               goto out;
+       }
+
+       cfg.physAddr = dma_handle;
+       cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
+
+       error = mpt_config(ioc, &cfg);
+       if (error)
+               goto out_free_consistent;
+
+       mptsas_print_device_pg0(buffer);
+
+       device_info->handle = le16_to_cpu(buffer->DevHandle);
+       device_info->phy_id = buffer->PhyNum;
+       device_info->port_id = buffer->PhysicalPort;
+       device_info->target = buffer->TargetID;
+       device_info->bus = buffer->Bus;
+       memcpy(&sas_address, &buffer->SASAddress, sizeof(__le64));
+       device_info->sas_address = le64_to_cpu(sas_address);
+       device_info->device_info =
+           le32_to_cpu(buffer->DeviceInfo);
+
+ out_free_consistent:
+       pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
+                           buffer, dma_handle);
+ out:
+       return error;
+}
+
+static int
+mptsas_sas_expander_pg0(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info,
+               u32 form, u32 form_specific)
+{
+       ConfigExtendedPageHeader_t hdr;
+       CONFIGPARMS cfg;
+       SasExpanderPage0_t *buffer;
+       dma_addr_t dma_handle;
+       int error;
+
+       hdr.PageVersion = MPI_SASEXPANDER0_PAGEVERSION;
+       hdr.ExtPageLength = 0;
+       hdr.PageNumber = 0;
+       hdr.Reserved1 = 0;
+       hdr.Reserved2 = 0;
+       hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
+       hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_EXPANDER;
+
+       cfg.cfghdr.ehdr = &hdr;
+       cfg.physAddr = -1;
+       cfg.pageAddr = form + form_specific;
+       cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
+       cfg.dir = 0;    /* read */
+       cfg.timeout = 10;
+
+       error = mpt_config(ioc, &cfg);
+       if (error)
+               goto out;
+
+       if (!hdr.ExtPageLength) {
+               error = -ENXIO;
+               goto out;
+       }
+
+       buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
+                                     &dma_handle);
+       if (!buffer) {
+               error = -ENOMEM;
+               goto out;
+       }
+
+       cfg.physAddr = dma_handle;
+       cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
+
+       error = mpt_config(ioc, &cfg);
+       if (error)
+               goto out_free_consistent;
+
+       /* save config data */
+       port_info->num_phys = buffer->NumPhys;
+       port_info->handle = le16_to_cpu(buffer->DevHandle);
+       port_info->phy_info = kcalloc(port_info->num_phys,
+               sizeof(struct mptsas_phyinfo),GFP_KERNEL);
+       if (!port_info->phy_info) {
+               error = -ENOMEM;
+               goto out_free_consistent;
+       }
+
+ out_free_consistent:
+       pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
+                           buffer, dma_handle);
+ out:
+       return error;
+}
+
+static int
+mptsas_sas_expander_pg1(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info,
+               u32 form, u32 form_specific)
+{
+       ConfigExtendedPageHeader_t hdr;
+       CONFIGPARMS cfg;
+       SasExpanderPage1_t *buffer;
+       dma_addr_t dma_handle;
+       int error;
+
+       hdr.PageVersion = MPI_SASEXPANDER0_PAGEVERSION;
+       hdr.ExtPageLength = 0;
+       hdr.PageNumber = 1;
+       hdr.Reserved1 = 0;
+       hdr.Reserved2 = 0;
+       hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
+       hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_EXPANDER;
+
+       cfg.cfghdr.ehdr = &hdr;
+       cfg.physAddr = -1;
+       cfg.pageAddr = form + form_specific;
+       cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
+       cfg.dir = 0;    /* read */
+       cfg.timeout = 10;
+
+       error = mpt_config(ioc, &cfg);
+       if (error)
+               goto out;
+
+       if (!hdr.ExtPageLength) {
+               error = -ENXIO;
+               goto out;
+       }
+
+       buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
+                                     &dma_handle);
+       if (!buffer) {
+               error = -ENOMEM;
+               goto out;
+       }
+
+       cfg.physAddr = dma_handle;
+       cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
+
+       error = mpt_config(ioc, &cfg);
+       if (error)
+               goto out_free_consistent;
+
+
+       mptsas_print_expander_pg1(buffer);
+
+       /* save config data */
+       phy_info->phy_id = buffer->Phy;
+       phy_info->port_id = buffer->PhysicalPort;
+       phy_info->negotiated_link_rate = buffer->NegotiatedLinkRate;
+       phy_info->programmed_link_rate = buffer->ProgrammedLinkRate;
+       phy_info->hw_link_rate = buffer->HwLinkRate;
+       phy_info->identify.handle = le16_to_cpu(buffer->OwnerDevHandle);
+       phy_info->attached.handle = le16_to_cpu(buffer->AttachedDevHandle);
+
+
+ out_free_consistent:
+       pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
+                           buffer, dma_handle);
+ out:
+       return error;
+}
+
+static void
+mptsas_parse_device_info(struct sas_identify *identify,
+               struct mptsas_devinfo *device_info)
+{
+       u16 protocols;
+
+       identify->sas_address = device_info->sas_address;
+       identify->phy_identifier = device_info->phy_id;
+
+       /*
+        * Fill in Phy Initiator Port Protocol.
+        * Bits 6:3, more than one bit can be set, fall through cases.
+        */
+       protocols = device_info->device_info & 0x78;
+       identify->initiator_port_protocols = 0;
+       if (protocols & MPI_SAS_DEVICE_INFO_SSP_INITIATOR)
+               identify->initiator_port_protocols |= SAS_PROTOCOL_SSP;
+       if (protocols & MPI_SAS_DEVICE_INFO_STP_INITIATOR)
+               identify->initiator_port_protocols |= SAS_PROTOCOL_STP;
+       if (protocols & MPI_SAS_DEVICE_INFO_SMP_INITIATOR)
+               identify->initiator_port_protocols |= SAS_PROTOCOL_SMP;
+       if (protocols & MPI_SAS_DEVICE_INFO_SATA_HOST)
+               identify->initiator_port_protocols |= SAS_PROTOCOL_SATA;
+
+       /*
+        * Fill in Phy Target Port Protocol.
+        * Bits 10:7, more than one bit can be set, fall through cases.
+        */
+       protocols = device_info->device_info & 0x780;
+       identify->target_port_protocols = 0;
+       if (protocols & MPI_SAS_DEVICE_INFO_SSP_TARGET)
+               identify->target_port_protocols |= SAS_PROTOCOL_SSP;
+       if (protocols & MPI_SAS_DEVICE_INFO_STP_TARGET)
+               identify->target_port_protocols |= SAS_PROTOCOL_STP;
+       if (protocols & MPI_SAS_DEVICE_INFO_SMP_TARGET)
+               identify->target_port_protocols |= SAS_PROTOCOL_SMP;
+       if (protocols & MPI_SAS_DEVICE_INFO_SATA_DEVICE)
+               identify->target_port_protocols |= SAS_PROTOCOL_SATA;
+
+       /*
+        * Fill in Attached device type.
+        */
+       switch (device_info->device_info &
+                       MPI_SAS_DEVICE_INFO_MASK_DEVICE_TYPE) {
+       case MPI_SAS_DEVICE_INFO_NO_DEVICE:
+               identify->device_type = SAS_PHY_UNUSED;
+               break;
+       case MPI_SAS_DEVICE_INFO_END_DEVICE:
+               identify->device_type = SAS_END_DEVICE;
+               break;
+       case MPI_SAS_DEVICE_INFO_EDGE_EXPANDER:
+               identify->device_type = SAS_EDGE_EXPANDER_DEVICE;
+               break;
+       case MPI_SAS_DEVICE_INFO_FANOUT_EXPANDER:
+               identify->device_type = SAS_FANOUT_EXPANDER_DEVICE;
+               break;
+       }
+}
+
+static int mptsas_probe_one_phy(struct device *dev,
+               struct mptsas_phyinfo *phy_info, int index)
+{
+       struct sas_phy *port;
+       int error;
+
+       port = sas_phy_alloc(dev, index);
+       if (!port)
+               return -ENOMEM;
+
+       port->port_identifier = phy_info->port_id;
+       mptsas_parse_device_info(&port->identify, &phy_info->identify);
+
+       /*
+        * Set Negotiated link rate.
+        */
+       switch (phy_info->negotiated_link_rate) {
+       case MPI_SAS_IOUNIT0_RATE_PHY_DISABLED:
+               port->negotiated_linkrate = SAS_PHY_DISABLED;
+               break;
+       case MPI_SAS_IOUNIT0_RATE_FAILED_SPEED_NEGOTIATION:
+               port->negotiated_linkrate = SAS_LINK_RATE_FAILED;
+               break;
+       case MPI_SAS_IOUNIT0_RATE_1_5:
+               port->negotiated_linkrate = SAS_LINK_RATE_1_5_GBPS;
+               break;
+       case MPI_SAS_IOUNIT0_RATE_3_0:
+               port->negotiated_linkrate = SAS_LINK_RATE_3_0_GBPS;
+               break;
+       case MPI_SAS_IOUNIT0_RATE_SATA_OOB_COMPLETE:
+       case MPI_SAS_IOUNIT0_RATE_UNKNOWN:
+       default:
+               port->negotiated_linkrate = SAS_LINK_RATE_UNKNOWN;
+               break;
+       }
+
+       /*
+        * Set Max hardware link rate.
+        */
+       switch (phy_info->hw_link_rate & MPI_SAS_PHY0_PRATE_MAX_RATE_MASK) {
+       case MPI_SAS_PHY0_HWRATE_MAX_RATE_1_5:
+               port->maximum_linkrate_hw = SAS_LINK_RATE_1_5_GBPS;
+               break;
+       case MPI_SAS_PHY0_PRATE_MAX_RATE_3_0:
+               port->maximum_linkrate_hw = SAS_LINK_RATE_3_0_GBPS;
+               break;
+       default:
+               break;
+       }
+
+       /*
+        * Set Max programmed link rate.
+        */
+       switch (phy_info->programmed_link_rate &
+                       MPI_SAS_PHY0_PRATE_MAX_RATE_MASK) {
+       case MPI_SAS_PHY0_PRATE_MAX_RATE_1_5:
+               port->maximum_linkrate = SAS_LINK_RATE_1_5_GBPS;
+               break;
+       case MPI_SAS_PHY0_PRATE_MAX_RATE_3_0:
+               port->maximum_linkrate = SAS_LINK_RATE_3_0_GBPS;
+               break;
+       default:
+               break;
+       }
+
+       /*
+        * Set Min hardware link rate.
+        */
+       switch (phy_info->hw_link_rate & MPI_SAS_PHY0_HWRATE_MIN_RATE_MASK) {
+       case MPI_SAS_PHY0_HWRATE_MIN_RATE_1_5:
+               port->minimum_linkrate_hw = SAS_LINK_RATE_1_5_GBPS;
+               break;
+       case MPI_SAS_PHY0_PRATE_MIN_RATE_3_0:
+               port->minimum_linkrate_hw = SAS_LINK_RATE_3_0_GBPS;
+               break;
+       default:
+               break;
+       }
+
+       /*
+        * Set Min programmed link rate.
+        */
+       switch (phy_info->programmed_link_rate &
+                       MPI_SAS_PHY0_PRATE_MIN_RATE_MASK) {
+       case MPI_SAS_PHY0_PRATE_MIN_RATE_1_5:
+               port->minimum_linkrate = SAS_LINK_RATE_1_5_GBPS;
+               break;
+       case MPI_SAS_PHY0_PRATE_MIN_RATE_3_0:
+               port->minimum_linkrate = SAS_LINK_RATE_3_0_GBPS;
+               break;
+       default:
+               break;
+       }
+
+       error = sas_phy_add(port);
+       if (error) {
+               sas_phy_free(port);
+               return error;
+       }
+
+       if (phy_info->attached.handle) {
+               struct sas_rphy *rphy;
+
+               rphy = sas_rphy_alloc(port);
+               if (!rphy)
+                       return 0; /* non-fatal: an rphy can be added later */
+
+               mptsas_parse_device_info(&rphy->identify, &phy_info->attached);
+               error = sas_rphy_add(rphy);
+               if (error) {
+                       sas_rphy_free(rphy);
+                       return error;
+               }
+
+               phy_info->rphy = rphy;
+       }
+
+       return 0;
+}
+
+static int
+mptsas_probe_hba_phys(MPT_ADAPTER *ioc, int *index)
+{
+       struct mptsas_portinfo *port_info;
+       u32 handle = 0xFFFF;
+       int error = -ENOMEM, i;
+
+       port_info = kmalloc(sizeof(*port_info), GFP_KERNEL);
+       if (!port_info)
+               goto out;
+       memset(port_info, 0, sizeof(*port_info));
+
+       error = mptsas_sas_io_unit_pg0(ioc, port_info);
+       if (error)
+               goto out_free_port_info;
+
+       list_add_tail(&port_info->list, &ioc->sas_topology);
+
+       for (i = 0; i < port_info->num_phys; i++) {
+               mptsas_sas_phy_pg0(ioc, &port_info->phy_info[i],
+                       (MPI_SAS_PHY_PGAD_FORM_PHY_NUMBER <<
+                        MPI_SAS_PHY_PGAD_FORM_SHIFT), i);
+
+               mptsas_sas_device_pg0(ioc, &port_info->phy_info[i].identify,
+                       (MPI_SAS_DEVICE_PGAD_FORM_GET_NEXT_HANDLE <<
+                        MPI_SAS_DEVICE_PGAD_FORM_SHIFT), handle);
+               handle = port_info->phy_info[i].identify.handle;
+
+               if (port_info->phy_info[i].attached.handle) {
+                       mptsas_sas_device_pg0(ioc,
+                               &port_info->phy_info[i].attached,
+                               (MPI_SAS_DEVICE_PGAD_FORM_HANDLE <<
+                                MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
+                               port_info->phy_info[i].attached.handle);
+               }
+
+               mptsas_probe_one_phy(&ioc->sh->shost_gendev,
+                                    &port_info->phy_info[i], *index);
+               (*index)++;
+       }
+
+       return 0;
+
+ out_free_port_info:
+       kfree(port_info);
+ out:
+       return error;
+}
+
+static int
+mptsas_probe_expander_phys(MPT_ADAPTER *ioc, u32 *handle, int *index)
+{
+       struct mptsas_portinfo *port_info, *p;
+       int error = -ENOMEM, i, j;
+
+       port_info = kmalloc(sizeof(*port_info), GFP_KERNEL);
+       if (!port_info)
+               goto out;
+       memset(port_info, 0, sizeof(*port_info));
+
+       error = mptsas_sas_expander_pg0(ioc, port_info,
+               (MPI_SAS_EXPAND_PGAD_FORM_GET_NEXT_HANDLE <<
+                MPI_SAS_EXPAND_PGAD_FORM_SHIFT), *handle);
+       if (error)
+               goto out_free_port_info;
+
+       *handle = port_info->handle;
+
+       list_add_tail(&port_info->list, &ioc->sas_topology);
+       for (i = 0; i < port_info->num_phys; i++) {
+               struct device *parent;
+
+               mptsas_sas_expander_pg1(ioc, &port_info->phy_info[i],
+                       (MPI_SAS_EXPAND_PGAD_FORM_HANDLE_PHY_NUM <<
+                        MPI_SAS_EXPAND_PGAD_FORM_SHIFT), (i << 16) + *handle);
+
+               if (port_info->phy_info[i].identify.handle) {
+                       mptsas_sas_device_pg0(ioc,
+                               &port_info->phy_info[i].identify,
+                               (MPI_SAS_DEVICE_PGAD_FORM_HANDLE <<
+                                MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
+                               port_info->phy_info[i].identify.handle);
+               }
+
+               if (port_info->phy_info[i].attached.handle) {
+                       mptsas_sas_device_pg0(ioc,
+                               &port_info->phy_info[i].attached,
+                               (MPI_SAS_DEVICE_PGAD_FORM_HANDLE <<
+                                MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
+                               port_info->phy_info[i].attached.handle);
+               }
+
+               /*
+                * If we find a parent port handle this expander is
+                * attached to another expander, else it hangs of the
+                * HBA phys.
+                */
+               parent = &ioc->sh->shost_gendev;
+               list_for_each_entry(p, &ioc->sas_topology, list) {
+                       for (j = 0; j < p->num_phys; j++) {
+                               if (port_info->phy_info[i].identify.handle ==
+                                               p->phy_info[j].attached.handle)
+                                       parent = &p->phy_info[j].rphy->dev;
+                       }
+               }
+
+               mptsas_probe_one_phy(parent, &port_info->phy_info[i], *index);
+               (*index)++;
+       }
+
+       return 0;
+
+ out_free_port_info:
+       kfree(port_info);
+ out:
+       return error;
+}
+
+static void
+mptsas_scan_sas_topology(MPT_ADAPTER *ioc)
+{
+       u32 handle = 0xFFFF;
+       int index = 0;
+
+       mptsas_probe_hba_phys(ioc, &index);
+       while (!mptsas_probe_expander_phys(ioc, &handle, &index))
+               ;
+}
+
+static int
+mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+{
+       struct Scsi_Host        *sh;
+       MPT_SCSI_HOST           *hd;
+       MPT_ADAPTER             *ioc;
+       unsigned long            flags;
+       int                      sz, ii;
+       int                      numSGE = 0;
+       int                      scale;
+       int                      ioc_cap;
+       u8                      *mem;
+       int                     error=0;
+       int                     r;
+
+       r = mpt_attach(pdev,id);
+       if (r)
+               return r;
+
+       ioc = pci_get_drvdata(pdev);
+       ioc->DoneCtx = mptsasDoneCtx;
+       ioc->TaskCtx = mptsasTaskCtx;
+       ioc->InternalCtx = mptsasInternalCtx;
+
+       /*  Added sanity check on readiness of the MPT adapter.
+        */
+       if (ioc->last_state != MPI_IOC_STATE_OPERATIONAL) {
+               printk(MYIOC_s_WARN_FMT
+                 "Skipping because it's not operational!\n",
+                 ioc->name);
+               return -ENODEV;
+       }
+
+       if (!ioc->active) {
+               printk(MYIOC_s_WARN_FMT "Skipping because it's disabled!\n",
+                 ioc->name);
+               return -ENODEV;
+       }
+
+       /*  Sanity check - ensure at least 1 port is INITIATOR capable
+        */
+       ioc_cap = 0;
+       for (ii = 0; ii < ioc->facts.NumberOfPorts; ii++) {
+               if (ioc->pfacts[ii].ProtocolFlags &
+                               MPI_PORTFACTS_PROTOCOL_INITIATOR)
+                       ioc_cap++;
+       }
+
+       if (!ioc_cap) {
+               printk(MYIOC_s_WARN_FMT
+                       "Skipping ioc=%p because SCSI Initiator mode "
+                       "is NOT enabled!\n", ioc->name, ioc);
+               return 0;
+       }
+
+       sh = scsi_host_alloc(&mptsas_driver_template, sizeof(MPT_SCSI_HOST));
+       if (!sh) {
+               printk(MYIOC_s_WARN_FMT
+                       "Unable to register controller with SCSI subsystem\n",
+                       ioc->name);
+                return -1;
+        }
+
+       spin_lock_irqsave(&ioc->FreeQlock, flags);
+
+       /* Attach the SCSI Host to the IOC structure
+        */
+       ioc->sh = sh;
+
+       sh->io_port = 0;
+       sh->n_io_port = 0;
+       sh->irq = 0;
+
+       /* set 16 byte cdb's */
+       sh->max_cmd_len = 16;
+
+       sh->max_id = ioc->pfacts->MaxDevices + 1;
+
+       sh->transportt = mptsas_transport_template;
+
+       sh->max_lun = MPT_LAST_LUN + 1;
+       sh->max_channel = 0;
+       sh->this_id = ioc->pfacts[0].PortSCSIID;
+
+       /* Required entry.
+        */
+       sh->unique_id = ioc->id;
+
+       INIT_LIST_HEAD(&ioc->sas_topology);
+
+       /* Verify that we won't exceed the maximum
+        * number of chain buffers
+        * We can optimize:  ZZ = req_sz/sizeof(SGE)
+        * For 32bit SGE's:
+        *  numSGE = 1 + (ZZ-1)*(maxChain -1) + ZZ
+        *               + (req_sz - 64)/sizeof(SGE)
+        * A slightly different algorithm is required for
+        * 64bit SGEs.
+        */
+       scale = ioc->req_sz/(sizeof(dma_addr_t) + sizeof(u32));
+       if (sizeof(dma_addr_t) == sizeof(u64)) {
+               numSGE = (scale - 1) *
+                 (ioc->facts.MaxChainDepth-1) + scale +
+                 (ioc->req_sz - 60) / (sizeof(dma_addr_t) +
+                 sizeof(u32));
+       } else {
+               numSGE = 1 + (scale - 1) *
+                 (ioc->facts.MaxChainDepth-1) + scale +
+                 (ioc->req_sz - 64) / (sizeof(dma_addr_t) +
+                 sizeof(u32));
+       }
+
+       if (numSGE < sh->sg_tablesize) {
+               /* Reset this value */
+               dprintk((MYIOC_s_INFO_FMT
+                 "Resetting sg_tablesize to %d from %d\n",
+                 ioc->name, numSGE, sh->sg_tablesize));
+               sh->sg_tablesize = numSGE;
+       }
+
+       spin_unlock_irqrestore(&ioc->FreeQlock, flags);
+
+       hd = (MPT_SCSI_HOST *) sh->hostdata;
+       hd->ioc = ioc;
+
+       /* SCSI needs scsi_cmnd lookup table!
+        * (with size equal to req_depth*PtrSz!)
+        */
+       sz = ioc->req_depth * sizeof(void *);
+       mem = kmalloc(sz, GFP_ATOMIC);
+       if (mem == NULL) {
+               error = -ENOMEM;
+               goto mptsas_probe_failed;
+       }
+
+       memset(mem, 0, sz);
+       hd->ScsiLookup = (struct scsi_cmnd **) mem;
+
+       dprintk((MYIOC_s_INFO_FMT "ScsiLookup @ %p, sz=%d\n",
+                ioc->name, hd->ScsiLookup, sz));
+
+       /* Allocate memory for the device structures.
+        * A non-Null pointer at an offset
+        * indicates a device exists.
+        * max_id = 1 + maximum id (hosts.h)
+        */
+       sz = sh->max_id * sizeof(void *);
+       mem = kmalloc(sz, GFP_ATOMIC);
+       if (mem == NULL) {
+               error = -ENOMEM;
+               goto mptsas_probe_failed;
+       }
+
+       memset(mem, 0, sz);
+       hd->Targets = (VirtDevice **) mem;
+
+       dprintk((KERN_INFO
+         "  Targets @ %p, sz=%d\n", hd->Targets, sz));
+
+       /* Clear the TM flags
+        */
+       hd->tmPending = 0;
+       hd->tmState = TM_STATE_NONE;
+       hd->resetPending = 0;
+       hd->abortSCpnt = NULL;
+
+       /* Clear the pointer used to store
+        * single-threaded commands, i.e., those
+        * issued during a bus scan, dv and
+        * configuration pages.
+        */
+       hd->cmdPtr = NULL;
+
+       /* Initialize this SCSI Hosts' timers
+        * To use, set the timer expires field
+        * and add_timer
+        */
+       init_timer(&hd->timer);
+       hd->timer.data = (unsigned long) hd;
+       hd->timer.function = mptscsih_timer_expired;
+
+       hd->mpt_pq_filter = mpt_pq_filter;
+       ioc->sas_data.ptClear = mpt_pt_clear;
+
+       if (ioc->sas_data.ptClear==1) {
+               mptbase_sas_persist_operation(
+                   ioc, MPI_SAS_OP_CLEAR_ALL_PERSISTENT);
+       }
+
+       ddvprintk((MYIOC_s_INFO_FMT
+               "mpt_pq_filter %x mpt_pq_filter %x\n",
+               ioc->name,
+               mpt_pq_filter,
+               mpt_pq_filter));
+
+       init_waitqueue_head(&hd->scandv_waitq);
+       hd->scandv_wait_done = 0;
+       hd->last_queue_full = 0;
+
+       error = scsi_add_host(sh, &ioc->pcidev->dev);
+       if (error) {
+               dprintk((KERN_ERR MYNAM
+                 "scsi_add_host failed\n"));
+               goto mptsas_probe_failed;
+       }
+
+       mptsas_scan_sas_topology(ioc);
+
+       return 0;
+
+mptsas_probe_failed:
+
+       mptscsih_remove(pdev);
+       return error;
+}
+
+static void __devexit mptsas_remove(struct pci_dev *pdev)
+{
+       MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
+       struct mptsas_portinfo *p, *n;
+
+       sas_remove_host(ioc->sh);
+
+       list_for_each_entry_safe(p, n, &ioc->sas_topology, list) {
+               list_del(&p->list);
+               kfree(p);
+       }
+
+       mptscsih_remove(pdev);
+}
+
+static struct pci_device_id mptsas_pci_table[] = {
+       { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS1064,
+               PCI_ANY_ID, PCI_ANY_ID },
+       { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS1066,
+               PCI_ANY_ID, PCI_ANY_ID },
+       { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS1068,
+               PCI_ANY_ID, PCI_ANY_ID },
+       { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS1064E,
+               PCI_ANY_ID, PCI_ANY_ID },
+       { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS1066E,
+               PCI_ANY_ID, PCI_ANY_ID },
+       { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS1068E,
+               PCI_ANY_ID, PCI_ANY_ID },
+       {0}     /* Terminating entry */
+};
+MODULE_DEVICE_TABLE(pci, mptsas_pci_table);
+
+
+static struct pci_driver mptsas_driver = {
+       .name           = "mptsas",
+       .id_table       = mptsas_pci_table,
+       .probe          = mptsas_probe,
+       .remove         = __devexit_p(mptsas_remove),
+       .shutdown       = mptscsih_shutdown,
+#ifdef CONFIG_PM
+       .suspend        = mptscsih_suspend,
+       .resume         = mptscsih_resume,
+#endif
+};
+
+static int __init
+mptsas_init(void)
+{
+       show_mptmod_ver(my_NAME, my_VERSION);
+
+       mptsas_transport_template =
+           sas_attach_transport(&mptsas_transport_functions);
+       if (!mptsas_transport_template)
+               return -ENODEV;
+
+       mptsasDoneCtx = mpt_register(mptscsih_io_done, MPTSAS_DRIVER);
+       mptsasTaskCtx = mpt_register(mptscsih_taskmgmt_complete, MPTSAS_DRIVER);
+       mptsasInternalCtx =
+               mpt_register(mptscsih_scandv_complete, MPTSAS_DRIVER);
+
+       if (mpt_event_register(mptsasDoneCtx, mptscsih_event_process) == 0) {
+               devtprintk((KERN_INFO MYNAM
+                 ": Registered for IOC event notifications\n"));
+       }
+
+       if (mpt_reset_register(mptsasDoneCtx, mptscsih_ioc_reset) == 0) {
+               dprintk((KERN_INFO MYNAM
+                 ": Registered for IOC reset notifications\n"));
+       }
+
+       return pci_register_driver(&mptsas_driver);
+}
+
+static void __exit
+mptsas_exit(void)
+{
+       pci_unregister_driver(&mptsas_driver);
+       sas_release_transport(mptsas_transport_template);
+
+       mpt_reset_deregister(mptsasDoneCtx);
+       mpt_event_deregister(mptsasDoneCtx);
+
+       mpt_deregister(mptsasInternalCtx);
+       mpt_deregister(mptsasTaskCtx);
+       mpt_deregister(mptsasDoneCtx);
+}
+
+module_init(mptsas_init);
+module_exit(mptsas_exit);
index 4a003dc5fde86084b66cd8316467c3fe1e5f2d57..5cb07eb224d71be05a3c39f6db4fb474ec4bf6a7 100644 (file)
@@ -62,6 +62,7 @@
 #include <scsi/scsi_device.h>
 #include <scsi/scsi_host.h>
 #include <scsi/scsi_tcq.h>
+#include <scsi/scsi_dbg.h>
 
 #include "mptbase.h"
 #include "mptscsih.h"
@@ -93,8 +94,9 @@ typedef struct _BIG_SENSE_BUF {
 
 #define MPT_ICFLAG_BUF_CAP     0x01    /* ReadBuffer Read Capacity format */
 #define MPT_ICFLAG_ECHO                0x02    /* ReadBuffer Echo buffer format */
-#define MPT_ICFLAG_PHYS_DISK   0x04    /* Any SCSI IO but do Phys Disk Format */
-#define MPT_ICFLAG_TAGGED_CMD  0x08    /* Do tagged IO */
+#define MPT_ICFLAG_EBOS                0x04    /* ReadBuffer Echo buffer has EBOS */
+#define MPT_ICFLAG_PHYS_DISK   0x08    /* Any SCSI IO but do Phys Disk Format */
+#define MPT_ICFLAG_TAGGED_CMD  0x10    /* Do tagged IO */
 #define MPT_ICFLAG_DID_RESET   0x20    /* Bus Reset occurred with this command */
 #define MPT_ICFLAG_RESERVED    0x40    /* Reserved has been issued */
 
@@ -159,6 +161,8 @@ int         mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR
 static int     mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *iocmd);
 static int     mptscsih_synchronize_cache(MPT_SCSI_HOST *hd, int portnum);
 
+static struct work_struct   mptscsih_persistTask;
+
 #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
 static int     mptscsih_do_raid(MPT_SCSI_HOST *hd, u8 action, INTERNAL_CMD *io);
 static void    mptscsih_domainValidation(void *hd);
@@ -167,6 +171,7 @@ static void mptscsih_qas_check(MPT_SCSI_HOST *hd, int id);
 static int     mptscsih_doDv(MPT_SCSI_HOST *hd, int channel, int target);
 static void    mptscsih_dv_parms(MPT_SCSI_HOST *hd, DVPARAMETERS *dv,void *pPage);
 static void    mptscsih_fillbuf(char *buffer, int size, int index, int width);
+static void    mptscsih_set_dvflags_raid(MPT_SCSI_HOST *hd, int id);
 #endif
 
 void           mptscsih_remove(struct pci_dev *);
@@ -606,11 +611,24 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
                xfer_cnt = le32_to_cpu(pScsiReply->TransferCount);
                sc->resid = sc->request_bufflen - xfer_cnt;
 
+               /*
+                *  if we get a data underrun indication, yet no data was
+                *  transferred and the SCSI status indicates that the
+                *  command was never started, change the data underrun
+                *  to success
+                */
+               if (status == MPI_IOCSTATUS_SCSI_DATA_UNDERRUN && xfer_cnt == 0 &&
+                   (scsi_status == MPI_SCSI_STATUS_BUSY ||
+                    scsi_status == MPI_SCSI_STATUS_RESERVATION_CONFLICT ||
+                    scsi_status == MPI_SCSI_STATUS_TASK_SET_FULL)) {
+                       status = MPI_IOCSTATUS_SUCCESS;
+               }
+
                dreplyprintk((KERN_NOTICE "Reply ha=%d id=%d lun=%d:\n"
                        "IOCStatus=%04xh SCSIState=%02xh SCSIStatus=%02xh\n"
                        "resid=%d bufflen=%d xfer_cnt=%d\n",
                        ioc->id, pScsiReq->TargetID, pScsiReq->LUN[1],
-                       status, scsi_state, scsi_status, sc->resid, 
+                       status, scsi_state, scsi_status, sc->resid,
                        sc->request_bufflen, xfer_cnt));
 
                if (scsi_state & MPI_SCSI_STATE_AUTOSENSE_VALID)
@@ -619,8 +637,11 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
                /*
                 *  Look for + dump FCP ResponseInfo[]!
                 */
-               if (scsi_state & MPI_SCSI_STATE_RESPONSE_INFO_VALID) {
-                       printk(KERN_NOTICE "  FCP_ResponseInfo=%08xh\n",
+               if (scsi_state & MPI_SCSI_STATE_RESPONSE_INFO_VALID &&
+                   pScsiReply->ResponseInfo) {
+                       printk(KERN_NOTICE "ha=%d id=%d lun=%d: "
+                       "FCP_ResponseInfo=%08xh\n",
+                       ioc->id, pScsiReq->TargetID, pScsiReq->LUN[1],
                        le32_to_cpu(pScsiReply->ResponseInfo));
                }
 
@@ -661,23 +682,13 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
                        break;
 
                case MPI_IOCSTATUS_SCSI_RESIDUAL_MISMATCH:      /* 0x0049 */
-                       if ( xfer_cnt >= sc->underflow ) {
-                               /* Sufficient data transfer occurred */
+                       sc->resid = sc->request_bufflen - xfer_cnt;
+                       if((xfer_cnt==0)||(sc->underflow > xfer_cnt))
+                               sc->result=DID_SOFT_ERROR << 16;
+                       else /* Sufficient data transfer occurred */
                                sc->result = (DID_OK << 16) | scsi_status;
-                       } else if ( xfer_cnt == 0 ) {
-                               /* A CRC Error causes this condition; retry */
-                               sc->result = (DRIVER_SENSE << 24) | (DID_OK << 16) |
-                                       (CHECK_CONDITION << 1);
-                               sc->sense_buffer[0] = 0x70;
-                               sc->sense_buffer[2] = NO_SENSE;
-                               sc->sense_buffer[12] = 0;
-                               sc->sense_buffer[13] = 0;
-                       } else {
-                               sc->result = DID_SOFT_ERROR << 16;
-                       }
-                       dreplyprintk((KERN_NOTICE
-                           "RESIDUAL_MISMATCH: result=%x on id=%d\n",
-                           sc->result, sc->device->id));
+                       dreplyprintk((KERN_NOTICE 
+                           "RESIDUAL_MISMATCH: result=%x on id=%d\n", sc->result, sc->device->id));
                        break;
 
                case MPI_IOCSTATUS_SCSI_DATA_UNDERRUN:          /* 0x0045 */
@@ -692,7 +703,10 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
                                ;
                        } else {
                                if (xfer_cnt < sc->underflow) {
-                                       sc->result = DID_SOFT_ERROR << 16;
+                                       if (scsi_status == SAM_STAT_BUSY)
+                                               sc->result = SAM_STAT_BUSY;
+                                       else
+                                               sc->result = DID_SOFT_ERROR << 16;
                                }
                                if (scsi_state & (MPI_SCSI_STATE_AUTOSENSE_FAILED | MPI_SCSI_STATE_NO_SCSI_STATUS)) {
                                        /* What to do?
@@ -717,8 +731,10 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
 
                case MPI_IOCSTATUS_SCSI_RECOVERED_ERROR:        /* 0x0040 */
                case MPI_IOCSTATUS_SUCCESS:                     /* 0x0000 */
-                       scsi_status = pScsiReply->SCSIStatus;
-                       sc->result = (DID_OK << 16) | scsi_status;
+                       if (scsi_status == MPI_SCSI_STATUS_BUSY)
+                               sc->result = (DID_BUS_BUSY << 16) | scsi_status;
+                       else
+                               sc->result = (DID_OK << 16) | scsi_status;
                        if (scsi_state == 0) {
                                ;
                        } else if (scsi_state & MPI_SCSI_STATE_AUTOSENSE_VALID) {
@@ -890,12 +906,13 @@ mptscsih_search_running_cmds(MPT_SCSI_HOST *hd, uint target, uint lun)
        SCSIIORequest_t *mf = NULL;
        int              ii;
        int              max = hd->ioc->req_depth;
+       struct scsi_cmnd *sc;
 
        dsprintk((KERN_INFO MYNAM ": search_running target %d lun %d max %d\n",
                        target, lun, max));
 
        for (ii=0; ii < max; ii++) {
-               if (hd->ScsiLookup[ii] != NULL) {
+               if ((sc = hd->ScsiLookup[ii]) != NULL) {
 
                        mf = (SCSIIORequest_t *)MPT_INDEX_2_MFPTR(hd->ioc, ii);
 
@@ -910,9 +927,22 @@ mptscsih_search_running_cmds(MPT_SCSI_HOST *hd, uint target, uint lun)
                        hd->ScsiLookup[ii] = NULL;
                        mptscsih_freeChainBuffers(hd->ioc, ii);
                        mpt_free_msg_frame(hd->ioc, (MPT_FRAME_HDR *)mf);
+                       if (sc->use_sg) {
+                               pci_unmap_sg(hd->ioc->pcidev,
+                               (struct scatterlist *) sc->request_buffer,
+                                       sc->use_sg,
+                                       sc->sc_data_direction);
+                       } else if (sc->request_bufflen) {
+                               pci_unmap_single(hd->ioc->pcidev,
+                                       sc->SCp.dma_handle,
+                                       sc->request_bufflen,
+                                       sc->sc_data_direction);
+                       }
+                       sc->host_scribble = NULL;
+                       sc->result = DID_NO_CONNECT << 16;
+                       sc->scsi_done(sc);
                }
        }
-
        return;
 }
 
@@ -967,8 +997,10 @@ mptscsih_remove(struct pci_dev *pdev)
        unsigned long           flags;
        int sz1;
 
-       if(!host)
+       if(!host) {
+               mpt_detach(pdev);
                return;
+       }
 
        scsi_remove_host(host);
 
@@ -1256,8 +1288,7 @@ mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
        MPT_SCSI_HOST           *hd;
        MPT_FRAME_HDR           *mf;
        SCSIIORequest_t         *pScsiReq;
-       VirtDevice              *pTarget;
-       int      target;
+       VirtDevice              *pTarget = SCpnt->device->hostdata;
        int      lun;
        u32      datalen;
        u32      scsictl;
@@ -1267,12 +1298,9 @@ mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
        int      ii;
 
        hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata;
-       target = SCpnt->device->id;
        lun = SCpnt->device->lun;
        SCpnt->scsi_done = done;
 
-       pTarget = hd->Targets[target];
-
        dmfprintk((MYIOC_s_INFO_FMT "qcmd: SCpnt=%p, done()=%p\n",
                        (hd && hd->ioc) ? hd->ioc->name : "ioc?", SCpnt, done));
 
@@ -1315,7 +1343,7 @@ mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
        /* Default to untagged. Once a target structure has been allocated,
         * use the Inquiry data to determine if device supports tagged.
         */
-       if (   pTarget
+       if (pTarget
            && (pTarget->tflags & MPT_TARGET_FLAGS_Q_YES)
            && (SCpnt->device->tagged_supported)) {
                scsictl = scsidir | MPI_SCSIIO_CONTROL_SIMPLEQ;
@@ -1325,8 +1353,8 @@ mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
 
        /* Use the above information to set up the message frame
         */
-       pScsiReq->TargetID = (u8) target;
-       pScsiReq->Bus = (u8) SCpnt->device->channel;
+       pScsiReq->TargetID = (u8) pTarget->target_id;
+       pScsiReq->Bus = pTarget->bus_id;
        pScsiReq->ChainOffset = 0;
        pScsiReq->Function = MPI_FUNCTION_SCSI_IO_REQUEST;
        pScsiReq->CDBLength = SCpnt->cmd_len;
@@ -1378,7 +1406,7 @@ mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
 
 #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
        if (hd->ioc->bus_type == SCSI) {
-               int dvStatus = hd->ioc->spi_data.dvStatus[target];
+               int dvStatus = hd->ioc->spi_data.dvStatus[pTarget->target_id];
                int issueCmd = 1;
 
                if (dvStatus || hd->ioc->spi_data.forceDv) {
@@ -1426,6 +1454,7 @@ mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
        return 0;
 
  fail:
+       hd->ScsiLookup[my_idx] = NULL;
        mptscsih_freeChainBuffers(hd->ioc, my_idx);
        mpt_free_msg_frame(hd->ioc, mf);
        return SCSI_MLQUEUE_HOST_BUSY;
@@ -1713,24 +1742,23 @@ mptscsih_abort(struct scsi_cmnd * SCpnt)
        MPT_FRAME_HDR   *mf;
        u32              ctx2abort;
        int              scpnt_idx;
+       int              retval;
 
        /* If we can't locate our host adapter structure, return FAILED status.
         */
        if ((hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata) == NULL) {
                SCpnt->result = DID_RESET << 16;
                SCpnt->scsi_done(SCpnt);
-               dfailprintk((KERN_WARNING MYNAM ": mptscsih_abort: "
+               dfailprintk((KERN_INFO MYNAM ": mptscsih_abort: "
                           "Can't locate host! (sc=%p)\n",
                           SCpnt));
                return FAILED;
        }
 
        ioc = hd->ioc;
-       if (hd->resetPending)
+       if (hd->resetPending) {
                return FAILED;
-
-       printk(KERN_WARNING MYNAM ": %s: >> Attempting task abort! (sc=%p)\n",
-              hd->ioc->name, SCpnt);
+       }
 
        if (hd->timeouts < -1)
                hd->timeouts++;
@@ -1738,16 +1766,20 @@ mptscsih_abort(struct scsi_cmnd * SCpnt)
        /* Find this command
         */
        if ((scpnt_idx = SCPNT_TO_LOOKUP_IDX(SCpnt)) < 0) {
-               /* Cmd not found in ScsiLookup. 
+               /* Cmd not found in ScsiLookup.
                 * Do OS callback.
                 */
                SCpnt->result = DID_RESET << 16;
-               dtmprintk((KERN_WARNING MYNAM ": %s: mptscsih_abort: "
+               dtmprintk((KERN_INFO MYNAM ": %s: mptscsih_abort: "
                           "Command not in the active list! (sc=%p)\n",
                           hd->ioc->name, SCpnt));
                return SUCCESS;
        }
 
+       printk(KERN_WARNING MYNAM ": %s: attempting task abort! (sc=%p)\n",
+              hd->ioc->name, SCpnt);
+       scsi_print_command(SCpnt);
+
        /* Most important!  Set TaskMsgContext to SCpnt's MsgContext!
         * (the IO to be ABORT'd)
         *
@@ -1760,38 +1792,22 @@ mptscsih_abort(struct scsi_cmnd * SCpnt)
 
        hd->abortSCpnt = SCpnt;
 
-       if (mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK,
+       retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK,
                SCpnt->device->channel, SCpnt->device->id, SCpnt->device->lun,
-               ctx2abort, 2 /* 2 second timeout */)
-               < 0) {
+               ctx2abort, 2 /* 2 second timeout */);
 
-               /* The TM request failed and the subsequent FW-reload failed!
-                * Fatal error case.
-                */
-               printk(MYIOC_s_WARN_FMT "Error issuing abort task! (sc=%p)\n",
-                      hd->ioc->name, SCpnt);
+       printk (KERN_WARNING MYNAM ": %s: task abort: %s (sc=%p)\n",
+               hd->ioc->name,
+               ((retval == 0) ? "SUCCESS" : "FAILED" ), SCpnt);
 
-               /* We must clear our pending flag before clearing our state.
-                */
+       if (retval == 0)
+               return SUCCESS;
+
+       if(retval != FAILED ) {
                hd->tmPending = 0;
                hd->tmState = TM_STATE_NONE;
-
-               /* Unmap the DMA buffers, if any. */
-               if (SCpnt->use_sg) {
-                       pci_unmap_sg(ioc->pcidev, (struct scatterlist *) SCpnt->request_buffer,
-                                   SCpnt->use_sg, SCpnt->sc_data_direction);
-               } else if (SCpnt->request_bufflen) {
-                       pci_unmap_single(ioc->pcidev, SCpnt->SCp.dma_handle,
-                               SCpnt->request_bufflen, SCpnt->sc_data_direction);
-               }
-               hd->ScsiLookup[scpnt_idx] = NULL;
-               SCpnt->result = DID_RESET << 16;
-               SCpnt->scsi_done(SCpnt);                /* Issue the command callback */
-               mptscsih_freeChainBuffers(ioc, scpnt_idx);
-               mpt_free_msg_frame(ioc, mf);
-               return FAILED;
        }
-       return SUCCESS;
+       return FAILED;
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
@@ -1807,11 +1823,12 @@ int
 mptscsih_dev_reset(struct scsi_cmnd * SCpnt)
 {
        MPT_SCSI_HOST   *hd;
+       int              retval;
 
        /* If we can't locate our host adapter structure, return FAILED status.
         */
        if ((hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata) == NULL){
-               dtmprintk((KERN_WARNING MYNAM ": mptscsih_dev_reset: "
+               dtmprintk((KERN_INFO MYNAM ": mptscsih_dev_reset: "
                           "Can't locate host! (sc=%p)\n",
                           SCpnt));
                return FAILED;
@@ -1820,24 +1837,26 @@ mptscsih_dev_reset(struct scsi_cmnd * SCpnt)
        if (hd->resetPending)
                return FAILED;
 
-       printk(KERN_WARNING MYNAM ": %s: >> Attempting target reset! (sc=%p)\n",
+       printk(KERN_WARNING MYNAM ": %s: attempting target reset! (sc=%p)\n",
               hd->ioc->name, SCpnt);
+       scsi_print_command(SCpnt);
 
-       if (mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET,
+       retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET,
                SCpnt->device->channel, SCpnt->device->id,
-               0, 0, 5 /* 5 second timeout */)
-               < 0){
-               /* The TM request failed and the subsequent FW-reload failed!
-                * Fatal error case.
-                */
-               printk(MYIOC_s_WARN_FMT "Error processing TaskMgmt request (sc=%p)\n",
-                               hd->ioc->name, SCpnt);
+               0, 0, 5 /* 5 second timeout */);
+
+       printk (KERN_WARNING MYNAM ": %s: target reset: %s (sc=%p)\n",
+               hd->ioc->name,
+               ((retval == 0) ? "SUCCESS" : "FAILED" ), SCpnt);
+
+       if (retval == 0)
+               return SUCCESS;
+
+       if(retval != FAILED ) {
                hd->tmPending = 0;
                hd->tmState = TM_STATE_NONE;
-               return FAILED;
        }
-
-       return SUCCESS;
+       return FAILED;
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
@@ -1853,41 +1872,39 @@ int
 mptscsih_bus_reset(struct scsi_cmnd * SCpnt)
 {
        MPT_SCSI_HOST   *hd;
-       spinlock_t      *host_lock = SCpnt->device->host->host_lock;
+       int              retval;
 
        /* If we can't locate our host adapter structure, return FAILED status.
         */
        if ((hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata) == NULL){
-               dtmprintk((KERN_WARNING MYNAM ": mptscsih_bus_reset: "
+               dtmprintk((KERN_INFO MYNAM ": mptscsih_bus_reset: "
                           "Can't locate host! (sc=%p)\n",
                           SCpnt ) );
                return FAILED;
        }
 
-       printk(KERN_WARNING MYNAM ": %s: >> Attempting bus reset! (sc=%p)\n",
+       printk(KERN_WARNING MYNAM ": %s: attempting bus reset! (sc=%p)\n",
               hd->ioc->name, SCpnt);
+       scsi_print_command(SCpnt);
 
        if (hd->timeouts < -1)
                hd->timeouts++;
 
-       /* We are now ready to execute the task management request. */
-       if (mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS,
-               SCpnt->device->channel, 0, 0, 0, 5 /* 5 second timeout */)
-           < 0){
+       retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS,
+               SCpnt->device->channel, 0, 0, 0, 5 /* 5 second timeout */);
 
-               /* The TM request failed and the subsequent FW-reload failed!
-                * Fatal error case.
-                */
-               printk(MYIOC_s_WARN_FMT
-                      "Error processing TaskMgmt request (sc=%p)\n",
-                      hd->ioc->name, SCpnt);
+       printk (KERN_WARNING MYNAM ": %s: bus reset: %s (sc=%p)\n",
+               hd->ioc->name,
+               ((retval == 0) ? "SUCCESS" : "FAILED" ), SCpnt);
+
+       if (retval == 0)
+               return SUCCESS;
+
+       if(retval != FAILED ) {
                hd->tmPending = 0;
                hd->tmState = TM_STATE_NONE;
-               spin_lock_irq(host_lock);
-               return FAILED;
        }
-
-       return SUCCESS;
+       return FAILED;
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
@@ -2169,7 +2186,7 @@ mptscsih_slave_alloc(struct scsi_device *device)
        vdev->raidVolume = 0;
        hd->Targets[device->id] = vdev;
        if (hd->ioc->bus_type == SCSI) {
-               if (hd->ioc->spi_data.isRaid & (1 << device->id)) {
+               if (hd->ioc->raid_data.isRaid & (1 << device->id)) {
                        vdev->raidVolume = 1;
                        ddvtprintk((KERN_INFO
                            "RAID Volume @ id %d\n", device->id));
@@ -2180,22 +2197,7 @@ mptscsih_slave_alloc(struct scsi_device *device)
 
  out:
        vdev->num_luns++;
-       return 0;
-}
-
-static int 
-mptscsih_is_raid_volume(MPT_SCSI_HOST *hd, uint id)
-{
-       int i;
-
-       if (!hd->ioc->spi_data.isRaid || !hd->ioc->spi_data.pIocPg3)
-               return 0;
-
-       for (i = 0; i < hd->ioc->spi_data.pIocPg3->NumPhysDisks; i++) {
-               if (id == hd->ioc->spi_data.pIocPg3->PhysDisk[i].PhysDiskID)
-                       return 1;
-       }
-
+       device->hostdata = vdev;
        return 0;
 }
 
@@ -2226,7 +2228,7 @@ mptscsih_slave_destroy(struct scsi_device *device)
        hd->Targets[target] = NULL;
 
        if (hd->ioc->bus_type == SCSI) {
-               if (mptscsih_is_raid_volume(hd, target)) {
+               if (mptscsih_is_phys_disk(hd->ioc, target)) {
                        hd->ioc->spi_data.forceDv |= MPT_SCSICFG_RELOAD_IOC_PG3;
                } else {
                        hd->ioc->spi_data.dvStatus[target] =
@@ -2439,6 +2441,7 @@ mptscsih_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
 {
        MPT_SCSI_HOST   *hd;
        unsigned long    flags;
+       int             ii;
 
        dtmprintk((KERN_WARNING MYNAM
                        ": IOC %s_reset routed to SCSI host driver!\n",
@@ -2496,11 +2499,8 @@ mptscsih_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
 
                /* ScsiLookup initialization
                 */
-               {
-                       int ii;
-                       for (ii=0; ii < hd->ioc->req_depth; ii++)
-                               hd->ScsiLookup[ii] = NULL;
-               }
+               for (ii=0; ii < hd->ioc->req_depth; ii++)
+                       hd->ScsiLookup[ii] = NULL;
 
                /* 2. Chain Buffer initialization
                 */
@@ -2548,6 +2548,16 @@ mptscsih_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
        return 1;               /* currently means nothing really */
 }
 
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/* work queue thread to clear the persitency table */
+static void
+mptscsih_sas_persist_clear_table(void * arg)
+{
+       MPT_ADAPTER *ioc = (MPT_ADAPTER *)arg;
+
+       mptbase_sas_persist_operation(ioc, MPI_SAS_OP_CLEAR_NOT_PRESENT);
+}
+
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 int
 mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply)
@@ -2558,18 +2568,18 @@ mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply)
        devtprintk((MYIOC_s_INFO_FMT "MPT event (=%02Xh) routed to SCSI host driver!\n",
                        ioc->name, event));
 
+       if (ioc->sh == NULL ||
+               ((hd = (MPT_SCSI_HOST *)ioc->sh->hostdata) == NULL))
+               return 1;
+
        switch (event) {
        case MPI_EVENT_UNIT_ATTENTION:                  /* 03 */
                /* FIXME! */
                break;
        case MPI_EVENT_IOC_BUS_RESET:                   /* 04 */
        case MPI_EVENT_EXT_BUS_RESET:                   /* 05 */
-               hd = NULL;
-               if (ioc->sh) {
-                       hd = (MPT_SCSI_HOST *) ioc->sh->hostdata;
-                       if (hd && (ioc->bus_type == SCSI) && (hd->soft_resets < -1))
-                               hd->soft_resets++;
-               }
+               if (hd && (ioc->bus_type == SCSI) && (hd->soft_resets < -1))
+                       hd->soft_resets++;
                break;
        case MPI_EVENT_LOGOUT:                          /* 09 */
                /* FIXME! */
@@ -2588,69 +2598,24 @@ mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply)
                break;
 
        case MPI_EVENT_INTEGRATED_RAID:                 /* 0B */
+       {
+               pMpiEventDataRaid_t pRaidEventData =
+                   (pMpiEventDataRaid_t) pEvReply->Data;
 #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
-               /* negoNvram set to 0 if DV enabled and to USE_NVRAM if
-                * if DV disabled. Need to check for target mode.
-                */
-               hd = NULL;
-               if (ioc->sh)
-                       hd = (MPT_SCSI_HOST *) ioc->sh->hostdata;
-
-               if (hd && (ioc->bus_type == SCSI) && (hd->negoNvram == 0)) {
-                       ScsiCfgData     *pSpi;
-                       Ioc3PhysDisk_t  *pPDisk;
-                       int              numPDisk;
-                       u8               reason;
-                       u8               physDiskNum;
-
-                       reason = (le32_to_cpu(pEvReply->Data[0]) & 0x00FF0000) >> 16;
-                       if (reason == MPI_EVENT_RAID_RC_DOMAIN_VAL_NEEDED) {
-                               /* New or replaced disk.
-                                * Set DV flag and schedule DV.
-                                */
-                               pSpi = &ioc->spi_data;
-                               physDiskNum = (le32_to_cpu(pEvReply->Data[0]) & 0xFF000000) >> 24;
-                               ddvtprintk(("DV requested for phys disk id %d\n", physDiskNum));
-                               if (pSpi->pIocPg3) {
-                                       pPDisk =  pSpi->pIocPg3->PhysDisk;
-                                       numPDisk =pSpi->pIocPg3->NumPhysDisks;
-
-                                       while (numPDisk) {
-                                               if (physDiskNum == pPDisk->PhysDiskNum) {
-                                                       pSpi->dvStatus[pPDisk->PhysDiskID] = (MPT_SCSICFG_NEED_DV | MPT_SCSICFG_DV_NOT_DONE);
-                                                       pSpi->forceDv = MPT_SCSICFG_NEED_DV;
-                                                       ddvtprintk(("NEED_DV set for phys disk id %d\n", pPDisk->PhysDiskID));
-                                                       break;
-                                               }
-                                               pPDisk++;
-                                               numPDisk--;
-                                       }
-
-                                       if (numPDisk == 0) {
-                                               /* The physical disk that needs DV was not found
-                                                * in the stored IOC Page 3. The driver must reload
-                                                * this page. DV routine will set the NEED_DV flag for
-                                                * all phys disks that have DV_NOT_DONE set.
-                                                */
-                                               pSpi->forceDv = MPT_SCSICFG_NEED_DV | MPT_SCSICFG_RELOAD_IOC_PG3;
-                                               ddvtprintk(("phys disk %d not found. Setting reload IOC Pg3 Flag\n", physDiskNum));
-                                       }
-                               }
-                       }
-               }
+               /* Domain Validation Needed */
+               if (ioc->bus_type == SCSI &&
+                   pRaidEventData->ReasonCode ==
+                   MPI_EVENT_RAID_RC_DOMAIN_VAL_NEEDED)
+                       mptscsih_set_dvflags_raid(hd, pRaidEventData->PhysDiskNum);
 #endif
+               break;
+       }
 
-#if defined(MPT_DEBUG_DV) || defined(MPT_DEBUG_DV_TINY)
-               printk("Raid Event RF: ");
-               {
-                       u32 *m = (u32 *)pEvReply;
-                       int ii;
-                       int n = (int)pEvReply->MsgLength;
-                       for (ii=6; ii < n; ii++)
-                               printk(" %08x", le32_to_cpu(m[ii]));
-                       printk("\n");
-               }
-#endif
+       /* Persistent table is full. */
+       case MPI_EVENT_PERSISTENT_TABLE_FULL:
+               INIT_WORK(&mptscsih_persistTask,
+                   mptscsih_sas_persist_clear_table,(void *)ioc);
+               schedule_work(&mptscsih_persistTask);
                break;
 
        case MPI_EVENT_NONE:                            /* 00 */
@@ -2687,7 +2652,7 @@ mptscsih_initTarget(MPT_SCSI_HOST *hd, int bus_id, int target_id, u8 lun, char *
 {
        int             indexed_lun, lun_index;
        VirtDevice      *vdev;
-       ScsiCfgData     *pSpi;
+       SpiCfgData      *pSpi;
        char            data_56;
 
        dinitprintk((MYIOC_s_INFO_FMT "initTarget bus=%d id=%d lun=%d hd=%p\n",
@@ -2794,7 +2759,7 @@ mptscsih_initTarget(MPT_SCSI_HOST *hd, int bus_id, int target_id, u8 lun, char *
 static void
 mptscsih_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtDevice *target, char byte56)
 {
-       ScsiCfgData *pspi_data = &hd->ioc->spi_data;
+       SpiCfgData *pspi_data = &hd->ioc->spi_data;
        int  id = (int) target->target_id;
        int  nvram;
        VirtDevice      *vdev;
@@ -2973,11 +2938,13 @@ mptscsih_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtDevice *target, char byte56)
 static void
 mptscsih_set_dvflags(MPT_SCSI_HOST *hd, SCSIIORequest_t *pReq)
 {
+       MPT_ADAPTER     *ioc = hd->ioc;
        u8 cmd;
-       ScsiCfgData *pSpi;
+       SpiCfgData      *pSpi;
 
-       ddvtprintk((" set_dvflags: id=%d lun=%d negoNvram=%x cmd=%x\n", 
-               pReq->TargetID, pReq->LUN[1], hd->negoNvram, pReq->CDB[0]));
+       ddvtprintk((MYIOC_s_NOTE_FMT
+               " set_dvflags: id=%d lun=%d negoNvram=%x cmd=%x\n",
+               hd->ioc->name, pReq->TargetID, pReq->LUN[1], hd->negoNvram, pReq->CDB[0]));
 
        if ((pReq->LUN[1] != 0) || (hd->negoNvram != 0))
                return;
@@ -2985,12 +2952,12 @@ mptscsih_set_dvflags(MPT_SCSI_HOST *hd, SCSIIORequest_t *pReq)
        cmd = pReq->CDB[0];
 
        if ((cmd == READ_CAPACITY) || (cmd == MODE_SENSE)) {
-               pSpi = &hd->ioc->spi_data;
-               if ((pSpi->isRaid & (1 << pReq->TargetID)) && pSpi->pIocPg3) {
+               pSpi = &ioc->spi_data;
+               if ((ioc->raid_data.isRaid & (1 << pReq->TargetID)) && ioc->raid_data.pIocPg3) {
                        /* Set NEED_DV for all hidden disks
                         */
-                       Ioc3PhysDisk_t *pPDisk =  pSpi->pIocPg3->PhysDisk;
-                       int             numPDisk = pSpi->pIocPg3->NumPhysDisks;
+                       Ioc3PhysDisk_t *pPDisk =  ioc->raid_data.pIocPg3->PhysDisk;
+                       int             numPDisk = ioc->raid_data.pIocPg3->NumPhysDisks;
 
                        while (numPDisk) {
                                pSpi->dvStatus[pPDisk->PhysDiskID] |= MPT_SCSICFG_NEED_DV;
@@ -3004,6 +2971,50 @@ mptscsih_set_dvflags(MPT_SCSI_HOST *hd, SCSIIORequest_t *pReq)
        }
 }
 
+/* mptscsih_raid_set_dv_flags()
+ *
+ * New or replaced disk. Set DV flag and schedule DV.
+ */
+static void
+mptscsih_set_dvflags_raid(MPT_SCSI_HOST *hd, int id)
+{
+       MPT_ADAPTER     *ioc = hd->ioc;
+       SpiCfgData      *pSpi = &ioc->spi_data;
+       Ioc3PhysDisk_t  *pPDisk;
+       int              numPDisk;
+
+       if (hd->negoNvram != 0)
+               return;
+
+       ddvtprintk(("DV requested for phys disk id %d\n", id));
+       if (ioc->raid_data.pIocPg3) {
+               pPDisk =  ioc->raid_data.pIocPg3->PhysDisk;
+               numPDisk = ioc->raid_data.pIocPg3->NumPhysDisks;
+               while (numPDisk) {
+                       if (id == pPDisk->PhysDiskNum) {
+                               pSpi->dvStatus[pPDisk->PhysDiskID] =
+                                   (MPT_SCSICFG_NEED_DV | MPT_SCSICFG_DV_NOT_DONE);
+                               pSpi->forceDv = MPT_SCSICFG_NEED_DV;
+                               ddvtprintk(("NEED_DV set for phys disk id %d\n",
+                                   pPDisk->PhysDiskID));
+                               break;
+                       }
+                       pPDisk++;
+                       numPDisk--;
+               }
+
+               if (numPDisk == 0) {
+                       /* The physical disk that needs DV was not found
+                        * in the stored IOC Page 3. The driver must reload
+                        * this page. DV routine will set the NEED_DV flag for
+                        * all phys disks that have DV_NOT_DONE set.
+                        */
+                       pSpi->forceDv = MPT_SCSICFG_NEED_DV | MPT_SCSICFG_RELOAD_IOC_PG3;
+                       ddvtprintk(("phys disk %d not found. Setting reload IOC Pg3 Flag\n",id));
+               }
+       }
+}
+
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /*
  * If no Target, bus reset on 1st I/O. Set the flag to
@@ -3091,7 +3102,7 @@ mptscsih_writeSDP1(MPT_SCSI_HOST *hd, int portnum, int target_id, int flags)
        MPT_ADAPTER             *ioc = hd->ioc;
        Config_t                *pReq;
        SCSIDevicePage1_t       *pData;
-       VirtDevice              *pTarget;
+       VirtDevice              *pTarget=NULL;
        MPT_FRAME_HDR           *mf;
        dma_addr_t               dataDma;
        u16                      req_idx;
@@ -3190,7 +3201,7 @@ mptscsih_writeSDP1(MPT_SCSI_HOST *hd, int portnum, int target_id, int flags)
 #endif
 
                if (flags & MPT_SCSICFG_BLK_NEGO)
-                       negoFlags = MPT_TARGET_NO_NEGO_WIDE | MPT_TARGET_NO_NEGO_SYNC;
+                       negoFlags |= MPT_TARGET_NO_NEGO_WIDE | MPT_TARGET_NO_NEGO_SYNC;
 
                mptscsih_setDevicePage1Flags(width, factor, offset,
                                        &requested, &configuration, negoFlags);
@@ -4011,7 +4022,7 @@ mptscsih_synchronize_cache(MPT_SCSI_HOST *hd, int portnum)
 
                /* If target Ptr NULL or if this target is NOT a disk, skip.
                 */
-               if ((pTarget) && (pTarget->tflags & MPT_TARGET_FLAGS_Q_YES)){
+               if ((pTarget) && (pTarget->inq_data[0] == TYPE_DISK)){
                        for (lun=0; lun <= MPT_LAST_LUN; lun++) {
                                /* If LUN present, issue the command
                                 */
@@ -4106,9 +4117,9 @@ mptscsih_domainValidation(void *arg)
 
                        if ((ioc->spi_data.forceDv & MPT_SCSICFG_RELOAD_IOC_PG3) != 0) {
                                mpt_read_ioc_pg_3(ioc);
-                               if (ioc->spi_data.pIocPg3) {
-                                       Ioc3PhysDisk_t *pPDisk = ioc->spi_data.pIocPg3->PhysDisk;
-                                       int             numPDisk = ioc->spi_data.pIocPg3->NumPhysDisks;
+                               if (ioc->raid_data.pIocPg3) {
+                                       Ioc3PhysDisk_t *pPDisk = ioc->raid_data.pIocPg3->PhysDisk;
+                                       int             numPDisk = ioc->raid_data.pIocPg3->NumPhysDisks;
 
                                        while (numPDisk) {
                                                if (ioc->spi_data.dvStatus[pPDisk->PhysDiskID] & MPT_SCSICFG_DV_NOT_DONE)
@@ -4147,7 +4158,7 @@ mptscsih_domainValidation(void *arg)
                                        isPhysDisk = mptscsih_is_phys_disk(ioc, id);
                                        if (isPhysDisk) {
                                                for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) {
-                                                       if (hd->ioc->spi_data.isRaid & (1 << ii)) {
+                                                       if (hd->ioc->raid_data.isRaid & (1 << ii)) {
                                                                hd->ioc->spi_data.dvStatus[ii] |= MPT_SCSICFG_DV_PENDING;
                                                        }
                                                }
@@ -4166,7 +4177,7 @@ mptscsih_domainValidation(void *arg)
 
                                        if (isPhysDisk) {
                                                for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) {
-                                                       if (hd->ioc->spi_data.isRaid & (1 << ii)) {
+                                                       if (hd->ioc->raid_data.isRaid & (1 << ii)) {
                                                                hd->ioc->spi_data.dvStatus[ii] &= ~MPT_SCSICFG_DV_PENDING;
                                                        }
                                                }
@@ -4188,21 +4199,21 @@ mptscsih_domainValidation(void *arg)
 
 /* Search IOC page 3 to determine if this is hidden physical disk
  */
-static int 
+/* Search IOC page 3 to determine if this is hidden physical disk
+ */
+static int
 mptscsih_is_phys_disk(MPT_ADAPTER *ioc, int id)
 {
-       if (ioc->spi_data.pIocPg3) {
-               Ioc3PhysDisk_t *pPDisk =  ioc->spi_data.pIocPg3->PhysDisk;
-               int             numPDisk = ioc->spi_data.pIocPg3->NumPhysDisks;
+       int i;
 
-               while (numPDisk) {
-                       if (pPDisk->PhysDiskID == id) {
-                               return 1;
-                       }
-                       pPDisk++;
-                       numPDisk--;
-               }
+       if (!ioc->raid_data.isRaid || !ioc->raid_data.pIocPg3)
+               return 0;
+
+       for (i = 0; i < ioc->raid_data.pIocPg3->NumPhysDisks; i++) {
+               if (id == ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskID)
+                       return 1;
        }
+
        return 0;
 }
 
@@ -4408,7 +4419,7 @@ mptscsih_doDv(MPT_SCSI_HOST *hd, int bus_number, int id)
        /* Skip this ID? Set cfg.cfghdr.hdr to force config page write
         */
        {
-               ScsiCfgData *pspi_data = &hd->ioc->spi_data;
+               SpiCfgData *pspi_data = &hd->ioc->spi_data;
                if (pspi_data->nvram && (pspi_data->nvram[id] != MPT_HOST_NVRAM_INVALID)) {
                        /* Set the factor from nvram */
                        nfactor = (pspi_data->nvram[id] & MPT_NVRAM_SYNC_MASK) >> 8;
@@ -4438,11 +4449,11 @@ mptscsih_doDv(MPT_SCSI_HOST *hd, int bus_number, int id)
        }
 
        /* Finish iocmd inititialization - hidden or visible disk? */
-       if (ioc->spi_data.pIocPg3) {
+       if (ioc->raid_data.pIocPg3) {
                /* Search IOC page 3 for matching id
                 */
-               Ioc3PhysDisk_t *pPDisk =  ioc->spi_data.pIocPg3->PhysDisk;
-               int             numPDisk = ioc->spi_data.pIocPg3->NumPhysDisks;
+               Ioc3PhysDisk_t *pPDisk =  ioc->raid_data.pIocPg3->PhysDisk;
+               int             numPDisk = ioc->raid_data.pIocPg3->NumPhysDisks;
 
                while (numPDisk) {
                        if (pPDisk->PhysDiskID == id) {
@@ -4466,7 +4477,7 @@ mptscsih_doDv(MPT_SCSI_HOST *hd, int bus_number, int id)
        /* RAID Volume ID's may double for a physical device. If RAID but
         * not a physical ID as well, skip DV.
         */
-       if ((hd->ioc->spi_data.isRaid & (1 << id)) && !(iocmd.flags & MPT_ICFLAG_PHYS_DISK))
+       if ((hd->ioc->raid_data.isRaid & (1 << id)) && !(iocmd.flags & MPT_ICFLAG_PHYS_DISK))
                goto target_done;
 
 
@@ -4815,6 +4826,8 @@ mptscsih_doDv(MPT_SCSI_HOST *hd, int bus_number, int id)
                                        notDone = 0;
                                        if (iocmd.flags & MPT_ICFLAG_ECHO) {
                                                bufsize =  ((pbuf1[2] & 0x1F) <<8) | pbuf1[3];
+                                               if (pbuf1[0] & 0x01)
+                                                       iocmd.flags |= MPT_ICFLAG_EBOS;
                                        } else {
                                                bufsize =  pbuf1[1]<<16 | pbuf1[2]<<8 | pbuf1[3];
                                        }
@@ -4911,6 +4924,9 @@ mptscsih_doDv(MPT_SCSI_HOST *hd, int bus_number, int id)
                }
                iocmd.flags &= ~MPT_ICFLAG_DID_RESET;
 
+               if (iocmd.flags & MPT_ICFLAG_EBOS)
+                       goto skip_Reserve;
+
                repeat = 5;
                while (repeat && (!(iocmd.flags & MPT_ICFLAG_RESERVED))) {
                        iocmd.cmd = RESERVE;
@@ -4954,6 +4970,7 @@ mptscsih_doDv(MPT_SCSI_HOST *hd, int bus_number, int id)
                        }
                }
 
+skip_Reserve:
                mptscsih_fillbuf(pbuf1, sz, patt, 1);
                iocmd.cmd = WRITE_BUFFER;
                iocmd.data_dma = buf1_dma;
@@ -5198,11 +5215,12 @@ mptscsih_dv_parms(MPT_SCSI_HOST *hd, DVPARAMETERS *dv,void *pPage)
                 * If not an LVD bus, the adapter minSyncFactor has been
                 * already throttled back.
                 */
+               negoFlags = hd->ioc->spi_data.noQas;
                if ((hd->Targets)&&((pTarget = hd->Targets[(int)id]) != NULL) && !pTarget->raidVolume) {
                        width = pTarget->maxWidth;
                        offset = pTarget->maxOffset;
                        factor = pTarget->minSyncFactor;
-                       negoFlags = pTarget->negoFlags;
+                       negoFlags |= pTarget->negoFlags;
                } else {
                        if (hd->ioc->spi_data.nvram && (hd->ioc->spi_data.nvram[id] != MPT_HOST_NVRAM_INVALID)) {
                                data = hd->ioc->spi_data.nvram[id];
@@ -5223,7 +5241,6 @@ mptscsih_dv_parms(MPT_SCSI_HOST *hd, DVPARAMETERS *dv,void *pPage)
                        }
 
                        /* Set the negotiation flags */
-                       negoFlags = hd->ioc->spi_data.noQas;
                        if (!width)
                                negoFlags |= MPT_TARGET_NO_NEGO_WIDE;
 
index 51c0255ac16ec23b9f5634c7f0fec1e3862caebd..971fda4b8b57998c56ffeb2fb7aaa3a2d4ae5236 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  linux/drivers/message/fusion/mptscsi.h
+ *  linux/drivers/message/fusion/mptscsih.h
  *      High performance SCSI / Fibre Channel SCSI Host device driver.
  *      For use with PCI chip/adapter(s):
  *          LSIFC9xx/LSI409xx Fibre Channel
@@ -53,8 +53,8 @@
  *     SCSI Public stuff...
  */
 
-#define MPT_SCSI_CMD_PER_DEV_HIGH      31
-#define MPT_SCSI_CMD_PER_DEV_LOW       7
+#define MPT_SCSI_CMD_PER_DEV_HIGH      64
+#define MPT_SCSI_CMD_PER_DEV_LOW       32
 
 #define MPT_SCSI_CMD_PER_LUN           7
 
@@ -77,6 +77,7 @@
 #define MPTSCSIH_MAX_WIDTH              1
 #define MPTSCSIH_MIN_SYNC               0x08
 #define MPTSCSIH_SAF_TE                 0
+#define MPTSCSIH_PT_CLEAR               0
 
 
 #endif
index 587d1274fd74f665dc3f477b04141096c147c530..5c0e307d1d5d4c4c9440b5625b754b0ead959ff1 100644 (file)
@@ -199,7 +199,7 @@ mptspi_probe(struct pci_dev *pdev, const struct pci_device_id *id)
                printk(MYIOC_s_WARN_FMT
                        "Skipping ioc=%p because SCSI Initiator mode is NOT enabled!\n",
                        ioc->name, ioc);
-               return -ENODEV;
+               return 0;
        }
 
        sh = scsi_host_alloc(&mptspi_driver_template, sizeof(MPT_SCSI_HOST));
index af32ab4e90cd28eff940016f57f9e2c06e50cf6d..10432f6652012aff5f08bd302bf8e22da5df4796 100644 (file)
@@ -56,8 +56,11 @@ static int __init i2o_config_init(void)
                return -EBUSY;
        }
 #ifdef CONFIG_I2O_CONFIG_OLD_IOCTL
-       if (i2o_config_old_init())
+       if (i2o_config_old_init()) {
+               osm_err("old config handler initialization failed\n");
                i2o_driver_unregister(&i2o_config_driver);
+               return -EBUSY;
+       }
 #endif
 
        return 0;
index 9a087c1fb0b77044450775980052935b6be9b197..24f670b5a4f34e4b36751fe66479ada3d78843f6 100644 (file)
@@ -40,7 +40,7 @@
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/doc2000.h>
 
-#define DEBUG 0
+#define DEBUG_ECC 0
 /* need to undef it (from asm/termbits.h) */
 #undef B0
 
@@ -249,7 +249,7 @@ eras_dec_rs(dtype Alpha_to[NN + 1], dtype Index_of[NN + 1],
          lambda[j] ^= Alpha_to[modnn(u + tmp)];
       }
     }
-#if DEBUG >= 1
+#if DEBUG_ECC >= 1
     /* Test code that verifies the erasure locator polynomial just constructed
        Needed only for decoder debugging. */
     
@@ -276,7 +276,7 @@ eras_dec_rs(dtype Alpha_to[NN + 1], dtype Index_of[NN + 1],
       count = -1;
       goto finish;
     }
-#if DEBUG >= 2
+#if DEBUG_ECC >= 2
     printf("\n Erasure positions as determined by roots of Eras Loc Poly:\n");
     for (i = 0; i < count; i++)
       printf("%d ", loc[i]);
@@ -409,7 +409,7 @@ eras_dec_rs(dtype Alpha_to[NN + 1], dtype Index_of[NN + 1],
        den ^= Alpha_to[modnn(lambda[i+1] + i * root[j])];
     }
     if (den == 0) {
-#if DEBUG >= 1
+#if DEBUG_ECC >= 1
       printf("\n ERROR: denominator = 0\n");
 #endif
       /* Convert to dual- basis */
index d15da6fd84c10fce1c41aaba3f96a87afe997816..b7f093fbf9b05396dc1f54a6c14bb3b0c501268e 100644 (file)
@@ -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 {
index 9853b87bb756d67ce7f42899f5af54b68a28814d..88b5b5b40b43aa07fed88f2b56edfb1b1b9cdab2 100644 (file)
@@ -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;
        }
index 34b80de34faec69fa86927f501214377279d5c83..bc537440ca025931124c278d81f66a3d742cabf6 100644 (file)
@@ -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 = {
index 6d76f3a99b175f533d06451a76f773f692f8cc8d..f87027420081e72845b3ef766748eca339270b41 100644 (file)
@@ -1094,7 +1094,7 @@ static void NS8390_trigger_send(struct net_device *dev, unsigned int length,
    
        outb_p(E8390_NODMA+E8390_PAGE0, e8390_base+E8390_CMD);
     
-       if (inb_p(e8390_base) & E8390_TRANS) 
+       if (inb_p(e8390_base + E8390_CMD) & E8390_TRANS) 
        {
                printk(KERN_WARNING "%s: trigger_send() called with the transmitter busy.\n",
                        dev->name);
index 54fff9c2e8028cb0a7509dae5cb5ed017bab39ab..96f14ab1c1f52f805e64c62959fadc84d1b1e412 100644 (file)
@@ -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.
index 52c77cbe8c62cf8e104d3639b3ac047737e8d5aa..1f03027354167cd29ba1c82467192f4d6892eecb 100644 (file)
@@ -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;
index 94c9f68dd16bacf4686eac5cb7da66062bf8df33..6d00c3de1a836a8ec703bab4480646a8c6e7aed1 100644 (file)
@@ -1653,7 +1653,8 @@ static int bond_enslave(struct net_device *bond_dev, struct net_device *slave_de
        int old_features = bond_dev->features;
        int res = 0;
 
-       if (slave_dev->do_ioctl == NULL) {
+       if (!bond->params.use_carrier && slave_dev->ethtool_ops == NULL &&
+               slave_dev->do_ioctl == NULL) {
                printk(KERN_WARNING DRV_NAME
                       ": Warning : no link monitoring support for %s\n",
                       slave_dev->name);
@@ -2879,6 +2880,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 +2900,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 +2912,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 +5040,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();
 
index 25cc20e415dae23247825fe947b4cb19725ee0bf..fbf1c06ec5c12aac8c83defb67221339325337e3 100644 (file)
@@ -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++;
index 7c8a0a22dcd5425545389fb056f9e9a1f4ee8f90..ee687c902a20be52d0bdf95ef4fc58b03f5317a3 100644 (file)
@@ -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;
index 5c555373adbe5802054b2ed3558219269d0e9ca5..89d6d69be382a3d625892823d8859cbae8237908 100644 (file)
@@ -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;
         */
index f0471d102e3c61bcfc6089c483009e52b2427cfb..f9223c1c5aa45f95cb501252a341073ff8e19483 100644 (file)
@@ -100,11 +100,11 @@ VERSION 2.2LK     <2005/01/25>
 
 #ifdef CONFIG_R8169_NAPI
 #define rtl8169_rx_skb                 netif_receive_skb
-#define rtl8169_rx_hwaccel_skb         vlan_hwaccel_rx
+#define rtl8169_rx_hwaccel_skb         vlan_hwaccel_receive_skb
 #define rtl8169_rx_quota(count, quota) min(count, quota)
 #else
 #define rtl8169_rx_skb                 netif_rx
-#define rtl8169_rx_hwaccel_skb         vlan_hwaccel_receive_skb
+#define rtl8169_rx_hwaccel_skb         vlan_hwaccel_rx
 #define rtl8169_rx_quota(count, quota) count
 #endif
 
index c829e6a2e8a681242b03fbcb6f26210c633aeb2e..dd451e099a4c46bd650dbc1696c40f7fae3468f6 100644 (file)
@@ -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);
        }
index 6ee4771addf1e22c5ef1e293889926c83c422f9b..2e72d79a143c1ae4c57959eae8cfbcccd76f6968 100644 (file)
@@ -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);
index d7c98515fdfdd55d91cdd3fb54b1ca252ce2ec09..fd398da4993b37f1a1399933b98287c2772bb4e0 100644 (file)
@@ -42,7 +42,7 @@
 #include "skge.h"
 
 #define DRV_NAME               "skge"
-#define DRV_VERSION            "0.9"
+#define DRV_VERSION            "1.1"
 #define PFX                    DRV_NAME " "
 
 #define DEFAULT_TX_RING_SIZE   128
@@ -105,41 +105,28 @@ static const u32 rxirqmask[] = { IS_R1_F, IS_R2_F };
 static const u32 txirqmask[] = { IS_XA1_F, IS_XA2_F };
 static const u32 portirqmask[] = { IS_PORT_1, IS_PORT_2 };
 
-/* Don't need to look at whole 16K.
- * last interesting register is descriptor poll timer.
- */
-#define SKGE_REGS_LEN  (29*128)
-
 static int skge_get_regs_len(struct net_device *dev)
 {
-       return SKGE_REGS_LEN;
+       return 0x4000;
 }
 
 /*
- * Returns copy of control register region
- * I/O region is divided into banks and certain regions are unreadable
+ * Returns copy of whole control register region
+ * Note: skip RAM address register because accessing it will
+ *      cause bus hangs!
  */
 static void skge_get_regs(struct net_device *dev, struct ethtool_regs *regs,
                          void *p)
 {
        const struct skge_port *skge = netdev_priv(dev);
-       unsigned long offs;
        const void __iomem *io = skge->hw->regs;
-       static const unsigned long bankmap
-               = (1<<0) | (1<<2) | (1<<8) | (1<<9)
-                 | (1<<12) | (1<<13) | (1<<14) | (1<<15) | (1<<16)
-                 | (1<<17) | (1<<20) | (1<<21) | (1<<22) | (1<<23)
-                 | (1<<24)  | (1<<25) | (1<<26) | (1<<27) | (1<<28);
 
        regs->version = 1;
-       for (offs = 0; offs < regs->len; offs += 128) {
-               u32 len = min_t(u32, 128, regs->len - offs);
+       memset(p, 0, regs->len);
+       memcpy_fromio(p, io, B3_RAM_ADDR);
 
-               if (bankmap & (1<<(offs/128)))
-                       memcpy_fromio(p + offs, io + offs, len);
-               else
-                       memset(p + offs, 0, len);
-       }
+       memcpy_fromio(p + B3_RI_WTO_R1, io + B3_RI_WTO_R1,
+                     regs->len - B3_RI_WTO_R1);
 }
 
 /* Wake on Lan only supported on Yukon chps with rev 1 or above */
@@ -669,7 +656,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 ?
@@ -775,17 +762,6 @@ static int skge_ring_alloc(struct skge_ring *ring, void *vaddr, u64 base)
        return 0;
 }
 
-static struct sk_buff *skge_rx_alloc(struct net_device *dev, unsigned int size)
-{
-       struct sk_buff *skb = dev_alloc_skb(size);
-
-       if (likely(skb)) {
-               skb->dev = dev;
-               skb_reserve(skb, NET_IP_ALIGN);
-       }
-       return skb;
-}
-
 /* Allocate and setup a new buffer for receiving */
 static void skge_rx_setup(struct skge_port *skge, struct skge_element *e,
                          struct sk_buff *skb, unsigned int bufsize)
@@ -858,16 +834,17 @@ static int skge_rx_fill(struct skge_port *skge)
 {
        struct skge_ring *ring = &skge->rx_ring;
        struct skge_element *e;
-       unsigned int bufsize = skge->rx_buf_size;
 
        e = ring->start;
        do {
-               struct sk_buff *skb = skge_rx_alloc(skge->netdev, bufsize);
+               struct sk_buff *skb;
 
+               skb = dev_alloc_skb(skge->rx_buf_size + NET_IP_ALIGN);
                if (!skb)
                        return -ENOMEM;
 
-               skge_rx_setup(skge, e, skb, bufsize);
+               skb_reserve(skb, NET_IP_ALIGN);
+               skge_rx_setup(skge, e, skb, skge->rx_buf_size);
        } while ( (e = e->next) != ring->start);
 
        ring->to_clean = ring->start;
@@ -876,7 +853,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 +964,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 +1000,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 +1083,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 +1315,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 +1442,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 +1554,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);
 
@@ -1668,6 +1643,22 @@ static void yukon_reset(struct skge_hw *hw, int port)
                         | GM_RXCR_UCF_ENA | GM_RXCR_MCF_ENA);
 }
 
+/* Apparently, early versions of Yukon-Lite had wrong chip_id? */
+static int is_yukon_lite_a0(struct skge_hw *hw)
+{
+       u32 reg;
+       int ret;
+
+       if (hw->chip_id != CHIP_ID_YUKON)
+               return 0;
+
+       reg = skge_read32(hw, B2_FAR);
+       skge_write8(hw, B2_FAR + 3, 0xff);
+       ret = (skge_read8(hw, B2_FAR + 3) != 0);
+       skge_write32(hw, B2_FAR, reg);
+       return ret;
+}
+
 static void yukon_mac_init(struct skge_hw *hw, int port)
 {
        struct skge_port *skge = netdev_priv(hw->dev[port]);
@@ -1677,9 +1668,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 +1680,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 +1724,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);
 
@@ -1779,9 +1774,11 @@ static void yukon_mac_init(struct skge_hw *hw, int port)
        /* Configure Rx MAC FIFO */
        skge_write16(hw, SK_REG(port, RX_GMF_FL_MSK), RX_FF_FL_DEF_MSK);
        reg = GMF_OPER_ON | GMF_RX_F_FL_ON;
-       if (hw->chip_id == CHIP_ID_YUKON_LITE &&
-           hw->chip_rev >= CHIP_REV_YU_LITE_A3)
+
+       /* disable Rx GMAC FIFO Flush for YUKON-Lite Rev. A0 only */
+       if (is_yukon_lite_a0(hw))
                reg &= ~GMF_RX_F_FL_ON;
+
        skge_write8(hw, SK_REG(port, RX_GMF_CTRL_T), GMF_RST_CLR);
        skge_write16(hw, SK_REG(port, RX_GMF_CTRL_T), reg);
        /*
@@ -1801,20 +1798,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 +1876,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 +1897,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 +2112,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 +2134,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 +2371,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)
@@ -2435,6 +2437,14 @@ static void yukon_set_multicast(struct net_device *dev)
        gma_write16(hw, port, GM_RX_CTRL, reg);
 }
 
+static inline u16 phy_length(const struct skge_hw *hw, u32 status)
+{
+       if (hw->chip_id == CHIP_ID_GENESIS)
+               return status >> XMR_FS_LEN_SHIFT;
+       else
+               return status >> GMR_FS_LEN_SHIFT;
+}
+
 static inline int bad_phy_status(const struct skge_hw *hw, u32 status)
 {
        if (hw->chip_id == CHIP_ID_GENESIS)
@@ -2444,80 +2454,99 @@ static inline int bad_phy_status(const struct skge_hw *hw, u32 status)
                        (status & GMR_FS_RX_OK) == 0;
 }
 
-static void skge_rx_error(struct skge_port *skge, int slot,
-                         u32 control, u32 status)
-{
-       if (netif_msg_rx_err(skge))
-               printk(KERN_DEBUG PFX "%s: rx err, slot %d control 0x%x status 0x%x\n",
-                      skge->netdev->name, slot, control, status);
-
-       if ((control & (BMU_EOF|BMU_STF)) != (BMU_STF|BMU_EOF))
-               skge->net_stats.rx_length_errors++;
-       else if (skge->hw->chip_id == CHIP_ID_GENESIS) {
-               if (status & (XMR_FS_RUNT|XMR_FS_LNG_ERR))
-                       skge->net_stats.rx_length_errors++;
-               if (status & XMR_FS_FRA_ERR)
-                       skge->net_stats.rx_frame_errors++;
-               if (status & XMR_FS_FCS_ERR)
-                       skge->net_stats.rx_crc_errors++;
-       } else {
-               if (status & (GMR_FS_LONG_ERR|GMR_FS_UN_SIZE))
-                       skge->net_stats.rx_length_errors++;
-               if (status & GMR_FS_FRAGMENT)
-                       skge->net_stats.rx_frame_errors++;
-               if (status & GMR_FS_CRC_ERR)
-                       skge->net_stats.rx_crc_errors++;
-       }
-}
 
 /* Get receive buffer from descriptor.
  * Handles copy of small buffers and reallocation failures
  */
 static inline struct sk_buff *skge_rx_get(struct skge_port *skge,
                                          struct skge_element *e,
-                                         unsigned int len)
+                                         u32 control, u32 status, u16 csum)
 {
-       struct sk_buff *nskb, *skb;
+       struct sk_buff *skb;
+       u16 len = control & BMU_BBC;
+
+       if (unlikely(netif_msg_rx_status(skge)))
+               printk(KERN_DEBUG PFX "%s: rx slot %td status 0x%x len %d\n",
+                      skge->netdev->name, e - skge->rx_ring.start,
+                      status, len);
+
+       if (len > skge->rx_buf_size)
+               goto error;
+
+       if ((control & (BMU_EOF|BMU_STF)) != (BMU_STF|BMU_EOF))
+               goto error;
+
+       if (bad_phy_status(skge->hw, status))
+               goto error;
+
+       if (phy_length(skge->hw, status) != len)
+               goto error;
 
        if (len < RX_COPY_THRESHOLD) {
-               nskb = skge_rx_alloc(skge->netdev, len + NET_IP_ALIGN);
-               if (unlikely(!nskb))
-                       return NULL;
+               skb = dev_alloc_skb(len + 2);
+               if (!skb)
+                       goto resubmit;
 
+               skb_reserve(skb, 2);
                pci_dma_sync_single_for_cpu(skge->hw->pdev,
                                            pci_unmap_addr(e, mapaddr),
                                            len, PCI_DMA_FROMDEVICE);
-               memcpy(nskb->data, e->skb->data, len);
+               memcpy(skb->data, e->skb->data, len);
                pci_dma_sync_single_for_device(skge->hw->pdev,
                                               pci_unmap_addr(e, mapaddr),
                                               len, PCI_DMA_FROMDEVICE);
-
-               if (skge->rx_csum) {
-                       struct skge_rx_desc *rd = e->desc;
-                       nskb->csum = le16_to_cpu(rd->csum2);
-                       nskb->ip_summed = CHECKSUM_HW;
-               }
                skge_rx_reuse(e, skge->rx_buf_size);
-               return nskb;
        } else {
-               nskb = skge_rx_alloc(skge->netdev, skge->rx_buf_size);
-               if (unlikely(!nskb))
-                       return NULL;
+               struct sk_buff *nskb;
+               nskb = dev_alloc_skb(skge->rx_buf_size + NET_IP_ALIGN);
+               if (!nskb)
+                       goto resubmit;
 
                pci_unmap_single(skge->hw->pdev,
                                 pci_unmap_addr(e, mapaddr),
                                 pci_unmap_len(e, maplen),
                                 PCI_DMA_FROMDEVICE);
                skb = e->skb;
-               if (skge->rx_csum) {
-                       struct skge_rx_desc *rd = e->desc;
-                       skb->csum = le16_to_cpu(rd->csum2);
-                       skb->ip_summed = CHECKSUM_HW;
-               }
-
+               prefetch(skb->data);
                skge_rx_setup(skge, e, nskb, skge->rx_buf_size);
-               return skb;
        }
+
+       skb_put(skb, len);
+       skb->dev = skge->netdev;
+       if (skge->rx_csum) {
+               skb->csum = csum;
+               skb->ip_summed = CHECKSUM_HW;
+       }
+
+       skb->protocol = eth_type_trans(skb, skge->netdev);
+
+       return skb;
+error:
+
+       if (netif_msg_rx_err(skge))
+               printk(KERN_DEBUG PFX "%s: rx err, slot %td control 0x%x status 0x%x\n",
+                      skge->netdev->name, e - skge->rx_ring.start,
+                      control, status);
+
+       if (skge->hw->chip_id == CHIP_ID_GENESIS) {
+               if (status & (XMR_FS_RUNT|XMR_FS_LNG_ERR))
+                       skge->net_stats.rx_length_errors++;
+               if (status & XMR_FS_FRA_ERR)
+                       skge->net_stats.rx_frame_errors++;
+               if (status & XMR_FS_FCS_ERR)
+                       skge->net_stats.rx_crc_errors++;
+       } else {
+               if (status & (GMR_FS_LONG_ERR|GMR_FS_UN_SIZE))
+                       skge->net_stats.rx_length_errors++;
+               if (status & GMR_FS_FRAGMENT)
+                       skge->net_stats.rx_frame_errors++;
+               if (status & GMR_FS_CRC_ERR)
+                       skge->net_stats.rx_crc_errors++;
+       }
+
+resubmit:
+       skge_rx_reuse(e, skge->rx_buf_size);
+       return NULL;
 }
 
 
@@ -2530,37 +2559,19 @@ 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;
-               u32 control, len, status;
+               u32 control;
 
                rmb();
                control = rd->control;
                if (control & BMU_OWN)
                        break;
 
-               len = control & BMU_BBC;
-               status = rd->status;
-
-               if (unlikely((control & (BMU_EOF|BMU_STF)) != (BMU_STF|BMU_EOF)
-                            || bad_phy_status(hw, status))) {
-                       skge_rx_error(skge, e - ring->start, control, status);
-                       skge_rx_reuse(e, skge->rx_buf_size);
-                       continue;
-               }
-
-               if (netif_msg_rx_status(skge))
-                   printk(KERN_DEBUG PFX "%s: rx slot %td status 0x%x len %d\n",
-                          dev->name, e - ring->start, rd->status, len);
-
-               skb = skge_rx_get(skge, e, len);
+               skb = skge_rx_get(skge, e, control, rd->status,
+                                 le16_to_cpu(rd->csum2));
                if (likely(skb)) {
-                       skb_put(skb, len);
-                       skb->protocol = eth_type_trans(skb, dev);
-
                        dev->last_rx = jiffies;
                        netif_receive_skb(skb);
 
@@ -2672,9 +2683,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 +3011,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 +3238,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 +3251,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 +3270,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;
index f1680beb8e68a903d22228755bc84526656d4b1e..72c175b87a5a26d8aeb15bfb286712cebb5ef364 100644 (file)
@@ -953,6 +953,7 @@ enum {
  */
 enum {
        XMR_FS_LEN      = 0x3fff<<18,   /* Bit 31..18:  Rx Frame Length */
+       XMR_FS_LEN_SHIFT = 18,
        XMR_FS_2L_VLAN  = 1<<17, /* Bit 17:     tagged wh 2Lev VLAN ID*/
        XMR_FS_1_VLAN   = 1<<16, /* Bit 16:     tagged wh 1ev VLAN ID*/
        XMR_FS_BC       = 1<<15, /* Bit 15:     Broadcast Frame */
@@ -1868,6 +1869,7 @@ enum {
 /* Receive Frame Status Encoding */
 enum {
        GMR_FS_LEN      = 0xffff<<16, /* Bit 31..16:    Rx Frame Length */
+       GMR_FS_LEN_SHIFT = 16,
        GMR_FS_VLAN     = 1<<13, /* Bit 13:     VLAN Packet */
        GMR_FS_JABBER   = 1<<12, /* Bit 12:     Jabber Packet */
        GMR_FS_UN_SIZE  = 1<<11, /* Bit 11:     Undersize Packet */
@@ -2008,7 +2010,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 */
index 4e19220473d0ddcaaa1a0417647a827f6bfca597..c796f41b4a52f3f8c0d91de463bc2dd6cda0cff2 100644 (file)
@@ -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");
index 7599f52e15b3ca65abd356ce4e13d424e064a21c..81f4aedf534c32bfe1faaabb8dd4cc301b00f3ab 100644 (file)
@@ -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);
index 26cc4f6378c70011f586e5f5111a1a47843b0adc..60d1e05ab732360af639655550cc24314d342b46 100644 (file)
@@ -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
 
index 48c03c11cd9a36bc28b115fe3a52c1c0ccbe9362..a01efa6d5c629bd81457a64769f015f75ebea4c7 100644 (file)
@@ -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);
index 2be65d308fbeab14e24f759a2da5ebca6b90c8bf..06998c2240d9f167096426a582ec588bebbce7fc 100644 (file)
@@ -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);
 
index d1fb1bab8aa879c2322398f493fba934355bb848..bedd7f9f23e48cd37201e79f6a3b4c3b35697bc6 100644 (file)
@@ -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),
index 10444988a10b58532dd942a0af906594904bd5fe..e1743be3190938b3f7d9107c228d9c0f9aa11677 100644 (file)
@@ -7,7 +7,6 @@ int pci_hotplug (struct device *dev, char **envp, int num_envp,
                 char *buffer, int buffer_size)
 {
        struct pci_dev *pdev;
-       char *scratch;
        int i = 0;
        int length = 0;
 
@@ -18,9 +17,6 @@ int pci_hotplug (struct device *dev, char **envp, int num_envp,
        if (!pdev)
                return -ENODEV;
 
-       scratch = buffer;
-
-
        if (add_hotplug_env_var(envp, num_envp, &i,
                                buffer, buffer_size, &length,
                                "PCI_CLASS=%04X", pdev->class))
index 8122fe734aa78d40cd23ea6bd236dcbb040a0bcb..b1ba429e0a2ddca4aa84cb99a2533d47dbda2e0f 100644 (file)
@@ -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;
index 0e0947601526e8df2c4069609feab765cd2ce3dc..898f6da6f0dec65fae4500f44e4872ce1614cd2b 100644 (file)
@@ -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);
index 752e6513c447dce6ab3f5882a075e0f66eaf9dca..db69be85b4583100907368d580d03c35779a7576 100644 (file)
@@ -62,7 +62,7 @@ static ssize_t add_slot_store(struct dlpar_io_attr *dlpar_attr,
        char drc_name[MAX_DRC_NAME_LEN];
        char *end;
 
-       if (nbytes > MAX_DRC_NAME_LEN)
+       if (nbytes >= MAX_DRC_NAME_LEN)
                return 0;
 
        memcpy(drc_name, buf, nbytes);
@@ -83,7 +83,7 @@ static ssize_t remove_slot_store(struct dlpar_io_attr *dlpar_attr,
        char drc_name[MAX_DRC_NAME_LEN];
        char *end;
 
-       if (nbytes > MAX_DRC_NAME_LEN)
+       if (nbytes >= MAX_DRC_NAME_LEN)
                return 0;
 
        memcpy(drc_name, buf, nbytes);
index b1409441c1cde52a605e6daf4e6d40ec173e5e52..a32ae82e59220b22a8cd305b69eed2971024a55e 100644 (file)
@@ -159,7 +159,7 @@ static int sn_hp_slot_private_alloc(struct hotplug_slot *bss_hotplug_slot,
 
        pcibus_info = SN_PCIBUS_BUSSOFT_INFO(pci_bus);
 
-       slot = kcalloc(1, sizeof(*slot), GFP_KERNEL);
+       slot = kzalloc(sizeof(*slot), GFP_KERNEL);
        if (!slot)
                return -ENOMEM;
        bss_hotplug_slot->private = slot;
@@ -491,7 +491,7 @@ static int sn_hotplug_slot_register(struct pci_bus *pci_bus)
                if (sn_pci_slot_valid(pci_bus, device) != 1)
                        continue;
 
-               bss_hotplug_slot = kcalloc(1, sizeof(*bss_hotplug_slot),
+               bss_hotplug_slot = kzalloc(sizeof(*bss_hotplug_slot),
                                           GFP_KERNEL);
                if (!bss_hotplug_slot) {
                        rc = -ENOMEM;
@@ -499,7 +499,7 @@ static int sn_hotplug_slot_register(struct pci_bus *pci_bus)
                }
 
                bss_hotplug_slot->info =
-                       kcalloc(1, sizeof(struct hotplug_slot_info),
+                       kzalloc(sizeof(struct hotplug_slot_info),
                                GFP_KERNEL);
                if (!bss_hotplug_slot->info) {
                        rc = -ENOMEM;
index 783b5abb07172e70b2f376658fce051ba4dd57c0..91c9903e621fc786d9058276e037d1824d801e36 100644 (file)
@@ -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);
index 56a3b397efee217736b1ce54d6f7621619cb04f4..2898830c496fca15ae10e77ea09d2b4839a20d0c 100644 (file)
@@ -360,7 +360,7 @@ pci_create_resource_files(struct pci_dev *pdev)
                        continue;
 
                /* allocate attribute structure, piggyback attribute name */
-               res_attr = kcalloc(1, sizeof(*res_attr) + 10, GFP_ATOMIC);
+               res_attr = kzalloc(sizeof(*res_attr) + 10, GFP_ATOMIC);
                if (res_attr) {
                        char *res_attr_name = (char *)(res_attr + 1);
 
index 992db89adce7b2ea6b03902f012b664d1ff7f0fe..259d247b75513e5da263edeaea9ee7769596516e 100644 (file)
@@ -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 */
index 26a55d08b506afde854a79dc4bfebd4e57c1ed6a..005786416bb5be5cc7a99f010f9ed0662f64706c 100644 (file)
@@ -165,7 +165,7 @@ static void pci_read_bases(struct pci_dev *dev, unsigned int howmany, int rom)
                if (l == 0xffffffff)
                        l = 0;
                if ((l & PCI_BASE_ADDRESS_SPACE) == PCI_BASE_ADDRESS_SPACE_MEMORY) {
-                       sz = pci_size(l, sz, PCI_BASE_ADDRESS_MEM_MASK);
+                       sz = pci_size(l, sz, (u32)PCI_BASE_ADDRESS_MEM_MASK);
                        if (!sz)
                                continue;
                        res->start = l & PCI_BASE_ADDRESS_MEM_MASK;
@@ -215,7 +215,7 @@ static void pci_read_bases(struct pci_dev *dev, unsigned int howmany, int rom)
                if (l == 0xffffffff)
                        l = 0;
                if (sz && sz != 0xffffffff) {
-                       sz = pci_size(l, sz, PCI_ROM_ADDRESS_MASK);
+                       sz = pci_size(l, sz, (u32)PCI_ROM_ADDRESS_MASK);
                        if (sz) {
                                res->flags = (l & IORESOURCE_ROM_ENABLE) |
                                  IORESOURCE_MEM | IORESOURCE_PREFETCH |
@@ -402,6 +402,12 @@ static void pci_enable_crs(struct pci_dev *dev)
 static void __devinit pci_fixup_parent_subordinate_busnr(struct pci_bus *child, int max)
 {
        struct pci_bus *parent = child->parent;
+
+       /* Attempts to fix that up are really dangerous unless
+          we're going to re-assign all bus numbers. */
+       if (!pcibios_assign_all_busses())
+               return;
+
        while (parent->parent && parent->subordinate < max) {
                parent->subordinate = max;
                pci_write_config_byte(parent->self, PCI_SUBORDINATE_BUS, max);
@@ -478,8 +484,18 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev * dev, int max
                 * We need to assign a number to this bus which we always
                 * do in the second pass.
                 */
-               if (!pass)
+               if (!pass) {
+                       if (pcibios_assign_all_busses())
+                               /* Temporarily disable forwarding of the
+                                  configuration cycles on all bridges in
+                                  this bus segment to avoid possible
+                                  conflicts in the second pass between two
+                                  bridges programmed with overlapping
+                                  bus ranges. */
+                               pci_write_config_dword(dev, PCI_PRIMARY_BUS,
+                                                      buses & ~0xffffff);
                        return max;
+               }
 
                /* Clear errors */
                pci_write_config_word(dev, PCI_STATUS, 0xffff);
index 39ba6406fd54ef8b9a398eafb3c425a6706837f5..80969f7e7a0be4eddc31e675ab404e6f144593f3 100644 (file)
@@ -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;
index f0997c36c9b714b9aaf3a675c6cfb27b96616cdd..ba4d78e5b121fdd126fd54d7651a4740da83490f 100644 (file)
@@ -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;
index aac83ce6469cf8ef57e9926848993dd6a27f2c2a..a1c52a682191555ff600eed6917ebd1d5902bf27 100644 (file)
@@ -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;
index 91ea8e4777f340b2c47fe76ac5f68cab43e54ffa..dbb3eb0e330b00d017ca7b98817d8f2fde5f4932 100644 (file)
@@ -437,7 +437,7 @@ __ccwgroup_get_gdev_by_cdev(struct ccw_device *cdev)
        if (cdev->dev.driver_data) {
                gdev = (struct ccwgroup_device *)cdev->dev.driver_data;
                if (get_device(&gdev->dev)) {
-                       if (klist_node_attached(&gdev->dev.knode_bus))
+                       if (device_is_registered(&gdev->dev))
                                return gdev;
                        put_device(&gdev->dev);
                }
index 6aeef3bacc3345407c1fa0b061585feb003722b9..0cb47eca91f3d9d459132ee34574da528c7f0831 100644 (file)
@@ -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");
index 96ca863eaff2826fe30c46e9d9a961a5a9fa3131..0db4f57a6a95e4a60538031bcdd09b9ae7a51eb8 100644 (file)
@@ -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
  *
  * 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 $
  *
  */
-\f
 #undef DEBUG
 #include <linux/module.h>
 #include <linux/init.h>
@@ -135,7 +134,7 @@ static const char *dev_event_names[] = {
        "TX down",
        "Restart",
 };
-\f
+
 /**
  * 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",
 };
-\f
+
 #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)
 {
 }
-\f
+
 /**
  * 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);
 }
 
-\f
 /**
  * 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);
-\f
+
 /**
  * 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);
 
 }
-\f
+
 /**
  * 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;
 }
-\f
+
 /**
  * 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;
 }
 
-\f
 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)
 {
index 3a0285669adfab840b0bcd0d775fffe72f5bfdc5..2ad4797ce024b058e460e1cca6334cf9d32d729e 100644 (file)
@@ -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 *,
index 79c74f3a11f5f471d79fa6c3507e56d9fe553a33..86582cf1e19e01026556effa5ef2b13162806a47 100644 (file)
@@ -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
  * 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>");
index 98bedb0cb3875a87e2bd2d78b7b2fd34c2f94d77..dda105b73063d09a7091b25c627c1c28e05985ed 100644 (file)
@@ -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;
 }
 
index fc145307a7d46e41cffed34be8243d2ec89bf2ec..d6a78f1a2f16e72680be37eba86d40be2c8e6441 100644 (file)
@@ -3,7 +3,7 @@
 #
 
 zfcp-objs := zfcp_aux.o zfcp_ccw.o zfcp_scsi.o zfcp_erp.o zfcp_qdio.o \
-            zfcp_fsf.o zfcp_sysfs_adapter.o zfcp_sysfs_port.o \
+            zfcp_fsf.o zfcp_dbf.o zfcp_sysfs_adapter.o zfcp_sysfs_port.o \
             zfcp_sysfs_unit.o zfcp_sysfs_driver.o
 
 obj-$(CONFIG_ZFCP) += zfcp.o
index bfe3ba73bc0f65310f58caa67e2b46412992d0c1..0b5087f7cabc3bced7e87f0f78fe77ea0fcb01af 100644 (file)
@@ -122,95 +122,6 @@ _zfcp_hex_dump(char *addr, int count)
 
 #define ZFCP_LOG_AREA                  ZFCP_LOG_AREA_OTHER
 
-static inline int
-zfcp_fsf_req_is_scsi_cmnd(struct zfcp_fsf_req *fsf_req)
-{
-       return ((fsf_req->fsf_command == FSF_QTCB_FCP_CMND) &&
-               !(fsf_req->status & ZFCP_STATUS_FSFREQ_TASK_MANAGEMENT));
-}
-
-void
-zfcp_cmd_dbf_event_fsf(const char *text, struct zfcp_fsf_req *fsf_req,
-                      void *add_data, int add_length)
-{
-       struct zfcp_adapter *adapter = fsf_req->adapter;
-       struct scsi_cmnd *scsi_cmnd;
-       int level = 3;
-       int i;
-       unsigned long flags;
-
-       spin_lock_irqsave(&adapter->dbf_lock, flags);
-       if (zfcp_fsf_req_is_scsi_cmnd(fsf_req)) {
-               scsi_cmnd = fsf_req->data.send_fcp_command_task.scsi_cmnd;
-               debug_text_event(adapter->cmd_dbf, level, "fsferror");
-               debug_text_event(adapter->cmd_dbf, level, text);
-               debug_event(adapter->cmd_dbf, level, &fsf_req,
-                           sizeof (unsigned long));
-               debug_event(adapter->cmd_dbf, level, &fsf_req->seq_no,
-                           sizeof (u32));
-               debug_event(adapter->cmd_dbf, level, &scsi_cmnd,
-                           sizeof (unsigned long));
-               debug_event(adapter->cmd_dbf, level, &scsi_cmnd->cmnd,
-                           min(ZFCP_CMD_DBF_LENGTH, (int)scsi_cmnd->cmd_len));
-               for (i = 0; i < add_length; i += ZFCP_CMD_DBF_LENGTH)
-                       debug_event(adapter->cmd_dbf,
-                                   level,
-                                   (char *) add_data + i,
-                                   min(ZFCP_CMD_DBF_LENGTH, add_length - i));
-       }
-       spin_unlock_irqrestore(&adapter->dbf_lock, flags);
-}
-
-/* XXX additionally log unit if available */
-/* ---> introduce new parameter for unit, see 2.4 code */
-void
-zfcp_cmd_dbf_event_scsi(const char *text, struct scsi_cmnd *scsi_cmnd)
-{
-       struct zfcp_adapter *adapter;
-       union zfcp_req_data *req_data;
-       struct zfcp_fsf_req *fsf_req;
-       int level = ((host_byte(scsi_cmnd->result) != 0) ? 1 : 5);
-       unsigned long flags;
-
-       adapter = (struct zfcp_adapter *) scsi_cmnd->device->host->hostdata[0];
-       req_data = (union zfcp_req_data *) scsi_cmnd->host_scribble;
-       fsf_req = (req_data ? req_data->send_fcp_command_task.fsf_req : NULL);
-       spin_lock_irqsave(&adapter->dbf_lock, flags);
-       debug_text_event(adapter->cmd_dbf, level, "hostbyte");
-       debug_text_event(adapter->cmd_dbf, level, text);
-       debug_event(adapter->cmd_dbf, level, &scsi_cmnd->result, sizeof (u32));
-       debug_event(adapter->cmd_dbf, level, &scsi_cmnd,
-                   sizeof (unsigned long));
-       debug_event(adapter->cmd_dbf, level, &scsi_cmnd->cmnd,
-                   min(ZFCP_CMD_DBF_LENGTH, (int)scsi_cmnd->cmd_len));
-       if (likely(fsf_req)) {
-               debug_event(adapter->cmd_dbf, level, &fsf_req,
-                           sizeof (unsigned long));
-               debug_event(adapter->cmd_dbf, level, &fsf_req->seq_no,
-                           sizeof (u32));
-       } else {
-               debug_text_event(adapter->cmd_dbf, level, "");
-               debug_text_event(adapter->cmd_dbf, level, "");
-       }
-       spin_unlock_irqrestore(&adapter->dbf_lock, flags);
-}
-
-void
-zfcp_in_els_dbf_event(struct zfcp_adapter *adapter, const char *text,
-                     struct fsf_status_read_buffer *status_buffer, int length)
-{
-       int level = 1;
-       int i;
-
-       debug_text_event(adapter->in_els_dbf, level, text);
-       debug_event(adapter->in_els_dbf, level, &status_buffer->d_id, 8);
-       for (i = 0; i < length; i += ZFCP_IN_ELS_DBF_LENGTH)
-               debug_event(adapter->in_els_dbf,
-                           level,
-                           (char *) status_buffer->payload + i,
-                           min(ZFCP_IN_ELS_DBF_LENGTH, length - i));
-}
-
 /**
  * zfcp_device_setup - setup function
  * @str: pointer to parameter string
@@ -1017,81 +928,6 @@ zfcp_free_low_mem_buffers(struct zfcp_adapter *adapter)
                mempool_destroy(adapter->pool.data_gid_pn);
 }
 
-/**
- * zfcp_adapter_debug_register - registers debug feature for an adapter
- * @adapter: pointer to adapter for which debug features should be registered
- * return: -ENOMEM on error, 0 otherwise
- */
-int
-zfcp_adapter_debug_register(struct zfcp_adapter *adapter)
-{
-       char dbf_name[20];
-
-       /* debug feature area which records SCSI command failures (hostbyte) */
-       spin_lock_init(&adapter->dbf_lock);
-
-       sprintf(dbf_name, ZFCP_CMD_DBF_NAME "%s",
-               zfcp_get_busid_by_adapter(adapter));
-       adapter->cmd_dbf = debug_register(dbf_name, ZFCP_CMD_DBF_INDEX,
-                                         ZFCP_CMD_DBF_AREAS,
-                                         ZFCP_CMD_DBF_LENGTH);
-       debug_register_view(adapter->cmd_dbf, &debug_hex_ascii_view);
-       debug_set_level(adapter->cmd_dbf, ZFCP_CMD_DBF_LEVEL);
-
-       /* debug feature area which records SCSI command aborts */
-       sprintf(dbf_name, ZFCP_ABORT_DBF_NAME "%s",
-               zfcp_get_busid_by_adapter(adapter));
-       adapter->abort_dbf = debug_register(dbf_name, ZFCP_ABORT_DBF_INDEX,
-                                           ZFCP_ABORT_DBF_AREAS,
-                                           ZFCP_ABORT_DBF_LENGTH);
-       debug_register_view(adapter->abort_dbf, &debug_hex_ascii_view);
-       debug_set_level(adapter->abort_dbf, ZFCP_ABORT_DBF_LEVEL);
-
-       /* debug feature area which records incoming ELS commands */
-       sprintf(dbf_name, ZFCP_IN_ELS_DBF_NAME "%s",
-               zfcp_get_busid_by_adapter(adapter));
-       adapter->in_els_dbf = debug_register(dbf_name, ZFCP_IN_ELS_DBF_INDEX,
-                                            ZFCP_IN_ELS_DBF_AREAS,
-                                            ZFCP_IN_ELS_DBF_LENGTH);
-       debug_register_view(adapter->in_els_dbf, &debug_hex_ascii_view);
-       debug_set_level(adapter->in_els_dbf, ZFCP_IN_ELS_DBF_LEVEL);
-
-       /* debug feature area which records erp events */
-       sprintf(dbf_name, ZFCP_ERP_DBF_NAME "%s",
-               zfcp_get_busid_by_adapter(adapter));
-       adapter->erp_dbf = debug_register(dbf_name, ZFCP_ERP_DBF_INDEX,
-                                         ZFCP_ERP_DBF_AREAS,
-                                         ZFCP_ERP_DBF_LENGTH);
-       debug_register_view(adapter->erp_dbf, &debug_hex_ascii_view);
-       debug_set_level(adapter->erp_dbf, ZFCP_ERP_DBF_LEVEL);
-
-       if (!(adapter->cmd_dbf && adapter->abort_dbf &&
-             adapter->in_els_dbf && adapter->erp_dbf)) {
-               zfcp_adapter_debug_unregister(adapter);
-               return -ENOMEM;
-       }
-
-       return 0;
-
-}
-
-/**
- * zfcp_adapter_debug_unregister - unregisters debug feature for an adapter
- * @adapter: pointer to adapter for which debug features should be unregistered
- */
-void
-zfcp_adapter_debug_unregister(struct zfcp_adapter *adapter)
-{
-       debug_unregister(adapter->abort_dbf);
-       debug_unregister(adapter->cmd_dbf);
-       debug_unregister(adapter->erp_dbf);
-       debug_unregister(adapter->in_els_dbf);
-       adapter->abort_dbf = NULL;
-       adapter->cmd_dbf = NULL;
-       adapter->erp_dbf = NULL;
-       adapter->in_els_dbf = NULL;
-}
-
 void
 zfcp_dummy_release(struct device *dev)
 {
@@ -1462,10 +1298,6 @@ zfcp_fsf_incoming_els_rscn(struct zfcp_adapter *adapter,
        /* see FC-FS */
        no_entries = (fcp_rscn_head->payload_len / 4);
 
-       zfcp_in_els_dbf_event(adapter, "##rscn", status_buffer,
-                             fcp_rscn_head->payload_len);
-
-       debug_text_event(adapter->erp_dbf, 1, "unsol_els_rscn:");
        for (i = 1; i < no_entries; i++) {
                /* skip head and start with 1st element */
                fcp_rscn_element++;
@@ -1497,8 +1329,6 @@ zfcp_fsf_incoming_els_rscn(struct zfcp_adapter *adapter,
                            (ZFCP_STATUS_PORT_DID_DID, &port->status)) {
                                ZFCP_LOG_INFO("incoming RSCN, trying to open "
                                              "port 0x%016Lx\n", port->wwpn);
-                               debug_text_event(adapter->erp_dbf, 1,
-                                                "unsol_els_rscnu:");
                                zfcp_erp_port_reopen(port,
                                                     ZFCP_STATUS_COMMON_ERP_FAILED);
                                continue;
@@ -1524,8 +1354,6 @@ zfcp_fsf_incoming_els_rscn(struct zfcp_adapter *adapter,
                                 */
                                ZFCP_LOG_INFO("incoming RSCN, trying to open "
                                              "port 0x%016Lx\n", port->wwpn);
-                               debug_text_event(adapter->erp_dbf, 1,
-                                                "unsol_els_rscnk:");
                                zfcp_test_link(port);
                        }
                }
@@ -1541,8 +1369,6 @@ zfcp_fsf_incoming_els_plogi(struct zfcp_adapter *adapter,
        struct zfcp_port *port;
        unsigned long flags;
 
-       zfcp_in_els_dbf_event(adapter, "##plogi", status_buffer, 28);
-
        read_lock_irqsave(&zfcp_data.config_lock, flags);
        list_for_each_entry(port, &adapter->port_list_head, list) {
                if (port->wwpn == (*(wwn_t *) & els_logi->nport_wwn))
@@ -1556,8 +1382,6 @@ zfcp_fsf_incoming_els_plogi(struct zfcp_adapter *adapter,
                               status_buffer->d_id,
                               zfcp_get_busid_by_adapter(adapter));
        } else {
-               debug_text_event(adapter->erp_dbf, 1, "unsol_els_plogi:");
-               debug_event(adapter->erp_dbf, 1, &els_logi->nport_wwn, 8);
                zfcp_erp_port_forced_reopen(port, 0);
        }
 }
@@ -1570,8 +1394,6 @@ zfcp_fsf_incoming_els_logo(struct zfcp_adapter *adapter,
        struct zfcp_port *port;
        unsigned long flags;
 
-       zfcp_in_els_dbf_event(adapter, "##logo", status_buffer, 16);
-
        read_lock_irqsave(&zfcp_data.config_lock, flags);
        list_for_each_entry(port, &adapter->port_list_head, list) {
                if (port->wwpn == els_logo->nport_wwpn)
@@ -1585,8 +1407,6 @@ zfcp_fsf_incoming_els_logo(struct zfcp_adapter *adapter,
                               status_buffer->d_id,
                               zfcp_get_busid_by_adapter(adapter));
        } else {
-               debug_text_event(adapter->erp_dbf, 1, "unsol_els_logo:");
-               debug_event(adapter->erp_dbf, 1, &els_logo->nport_wwpn, 8);
                zfcp_erp_port_forced_reopen(port, 0);
        }
 }
@@ -1595,7 +1415,6 @@ static void
 zfcp_fsf_incoming_els_unknown(struct zfcp_adapter *adapter,
                              struct fsf_status_read_buffer *status_buffer)
 {
-       zfcp_in_els_dbf_event(adapter, "##undef", status_buffer, 24);
        ZFCP_LOG_NORMAL("warning: unknown incoming ELS 0x%08x "
                        "for adapter %s\n", *(u32 *) (status_buffer->payload),
                        zfcp_get_busid_by_adapter(adapter));
@@ -1609,10 +1428,11 @@ zfcp_fsf_incoming_els(struct zfcp_fsf_req *fsf_req)
        u32 els_type;
        struct zfcp_adapter *adapter;
 
-       status_buffer = fsf_req->data.status_read.buffer;
+       status_buffer = (struct fsf_status_read_buffer *) fsf_req->data;
        els_type = *(u32 *) (status_buffer->payload);
        adapter = fsf_req->adapter;
 
+       zfcp_san_dbf_event_incoming_els(fsf_req);
        if (els_type == LS_PLOGI)
                zfcp_fsf_incoming_els_plogi(adapter, status_buffer);
        else if (els_type == LS_LOGO)
index b30abab77da39841b8c0db3f37545fd3ae540b07..0fc46381fc22735d1a884fe24f913e200dfbb770 100644 (file)
@@ -202,19 +202,9 @@ static int
 zfcp_ccw_set_offline(struct ccw_device *ccw_device)
 {
        struct zfcp_adapter *adapter;
-       struct zfcp_port *port;
-       struct fc_rport *rport;
 
        down(&zfcp_data.config_sema);
        adapter = dev_get_drvdata(&ccw_device->dev);
-       /* might be racy, but we cannot take config_lock due to the fact that
-          fc_remote_port_delete might sleep */
-       list_for_each_entry(port, &adapter->port_list_head, list)
-               if (port->rport) {
-                       rport = port->rport;
-                       port->rport = NULL;
-                       fc_remote_port_delete(rport);
-               }
        zfcp_erp_adapter_shutdown(adapter, 0);
        zfcp_erp_wait(adapter);
        zfcp_adapter_scsi_unregister(adapter);
diff --git a/drivers/s390/scsi/zfcp_dbf.c b/drivers/s390/scsi/zfcp_dbf.c
new file mode 100644 (file)
index 0000000..826fb3b
--- /dev/null
@@ -0,0 +1,995 @@
+/*
+ *
+ * linux/drivers/s390/scsi/zfcp_dbf.c
+ *
+ * FCP adapter driver for IBM eServer zSeries
+ *
+ * Debugging facilities
+ *
+ * (C) Copyright IBM Corp. 2005
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#define ZFCP_DBF_REVISION "$Revision$"
+
+#include <asm/debug.h>
+#include <linux/ctype.h>
+#include "zfcp_ext.h"
+
+static u32 dbfsize = 4;
+
+module_param(dbfsize, uint, 0400);
+MODULE_PARM_DESC(dbfsize,
+                "number of pages for each debug feature area (default 4)");
+
+#define ZFCP_LOG_AREA                  ZFCP_LOG_AREA_OTHER
+
+static inline int
+zfcp_dbf_stck(char *out_buf, const char *label, unsigned long long stck)
+{
+       unsigned long long sec;
+       struct timespec xtime;
+       int len = 0;
+
+       stck -= 0x8126d60e46000000LL - (0x3c26700LL * 1000000 * 4096);
+       sec = stck >> 12;
+       do_div(sec, 1000000);
+       xtime.tv_sec = sec;
+       stck -= (sec * 1000000) << 12;
+       xtime.tv_nsec = ((stck * 1000) >> 12);
+       len += sprintf(out_buf + len, "%-24s%011lu:%06lu\n",
+                      label, xtime.tv_sec, xtime.tv_nsec);
+
+       return len;
+}
+
+static int zfcp_dbf_tag(char *out_buf, const char *label, const char *tag)
+{
+       int len = 0, i;
+
+       len += sprintf(out_buf + len, "%-24s", label);
+       for (i = 0; i < ZFCP_DBF_TAG_SIZE; i++)
+               len += sprintf(out_buf + len, "%c", tag[i]);
+       len += sprintf(out_buf + len, "\n");
+
+       return len;
+}
+
+static int
+zfcp_dbf_view(char *out_buf, const char *label, const char *format, ...)
+{
+       va_list arg;
+       int len = 0;
+
+       len += sprintf(out_buf + len, "%-24s", label);
+       va_start(arg, format);
+       len += vsprintf(out_buf + len, format, arg);
+       va_end(arg);
+       len += sprintf(out_buf + len, "\n");
+
+       return len;
+}
+
+static int
+zfcp_dbf_view_dump(char *out_buf, const char *label,
+                  char *buffer, int buflen, int offset, int total_size)
+{
+       int len = 0;
+
+       if (offset == 0)
+               len += sprintf(out_buf + len, "%-24s  ", label);
+
+       while (buflen--) {
+               if (offset > 0) {
+                       if ((offset % 32) == 0)
+                               len += sprintf(out_buf + len, "\n%-24c  ", ' ');
+                       else if ((offset % 4) == 0)
+                               len += sprintf(out_buf + len, " ");
+               }
+               len += sprintf(out_buf + len, "%02x", *buffer++);
+               if (++offset == total_size) {
+                       len += sprintf(out_buf + len, "\n");
+                       break;
+               }
+       }
+
+       if (total_size == 0)
+               len += sprintf(out_buf + len, "\n");
+
+       return len;
+}
+
+static inline int
+zfcp_dbf_view_header(debug_info_t * id, struct debug_view *view, int area,
+                    debug_entry_t * entry, char *out_buf)
+{
+       struct zfcp_dbf_dump *dump = (struct zfcp_dbf_dump *)DEBUG_DATA(entry);
+       int len = 0;
+
+       if (strncmp(dump->tag, "dump", ZFCP_DBF_TAG_SIZE) != 0) {
+               len += zfcp_dbf_stck(out_buf + len, "timestamp",
+                                    entry->id.stck);
+               len += zfcp_dbf_view(out_buf + len, "cpu", "%02i",
+                                    entry->id.fields.cpuid);
+       } else {
+               len += zfcp_dbf_view_dump(out_buf + len, NULL,
+                                         dump->data,
+                                         dump->size,
+                                         dump->offset, dump->total_size);
+               if ((dump->offset + dump->size) == dump->total_size)
+                       len += sprintf(out_buf + len, "\n");
+       }
+
+       return len;
+}
+
+inline void zfcp_hba_dbf_event_fsf_response(struct zfcp_fsf_req *fsf_req)
+{
+       struct zfcp_adapter *adapter = fsf_req->adapter;
+       struct fsf_qtcb *qtcb = fsf_req->qtcb;
+       union fsf_prot_status_qual *prot_status_qual =
+           &qtcb->prefix.prot_status_qual;
+       union fsf_status_qual *fsf_status_qual = &qtcb->header.fsf_status_qual;
+       struct scsi_cmnd *scsi_cmnd;
+       struct zfcp_port *port;
+       struct zfcp_unit *unit;
+       struct zfcp_send_els *send_els;
+       struct zfcp_hba_dbf_record *rec = &adapter->hba_dbf_buf;
+       struct zfcp_hba_dbf_record_response *response = &rec->type.response;
+       int level;
+       unsigned long flags;
+
+       spin_lock_irqsave(&adapter->hba_dbf_lock, flags);
+       memset(rec, 0, sizeof(struct zfcp_hba_dbf_record));
+       strncpy(rec->tag, "resp", ZFCP_DBF_TAG_SIZE);
+
+       if ((qtcb->prefix.prot_status != FSF_PROT_GOOD) &&
+           (qtcb->prefix.prot_status != FSF_PROT_FSF_STATUS_PRESENTED)) {
+               strncpy(rec->tag2, "perr", ZFCP_DBF_TAG_SIZE);
+               level = 1;
+       } else if (qtcb->header.fsf_status != FSF_GOOD) {
+               strncpy(rec->tag2, "ferr", ZFCP_DBF_TAG_SIZE);
+               level = 1;
+       } else if ((fsf_req->fsf_command == FSF_QTCB_OPEN_PORT_WITH_DID) ||
+                  (fsf_req->fsf_command == FSF_QTCB_OPEN_LUN)) {
+               strncpy(rec->tag2, "open", ZFCP_DBF_TAG_SIZE);
+               level = 4;
+       } else if ((prot_status_qual->doubleword[0] != 0) ||
+                  (prot_status_qual->doubleword[1] != 0) ||
+                  (fsf_status_qual->doubleword[0] != 0) ||
+                  (fsf_status_qual->doubleword[1] != 0)) {
+               strncpy(rec->tag2, "qual", ZFCP_DBF_TAG_SIZE);
+               level = 3;
+       } else {
+               strncpy(rec->tag2, "norm", ZFCP_DBF_TAG_SIZE);
+               level = 6;
+       }
+
+       response->fsf_command = fsf_req->fsf_command;
+       response->fsf_reqid = (unsigned long)fsf_req;
+       response->fsf_seqno = fsf_req->seq_no;
+       response->fsf_issued = fsf_req->issued;
+       response->fsf_prot_status = qtcb->prefix.prot_status;
+       response->fsf_status = qtcb->header.fsf_status;
+       memcpy(response->fsf_prot_status_qual,
+              prot_status_qual, FSF_PROT_STATUS_QUAL_SIZE);
+       memcpy(response->fsf_status_qual,
+              fsf_status_qual, FSF_STATUS_QUALIFIER_SIZE);
+       response->fsf_req_status = fsf_req->status;
+       response->sbal_first = fsf_req->sbal_first;
+       response->sbal_curr = fsf_req->sbal_curr;
+       response->sbal_last = fsf_req->sbal_last;
+       response->pool = fsf_req->pool != NULL;
+       response->erp_action = (unsigned long)fsf_req->erp_action;
+
+       switch (fsf_req->fsf_command) {
+       case FSF_QTCB_FCP_CMND:
+               if (fsf_req->status & ZFCP_STATUS_FSFREQ_TASK_MANAGEMENT)
+                       break;
+               scsi_cmnd = (struct scsi_cmnd *)fsf_req->data;
+               if (scsi_cmnd != NULL) {
+                       response->data.send_fcp.scsi_cmnd
+                           = (unsigned long)scsi_cmnd;
+                       response->data.send_fcp.scsi_serial
+                           = scsi_cmnd->serial_number;
+               }
+               break;
+
+       case FSF_QTCB_OPEN_PORT_WITH_DID:
+       case FSF_QTCB_CLOSE_PORT:
+       case FSF_QTCB_CLOSE_PHYSICAL_PORT:
+               port = (struct zfcp_port *)fsf_req->data;
+               response->data.port.wwpn = port->wwpn;
+               response->data.port.d_id = port->d_id;
+               response->data.port.port_handle = qtcb->header.port_handle;
+               break;
+
+       case FSF_QTCB_OPEN_LUN:
+       case FSF_QTCB_CLOSE_LUN:
+               unit = (struct zfcp_unit *)fsf_req->data;
+               port = unit->port;
+               response->data.unit.wwpn = port->wwpn;
+               response->data.unit.fcp_lun = unit->fcp_lun;
+               response->data.unit.port_handle = qtcb->header.port_handle;
+               response->data.unit.lun_handle = qtcb->header.lun_handle;
+               break;
+
+       case FSF_QTCB_SEND_ELS:
+               send_els = (struct zfcp_send_els *)fsf_req->data;
+               response->data.send_els.d_id = qtcb->bottom.support.d_id;
+               response->data.send_els.ls_code = send_els->ls_code >> 24;
+               break;
+
+       case FSF_QTCB_ABORT_FCP_CMND:
+       case FSF_QTCB_SEND_GENERIC:
+       case FSF_QTCB_EXCHANGE_CONFIG_DATA:
+       case FSF_QTCB_EXCHANGE_PORT_DATA:
+       case FSF_QTCB_DOWNLOAD_CONTROL_FILE:
+       case FSF_QTCB_UPLOAD_CONTROL_FILE:
+               break;
+       }
+
+       debug_event(adapter->hba_dbf, level,
+                   rec, sizeof(struct zfcp_hba_dbf_record));
+       spin_unlock_irqrestore(&adapter->hba_dbf_lock, flags);
+}
+
+inline void
+zfcp_hba_dbf_event_fsf_unsol(const char *tag, struct zfcp_adapter *adapter,
+                            struct fsf_status_read_buffer *status_buffer)
+{
+       struct zfcp_hba_dbf_record *rec = &adapter->hba_dbf_buf;
+       unsigned long flags;
+
+       spin_lock_irqsave(&adapter->hba_dbf_lock, flags);
+       memset(rec, 0, sizeof(struct zfcp_hba_dbf_record));
+       strncpy(rec->tag, "stat", ZFCP_DBF_TAG_SIZE);
+       strncpy(rec->tag2, tag, ZFCP_DBF_TAG_SIZE);
+
+       rec->type.status.failed = adapter->status_read_failed;
+       if (status_buffer != NULL) {
+               rec->type.status.status_type = status_buffer->status_type;
+               rec->type.status.status_subtype = status_buffer->status_subtype;
+               memcpy(&rec->type.status.queue_designator,
+                      &status_buffer->queue_designator,
+                      sizeof(struct fsf_queue_designator));
+
+               switch (status_buffer->status_type) {
+               case FSF_STATUS_READ_SENSE_DATA_AVAIL:
+                       rec->type.status.payload_size =
+                           ZFCP_DBF_UNSOL_PAYLOAD_SENSE_DATA_AVAIL;
+                       break;
+
+               case FSF_STATUS_READ_BIT_ERROR_THRESHOLD:
+                       rec->type.status.payload_size =
+                           ZFCP_DBF_UNSOL_PAYLOAD_BIT_ERROR_THRESHOLD;
+                       break;
+
+               case FSF_STATUS_READ_LINK_DOWN:
+                       switch (status_buffer->status_subtype) {
+                       case FSF_STATUS_READ_SUB_NO_PHYSICAL_LINK:
+                       case FSF_STATUS_READ_SUB_FDISC_FAILED:
+                               rec->type.status.payload_size =
+                                       sizeof(struct fsf_link_down_info);
+                       }
+                       break;
+
+               case FSF_STATUS_READ_FEATURE_UPDATE_ALERT:
+                       rec->type.status.payload_size =
+                           ZFCP_DBF_UNSOL_PAYLOAD_FEATURE_UPDATE_ALERT;
+                       break;
+               }
+               memcpy(&rec->type.status.payload,
+                      &status_buffer->payload, rec->type.status.payload_size);
+       }
+
+       debug_event(adapter->hba_dbf, 2,
+                   rec, sizeof(struct zfcp_hba_dbf_record));
+       spin_unlock_irqrestore(&adapter->hba_dbf_lock, flags);
+}
+
+inline void
+zfcp_hba_dbf_event_qdio(struct zfcp_adapter *adapter, unsigned int status,
+                       unsigned int qdio_error, unsigned int siga_error,
+                       int sbal_index, int sbal_count)
+{
+       struct zfcp_hba_dbf_record *rec = &adapter->hba_dbf_buf;
+       unsigned long flags;
+
+       spin_lock_irqsave(&adapter->hba_dbf_lock, flags);
+       memset(rec, 0, sizeof(struct zfcp_hba_dbf_record));
+       strncpy(rec->tag, "qdio", ZFCP_DBF_TAG_SIZE);
+       rec->type.qdio.status = status;
+       rec->type.qdio.qdio_error = qdio_error;
+       rec->type.qdio.siga_error = siga_error;
+       rec->type.qdio.sbal_index = sbal_index;
+       rec->type.qdio.sbal_count = sbal_count;
+       debug_event(adapter->hba_dbf, 0,
+                   rec, sizeof(struct zfcp_hba_dbf_record));
+       spin_unlock_irqrestore(&adapter->hba_dbf_lock, flags);
+}
+
+static inline int
+zfcp_hba_dbf_view_response(char *out_buf,
+                          struct zfcp_hba_dbf_record_response *rec)
+{
+       int len = 0;
+
+       len += zfcp_dbf_view(out_buf + len, "fsf_command", "0x%08x",
+                            rec->fsf_command);
+       len += zfcp_dbf_view(out_buf + len, "fsf_reqid", "0x%0Lx",
+                            rec->fsf_reqid);
+       len += zfcp_dbf_view(out_buf + len, "fsf_seqno", "0x%08x",
+                            rec->fsf_seqno);
+       len += zfcp_dbf_stck(out_buf + len, "fsf_issued", rec->fsf_issued);
+       len += zfcp_dbf_view(out_buf + len, "fsf_prot_status", "0x%08x",
+                            rec->fsf_prot_status);
+       len += zfcp_dbf_view(out_buf + len, "fsf_status", "0x%08x",
+                            rec->fsf_status);
+       len += zfcp_dbf_view_dump(out_buf + len, "fsf_prot_status_qual",
+                                 rec->fsf_prot_status_qual,
+                                 FSF_PROT_STATUS_QUAL_SIZE,
+                                 0, FSF_PROT_STATUS_QUAL_SIZE);
+       len += zfcp_dbf_view_dump(out_buf + len, "fsf_status_qual",
+                                 rec->fsf_status_qual,
+                                 FSF_STATUS_QUALIFIER_SIZE,
+                                 0, FSF_STATUS_QUALIFIER_SIZE);
+       len += zfcp_dbf_view(out_buf + len, "fsf_req_status", "0x%08x",
+                            rec->fsf_req_status);
+       len += zfcp_dbf_view(out_buf + len, "sbal_first", "0x%02x",
+                            rec->sbal_first);
+       len += zfcp_dbf_view(out_buf + len, "sbal_curr", "0x%02x",
+                            rec->sbal_curr);
+       len += zfcp_dbf_view(out_buf + len, "sbal_last", "0x%02x",
+                            rec->sbal_last);
+       len += zfcp_dbf_view(out_buf + len, "pool", "0x%02x", rec->pool);
+
+       switch (rec->fsf_command) {
+       case FSF_QTCB_FCP_CMND:
+               if (rec->fsf_req_status & ZFCP_STATUS_FSFREQ_TASK_MANAGEMENT)
+                       break;
+               len += zfcp_dbf_view(out_buf + len, "scsi_cmnd", "0x%0Lx",
+                                    rec->data.send_fcp.scsi_cmnd);
+               len += zfcp_dbf_view(out_buf + len, "scsi_serial", "0x%016Lx",
+                                    rec->data.send_fcp.scsi_serial);
+               break;
+
+       case FSF_QTCB_OPEN_PORT_WITH_DID:
+       case FSF_QTCB_CLOSE_PORT:
+       case FSF_QTCB_CLOSE_PHYSICAL_PORT:
+               len += zfcp_dbf_view(out_buf + len, "wwpn", "0x%016Lx",
+                                    rec->data.port.wwpn);
+               len += zfcp_dbf_view(out_buf + len, "d_id", "0x%06x",
+                                    rec->data.port.d_id);
+               len += zfcp_dbf_view(out_buf + len, "port_handle", "0x%08x",
+                                    rec->data.port.port_handle);
+               break;
+
+       case FSF_QTCB_OPEN_LUN:
+       case FSF_QTCB_CLOSE_LUN:
+               len += zfcp_dbf_view(out_buf + len, "wwpn", "0x%016Lx",
+                                    rec->data.unit.wwpn);
+               len += zfcp_dbf_view(out_buf + len, "fcp_lun", "0x%016Lx",
+                                    rec->data.unit.fcp_lun);
+               len += zfcp_dbf_view(out_buf + len, "port_handle", "0x%08x",
+                                    rec->data.unit.port_handle);
+               len += zfcp_dbf_view(out_buf + len, "lun_handle", "0x%08x",
+                                    rec->data.unit.lun_handle);
+               break;
+
+       case FSF_QTCB_SEND_ELS:
+               len += zfcp_dbf_view(out_buf + len, "d_id", "0x%06x",
+                                    rec->data.send_els.d_id);
+               len += zfcp_dbf_view(out_buf + len, "ls_code", "0x%02x",
+                                    rec->data.send_els.ls_code);
+               break;
+
+       case FSF_QTCB_ABORT_FCP_CMND:
+       case FSF_QTCB_SEND_GENERIC:
+       case FSF_QTCB_EXCHANGE_CONFIG_DATA:
+       case FSF_QTCB_EXCHANGE_PORT_DATA:
+       case FSF_QTCB_DOWNLOAD_CONTROL_FILE:
+       case FSF_QTCB_UPLOAD_CONTROL_FILE:
+               break;
+       }
+
+       return len;
+}
+
+static inline int
+zfcp_hba_dbf_view_status(char *out_buf, struct zfcp_hba_dbf_record_status *rec)
+{
+       int len = 0;
+
+       len += zfcp_dbf_view(out_buf + len, "failed", "0x%02x", rec->failed);
+       len += zfcp_dbf_view(out_buf + len, "status_type", "0x%08x",
+                            rec->status_type);
+       len += zfcp_dbf_view(out_buf + len, "status_subtype", "0x%08x",
+                            rec->status_subtype);
+       len += zfcp_dbf_view_dump(out_buf + len, "queue_designator",
+                                 (char *)&rec->queue_designator,
+                                 sizeof(struct fsf_queue_designator),
+                                 0, sizeof(struct fsf_queue_designator));
+       len += zfcp_dbf_view_dump(out_buf + len, "payload",
+                                 (char *)&rec->payload,
+                                 rec->payload_size, 0, rec->payload_size);
+
+       return len;
+}
+
+static inline int
+zfcp_hba_dbf_view_qdio(char *out_buf, struct zfcp_hba_dbf_record_qdio *rec)
+{
+       int len = 0;
+
+       len += zfcp_dbf_view(out_buf + len, "status", "0x%08x", rec->status);
+       len += zfcp_dbf_view(out_buf + len, "qdio_error", "0x%08x",
+                            rec->qdio_error);
+       len += zfcp_dbf_view(out_buf + len, "siga_error", "0x%08x",
+                            rec->siga_error);
+       len += zfcp_dbf_view(out_buf + len, "sbal_index", "0x%02x",
+                            rec->sbal_index);
+       len += zfcp_dbf_view(out_buf + len, "sbal_count", "0x%02x",
+                            rec->sbal_count);
+
+       return len;
+}
+
+static int
+zfcp_hba_dbf_view_format(debug_info_t * id, struct debug_view *view,
+                        char *out_buf, const char *in_buf)
+{
+       struct zfcp_hba_dbf_record *rec = (struct zfcp_hba_dbf_record *)in_buf;
+       int len = 0;
+
+       if (strncmp(rec->tag, "dump", ZFCP_DBF_TAG_SIZE) == 0)
+               return 0;
+
+       len += zfcp_dbf_tag(out_buf + len, "tag", rec->tag);
+       if (isalpha(rec->tag2[0]))
+               len += zfcp_dbf_tag(out_buf + len, "tag2", rec->tag2);
+       if (strncmp(rec->tag, "resp", ZFCP_DBF_TAG_SIZE) == 0)
+               len += zfcp_hba_dbf_view_response(out_buf + len,
+                                                 &rec->type.response);
+       else if (strncmp(rec->tag, "stat", ZFCP_DBF_TAG_SIZE) == 0)
+               len += zfcp_hba_dbf_view_status(out_buf + len,
+                                               &rec->type.status);
+       else if (strncmp(rec->tag, "qdio", ZFCP_DBF_TAG_SIZE) == 0)
+               len += zfcp_hba_dbf_view_qdio(out_buf + len, &rec->type.qdio);
+
+       len += sprintf(out_buf + len, "\n");
+
+       return len;
+}
+
+struct debug_view zfcp_hba_dbf_view = {
+       "structured",
+       NULL,
+       &zfcp_dbf_view_header,
+       &zfcp_hba_dbf_view_format,
+       NULL,
+       NULL
+};
+
+inline void
+_zfcp_san_dbf_event_common_ct(const char *tag, struct zfcp_fsf_req *fsf_req,
+                             u32 s_id, u32 d_id, void *buffer, int buflen)
+{
+       struct zfcp_send_ct *send_ct = (struct zfcp_send_ct *)fsf_req->data;
+       struct zfcp_port *port = send_ct->port;
+       struct zfcp_adapter *adapter = port->adapter;
+       struct ct_hdr *header = (struct ct_hdr *)buffer;
+       struct zfcp_san_dbf_record *rec = &adapter->san_dbf_buf;
+       struct zfcp_san_dbf_record_ct *ct = &rec->type.ct;
+       unsigned long flags;
+
+       spin_lock_irqsave(&adapter->san_dbf_lock, flags);
+       memset(rec, 0, sizeof(struct zfcp_san_dbf_record));
+       strncpy(rec->tag, tag, ZFCP_DBF_TAG_SIZE);
+       rec->fsf_reqid = (unsigned long)fsf_req;
+       rec->fsf_seqno = fsf_req->seq_no;
+       rec->s_id = s_id;
+       rec->d_id = d_id;
+       if (strncmp(tag, "octc", ZFCP_DBF_TAG_SIZE) == 0) {
+               ct->type.request.cmd_req_code = header->cmd_rsp_code;
+               ct->type.request.revision = header->revision;
+               ct->type.request.gs_type = header->gs_type;
+               ct->type.request.gs_subtype = header->gs_subtype;
+               ct->type.request.options = header->options;
+               ct->type.request.max_res_size = header->max_res_size;
+       } else if (strncmp(tag, "rctc", ZFCP_DBF_TAG_SIZE) == 0) {
+               ct->type.response.cmd_rsp_code = header->cmd_rsp_code;
+               ct->type.response.revision = header->revision;
+               ct->type.response.reason_code = header->reason_code;
+               ct->type.response.reason_code_expl = header->reason_code_expl;
+               ct->type.response.vendor_unique = header->vendor_unique;
+       }
+       ct->payload_size =
+           min(buflen - (int)sizeof(struct ct_hdr), ZFCP_DBF_CT_PAYLOAD);
+       memcpy(ct->payload, buffer + sizeof(struct ct_hdr), ct->payload_size);
+       debug_event(adapter->san_dbf, 3,
+                   rec, sizeof(struct zfcp_san_dbf_record));
+       spin_unlock_irqrestore(&adapter->san_dbf_lock, flags);
+}
+
+inline void zfcp_san_dbf_event_ct_request(struct zfcp_fsf_req *fsf_req)
+{
+       struct zfcp_send_ct *ct = (struct zfcp_send_ct *)fsf_req->data;
+       struct zfcp_port *port = ct->port;
+       struct zfcp_adapter *adapter = port->adapter;
+
+       _zfcp_san_dbf_event_common_ct("octc", fsf_req,
+                                     fc_host_port_id(adapter->scsi_host),
+                                     port->d_id, zfcp_sg_to_address(ct->req),
+                                     ct->req->length);
+}
+
+inline void zfcp_san_dbf_event_ct_response(struct zfcp_fsf_req *fsf_req)
+{
+       struct zfcp_send_ct *ct = (struct zfcp_send_ct *)fsf_req->data;
+       struct zfcp_port *port = ct->port;
+       struct zfcp_adapter *adapter = port->adapter;
+
+       _zfcp_san_dbf_event_common_ct("rctc", fsf_req, port->d_id,
+                                     fc_host_port_id(adapter->scsi_host),
+                                     zfcp_sg_to_address(ct->resp),
+                                     ct->resp->length);
+}
+
+static inline void
+_zfcp_san_dbf_event_common_els(const char *tag, int level,
+                              struct zfcp_fsf_req *fsf_req, u32 s_id,
+                              u32 d_id, u8 ls_code, void *buffer, int buflen)
+{
+       struct zfcp_adapter *adapter = fsf_req->adapter;
+       struct zfcp_san_dbf_record *rec = &adapter->san_dbf_buf;
+       struct zfcp_dbf_dump *dump = (struct zfcp_dbf_dump *)rec;
+       unsigned long flags;
+       int offset = 0;
+
+       spin_lock_irqsave(&adapter->san_dbf_lock, flags);
+       do {
+               memset(rec, 0, sizeof(struct zfcp_san_dbf_record));
+               if (offset == 0) {
+                       strncpy(rec->tag, tag, ZFCP_DBF_TAG_SIZE);
+                       rec->fsf_reqid = (unsigned long)fsf_req;
+                       rec->fsf_seqno = fsf_req->seq_no;
+                       rec->s_id = s_id;
+                       rec->d_id = d_id;
+                       rec->type.els.ls_code = ls_code;
+                       buflen = min(buflen, ZFCP_DBF_ELS_MAX_PAYLOAD);
+                       rec->type.els.payload_size = buflen;
+                       memcpy(rec->type.els.payload,
+                              buffer, min(buflen, ZFCP_DBF_ELS_PAYLOAD));
+                       offset += min(buflen, ZFCP_DBF_ELS_PAYLOAD);
+               } else {
+                       strncpy(dump->tag, "dump", ZFCP_DBF_TAG_SIZE);
+                       dump->total_size = buflen;
+                       dump->offset = offset;
+                       dump->size = min(buflen - offset,
+                                        (int)sizeof(struct zfcp_san_dbf_record)
+                                        - (int)sizeof(struct zfcp_dbf_dump));
+                       memcpy(dump->data, buffer + offset, dump->size);
+                       offset += dump->size;
+               }
+               debug_event(adapter->san_dbf, level,
+                           rec, sizeof(struct zfcp_san_dbf_record));
+       } while (offset < buflen);
+       spin_unlock_irqrestore(&adapter->san_dbf_lock, flags);
+}
+
+inline void zfcp_san_dbf_event_els_request(struct zfcp_fsf_req *fsf_req)
+{
+       struct zfcp_send_els *els = (struct zfcp_send_els *)fsf_req->data;
+
+       _zfcp_san_dbf_event_common_els("oels", 2, fsf_req,
+                                      fc_host_port_id(els->adapter->scsi_host),
+                                      els->d_id,
+                                      *(u8 *) zfcp_sg_to_address(els->req),
+                                      zfcp_sg_to_address(els->req),
+                                      els->req->length);
+}
+
+inline void zfcp_san_dbf_event_els_response(struct zfcp_fsf_req *fsf_req)
+{
+       struct zfcp_send_els *els = (struct zfcp_send_els *)fsf_req->data;
+
+       _zfcp_san_dbf_event_common_els("rels", 2, fsf_req, els->d_id,
+                                      fc_host_port_id(els->adapter->scsi_host),
+                                      *(u8 *) zfcp_sg_to_address(els->req),
+                                      zfcp_sg_to_address(els->resp),
+                                      els->resp->length);
+}
+
+inline void zfcp_san_dbf_event_incoming_els(struct zfcp_fsf_req *fsf_req)
+{
+       struct zfcp_adapter *adapter = fsf_req->adapter;
+       struct fsf_status_read_buffer *status_buffer =
+           (struct fsf_status_read_buffer *)fsf_req->data;
+       int length = (int)status_buffer->length -
+           (int)((void *)&status_buffer->payload - (void *)status_buffer);
+
+       _zfcp_san_dbf_event_common_els("iels", 1, fsf_req, status_buffer->d_id,
+                                      fc_host_port_id(adapter->scsi_host),
+                                      *(u8 *) status_buffer->payload,
+                                      (void *)status_buffer->payload, length);
+}
+
+static int
+zfcp_san_dbf_view_format(debug_info_t * id, struct debug_view *view,
+                        char *out_buf, const char *in_buf)
+{
+       struct zfcp_san_dbf_record *rec = (struct zfcp_san_dbf_record *)in_buf;
+       char *buffer = NULL;
+       int buflen = 0, total = 0;
+       int len = 0;
+
+       if (strncmp(rec->tag, "dump", ZFCP_DBF_TAG_SIZE) == 0)
+               return 0;
+
+       len += zfcp_dbf_tag(out_buf + len, "tag", rec->tag);
+       len += zfcp_dbf_view(out_buf + len, "fsf_reqid", "0x%0Lx",
+                            rec->fsf_reqid);
+       len += zfcp_dbf_view(out_buf + len, "fsf_seqno", "0x%08x",
+                            rec->fsf_seqno);
+       len += zfcp_dbf_view(out_buf + len, "s_id", "0x%06x", rec->s_id);
+       len += zfcp_dbf_view(out_buf + len, "d_id", "0x%06x", rec->d_id);
+
+       if (strncmp(rec->tag, "octc", ZFCP_DBF_TAG_SIZE) == 0) {
+               len += zfcp_dbf_view(out_buf + len, "cmd_req_code", "0x%04x",
+                                    rec->type.ct.type.request.cmd_req_code);
+               len += zfcp_dbf_view(out_buf + len, "revision", "0x%02x",
+                                    rec->type.ct.type.request.revision);
+               len += zfcp_dbf_view(out_buf + len, "gs_type", "0x%02x",
+                                    rec->type.ct.type.request.gs_type);
+               len += zfcp_dbf_view(out_buf + len, "gs_subtype", "0x%02x",
+                                    rec->type.ct.type.request.gs_subtype);
+               len += zfcp_dbf_view(out_buf + len, "options", "0x%02x",
+                                    rec->type.ct.type.request.options);
+               len += zfcp_dbf_view(out_buf + len, "max_res_size", "0x%04x",
+                                    rec->type.ct.type.request.max_res_size);
+               total = rec->type.ct.payload_size;
+               buffer = rec->type.ct.payload;
+               buflen = min(total, ZFCP_DBF_CT_PAYLOAD);
+       } else if (strncmp(rec->tag, "rctc", ZFCP_DBF_TAG_SIZE) == 0) {
+               len += zfcp_dbf_view(out_buf + len, "cmd_rsp_code", "0x%04x",
+                                    rec->type.ct.type.response.cmd_rsp_code);
+               len += zfcp_dbf_view(out_buf + len, "revision", "0x%02x",
+                                    rec->type.ct.type.response.revision);
+               len += zfcp_dbf_view(out_buf + len, "reason_code", "0x%02x",
+                                    rec->type.ct.type.response.reason_code);
+               len +=
+                   zfcp_dbf_view(out_buf + len, "reason_code_expl", "0x%02x",
+                                 rec->type.ct.type.response.reason_code_expl);
+               len +=
+                   zfcp_dbf_view(out_buf + len, "vendor_unique", "0x%02x",
+                                 rec->type.ct.type.response.vendor_unique);
+               total = rec->type.ct.payload_size;
+               buffer = rec->type.ct.payload;
+               buflen = min(total, ZFCP_DBF_CT_PAYLOAD);
+       } else if (strncmp(rec->tag, "oels", ZFCP_DBF_TAG_SIZE) == 0 ||
+                  strncmp(rec->tag, "rels", ZFCP_DBF_TAG_SIZE) == 0 ||
+                  strncmp(rec->tag, "iels", ZFCP_DBF_TAG_SIZE) == 0) {
+               len += zfcp_dbf_view(out_buf + len, "ls_code", "0x%02x",
+                                    rec->type.els.ls_code);
+               total = rec->type.els.payload_size;
+               buffer = rec->type.els.payload;
+               buflen = min(total, ZFCP_DBF_ELS_PAYLOAD);
+       }
+
+       len += zfcp_dbf_view_dump(out_buf + len, "payload",
+                                 buffer, buflen, 0, total);
+
+       if (buflen == total)
+               len += sprintf(out_buf + len, "\n");
+
+       return len;
+}
+
+struct debug_view zfcp_san_dbf_view = {
+       "structured",
+       NULL,
+       &zfcp_dbf_view_header,
+       &zfcp_san_dbf_view_format,
+       NULL,
+       NULL
+};
+
+static inline void
+_zfcp_scsi_dbf_event_common(const char *tag, const char *tag2, int level,
+                           struct zfcp_adapter *adapter,
+                           struct scsi_cmnd *scsi_cmnd,
+                           struct zfcp_fsf_req *new_fsf_req)
+{
+       struct zfcp_fsf_req *fsf_req =
+           (struct zfcp_fsf_req *)scsi_cmnd->host_scribble;
+       struct zfcp_scsi_dbf_record *rec = &adapter->scsi_dbf_buf;
+       struct zfcp_dbf_dump *dump = (struct zfcp_dbf_dump *)rec;
+       unsigned long flags;
+       struct fcp_rsp_iu *fcp_rsp;
+       char *fcp_rsp_info = NULL, *fcp_sns_info = NULL;
+       int offset = 0, buflen = 0;
+
+       spin_lock_irqsave(&adapter->scsi_dbf_lock, flags);
+       do {
+               memset(rec, 0, sizeof(struct zfcp_scsi_dbf_record));
+               if (offset == 0) {
+                       strncpy(rec->tag, tag, ZFCP_DBF_TAG_SIZE);
+                       strncpy(rec->tag2, tag2, ZFCP_DBF_TAG_SIZE);
+                       if (scsi_cmnd->device) {
+                               rec->scsi_id = scsi_cmnd->device->id;
+                               rec->scsi_lun = scsi_cmnd->device->lun;
+                       }
+                       rec->scsi_result = scsi_cmnd->result;
+                       rec->scsi_cmnd = (unsigned long)scsi_cmnd;
+                       rec->scsi_serial = scsi_cmnd->serial_number;
+                       memcpy(rec->scsi_opcode,
+                              &scsi_cmnd->cmnd,
+                              min((int)scsi_cmnd->cmd_len,
+                                  ZFCP_DBF_SCSI_OPCODE));
+                       rec->scsi_retries = scsi_cmnd->retries;
+                       rec->scsi_allowed = scsi_cmnd->allowed;
+                       if (fsf_req != NULL) {
+                               fcp_rsp = (struct fcp_rsp_iu *)
+                                   &(fsf_req->qtcb->bottom.io.fcp_rsp);
+                               fcp_rsp_info =
+                                   zfcp_get_fcp_rsp_info_ptr(fcp_rsp);
+                               fcp_sns_info =
+                                   zfcp_get_fcp_sns_info_ptr(fcp_rsp);
+
+                               rec->type.fcp.rsp_validity =
+                                   fcp_rsp->validity.value;
+                               rec->type.fcp.rsp_scsi_status =
+                                   fcp_rsp->scsi_status;
+                               rec->type.fcp.rsp_resid = fcp_rsp->fcp_resid;
+                               if (fcp_rsp->validity.bits.fcp_rsp_len_valid)
+                                       rec->type.fcp.rsp_code =
+                                           *(fcp_rsp_info + 3);
+                               if (fcp_rsp->validity.bits.fcp_sns_len_valid) {
+                                       buflen = min((int)fcp_rsp->fcp_sns_len,
+                                                    ZFCP_DBF_SCSI_MAX_FCP_SNS_INFO);
+                                       rec->type.fcp.sns_info_len = buflen;
+                                       memcpy(rec->type.fcp.sns_info,
+                                              fcp_sns_info,
+                                              min(buflen,
+                                                  ZFCP_DBF_SCSI_FCP_SNS_INFO));
+                                       offset += min(buflen,
+                                                     ZFCP_DBF_SCSI_FCP_SNS_INFO);
+                               }
+
+                               rec->fsf_reqid = (unsigned long)fsf_req;
+                               rec->fsf_seqno = fsf_req->seq_no;
+                               rec->fsf_issued = fsf_req->issued;
+                       }
+                       if (new_fsf_req != NULL) {
+                               rec->type.new_fsf_req.fsf_reqid =
+                                   (unsigned long)
+                                   new_fsf_req;
+                               rec->type.new_fsf_req.fsf_seqno =
+                                   new_fsf_req->seq_no;
+                               rec->type.new_fsf_req.fsf_issued =
+                                   new_fsf_req->issued;
+                       }
+               } else {
+                       strncpy(dump->tag, "dump", ZFCP_DBF_TAG_SIZE);
+                       dump->total_size = buflen;
+                       dump->offset = offset;
+                       dump->size = min(buflen - offset,
+                                        (int)sizeof(struct
+                                                    zfcp_scsi_dbf_record) -
+                                        (int)sizeof(struct zfcp_dbf_dump));
+                       memcpy(dump->data, fcp_sns_info + offset, dump->size);
+                       offset += dump->size;
+               }
+               debug_event(adapter->scsi_dbf, level,
+                           rec, sizeof(struct zfcp_scsi_dbf_record));
+       } while (offset < buflen);
+       spin_unlock_irqrestore(&adapter->scsi_dbf_lock, flags);
+}
+
+inline void
+zfcp_scsi_dbf_event_result(const char *tag, int level,
+                          struct zfcp_adapter *adapter,
+                          struct scsi_cmnd *scsi_cmnd)
+{
+       _zfcp_scsi_dbf_event_common("rslt",
+                                   tag, level, adapter, scsi_cmnd, NULL);
+}
+
+inline void
+zfcp_scsi_dbf_event_abort(const char *tag, struct zfcp_adapter *adapter,
+                         struct scsi_cmnd *scsi_cmnd,
+                         struct zfcp_fsf_req *new_fsf_req)
+{
+       _zfcp_scsi_dbf_event_common("abrt",
+                                   tag, 1, adapter, scsi_cmnd, new_fsf_req);
+}
+
+inline void
+zfcp_scsi_dbf_event_devreset(const char *tag, u8 flag, struct zfcp_unit *unit,
+                            struct scsi_cmnd *scsi_cmnd)
+{
+       struct zfcp_adapter *adapter = unit->port->adapter;
+
+       _zfcp_scsi_dbf_event_common(flag == FCP_TARGET_RESET ? "trst" : "lrst",
+                                   tag, 1, adapter, scsi_cmnd, NULL);
+}
+
+static int
+zfcp_scsi_dbf_view_format(debug_info_t * id, struct debug_view *view,
+                         char *out_buf, const char *in_buf)
+{
+       struct zfcp_scsi_dbf_record *rec =
+           (struct zfcp_scsi_dbf_record *)in_buf;
+       int len = 0;
+
+       if (strncmp(rec->tag, "dump", ZFCP_DBF_TAG_SIZE) == 0)
+               return 0;
+
+       len += zfcp_dbf_tag(out_buf + len, "tag", rec->tag);
+       len += zfcp_dbf_tag(out_buf + len, "tag2", rec->tag2);
+       len += zfcp_dbf_view(out_buf + len, "scsi_id", "0x%08x", rec->scsi_id);
+       len += zfcp_dbf_view(out_buf + len, "scsi_lun", "0x%08x",
+                            rec->scsi_lun);
+       len += zfcp_dbf_view(out_buf + len, "scsi_result", "0x%08x",
+                            rec->scsi_result);
+       len += zfcp_dbf_view(out_buf + len, "scsi_cmnd", "0x%0Lx",
+                            rec->scsi_cmnd);
+       len += zfcp_dbf_view(out_buf + len, "scsi_serial", "0x%016Lx",
+                            rec->scsi_serial);
+       len += zfcp_dbf_view_dump(out_buf + len, "scsi_opcode",
+                                 rec->scsi_opcode,
+                                 ZFCP_DBF_SCSI_OPCODE,
+                                 0, ZFCP_DBF_SCSI_OPCODE);
+       len += zfcp_dbf_view(out_buf + len, "scsi_retries", "0x%02x",
+                            rec->scsi_retries);
+       len += zfcp_dbf_view(out_buf + len, "scsi_allowed", "0x%02x",
+                            rec->scsi_allowed);
+       len += zfcp_dbf_view(out_buf + len, "fsf_reqid", "0x%0Lx",
+                            rec->fsf_reqid);
+       len += zfcp_dbf_view(out_buf + len, "fsf_seqno", "0x%08x",
+                            rec->fsf_seqno);
+       len += zfcp_dbf_stck(out_buf + len, "fsf_issued", rec->fsf_issued);
+       if (strncmp(rec->tag, "rslt", ZFCP_DBF_TAG_SIZE) == 0) {
+               len +=
+                   zfcp_dbf_view(out_buf + len, "fcp_rsp_validity", "0x%02x",
+                                 rec->type.fcp.rsp_validity);
+               len +=
+                   zfcp_dbf_view(out_buf + len, "fcp_rsp_scsi_status",
+                                 "0x%02x", rec->type.fcp.rsp_scsi_status);
+               len +=
+                   zfcp_dbf_view(out_buf + len, "fcp_rsp_resid", "0x%08x",
+                                 rec->type.fcp.rsp_resid);
+               len +=
+                   zfcp_dbf_view(out_buf + len, "fcp_rsp_code", "0x%08x",
+                                 rec->type.fcp.rsp_code);
+               len +=
+                   zfcp_dbf_view(out_buf + len, "fcp_sns_info_len", "0x%08x",
+                                 rec->type.fcp.sns_info_len);
+               len +=
+                   zfcp_dbf_view_dump(out_buf + len, "fcp_sns_info",
+                                      rec->type.fcp.sns_info,
+                                      min((int)rec->type.fcp.sns_info_len,
+                                          ZFCP_DBF_SCSI_FCP_SNS_INFO), 0,
+                                      rec->type.fcp.sns_info_len);
+       } else if (strncmp(rec->tag, "abrt", ZFCP_DBF_TAG_SIZE) == 0) {
+               len += zfcp_dbf_view(out_buf + len, "fsf_reqid_abort", "0x%0Lx",
+                                    rec->type.new_fsf_req.fsf_reqid);
+               len += zfcp_dbf_view(out_buf + len, "fsf_seqno_abort", "0x%08x",
+                                    rec->type.new_fsf_req.fsf_seqno);
+               len += zfcp_dbf_stck(out_buf + len, "fsf_issued",
+                                    rec->type.new_fsf_req.fsf_issued);
+       } else if ((strncmp(rec->tag, "trst", ZFCP_DBF_TAG_SIZE) == 0) ||
+                  (strncmp(rec->tag, "lrst", ZFCP_DBF_TAG_SIZE) == 0)) {
+               len += zfcp_dbf_view(out_buf + len, "fsf_reqid_reset", "0x%0Lx",
+                                    rec->type.new_fsf_req.fsf_reqid);
+               len += zfcp_dbf_view(out_buf + len, "fsf_seqno_reset", "0x%08x",
+                                    rec->type.new_fsf_req.fsf_seqno);
+               len += zfcp_dbf_stck(out_buf + len, "fsf_issued",
+                                    rec->type.new_fsf_req.fsf_issued);
+       }
+
+       len += sprintf(out_buf + len, "\n");
+
+       return len;
+}
+
+struct debug_view zfcp_scsi_dbf_view = {
+       "structured",
+       NULL,
+       &zfcp_dbf_view_header,
+       &zfcp_scsi_dbf_view_format,
+       NULL,
+       NULL
+};
+
+/**
+ * zfcp_adapter_debug_register - registers debug feature for an adapter
+ * @adapter: pointer to adapter for which debug features should be registered
+ * return: -ENOMEM on error, 0 otherwise
+ */
+int zfcp_adapter_debug_register(struct zfcp_adapter *adapter)
+{
+       char dbf_name[DEBUG_MAX_NAME_LEN];
+
+       /* debug feature area which records recovery activity */
+       spin_lock_init(&adapter->erp_dbf_lock);
+       sprintf(dbf_name, "zfcp_%s_erp", zfcp_get_busid_by_adapter(adapter));
+       adapter->erp_dbf = debug_register(dbf_name, dbfsize, 2,
+                                         sizeof(struct zfcp_erp_dbf_record));
+       if (!adapter->erp_dbf)
+               goto failed;
+       debug_register_view(adapter->erp_dbf, &debug_hex_ascii_view);
+       debug_set_level(adapter->erp_dbf, 3);
+
+       /* debug feature area which records HBA (FSF and QDIO) conditions */
+       spin_lock_init(&adapter->hba_dbf_lock);
+       sprintf(dbf_name, "zfcp_%s_hba", zfcp_get_busid_by_adapter(adapter));
+       adapter->hba_dbf = debug_register(dbf_name, dbfsize, 1,
+                                         sizeof(struct zfcp_hba_dbf_record));
+       if (!adapter->hba_dbf)
+               goto failed;
+       debug_register_view(adapter->hba_dbf, &debug_hex_ascii_view);
+       debug_register_view(adapter->hba_dbf, &zfcp_hba_dbf_view);
+       debug_set_level(adapter->hba_dbf, 3);
+
+       /* debug feature area which records SAN command failures and recovery */
+       spin_lock_init(&adapter->san_dbf_lock);
+       sprintf(dbf_name, "zfcp_%s_san", zfcp_get_busid_by_adapter(adapter));
+       adapter->san_dbf = debug_register(dbf_name, dbfsize, 1,
+                                         sizeof(struct zfcp_san_dbf_record));
+       if (!adapter->san_dbf)
+               goto failed;
+       debug_register_view(adapter->san_dbf, &debug_hex_ascii_view);
+       debug_register_view(adapter->san_dbf, &zfcp_san_dbf_view);
+       debug_set_level(adapter->san_dbf, 6);
+
+       /* debug feature area which records SCSI command failures and recovery */
+       spin_lock_init(&adapter->scsi_dbf_lock);
+       sprintf(dbf_name, "zfcp_%s_scsi", zfcp_get_busid_by_adapter(adapter));
+       adapter->scsi_dbf = debug_register(dbf_name, dbfsize, 1,
+                                          sizeof(struct zfcp_scsi_dbf_record));
+       if (!adapter->scsi_dbf)
+               goto failed;
+       debug_register_view(adapter->scsi_dbf, &debug_hex_ascii_view);
+       debug_register_view(adapter->scsi_dbf, &zfcp_scsi_dbf_view);
+       debug_set_level(adapter->scsi_dbf, 3);
+
+       return 0;
+
+ failed:
+       zfcp_adapter_debug_unregister(adapter);
+
+       return -ENOMEM;
+}
+
+/**
+ * zfcp_adapter_debug_unregister - unregisters debug feature for an adapter
+ * @adapter: pointer to adapter for which debug features should be unregistered
+ */
+void zfcp_adapter_debug_unregister(struct zfcp_adapter *adapter)
+{
+       debug_unregister(adapter->scsi_dbf);
+       debug_unregister(adapter->san_dbf);
+       debug_unregister(adapter->hba_dbf);
+       debug_unregister(adapter->erp_dbf);
+       adapter->scsi_dbf = NULL;
+       adapter->san_dbf = NULL;
+       adapter->hba_dbf = NULL;
+       adapter->erp_dbf = NULL;
+}
+
+#undef ZFCP_LOG_AREA
index 455e902533a9d9c8fb56a73ce932d813537d5421..d81b737d68ccafa8c92b3afe7738e7587ecfd596 100644 (file)
@@ -66,7 +66,7 @@
 /********************* GENERAL DEFINES *********************************/
 
 /* zfcp version number, it consists of major, minor, and patch-level number */
-#define ZFCP_VERSION           "4.3.0"
+#define ZFCP_VERSION           "4.5.0"
 
 /**
  * zfcp_sg_to_address - determine kernel address from struct scatterlist
@@ -154,13 +154,17 @@ typedef u32 scsi_lun_t;
 #define ZFCP_EXCHANGE_CONFIG_DATA_FIRST_SLEEP  100
 #define ZFCP_EXCHANGE_CONFIG_DATA_RETRIES      7
 
+/* Retry 5 times every 2 second, then every minute */
+#define ZFCP_EXCHANGE_PORT_DATA_SHORT_RETRIES  5
+#define ZFCP_EXCHANGE_PORT_DATA_SHORT_SLEEP    200
+#define ZFCP_EXCHANGE_PORT_DATA_LONG_SLEEP     6000
+
 /* timeout value for "default timer" for fsf requests */
 #define ZFCP_FSF_REQUEST_TIMEOUT (60*HZ);
 
 /*************** FIBRE CHANNEL PROTOCOL SPECIFIC DEFINES ********************/
 
 typedef unsigned long long wwn_t;
-typedef unsigned int       fc_id_t;
 typedef unsigned long long fcp_lun_t;
 /* data length field may be at variable position in FCP-2 FCP_CMND IU */
 typedef unsigned int       fcp_dl_t;
@@ -280,6 +284,171 @@ struct fcp_logo {
         wwn_t nport_wwpn;
 } __attribute__((packed));
 
+/*
+ * DBF stuff
+ */
+#define ZFCP_DBF_TAG_SIZE      4
+
+struct zfcp_dbf_dump {
+       u8 tag[ZFCP_DBF_TAG_SIZE];
+       u32 total_size;         /* size of total dump data */
+       u32 offset;             /* how much data has being already dumped */
+       u32 size;               /* how much data comes with this record */
+       u8 data[];              /* dump data */
+} __attribute__ ((packed));
+
+/* FIXME: to be inflated when reworking the erp dbf */
+struct zfcp_erp_dbf_record {
+       u8 dummy[16];
+} __attribute__ ((packed));
+
+struct zfcp_hba_dbf_record_response {
+       u32 fsf_command;
+       u64 fsf_reqid;
+       u32 fsf_seqno;
+       u64 fsf_issued;
+       u32 fsf_prot_status;
+       u32 fsf_status;
+       u8 fsf_prot_status_qual[FSF_PROT_STATUS_QUAL_SIZE];
+       u8 fsf_status_qual[FSF_STATUS_QUALIFIER_SIZE];
+       u32 fsf_req_status;
+       u8 sbal_first;
+       u8 sbal_curr;
+       u8 sbal_last;
+       u8 pool;
+       u64 erp_action;
+       union {
+               struct {
+                       u64 scsi_cmnd;
+                       u64 scsi_serial;
+               } send_fcp;
+               struct {
+                       u64 wwpn;
+                       u32 d_id;
+                       u32 port_handle;
+               } port;
+               struct {
+                       u64 wwpn;
+                       u64 fcp_lun;
+                       u32 port_handle;
+                       u32 lun_handle;
+               } unit;
+               struct {
+                       u32 d_id;
+                       u8 ls_code;
+               } send_els;
+       } data;
+} __attribute__ ((packed));
+
+struct zfcp_hba_dbf_record_status {
+       u8 failed;
+       u32 status_type;
+       u32 status_subtype;
+       struct fsf_queue_designator
+        queue_designator;
+       u32 payload_size;
+#define ZFCP_DBF_UNSOL_PAYLOAD                         80
+#define ZFCP_DBF_UNSOL_PAYLOAD_SENSE_DATA_AVAIL                32
+#define ZFCP_DBF_UNSOL_PAYLOAD_BIT_ERROR_THRESHOLD     56
+#define ZFCP_DBF_UNSOL_PAYLOAD_FEATURE_UPDATE_ALERT    2 * sizeof(u32)
+       u8 payload[ZFCP_DBF_UNSOL_PAYLOAD];
+} __attribute__ ((packed));
+
+struct zfcp_hba_dbf_record_qdio {
+       u32 status;
+       u32 qdio_error;
+       u32 siga_error;
+       u8 sbal_index;
+       u8 sbal_count;
+} __attribute__ ((packed));
+
+struct zfcp_hba_dbf_record {
+       u8 tag[ZFCP_DBF_TAG_SIZE];
+       u8 tag2[ZFCP_DBF_TAG_SIZE];
+       union {
+               struct zfcp_hba_dbf_record_response response;
+               struct zfcp_hba_dbf_record_status status;
+               struct zfcp_hba_dbf_record_qdio qdio;
+       } type;
+} __attribute__ ((packed));
+
+struct zfcp_san_dbf_record_ct {
+       union {
+               struct {
+                       u16 cmd_req_code;
+                       u8 revision;
+                       u8 gs_type;
+                       u8 gs_subtype;
+                       u8 options;
+                       u16 max_res_size;
+               } request;
+               struct {
+                       u16 cmd_rsp_code;
+                       u8 revision;
+                       u8 reason_code;
+                       u8 reason_code_expl;
+                       u8 vendor_unique;
+               } response;
+       } type;
+       u32 payload_size;
+#define ZFCP_DBF_CT_PAYLOAD    24
+       u8 payload[ZFCP_DBF_CT_PAYLOAD];
+} __attribute__ ((packed));
+
+struct zfcp_san_dbf_record_els {
+       u8 ls_code;
+       u32 payload_size;
+#define ZFCP_DBF_ELS_PAYLOAD   32
+#define ZFCP_DBF_ELS_MAX_PAYLOAD 1024
+       u8 payload[ZFCP_DBF_ELS_PAYLOAD];
+} __attribute__ ((packed));
+
+struct zfcp_san_dbf_record {
+       u8 tag[ZFCP_DBF_TAG_SIZE];
+       u64 fsf_reqid;
+       u32 fsf_seqno;
+       u32 s_id;
+       u32 d_id;
+       union {
+               struct zfcp_san_dbf_record_ct ct;
+               struct zfcp_san_dbf_record_els els;
+       } type;
+} __attribute__ ((packed));
+
+struct zfcp_scsi_dbf_record {
+       u8 tag[ZFCP_DBF_TAG_SIZE];
+       u8 tag2[ZFCP_DBF_TAG_SIZE];
+       u32 scsi_id;
+       u32 scsi_lun;
+       u32 scsi_result;
+       u64 scsi_cmnd;
+       u64 scsi_serial;
+#define ZFCP_DBF_SCSI_OPCODE   16
+       u8 scsi_opcode[ZFCP_DBF_SCSI_OPCODE];
+       u8 scsi_retries;
+       u8 scsi_allowed;
+       u64 fsf_reqid;
+       u32 fsf_seqno;
+       u64 fsf_issued;
+       union {
+               struct {
+                       u64 fsf_reqid;
+                       u32 fsf_seqno;
+                       u64 fsf_issued;
+               } new_fsf_req;
+               struct {
+                       u8 rsp_validity;
+                       u8 rsp_scsi_status;
+                       u32 rsp_resid;
+                       u8 rsp_code;
+#define ZFCP_DBF_SCSI_FCP_SNS_INFO     16
+#define ZFCP_DBF_SCSI_MAX_FCP_SNS_INFO 256
+                       u32 sns_info_len;
+                       u8 sns_info[ZFCP_DBF_SCSI_FCP_SNS_INFO];
+               } fcp;
+       } type;
+} __attribute__ ((packed));
+
 /*
  * FC-FS stuff
  */
@@ -339,34 +508,6 @@ struct zfcp_rc_entry {
  */
 #define ZFCP_CT_TIMEOUT                        (3 * R_A_TOV)
 
-
-/***************** S390 DEBUG FEATURE SPECIFIC DEFINES ***********************/
-
-/* debug feature entries per adapter */
-#define ZFCP_ERP_DBF_INDEX     1 
-#define ZFCP_ERP_DBF_AREAS     2
-#define ZFCP_ERP_DBF_LENGTH    16
-#define ZFCP_ERP_DBF_LEVEL     3
-#define ZFCP_ERP_DBF_NAME      "zfcperp"
-
-#define ZFCP_CMD_DBF_INDEX     2
-#define ZFCP_CMD_DBF_AREAS     1
-#define ZFCP_CMD_DBF_LENGTH    8
-#define ZFCP_CMD_DBF_LEVEL     3
-#define ZFCP_CMD_DBF_NAME      "zfcpcmd"
-
-#define ZFCP_ABORT_DBF_INDEX   2
-#define ZFCP_ABORT_DBF_AREAS   1
-#define ZFCP_ABORT_DBF_LENGTH  8
-#define ZFCP_ABORT_DBF_LEVEL   6
-#define ZFCP_ABORT_DBF_NAME    "zfcpabt"
-
-#define ZFCP_IN_ELS_DBF_INDEX  2
-#define ZFCP_IN_ELS_DBF_AREAS  1
-#define ZFCP_IN_ELS_DBF_LENGTH 8
-#define ZFCP_IN_ELS_DBF_LEVEL  6
-#define ZFCP_IN_ELS_DBF_NAME   "zfcpels"
-
 /******************** LOGGING MACROS AND DEFINES *****************************/
 
 /*
@@ -501,6 +642,7 @@ do { \
 #define ZFCP_STATUS_ADAPTER_ERP_THREAD_KILL    0x00000080
 #define ZFCP_STATUS_ADAPTER_ERP_PENDING                0x00000100
 #define ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED     0x00000200
+#define ZFCP_STATUS_ADAPTER_XPORT_OK           0x00000800
 
 #define ZFCP_STATUS_ADAPTER_SCSI_UP                    \
                (ZFCP_STATUS_COMMON_UNBLOCKED | \
@@ -635,45 +777,6 @@ struct zfcp_adapter_mempool {
        mempool_t *data_gid_pn;
 };
 
-struct  zfcp_exchange_config_data{
-};
-
-struct zfcp_open_port {
-        struct zfcp_port *port;
-};
-
-struct zfcp_close_port {
-       struct zfcp_port *port;
-};
-
-struct zfcp_open_unit {
-       struct zfcp_unit *unit;
-};
-
-struct zfcp_close_unit {
-       struct zfcp_unit *unit;
-};
-
-struct zfcp_close_physical_port {
-        struct zfcp_port *port;
-};
-
-struct zfcp_send_fcp_command_task {
-       struct zfcp_fsf_req *fsf_req;
-       struct zfcp_unit *unit;
-       struct scsi_cmnd *scsi_cmnd;
-       unsigned long start_jiffies;
-};
-
-struct zfcp_send_fcp_command_task_management {
-       struct zfcp_unit *unit;
-};
-
-struct zfcp_abort_fcp_command {
-       struct zfcp_fsf_req *fsf_req;
-       struct zfcp_unit *unit;
-};
-
 /*
  * header for CT_IU
  */
@@ -702,7 +805,7 @@ struct ct_iu_gid_pn_req {
 /* FS_ACC IU and data unit for GID_PN nameserver request */
 struct ct_iu_gid_pn_resp {
        struct ct_hdr header;
-       fc_id_t d_id;
+       u32 d_id;
 } __attribute__ ((packed));
 
 typedef void (*zfcp_send_ct_handler_t)(unsigned long);
@@ -768,7 +871,7 @@ typedef void (*zfcp_send_els_handler_t)(unsigned long);
 struct zfcp_send_els {
        struct zfcp_adapter *adapter;
        struct zfcp_port *port;
-       fc_id_t d_id;
+       u32 d_id;
        struct scatterlist *req;
        struct scatterlist *resp;
        unsigned int req_count;
@@ -781,33 +884,6 @@ struct zfcp_send_els {
        int status;
 };
 
-struct zfcp_status_read {
-       struct fsf_status_read_buffer *buffer;
-};
-
-struct zfcp_fsf_done {
-       struct completion *complete;
-       int status;
-};
-
-/* request specific data */
-union zfcp_req_data {
-       struct zfcp_exchange_config_data exchange_config_data;
-       struct zfcp_open_port             open_port;
-       struct zfcp_close_port            close_port;
-       struct zfcp_open_unit             open_unit;
-       struct zfcp_close_unit            close_unit;
-       struct zfcp_close_physical_port   close_physical_port;
-       struct zfcp_send_fcp_command_task send_fcp_command_task;
-        struct zfcp_send_fcp_command_task_management
-                                         send_fcp_command_task_management;
-       struct zfcp_abort_fcp_command     abort_fcp_command;
-       struct zfcp_send_ct *send_ct;
-       struct zfcp_send_els *send_els;
-       struct zfcp_status_read           status_read;
-       struct fsf_qtcb_bottom_port *port_data;
-};
-
 struct zfcp_qdio_queue {
        struct qdio_buffer *buffer[QDIO_MAX_BUFFERS_PER_Q]; /* SBALs */
        u8                 free_index;        /* index of next free bfr
@@ -838,21 +914,19 @@ struct zfcp_adapter {
        atomic_t                refcount;          /* reference count */
        wait_queue_head_t       remove_wq;         /* can be used to wait for
                                                      refcount drop to zero */
-       wwn_t                   wwnn;              /* WWNN */
-       wwn_t                   wwpn;              /* WWPN */
-       fc_id_t                 s_id;              /* N_Port ID */
        wwn_t                   peer_wwnn;         /* P2P peer WWNN */
        wwn_t                   peer_wwpn;         /* P2P peer WWPN */
-       fc_id_t                 peer_d_id;         /* P2P peer D_ID */
+       u32                     peer_d_id;         /* P2P peer D_ID */
+       wwn_t                   physical_wwpn;     /* WWPN of physical port */
+       u32                     physical_s_id;     /* local FC port ID */
        struct ccw_device       *ccw_device;       /* S/390 ccw device */
        u8                      fc_service_class;
        u32                     fc_topology;       /* FC topology */
-       u32                     fc_link_speed;     /* FC interface speed */
        u32                     hydra_version;     /* Hydra version */
        u32                     fsf_lic_version;
-        u32                    supported_features;/* of FCP channel */
+       u32                     adapter_features;  /* FCP channel features */
+       u32                     connection_features; /* host connection features */
         u32                    hardware_version;  /* of FCP channel */
-        u8                     serial_number[32]; /* of hardware */
        struct Scsi_Host        *scsi_host;        /* Pointer to mid-layer */
        unsigned short          scsi_host_no;      /* Assigned host number */
        unsigned char           name[9];
@@ -889,11 +963,18 @@ struct zfcp_adapter {
        u32                     erp_low_mem_count; /* nr of erp actions waiting
                                                      for memory */
        struct zfcp_port        *nameserver_port;  /* adapter's nameserver */
-        debug_info_t            *erp_dbf;          /* S/390 debug features */
-       debug_info_t            *abort_dbf;
-       debug_info_t            *in_els_dbf;
-       debug_info_t            *cmd_dbf;
-       spinlock_t              dbf_lock;
+       debug_info_t            *erp_dbf;
+       debug_info_t            *hba_dbf;
+       debug_info_t            *san_dbf;          /* debug feature areas */
+       debug_info_t            *scsi_dbf;
+       spinlock_t              erp_dbf_lock;
+       spinlock_t              hba_dbf_lock;
+       spinlock_t              san_dbf_lock;
+       spinlock_t              scsi_dbf_lock;
+       struct zfcp_erp_dbf_record      erp_dbf_buf;
+       struct zfcp_hba_dbf_record      hba_dbf_buf;
+       struct zfcp_san_dbf_record      san_dbf_buf;
+       struct zfcp_scsi_dbf_record     scsi_dbf_buf;
        struct zfcp_adapter_mempool     pool;      /* Adapter memory pools */
        struct qdio_initialize  qdio_init_data;    /* for qdio_establish */
        struct device           generic_services;  /* directory for WKA ports */
@@ -919,7 +1000,7 @@ struct zfcp_port {
        atomic_t               status;         /* status of this remote port */
        wwn_t                  wwnn;           /* WWNN if known */
        wwn_t                  wwpn;           /* WWPN */
-       fc_id_t                d_id;           /* D_ID */
+       u32                    d_id;           /* D_ID */
        u32                    handle;         /* handle assigned by FSF */
        struct zfcp_erp_action erp_action;     /* pending error recovery */
         atomic_t               erp_counter;
@@ -963,11 +1044,13 @@ struct zfcp_fsf_req {
        u32                    fsf_command;    /* FSF Command copy */
        struct fsf_qtcb        *qtcb;          /* address of associated QTCB */
        u32                    seq_no;         /* Sequence number of request */
-        union zfcp_req_data    data;           /* Info fields of request */ 
+        unsigned long          data;           /* private data of request */ 
        struct zfcp_erp_action *erp_action;    /* used if this request is
                                                  issued on behalf of erp */
        mempool_t              *pool;          /* used if request was alloacted
                                                  from emergency pool */
+       unsigned long long     issued;         /* request sent time (STCK) */
+       struct zfcp_unit       *unit;
 };
 
 typedef void zfcp_fsf_req_handler_t(struct zfcp_fsf_req*);
index cb4f612550baf459ed752ba385dbeca823574958..023f4e558ae426aa2fd9bc349aaecca53686715d 100644 (file)
@@ -82,6 +82,7 @@ static int zfcp_erp_adapter_strategy_open(struct zfcp_erp_action *);
 static int zfcp_erp_adapter_strategy_open_qdio(struct zfcp_erp_action *);
 static int zfcp_erp_adapter_strategy_open_fsf(struct zfcp_erp_action *);
 static int zfcp_erp_adapter_strategy_open_fsf_xconfig(struct zfcp_erp_action *);
+static int zfcp_erp_adapter_strategy_open_fsf_xport(struct zfcp_erp_action *);
 static int zfcp_erp_adapter_strategy_open_fsf_statusread(
        struct zfcp_erp_action *);
 
@@ -345,13 +346,13 @@ zfcp_erp_adisc(struct zfcp_port *port)
 
        /* acc. to FC-FS, hard_nport_id in ADISC should not be set for ports
           without FC-AL-2 capability, so we don't set it */
-       adisc->wwpn = adapter->wwpn;
-       adisc->wwnn = adapter->wwnn;
-       adisc->nport_id = adapter->s_id;
+       adisc->wwpn = fc_host_port_name(adapter->scsi_host);
+       adisc->wwnn = fc_host_node_name(adapter->scsi_host);
+       adisc->nport_id = fc_host_port_id(adapter->scsi_host);
        ZFCP_LOG_INFO("ADISC request from s_id 0x%08x to d_id 0x%08x "
                      "(wwpn=0x%016Lx, wwnn=0x%016Lx, "
                      "hard_nport_id=0x%08x, nport_id=0x%08x)\n",
-                     adapter->s_id, send_els->d_id, (wwn_t) adisc->wwpn,
+                     adisc->nport_id, send_els->d_id, (wwn_t) adisc->wwpn,
                      (wwn_t) adisc->wwnn, adisc->hard_nport_id,
                      adisc->nport_id);
 
@@ -404,7 +405,7 @@ zfcp_erp_adisc_handler(unsigned long data)
        struct zfcp_send_els *send_els;
        struct zfcp_port *port;
        struct zfcp_adapter *adapter;
-       fc_id_t d_id;
+       u32 d_id;
        struct zfcp_ls_adisc_acc *adisc;
 
        send_els = (struct zfcp_send_els *) data;
@@ -435,9 +436,9 @@ zfcp_erp_adisc_handler(unsigned long data)
        ZFCP_LOG_INFO("ADISC response from d_id 0x%08x to s_id "
                      "0x%08x (wwpn=0x%016Lx, wwnn=0x%016Lx, "
                      "hard_nport_id=0x%08x, nport_id=0x%08x)\n",
-                     d_id, adapter->s_id, (wwn_t) adisc->wwpn,
-                     (wwn_t) adisc->wwnn, adisc->hard_nport_id,
-                     adisc->nport_id);
+                     d_id, fc_host_port_id(adapter->scsi_host),
+                     (wwn_t) adisc->wwpn, (wwn_t) adisc->wwnn,
+                     adisc->hard_nport_id, adisc->nport_id);
 
        /* set wwnn for port */
        if (port->wwnn == 0)
@@ -886,7 +887,7 @@ static int
 zfcp_erp_strategy_check_fsfreq(struct zfcp_erp_action *erp_action)
 {
        int retval = 0;
-       struct zfcp_fsf_req *fsf_req;
+       struct zfcp_fsf_req *fsf_req = NULL;
        struct zfcp_adapter *adapter = erp_action->adapter;
 
        if (erp_action->fsf_req) {
@@ -896,7 +897,7 @@ zfcp_erp_strategy_check_fsfreq(struct zfcp_erp_action *erp_action)
                list_for_each_entry(fsf_req, &adapter->fsf_req_list_head, list)
                    if (fsf_req == erp_action->fsf_req)
                        break;
-               if (fsf_req == erp_action->fsf_req) {
+               if (fsf_req && (fsf_req->erp_action == erp_action)) {
                        /* fsf_req still exists */
                        debug_text_event(adapter->erp_dbf, 3, "a_ca_req");
                        debug_event(adapter->erp_dbf, 3, &fsf_req,
@@ -2258,16 +2259,21 @@ zfcp_erp_adapter_strategy_close_qdio(struct zfcp_erp_action *erp_action)
 static int
 zfcp_erp_adapter_strategy_open_fsf(struct zfcp_erp_action *erp_action)
 {
-       int retval;
+       int xconfig, xport;
+
+       if (atomic_test_mask(ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED,
+                            &erp_action->adapter->status)) {
+               zfcp_erp_adapter_strategy_open_fsf_xport(erp_action);
+               atomic_set(&erp_action->adapter->erp_counter, 0);
+               return ZFCP_ERP_FAILED;
+       }
 
-       /* do 'exchange configuration data' */
-       retval = zfcp_erp_adapter_strategy_open_fsf_xconfig(erp_action);
-       if (retval == ZFCP_ERP_FAILED)
-               return retval;
+       xconfig = zfcp_erp_adapter_strategy_open_fsf_xconfig(erp_action);
+       xport   = zfcp_erp_adapter_strategy_open_fsf_xport(erp_action);
+       if ((xconfig == ZFCP_ERP_FAILED) || (xport == ZFCP_ERP_FAILED))
+               return ZFCP_ERP_FAILED;
 
-       /* start the desired number of Status Reads */
-       retval = zfcp_erp_adapter_strategy_open_fsf_statusread(erp_action);
-       return retval;
+       return zfcp_erp_adapter_strategy_open_fsf_statusread(erp_action);
 }
 
 /*
@@ -2291,7 +2297,9 @@ zfcp_erp_adapter_strategy_open_fsf_xconfig(struct zfcp_erp_action *erp_action)
                atomic_clear_mask(ZFCP_STATUS_ADAPTER_HOST_CON_INIT,
                                  &adapter->status);
                ZFCP_LOG_DEBUG("Doing exchange config data\n");
+               write_lock(&adapter->erp_lock);
                zfcp_erp_action_to_running(erp_action);
+               write_unlock(&adapter->erp_lock);
                zfcp_erp_timeout_init(erp_action);
                if (zfcp_fsf_exchange_config_data(erp_action)) {
                        retval = ZFCP_ERP_FAILED;
@@ -2348,6 +2356,76 @@ zfcp_erp_adapter_strategy_open_fsf_xconfig(struct zfcp_erp_action *erp_action)
        return retval;
 }
 
+static int
+zfcp_erp_adapter_strategy_open_fsf_xport(struct zfcp_erp_action *erp_action)
+{
+       int retval = ZFCP_ERP_SUCCEEDED;
+       int retries;
+       int sleep;
+       struct zfcp_adapter *adapter = erp_action->adapter;
+
+       atomic_clear_mask(ZFCP_STATUS_ADAPTER_XPORT_OK, &adapter->status);
+
+       for (retries = 0; ; retries++) {
+               ZFCP_LOG_DEBUG("Doing exchange port data\n");
+               zfcp_erp_action_to_running(erp_action);
+               zfcp_erp_timeout_init(erp_action);
+               if (zfcp_fsf_exchange_port_data(erp_action, adapter, NULL)) {
+                       retval = ZFCP_ERP_FAILED;
+                       debug_text_event(adapter->erp_dbf, 5, "a_fstx_xf");
+                       ZFCP_LOG_INFO("error: initiation of exchange of "
+                                     "port data failed for adapter %s\n",
+                                     zfcp_get_busid_by_adapter(adapter));
+                       break;
+               }
+               debug_text_event(adapter->erp_dbf, 6, "a_fstx_xok");
+               ZFCP_LOG_DEBUG("Xchange underway\n");
+
+               /*
+                * Why this works:
+                * Both the normal completion handler as well as the timeout
+                * handler will do an 'up' when the 'exchange port data'
+                * request completes or times out. Thus, the signal to go on
+                * won't be lost utilizing this semaphore.
+                * Furthermore, this 'adapter_reopen' action is
+                * guaranteed to be the only action being there (highest action
+                * which prevents other actions from being created).
+                * Resulting from that, the wake signal recognized here
+                * _must_ be the one belonging to the 'exchange port
+                * data' request.
+                */
+               down(&adapter->erp_ready_sem);
+               if (erp_action->status & ZFCP_STATUS_ERP_TIMEDOUT) {
+                       ZFCP_LOG_INFO("error: exchange of port data "
+                                     "for adapter %s timed out\n",
+                                     zfcp_get_busid_by_adapter(adapter));
+                       break;
+               }
+
+               if (!atomic_test_mask(ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED,
+                                     &adapter->status))
+                       break;
+
+               ZFCP_LOG_DEBUG("host connection still initialising... "
+                              "waiting and retrying...\n");
+               /* sleep a little bit before retry */
+               sleep = retries < ZFCP_EXCHANGE_PORT_DATA_SHORT_RETRIES ?
+                               ZFCP_EXCHANGE_PORT_DATA_SHORT_SLEEP :
+                               ZFCP_EXCHANGE_PORT_DATA_LONG_SLEEP;
+               msleep(jiffies_to_msecs(sleep));
+       }
+
+       if (atomic_test_mask(ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED,
+                            &adapter->status)) {
+               ZFCP_LOG_INFO("error: exchange of port data for "
+                             "adapter %s failed\n",
+                             zfcp_get_busid_by_adapter(adapter));
+               retval = ZFCP_ERP_FAILED;
+       }
+
+       return retval;
+}
+
 /*
  * function:   
  *
@@ -3194,11 +3272,19 @@ zfcp_erp_action_enqueue(int action,
                /* fall through !!! */
 
        case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED:
-               if (atomic_test_mask
-                   (ZFCP_STATUS_COMMON_ERP_INUSE, &port->status)
-                   && port->erp_action.action ==
-                   ZFCP_ERP_ACTION_REOPEN_PORT_FORCED) {
-                       debug_text_event(adapter->erp_dbf, 4, "pf_actenq_drp");
+               if (atomic_test_mask(ZFCP_STATUS_COMMON_ERP_INUSE,
+                                    &port->status)) {
+                       if (port->erp_action.action !=
+                           ZFCP_ERP_ACTION_REOPEN_PORT_FORCED) {
+                               ZFCP_LOG_INFO("dropped erp action %i (port "
+                                             "0x%016Lx, action in use: %i)\n",
+                                             action, port->wwpn,
+                                             port->erp_action.action);
+                               debug_text_event(adapter->erp_dbf, 4,
+                                                "pf_actenq_drp");
+                       } else 
+                               debug_text_event(adapter->erp_dbf, 4,
+                                                "pf_actenq_drpcp");
                        debug_event(adapter->erp_dbf, 4, &port->wwpn,
                                    sizeof (wwn_t));
                        goto out;
@@ -3589,6 +3675,9 @@ zfcp_erp_adapter_access_changed(struct zfcp_adapter *adapter)
        struct zfcp_port *port;
        unsigned long flags;
 
+       if (adapter->connection_features & FSF_FEATURE_NPIV_MODE)
+               return;
+
        debug_text_event(adapter->erp_dbf, 3, "a_access_recover");
        debug_event(adapter->erp_dbf, 3, &adapter->name, 8);
 
index cd98a2de9f8fa4d997ae12d3058d186efe9e2b74..c3782261cb5cc9f61dab8d4948e61cff6aed47fa 100644 (file)
@@ -96,7 +96,8 @@ extern int  zfcp_fsf_open_unit(struct zfcp_erp_action *);
 extern int  zfcp_fsf_close_unit(struct zfcp_erp_action *);
 
 extern int  zfcp_fsf_exchange_config_data(struct zfcp_erp_action *);
-extern int  zfcp_fsf_exchange_port_data(struct zfcp_adapter *,
+extern int  zfcp_fsf_exchange_port_data(struct zfcp_erp_action *,
+                                       struct zfcp_adapter *,
                                        struct fsf_qtcb_bottom_port *);
 extern int  zfcp_fsf_control_file(struct zfcp_adapter *, struct zfcp_fsf_req **,
                                  u32, u32, struct zfcp_sg_list *);
@@ -109,7 +110,6 @@ extern int zfcp_fsf_req_create(struct zfcp_adapter *, u32, int, mempool_t *,
 extern int zfcp_fsf_send_ct(struct zfcp_send_ct *, mempool_t *,
                            struct zfcp_erp_action *);
 extern int zfcp_fsf_send_els(struct zfcp_send_els *);
-extern int  zfcp_fsf_req_wait_and_cleanup(struct zfcp_fsf_req *, int, u32 *);
 extern int  zfcp_fsf_send_fcp_command_task(struct zfcp_adapter *,
                                           struct zfcp_unit *,
                                           struct scsi_cmnd *,
@@ -182,9 +182,25 @@ extern void zfcp_erp_port_access_changed(struct zfcp_port *);
 extern void zfcp_erp_unit_access_changed(struct zfcp_unit *);
 
 /******************************** AUX ****************************************/
-extern void zfcp_cmd_dbf_event_fsf(const char *, struct zfcp_fsf_req *,
-                                  void *, int);
-extern void zfcp_cmd_dbf_event_scsi(const char *, struct scsi_cmnd *);
-extern void zfcp_in_els_dbf_event(struct zfcp_adapter *, const char *,
-                                 struct fsf_status_read_buffer *, int);
+extern void zfcp_hba_dbf_event_fsf_response(struct zfcp_fsf_req *);
+extern void zfcp_hba_dbf_event_fsf_unsol(const char *, struct zfcp_adapter *,
+                                        struct fsf_status_read_buffer *);
+extern void zfcp_hba_dbf_event_qdio(struct zfcp_adapter *,
+                                   unsigned int, unsigned int, unsigned int,
+                                   int, int);
+
+extern void zfcp_san_dbf_event_ct_request(struct zfcp_fsf_req *);
+extern void zfcp_san_dbf_event_ct_response(struct zfcp_fsf_req *);
+extern void zfcp_san_dbf_event_els_request(struct zfcp_fsf_req *);
+extern void zfcp_san_dbf_event_els_response(struct zfcp_fsf_req *);
+extern void zfcp_san_dbf_event_incoming_els(struct zfcp_fsf_req *);
+
+extern void zfcp_scsi_dbf_event_result(const char *, int, struct zfcp_adapter *,
+                                      struct scsi_cmnd *);
+extern void zfcp_scsi_dbf_event_abort(const char *, struct zfcp_adapter *,
+                                     struct scsi_cmnd *,
+                                     struct zfcp_fsf_req *);
+extern void zfcp_scsi_dbf_event_devreset(const char *, u8, struct zfcp_unit *,
+                                        struct scsi_cmnd *);
+
 #endif /* ZFCP_EXT_H */
index c007b6424e746cd63854ca8b69bfefbddcfc5802..3b0fc1163f5f4fa00e35438434e3e0f8da34300f 100644 (file)
@@ -59,6 +59,8 @@ static int zfcp_fsf_req_send(struct zfcp_fsf_req *, struct timer_list *);
 static int zfcp_fsf_protstatus_eval(struct zfcp_fsf_req *);
 static int zfcp_fsf_fsfstatus_eval(struct zfcp_fsf_req *);
 static int zfcp_fsf_fsfstatus_qual_eval(struct zfcp_fsf_req *);
+static void zfcp_fsf_link_down_info_eval(struct zfcp_adapter *,
+       struct fsf_link_down_info *);
 static int zfcp_fsf_req_dispatch(struct zfcp_fsf_req *);
 static void zfcp_fsf_req_dismiss(struct zfcp_fsf_req *);
 
@@ -285,51 +287,51 @@ zfcp_fsf_protstatus_eval(struct zfcp_fsf_req *fsf_req)
 {
        int retval = 0;
        struct zfcp_adapter *adapter = fsf_req->adapter;
+       struct fsf_qtcb *qtcb = fsf_req->qtcb;
+       union fsf_prot_status_qual *prot_status_qual =
+               &qtcb->prefix.prot_status_qual;
 
-       ZFCP_LOG_DEBUG("QTCB is at %p\n", fsf_req->qtcb);
+       zfcp_hba_dbf_event_fsf_response(fsf_req);
 
        if (fsf_req->status & ZFCP_STATUS_FSFREQ_DISMISSED) {
                ZFCP_LOG_DEBUG("fsf_req 0x%lx has been dismissed\n",
                               (unsigned long) fsf_req);
                fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR |
                        ZFCP_STATUS_FSFREQ_RETRY; /* only for SCSI cmnds. */
-               zfcp_cmd_dbf_event_fsf("dismiss", fsf_req, NULL, 0);
                goto skip_protstatus;
        }
 
        /* log additional information provided by FSF (if any) */
-       if (unlikely(fsf_req->qtcb->header.log_length)) {
+       if (unlikely(qtcb->header.log_length)) {
                /* do not trust them ;-) */
-               if (fsf_req->qtcb->header.log_start > sizeof(struct fsf_qtcb)) {
+               if (qtcb->header.log_start > sizeof(struct fsf_qtcb)) {
                        ZFCP_LOG_NORMAL
                            ("bug: ULP (FSF logging) log data starts "
                             "beyond end of packet header. Ignored. "
                             "(start=%i, size=%li)\n",
-                            fsf_req->qtcb->header.log_start,
+                            qtcb->header.log_start,
                             sizeof(struct fsf_qtcb));
                        goto forget_log;
                }
-               if ((size_t) (fsf_req->qtcb->header.log_start +
-                    fsf_req->qtcb->header.log_length)
+               if ((size_t) (qtcb->header.log_start + qtcb->header.log_length)
                    > sizeof(struct fsf_qtcb)) {
                        ZFCP_LOG_NORMAL("bug: ULP (FSF logging) log data ends "
                                        "beyond end of packet header. Ignored. "
                                        "(start=%i, length=%i, size=%li)\n",
-                                       fsf_req->qtcb->header.log_start,
-                                       fsf_req->qtcb->header.log_length,
+                                       qtcb->header.log_start,
+                                       qtcb->header.log_length,
                                        sizeof(struct fsf_qtcb));
                        goto forget_log;
                }
                ZFCP_LOG_TRACE("ULP log data: \n");
                ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_TRACE,
-                             (char *) fsf_req->qtcb +
-                             fsf_req->qtcb->header.log_start,
-                             fsf_req->qtcb->header.log_length);
+                             (char *) qtcb + qtcb->header.log_start,
+                             qtcb->header.log_length);
        }
  forget_log:
 
        /* evaluate FSF Protocol Status */
-       switch (fsf_req->qtcb->prefix.prot_status) {
+       switch (qtcb->prefix.prot_status) {
 
        case FSF_PROT_GOOD:
        case FSF_PROT_FSF_STATUS_PRESENTED:
@@ -340,14 +342,9 @@ zfcp_fsf_protstatus_eval(struct zfcp_fsf_req *fsf_req)
                                "microcode of version 0x%x, the device driver "
                                "only supports 0x%x. Aborting.\n",
                                zfcp_get_busid_by_adapter(adapter),
-                               fsf_req->qtcb->prefix.prot_status_qual.
-                               version_error.fsf_version, ZFCP_QTCB_VERSION);
-               /* stop operation for this adapter */
-               debug_text_exception(adapter->erp_dbf, 0, "prot_ver_err");
+                               prot_status_qual->version_error.fsf_version,
+                               ZFCP_QTCB_VERSION);
                zfcp_erp_adapter_shutdown(adapter, 0);
-               zfcp_cmd_dbf_event_fsf("qverserr", fsf_req,
-                                      &fsf_req->qtcb->prefix.prot_status_qual,
-                                      sizeof (union fsf_prot_status_qual));
                fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
                break;
 
@@ -355,16 +352,10 @@ zfcp_fsf_protstatus_eval(struct zfcp_fsf_req *fsf_req)
                ZFCP_LOG_NORMAL("bug: Sequence number mismatch between "
                                "driver (0x%x) and adapter %s (0x%x). "
                                "Restarting all operations on this adapter.\n",
-                               fsf_req->qtcb->prefix.req_seq_no,
+                               qtcb->prefix.req_seq_no,
                                zfcp_get_busid_by_adapter(adapter),
-                               fsf_req->qtcb->prefix.prot_status_qual.
-                               sequence_error.exp_req_seq_no);
-               debug_text_exception(adapter->erp_dbf, 0, "prot_seq_err");
-               /* restart operation on this adapter */
+                               prot_status_qual->sequence_error.exp_req_seq_no);
                zfcp_erp_adapter_reopen(adapter, 0);
-               zfcp_cmd_dbf_event_fsf("seqnoerr", fsf_req,
-                                      &fsf_req->qtcb->prefix.prot_status_qual,
-                                      sizeof (union fsf_prot_status_qual));
                fsf_req->status |= ZFCP_STATUS_FSFREQ_RETRY;
                fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
                break;
@@ -375,116 +366,35 @@ zfcp_fsf_protstatus_eval(struct zfcp_fsf_req *fsf_req)
                                "that used on adapter %s. "
                                "Stopping all operations on this adapter.\n",
                                zfcp_get_busid_by_adapter(adapter));
-               debug_text_exception(adapter->erp_dbf, 0, "prot_unsup_qtcb");
                zfcp_erp_adapter_shutdown(adapter, 0);
-               zfcp_cmd_dbf_event_fsf("unsqtcbt", fsf_req,
-                                      &fsf_req->qtcb->prefix.prot_status_qual,
-                                      sizeof (union fsf_prot_status_qual));
                fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
                break;
 
        case FSF_PROT_HOST_CONNECTION_INITIALIZING:
-               zfcp_cmd_dbf_event_fsf("hconinit", fsf_req,
-                                      &fsf_req->qtcb->prefix.prot_status_qual,
-                                      sizeof (union fsf_prot_status_qual));
                fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
                atomic_set_mask(ZFCP_STATUS_ADAPTER_HOST_CON_INIT,
                                &(adapter->status));
-               debug_text_event(adapter->erp_dbf, 3, "prot_con_init");
                break;
 
        case FSF_PROT_DUPLICATE_REQUEST_ID:
-               if (fsf_req->qtcb) {
                        ZFCP_LOG_NORMAL("bug: The request identifier 0x%Lx "
                                        "to the adapter %s is ambiguous. "
-                                       "Stopping all operations on this "
-                                       "adapter.\n",
-                                       *(unsigned long long *)
-                                       (&fsf_req->qtcb->bottom.support.
-                                        req_handle),
-                                       zfcp_get_busid_by_adapter(adapter));
-               } else {
-                       ZFCP_LOG_NORMAL("bug: The request identifier %p "
-                                       "to the adapter %s is ambiguous. "
-                                       "Stopping all operations on this "
-                                       "adapter. "
-                                       "(bug: got this for an unsolicited "
-                                       "status read request)\n",
-                                       fsf_req,
+                               "Stopping all operations on this adapter.\n",
+                               *(unsigned long long*)
+                               (&qtcb->bottom.support.req_handle),
                                        zfcp_get_busid_by_adapter(adapter));
-               }
-               debug_text_exception(adapter->erp_dbf, 0, "prot_dup_id");
                zfcp_erp_adapter_shutdown(adapter, 0);
-               zfcp_cmd_dbf_event_fsf("dupreqid", fsf_req,
-                                      &fsf_req->qtcb->prefix.prot_status_qual,
-                                      sizeof (union fsf_prot_status_qual));
                fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
                break;
 
        case FSF_PROT_LINK_DOWN:
-               /*
-                * 'test and set' is not atomic here -
-                * it's ok as long as calls to our response queue handler
-                * (and thus execution of this code here) are serialized
-                * by the qdio module
-                */
-               if (!atomic_test_mask(ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED,
-                                     &adapter->status)) {
-                       switch (fsf_req->qtcb->prefix.prot_status_qual.
-                               locallink_error.code) {
-                       case FSF_PSQ_LINK_NOLIGHT:
-                               ZFCP_LOG_INFO("The local link to adapter %s "
-                                             "is down (no light detected).\n",
-                                             zfcp_get_busid_by_adapter(
-                                                     adapter));
-                               break;
-                       case FSF_PSQ_LINK_WRAPPLUG:
-                               ZFCP_LOG_INFO("The local link to adapter %s "
-                                             "is down (wrap plug detected).\n",
-                                             zfcp_get_busid_by_adapter(
-                                                     adapter));
-                               break;
-                       case FSF_PSQ_LINK_NOFCP:
-                               ZFCP_LOG_INFO("The local link to adapter %s "
-                                             "is down (adjacent node on "
-                                             "link does not support FCP).\n",
-                                             zfcp_get_busid_by_adapter(
-                                                     adapter));
-                               break;
-                       default:
-                               ZFCP_LOG_INFO("The local link to adapter %s "
-                                             "is down "
-                                             "(warning: unknown reason "
-                                             "code).\n",
-                                             zfcp_get_busid_by_adapter(
-                                                     adapter));
-                               break;
-
-                       }
-                       /*
-                        * Due to the 'erp failed' flag the adapter won't
-                        * be recovered but will be just set to 'blocked'
-                        * state. All subordinary devices will have state
-                        * 'blocked' and 'erp failed', too.
-                        * Thus the adapter is still able to provide
-                        * 'link up' status without being flooded with
-                        * requests.
-                        * (note: even 'close port' is not permitted)
-                        */
-                       ZFCP_LOG_INFO("Stopping all operations for adapter "
-                                     "%s.\n",
-                                     zfcp_get_busid_by_adapter(adapter));
-                       atomic_set_mask(ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED |
-                                       ZFCP_STATUS_COMMON_ERP_FAILED,
-                                       &adapter->status);
-                       zfcp_erp_adapter_reopen(adapter, 0);
-               }
+               zfcp_fsf_link_down_info_eval(adapter,
+                                            &prot_status_qual->link_down_info);
                fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
                break;
 
        case FSF_PROT_REEST_QUEUE:
-               debug_text_event(adapter->erp_dbf, 1, "prot_reest_queue");
-               ZFCP_LOG_INFO("The local link to adapter with "
+               ZFCP_LOG_NORMAL("The local link to adapter with "
                              "%s was re-plugged. "
                              "Re-starting operations on this adapter.\n",
                              zfcp_get_busid_by_adapter(adapter));
@@ -495,9 +405,6 @@ zfcp_fsf_protstatus_eval(struct zfcp_fsf_req *fsf_req)
                zfcp_erp_adapter_reopen(adapter,
                                        ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED
                                        | ZFCP_STATUS_COMMON_ERP_FAILED);
-               zfcp_cmd_dbf_event_fsf("reestque", fsf_req,
-                                      &fsf_req->qtcb->prefix.prot_status_qual,
-                                      sizeof (union fsf_prot_status_qual));
                fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
                break;
 
@@ -507,12 +414,7 @@ zfcp_fsf_protstatus_eval(struct zfcp_fsf_req *fsf_req)
                                "Restarting all operations on this "
                                "adapter.\n",
                                zfcp_get_busid_by_adapter(adapter));
-               debug_text_event(adapter->erp_dbf, 0, "prot_err_sta");
-               /* restart operation on this adapter */
                zfcp_erp_adapter_reopen(adapter, 0);
-               zfcp_cmd_dbf_event_fsf("proterrs", fsf_req,
-                                      &fsf_req->qtcb->prefix.prot_status_qual,
-                                      sizeof (union fsf_prot_status_qual));
                fsf_req->status |= ZFCP_STATUS_FSFREQ_RETRY;
                fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
                break;
@@ -524,11 +426,7 @@ zfcp_fsf_protstatus_eval(struct zfcp_fsf_req *fsf_req)
                                "Stopping all operations on this adapter. "
                                "(debug info 0x%x).\n",
                                zfcp_get_busid_by_adapter(adapter),
-                               fsf_req->qtcb->prefix.prot_status);
-               debug_text_event(adapter->erp_dbf, 0, "prot_inval:");
-               debug_exception(adapter->erp_dbf, 0,
-                               &fsf_req->qtcb->prefix.prot_status,
-                               sizeof (u32));
+                               qtcb->prefix.prot_status);
                zfcp_erp_adapter_shutdown(adapter, 0);
                fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
        }
@@ -568,28 +466,18 @@ zfcp_fsf_fsfstatus_eval(struct zfcp_fsf_req *fsf_req)
                                "(debug info 0x%x).\n",
                                zfcp_get_busid_by_adapter(fsf_req->adapter),
                                fsf_req->qtcb->header.fsf_command);
-               debug_text_exception(fsf_req->adapter->erp_dbf, 0,
-                                    "fsf_s_unknown");
                zfcp_erp_adapter_shutdown(fsf_req->adapter, 0);
-               zfcp_cmd_dbf_event_fsf("unknownc", fsf_req,
-                                      &fsf_req->qtcb->header.fsf_status_qual,
-                                      sizeof (union fsf_status_qual));
                fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
                break;
 
        case FSF_FCP_RSP_AVAILABLE:
                ZFCP_LOG_DEBUG("FCP Sense data will be presented to the "
                               "SCSI stack.\n");
-               debug_text_event(fsf_req->adapter->erp_dbf, 3, "fsf_s_rsp");
                break;
 
        case FSF_ADAPTER_STATUS_AVAILABLE:
-               debug_text_event(fsf_req->adapter->erp_dbf, 2, "fsf_s_astatus");
                zfcp_fsf_fsfstatus_qual_eval(fsf_req);
                break;
-
-       default:
-               break;
        }
 
  skip_fsfstatus:
@@ -617,44 +505,28 @@ zfcp_fsf_fsfstatus_qual_eval(struct zfcp_fsf_req *fsf_req)
 
        switch (fsf_req->qtcb->header.fsf_status_qual.word[0]) {
        case FSF_SQ_FCP_RSP_AVAILABLE:
-               debug_text_event(fsf_req->adapter->erp_dbf, 4, "fsf_sq_rsp");
                break;
        case FSF_SQ_RETRY_IF_POSSIBLE:
                /* The SCSI-stack may now issue retries or escalate */
-               debug_text_event(fsf_req->adapter->erp_dbf, 2, "fsf_sq_retry");
-               zfcp_cmd_dbf_event_fsf("sqretry", fsf_req,
-                                      &fsf_req->qtcb->header.fsf_status_qual,
-                                      sizeof (union fsf_status_qual));
                fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
                break;
        case FSF_SQ_COMMAND_ABORTED:
                /* Carry the aborted state on to upper layer */
-               debug_text_event(fsf_req->adapter->erp_dbf, 2, "fsf_sq_abort");
-               zfcp_cmd_dbf_event_fsf("sqabort", fsf_req,
-                                      &fsf_req->qtcb->header.fsf_status_qual,
-                                      sizeof (union fsf_status_qual));
                fsf_req->status |= ZFCP_STATUS_FSFREQ_ABORTED;
                fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
                break;
        case FSF_SQ_NO_RECOM:
-               debug_text_exception(fsf_req->adapter->erp_dbf, 0,
-                                    "fsf_sq_no_rec");
                ZFCP_LOG_NORMAL("bug: No recommendation could be given for a"
                                "problem on the adapter %s "
                                "Stopping all operations on this adapter. ",
                                zfcp_get_busid_by_adapter(fsf_req->adapter));
                zfcp_erp_adapter_shutdown(fsf_req->adapter, 0);
-               zfcp_cmd_dbf_event_fsf("sqnrecom", fsf_req,
-                                      &fsf_req->qtcb->header.fsf_status_qual,
-                                      sizeof (union fsf_status_qual));
                fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
                break;
        case FSF_SQ_ULP_PROGRAMMING_ERROR:
                ZFCP_LOG_NORMAL("error: not enough SBALs for data transfer "
                                "(adapter %s)\n",
                                zfcp_get_busid_by_adapter(fsf_req->adapter));
-               debug_text_exception(fsf_req->adapter->erp_dbf, 0,
-                                    "fsf_sq_ulp_err");
                fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
                break;
        case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE:
@@ -668,13 +540,6 @@ zfcp_fsf_fsfstatus_qual_eval(struct zfcp_fsf_req *fsf_req)
                ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_NORMAL,
                              (char *) &fsf_req->qtcb->header.fsf_status_qual,
                              sizeof (union fsf_status_qual));
-               debug_text_event(fsf_req->adapter->erp_dbf, 0, "fsf_sq_inval:");
-               debug_exception(fsf_req->adapter->erp_dbf, 0,
-                               &fsf_req->qtcb->header.fsf_status_qual.word[0],
-                               sizeof (u32));
-               zfcp_cmd_dbf_event_fsf("squndef", fsf_req,
-                                      &fsf_req->qtcb->header.fsf_status_qual,
-                                      sizeof (union fsf_status_qual));
                fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
                break;
        }
@@ -682,6 +547,110 @@ zfcp_fsf_fsfstatus_qual_eval(struct zfcp_fsf_req *fsf_req)
        return retval;
 }
 
+/**
+ * zfcp_fsf_link_down_info_eval - evaluate link down information block
+ */
+static void
+zfcp_fsf_link_down_info_eval(struct zfcp_adapter *adapter,
+                            struct fsf_link_down_info *link_down)
+{
+       switch (link_down->error_code) {
+       case FSF_PSQ_LINK_NO_LIGHT:
+               ZFCP_LOG_NORMAL("The local link to adapter %s is down "
+                               "(no light detected)\n",
+                               zfcp_get_busid_by_adapter(adapter));
+               break;
+       case FSF_PSQ_LINK_WRAP_PLUG:
+               ZFCP_LOG_NORMAL("The local link to adapter %s is down "
+                               "(wrap plug detected)\n",
+                               zfcp_get_busid_by_adapter(adapter));
+               break;
+       case FSF_PSQ_LINK_NO_FCP:
+               ZFCP_LOG_NORMAL("The local link to adapter %s is down "
+                               "(adjacent node on link does not support FCP)\n",
+                               zfcp_get_busid_by_adapter(adapter));
+               break;
+       case FSF_PSQ_LINK_FIRMWARE_UPDATE:
+               ZFCP_LOG_NORMAL("The local link to adapter %s is down "
+                               "(firmware update in progress)\n",
+                               zfcp_get_busid_by_adapter(adapter));
+                       break;
+       case FSF_PSQ_LINK_INVALID_WWPN:
+               ZFCP_LOG_NORMAL("The local link to adapter %s is down "
+                               "(duplicate or invalid WWPN detected)\n",
+                               zfcp_get_busid_by_adapter(adapter));
+               break;
+       case FSF_PSQ_LINK_NO_NPIV_SUPPORT:
+               ZFCP_LOG_NORMAL("The local link to adapter %s is down "
+                               "(no support for NPIV by Fabric)\n",
+                               zfcp_get_busid_by_adapter(adapter));
+               break;
+       case FSF_PSQ_LINK_NO_FCP_RESOURCES:
+               ZFCP_LOG_NORMAL("The local link to adapter %s is down "
+                               "(out of resource in FCP daughtercard)\n",
+                               zfcp_get_busid_by_adapter(adapter));
+               break;
+       case FSF_PSQ_LINK_NO_FABRIC_RESOURCES:
+               ZFCP_LOG_NORMAL("The local link to adapter %s is down "
+                               "(out of resource in Fabric)\n",
+                               zfcp_get_busid_by_adapter(adapter));
+               break;
+       case FSF_PSQ_LINK_FABRIC_LOGIN_UNABLE:
+               ZFCP_LOG_NORMAL("The local link to adapter %s is down "
+                               "(unable to Fabric login)\n",
+                               zfcp_get_busid_by_adapter(adapter));
+               break;
+       case FSF_PSQ_LINK_WWPN_ASSIGNMENT_CORRUPTED:
+               ZFCP_LOG_NORMAL("WWPN assignment file corrupted on adapter %s\n",
+                               zfcp_get_busid_by_adapter(adapter));
+               break;
+       case FSF_PSQ_LINK_MODE_TABLE_CURRUPTED:
+               ZFCP_LOG_NORMAL("Mode table corrupted on adapter %s\n",
+                               zfcp_get_busid_by_adapter(adapter));
+               break;
+       case FSF_PSQ_LINK_NO_WWPN_ASSIGNMENT:
+               ZFCP_LOG_NORMAL("No WWPN for assignment table on adapter %s\n",
+                               zfcp_get_busid_by_adapter(adapter));
+               break;
+       default:
+               ZFCP_LOG_NORMAL("The local link to adapter %s is down "
+                               "(warning: unknown reason code %d)\n",
+                               zfcp_get_busid_by_adapter(adapter),
+                               link_down->error_code);
+       }
+
+       if (adapter->connection_features & FSF_FEATURE_NPIV_MODE)
+               ZFCP_LOG_DEBUG("Debug information to link down: "
+                              "primary_status=0x%02x "
+                              "ioerr_code=0x%02x "
+                              "action_code=0x%02x "
+                              "reason_code=0x%02x "
+                              "explanation_code=0x%02x "
+                              "vendor_specific_code=0x%02x\n",
+                               link_down->primary_status,
+                               link_down->ioerr_code,
+                               link_down->action_code,
+                               link_down->reason_code,
+                               link_down->explanation_code,
+                               link_down->vendor_specific_code);
+
+       if (!atomic_test_mask(ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED,
+                             &adapter->status)) {
+               atomic_set_mask(ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED,
+                               &adapter->status);
+               switch (link_down->error_code) {
+               case FSF_PSQ_LINK_NO_LIGHT:
+               case FSF_PSQ_LINK_WRAP_PLUG:
+               case FSF_PSQ_LINK_NO_FCP:
+               case FSF_PSQ_LINK_FIRMWARE_UPDATE:
+                       zfcp_erp_adapter_reopen(adapter, 0);
+                       break;
+               default:
+                       zfcp_erp_adapter_failed(adapter);
+               }
+       }
+}
+
 /*
  * function:   zfcp_fsf_req_dispatch
  *
@@ -696,11 +665,6 @@ zfcp_fsf_req_dispatch(struct zfcp_fsf_req *fsf_req)
        struct zfcp_adapter *adapter = fsf_req->adapter;
        int retval = 0;
 
-       if (unlikely(fsf_req->status & ZFCP_STATUS_FSFREQ_ERROR)) {
-               ZFCP_LOG_TRACE("fsf_req=%p, QTCB=%p\n", fsf_req, fsf_req->qtcb);
-               ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_TRACE,
-                             (char *) fsf_req->qtcb, sizeof(struct fsf_qtcb));
-       }
 
        switch (fsf_req->fsf_command) {
 
@@ -760,13 +724,13 @@ zfcp_fsf_req_dispatch(struct zfcp_fsf_req *fsf_req)
                fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
                ZFCP_LOG_NORMAL("bug: Command issued by the device driver is "
                                "not supported by the adapter %s\n",
-                               zfcp_get_busid_by_adapter(fsf_req->adapter));
+                               zfcp_get_busid_by_adapter(adapter));
                if (fsf_req->fsf_command != fsf_req->qtcb->header.fsf_command)
                        ZFCP_LOG_NORMAL
                            ("bug: Command issued by the device driver differs "
                             "from the command returned by the adapter %s "
                             "(debug info 0x%x, 0x%x).\n",
-                            zfcp_get_busid_by_adapter(fsf_req->adapter),
+                            zfcp_get_busid_by_adapter(adapter),
                             fsf_req->fsf_command,
                             fsf_req->qtcb->header.fsf_command);
        }
@@ -774,8 +738,6 @@ zfcp_fsf_req_dispatch(struct zfcp_fsf_req *fsf_req)
        if (!erp_action)
                return retval;
 
-       debug_text_event(adapter->erp_dbf, 3, "a_frh");
-       debug_event(adapter->erp_dbf, 3, &erp_action->action, sizeof (int));
        zfcp_erp_async_handler(erp_action, 0);
 
        return retval;
@@ -821,7 +783,7 @@ zfcp_fsf_status_read(struct zfcp_adapter *adapter, int req_flags)
                goto failed_buf;
        }
        memset(status_buffer, 0, sizeof (struct fsf_status_read_buffer));
-       fsf_req->data.status_read.buffer = status_buffer;
+       fsf_req->data = (unsigned long) status_buffer;
 
        /* insert pointer to respective buffer */
        sbale = zfcp_qdio_sbale_curr(fsf_req);
@@ -846,6 +808,7 @@ zfcp_fsf_status_read(struct zfcp_adapter *adapter, int req_flags)
  failed_buf:
        zfcp_fsf_req_free(fsf_req);
  failed_req_create:
+       zfcp_hba_dbf_event_fsf_unsol("fail", adapter, NULL);
  out:
        write_unlock_irqrestore(&adapter->request_queue.queue_lock, lock_flags);
        return retval;
@@ -859,7 +822,7 @@ zfcp_fsf_status_read_port_closed(struct zfcp_fsf_req *fsf_req)
        struct zfcp_port *port;
        unsigned long flags;
 
-       status_buffer = fsf_req->data.status_read.buffer;
+       status_buffer = (struct fsf_status_read_buffer *) fsf_req->data;
        adapter = fsf_req->adapter;
 
        read_lock_irqsave(&zfcp_data.config_lock, flags);
@@ -918,38 +881,33 @@ zfcp_fsf_status_read_handler(struct zfcp_fsf_req *fsf_req)
        int retval = 0;
        struct zfcp_adapter *adapter = fsf_req->adapter;
        struct fsf_status_read_buffer *status_buffer =
-           fsf_req->data.status_read.buffer;
+               (struct fsf_status_read_buffer *) fsf_req->data;
 
        if (fsf_req->status & ZFCP_STATUS_FSFREQ_DISMISSED) {
+               zfcp_hba_dbf_event_fsf_unsol("dism", adapter, status_buffer);
                mempool_free(status_buffer, adapter->pool.data_status_read);
                zfcp_fsf_req_free(fsf_req);
                goto out;
        }
 
+       zfcp_hba_dbf_event_fsf_unsol("read", adapter, status_buffer);
+
        switch (status_buffer->status_type) {
 
        case FSF_STATUS_READ_PORT_CLOSED:
-               debug_text_event(adapter->erp_dbf, 3, "unsol_pclosed:");
-               debug_event(adapter->erp_dbf, 3,
-                           &status_buffer->d_id, sizeof (u32));
                zfcp_fsf_status_read_port_closed(fsf_req);
                break;
 
        case FSF_STATUS_READ_INCOMING_ELS:
-               debug_text_event(adapter->erp_dbf, 3, "unsol_els:");
                zfcp_fsf_incoming_els(fsf_req);
                break;
 
        case FSF_STATUS_READ_SENSE_DATA_AVAIL:
-               debug_text_event(adapter->erp_dbf, 3, "unsol_sense:");
                ZFCP_LOG_INFO("unsolicited sense data received (adapter %s)\n",
                              zfcp_get_busid_by_adapter(adapter));
-                ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_NORMAL, (char *) status_buffer,
-                              sizeof(struct fsf_status_read_buffer));
                break;
 
        case FSF_STATUS_READ_BIT_ERROR_THRESHOLD:
-               debug_text_event(adapter->erp_dbf, 3, "unsol_bit_err:");
                ZFCP_LOG_NORMAL("Bit error threshold data received:\n");
                ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_NORMAL,
                              (char *) status_buffer,
@@ -957,17 +915,32 @@ zfcp_fsf_status_read_handler(struct zfcp_fsf_req *fsf_req)
                break;
 
        case FSF_STATUS_READ_LINK_DOWN:
-               debug_text_event(adapter->erp_dbf, 0, "unsol_link_down:");
-               ZFCP_LOG_INFO("Local link to adapter %s is down\n",
+               switch (status_buffer->status_subtype) {
+               case FSF_STATUS_READ_SUB_NO_PHYSICAL_LINK:
+                       ZFCP_LOG_INFO("Physical link to adapter %s is down\n",
+                                     zfcp_get_busid_by_adapter(adapter));
+                       break;
+               case FSF_STATUS_READ_SUB_FDISC_FAILED:
+                       ZFCP_LOG_INFO("Local link to adapter %s is down "
+                                     "due to failed FDISC login\n",
                              zfcp_get_busid_by_adapter(adapter));
-               atomic_set_mask(ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED,
-                               &adapter->status);
-               zfcp_erp_adapter_failed(adapter);
+                       break;
+               case FSF_STATUS_READ_SUB_FIRMWARE_UPDATE:
+                       ZFCP_LOG_INFO("Local link to adapter %s is down "
+                                     "due to firmware update on adapter\n",
+                                     zfcp_get_busid_by_adapter(adapter));
+                       break;
+               default:
+                       ZFCP_LOG_INFO("Local link to adapter %s is down "
+                                     "due to unknown reason\n",
+                                     zfcp_get_busid_by_adapter(adapter));
+               };
+               zfcp_fsf_link_down_info_eval(adapter,
+                       (struct fsf_link_down_info *) &status_buffer->payload);
                break;
 
        case FSF_STATUS_READ_LINK_UP:
-               debug_text_event(adapter->erp_dbf, 2, "unsol_link_up:");
-               ZFCP_LOG_INFO("Local link to adapter %s was replugged. "
+               ZFCP_LOG_NORMAL("Local link to adapter %s was replugged. "
                              "Restarting operations on this adapter\n",
                              zfcp_get_busid_by_adapter(adapter));
                /* All ports should be marked as ready to run again */
@@ -980,35 +953,40 @@ zfcp_fsf_status_read_handler(struct zfcp_fsf_req *fsf_req)
                break;
 
        case FSF_STATUS_READ_CFDC_UPDATED:
-               debug_text_event(adapter->erp_dbf, 2, "unsol_cfdc_update:");
-               ZFCP_LOG_INFO("CFDC has been updated on the adapter %s\n",
+               ZFCP_LOG_NORMAL("CFDC has been updated on the adapter %s\n",
                              zfcp_get_busid_by_adapter(adapter));
                zfcp_erp_adapter_access_changed(adapter);
                break;
 
        case FSF_STATUS_READ_CFDC_HARDENED:
-               debug_text_event(adapter->erp_dbf, 2, "unsol_cfdc_harden:");
                switch (status_buffer->status_subtype) {
                case FSF_STATUS_READ_SUB_CFDC_HARDENED_ON_SE:
-                       ZFCP_LOG_INFO("CFDC of adapter %s saved on SE\n",
+                       ZFCP_LOG_NORMAL("CFDC of adapter %s saved on SE\n",
                                      zfcp_get_busid_by_adapter(adapter));
                        break;
                case FSF_STATUS_READ_SUB_CFDC_HARDENED_ON_SE2:
-                       ZFCP_LOG_INFO("CFDC of adapter %s has been copied "
+                       ZFCP_LOG_NORMAL("CFDC of adapter %s has been copied "
                                      "to the secondary SE\n",
                                zfcp_get_busid_by_adapter(adapter));
                        break;
                default:
-                       ZFCP_LOG_INFO("CFDC of adapter %s has been hardened\n",
+                       ZFCP_LOG_NORMAL("CFDC of adapter %s has been hardened\n",
                                      zfcp_get_busid_by_adapter(adapter));
                }
                break;
 
+       case FSF_STATUS_READ_FEATURE_UPDATE_ALERT:
+               debug_text_event(adapter->erp_dbf, 2, "unsol_features:");
+               ZFCP_LOG_INFO("List of supported features on adapter %s has "
+                             "been changed from 0x%08X to 0x%08X\n",
+                             zfcp_get_busid_by_adapter(adapter),
+                             *(u32*) (status_buffer->payload + 4),
+                             *(u32*) (status_buffer->payload));
+               adapter->adapter_features = *(u32*) status_buffer->payload;
+               break;
+
        default:
-               debug_text_event(adapter->erp_dbf, 0, "unsol_unknown:");
-               debug_exception(adapter->erp_dbf, 0,
-                               &status_buffer->status_type, sizeof (u32));
-               ZFCP_LOG_NORMAL("bug: An unsolicited status packet of unknown "
+               ZFCP_LOG_NORMAL("warning: An unsolicited status packet of unknown "
                                "type was received (debug info 0x%x)\n",
                                status_buffer->status_type);
                ZFCP_LOG_DEBUG("Dump of status_read_buffer %p:\n",
@@ -1093,7 +1071,7 @@ zfcp_fsf_abort_fcp_command(unsigned long old_req_id,
         sbale[0].flags |= SBAL_FLAGS0_TYPE_READ;
         sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY;
 
-       fsf_req->data.abort_fcp_command.unit = unit;
+       fsf_req->data = (unsigned long) unit;
 
        /* set handles of unit and its parent port in QTCB */
        fsf_req->qtcb->header.lun_handle = unit->handle;
@@ -1139,7 +1117,7 @@ static int
 zfcp_fsf_abort_fcp_command_handler(struct zfcp_fsf_req *new_fsf_req)
 {
        int retval = -EINVAL;
-       struct zfcp_unit *unit = new_fsf_req->data.abort_fcp_command.unit;
+       struct zfcp_unit *unit;
        unsigned char status_qual =
            new_fsf_req->qtcb->header.fsf_status_qual.word[0];
 
@@ -1150,6 +1128,8 @@ zfcp_fsf_abort_fcp_command_handler(struct zfcp_fsf_req *new_fsf_req)
                goto skip_fsfstatus;
        }
 
+       unit = (struct zfcp_unit *) new_fsf_req->data;
+
        /* evaluate FSF status in QTCB */
        switch (new_fsf_req->qtcb->header.fsf_status) {
 
@@ -1364,7 +1344,7 @@ zfcp_fsf_send_ct(struct zfcp_send_ct *ct, mempool_t *pool,
                 sbale[3].addr = zfcp_sg_to_address(&ct->resp[0]);
                 sbale[3].length = ct->resp[0].length;
                 sbale[3].flags |= SBAL_FLAGS_LAST_ENTRY;
-        } else if (adapter->supported_features &
+       } else if (adapter->adapter_features &
                    FSF_FEATURE_ELS_CT_CHAINED_SBALS) {
                 /* try to use chained SBALs */
                 bytes = zfcp_qdio_sbals_from_sg(fsf_req,
@@ -1414,7 +1394,9 @@ zfcp_fsf_send_ct(struct zfcp_send_ct *ct, mempool_t *pool,
        fsf_req->qtcb->header.port_handle = port->handle;
        fsf_req->qtcb->bottom.support.service_class = adapter->fc_service_class;
        fsf_req->qtcb->bottom.support.timeout = ct->timeout;
-        fsf_req->data.send_ct = ct;
+        fsf_req->data = (unsigned long) ct;
+
+       zfcp_san_dbf_event_ct_request(fsf_req);
 
        /* start QDIO request for this FSF request */
        ret = zfcp_fsf_req_send(fsf_req, ct->timer);
@@ -1445,10 +1427,10 @@ zfcp_fsf_send_ct(struct zfcp_send_ct *ct, mempool_t *pool,
  * zfcp_fsf_send_ct_handler - handler for Generic Service requests
  * @fsf_req: pointer to struct zfcp_fsf_req
  *
- * Data specific for the Generic Service request is passed by
- * fsf_req->data.send_ct
- * Usually a specific handler for the request is called via
- * fsf_req->data.send_ct->handler at end of this function.
+ * Data specific for the Generic Service request is passed using
+ * fsf_req->data. There we find the pointer to struct zfcp_send_ct.
+ * Usually a specific handler for the CT request is called which is
+ * found in this structure.
  */
 static int
 zfcp_fsf_send_ct_handler(struct zfcp_fsf_req *fsf_req)
@@ -1462,7 +1444,7 @@ zfcp_fsf_send_ct_handler(struct zfcp_fsf_req *fsf_req)
        u16 subtable, rule, counter;
 
        adapter = fsf_req->adapter;
-       send_ct = fsf_req->data.send_ct;
+       send_ct = (struct zfcp_send_ct *) fsf_req->data;
        port = send_ct->port;
        header = &fsf_req->qtcb->header;
        bottom = &fsf_req->qtcb->bottom.support;
@@ -1474,6 +1456,7 @@ zfcp_fsf_send_ct_handler(struct zfcp_fsf_req *fsf_req)
        switch (header->fsf_status) {
 
         case FSF_GOOD:
+               zfcp_san_dbf_event_ct_response(fsf_req);
                 retval = 0;
                break;
 
@@ -1634,7 +1617,7 @@ zfcp_fsf_send_els(struct zfcp_send_els *els)
 {
        volatile struct qdio_buffer_element *sbale;
        struct zfcp_fsf_req *fsf_req;
-       fc_id_t d_id;
+       u32 d_id;
        struct zfcp_adapter *adapter;
        unsigned long lock_flags;
         int bytes;
@@ -1664,7 +1647,7 @@ zfcp_fsf_send_els(struct zfcp_send_els *els)
                 sbale[3].addr = zfcp_sg_to_address(&els->resp[0]);
                 sbale[3].length = els->resp[0].length;
                 sbale[3].flags |= SBAL_FLAGS_LAST_ENTRY;
-        } else if (adapter->supported_features &
+       } else if (adapter->adapter_features &
                    FSF_FEATURE_ELS_CT_CHAINED_SBALS) {
                 /* try to use chained SBALs */
                 bytes = zfcp_qdio_sbals_from_sg(fsf_req,
@@ -1714,10 +1697,12 @@ zfcp_fsf_send_els(struct zfcp_send_els *els)
        fsf_req->qtcb->bottom.support.d_id = d_id;
        fsf_req->qtcb->bottom.support.service_class = adapter->fc_service_class;
        fsf_req->qtcb->bottom.support.timeout = ZFCP_ELS_TIMEOUT;
-       fsf_req->data.send_els = els;
+       fsf_req->data = (unsigned long) els;
 
        sbale = zfcp_qdio_sbale_req(fsf_req, fsf_req->sbal_curr, 0);
 
+       zfcp_san_dbf_event_els_request(fsf_req);
+
        /* start QDIO request for this FSF request */
        ret = zfcp_fsf_req_send(fsf_req, els->timer);
        if (ret) {
@@ -1746,23 +1731,23 @@ zfcp_fsf_send_els(struct zfcp_send_els *els)
  * zfcp_fsf_send_els_handler - handler for ELS commands
  * @fsf_req: pointer to struct zfcp_fsf_req
  *
- * Data specific for the ELS command is passed by
- * fsf_req->data.send_els
- * Usually a specific handler for the command is called via
- * fsf_req->data.send_els->handler at end of this function.
+ * Data specific for the ELS command is passed using
+ * fsf_req->data. There we find the pointer to struct zfcp_send_els.
+ * Usually a specific handler for the ELS command is called which is
+ * found in this structure.
  */
 static int zfcp_fsf_send_els_handler(struct zfcp_fsf_req *fsf_req)
 {
        struct zfcp_adapter *adapter;
        struct zfcp_port *port;
-       fc_id_t d_id;
+       u32 d_id;
        struct fsf_qtcb_header *header;
        struct fsf_qtcb_bottom_support *bottom;
        struct zfcp_send_els *send_els;
        int retval = -EINVAL;
        u16 subtable, rule, counter;
 
-       send_els = fsf_req->data.send_els;
+       send_els = (struct zfcp_send_els *) fsf_req->data;
        adapter = send_els->adapter;
        port = send_els->port;
        d_id = send_els->d_id;
@@ -1775,6 +1760,7 @@ static int zfcp_fsf_send_els_handler(struct zfcp_fsf_req *fsf_req)
        switch (header->fsf_status) {
 
        case FSF_GOOD:
+               zfcp_san_dbf_event_els_response(fsf_req);
                retval = 0;
                break;
 
@@ -1954,7 +1940,9 @@ zfcp_fsf_exchange_config_data(struct zfcp_erp_action *erp_action)
 
        erp_action->fsf_req->erp_action = erp_action;
        erp_action->fsf_req->qtcb->bottom.config.feature_selection =
-               (FSF_FEATURE_CFDC | FSF_FEATURE_LUN_SHARING);
+                       FSF_FEATURE_CFDC |
+                       FSF_FEATURE_LUN_SHARING |
+                       FSF_FEATURE_UPDATE_ALERT;
 
        /* start QDIO request for this FSF request */
        retval = zfcp_fsf_req_send(erp_action->fsf_req, &erp_action->timer);
@@ -1990,29 +1978,36 @@ zfcp_fsf_exchange_config_evaluate(struct zfcp_fsf_req *fsf_req, int xchg_ok)
 {
        struct fsf_qtcb_bottom_config *bottom;
        struct zfcp_adapter *adapter = fsf_req->adapter;
+       struct Scsi_Host *shost = adapter->scsi_host;
 
        bottom = &fsf_req->qtcb->bottom.config;
        ZFCP_LOG_DEBUG("low/high QTCB version 0x%x/0x%x of FSF\n",
                       bottom->low_qtcb_version, bottom->high_qtcb_version);
        adapter->fsf_lic_version = bottom->lic_version;
-       adapter->supported_features = bottom->supported_features;
+       adapter->adapter_features = bottom->adapter_features;
+       adapter->connection_features = bottom->connection_features;
        adapter->peer_wwpn = 0;
        adapter->peer_wwnn = 0;
        adapter->peer_d_id = 0;
 
        if (xchg_ok) {
-               adapter->wwnn = bottom->nport_serv_param.wwnn;
-               adapter->wwpn = bottom->nport_serv_param.wwpn;
-               adapter->s_id = bottom->s_id & ZFCP_DID_MASK;
+               fc_host_node_name(shost) = bottom->nport_serv_param.wwnn;
+               fc_host_port_name(shost) = bottom->nport_serv_param.wwpn;
+               fc_host_port_id(shost) = bottom->s_id & ZFCP_DID_MASK;
+               fc_host_speed(shost) = bottom->fc_link_speed;
+               fc_host_supported_classes(shost) = FC_COS_CLASS2 | FC_COS_CLASS3;
                adapter->fc_topology = bottom->fc_topology;
-               adapter->fc_link_speed = bottom->fc_link_speed;
                adapter->hydra_version = bottom->adapter_type;
+               if (adapter->physical_wwpn == 0)
+                       adapter->physical_wwpn = fc_host_port_name(shost);
+               if (adapter->physical_s_id == 0)
+                       adapter->physical_s_id = fc_host_port_id(shost);
        } else {
-               adapter->wwnn = 0;
-               adapter->wwpn = 0;
-               adapter->s_id = 0;
+               fc_host_node_name(shost) = 0;
+               fc_host_port_name(shost) = 0;
+               fc_host_port_id(shost) = 0;
+               fc_host_speed(shost) = FC_PORTSPEED_UNKNOWN;
                adapter->fc_topology = 0;
-               adapter->fc_link_speed = 0;
                adapter->hydra_version = 0;
        }
 
@@ -2022,26 +2017,28 @@ zfcp_fsf_exchange_config_evaluate(struct zfcp_fsf_req *fsf_req, int xchg_ok)
                adapter->peer_wwnn = bottom->plogi_payload.wwnn;
        }
 
-       if(adapter->supported_features & FSF_FEATURE_HBAAPI_MANAGEMENT){
+       if (adapter->adapter_features & FSF_FEATURE_HBAAPI_MANAGEMENT) {
                adapter->hardware_version = bottom->hardware_version;
-               memcpy(adapter->serial_number, bottom->serial_number, 17);
-               EBCASC(adapter->serial_number, sizeof(adapter->serial_number));
+               memcpy(fc_host_serial_number(shost), bottom->serial_number,
+                      min(FC_SERIAL_NUMBER_SIZE, 17));
+               EBCASC(fc_host_serial_number(shost),
+                      min(FC_SERIAL_NUMBER_SIZE, 17));
        }
 
        ZFCP_LOG_NORMAL("The adapter %s reported the following characteristics:\n"
-                     "WWNN 0x%016Lx, "
-                     "WWPN 0x%016Lx, "
-                     "S_ID 0x%08x,\n"
-                     "adapter version 0x%x, "
-                     "LIC version 0x%x, "
-                     "FC link speed %d Gb/s\n",
-                     zfcp_get_busid_by_adapter(adapter),
-                     adapter->wwnn,
-                     adapter->wwpn,
-                     (unsigned int) adapter->s_id,
-                     adapter->hydra_version,
-                     adapter->fsf_lic_version,
-                     adapter->fc_link_speed);
+                       "WWNN 0x%016Lx, "
+                       "WWPN 0x%016Lx, "
+                       "S_ID 0x%08x,\n"
+                       "adapter version 0x%x, "
+                       "LIC version 0x%x, "
+                       "FC link speed %d Gb/s\n",
+                       zfcp_get_busid_by_adapter(adapter),
+                       (wwn_t) fc_host_node_name(shost),
+                       (wwn_t) fc_host_port_name(shost),
+                       fc_host_port_id(shost),
+                       adapter->hydra_version,
+                       adapter->fsf_lic_version,
+                       fc_host_speed(shost));
        if (ZFCP_QTCB_VERSION < bottom->low_qtcb_version) {
                ZFCP_LOG_NORMAL("error: the adapter %s "
                                "only supports newer control block "
@@ -2062,7 +2059,6 @@ zfcp_fsf_exchange_config_evaluate(struct zfcp_fsf_req *fsf_req, int xchg_ok)
                zfcp_erp_adapter_shutdown(adapter, 0);
                return -EIO;
        }
-       zfcp_set_fc_host_attrs(adapter);
        return 0;
 }
 
@@ -2078,11 +2074,12 @@ zfcp_fsf_exchange_config_data_handler(struct zfcp_fsf_req *fsf_req)
 {
        struct fsf_qtcb_bottom_config *bottom;
        struct zfcp_adapter *adapter = fsf_req->adapter;
+       struct fsf_qtcb *qtcb = fsf_req->qtcb;
 
        if (fsf_req->status & ZFCP_STATUS_FSFREQ_ERROR)
                return -EIO;
 
-       switch (fsf_req->qtcb->header.fsf_status) {
+       switch (qtcb->header.fsf_status) {
 
        case FSF_GOOD:
                if (zfcp_fsf_exchange_config_evaluate(fsf_req, 1))
@@ -2112,7 +2109,7 @@ zfcp_fsf_exchange_config_data_handler(struct zfcp_fsf_req *fsf_req)
                        zfcp_erp_adapter_shutdown(adapter, 0);
                        return -EIO;
                case FSF_TOPO_FABRIC:
-                       ZFCP_LOG_INFO("Switched fabric fibrechannel "
+                       ZFCP_LOG_NORMAL("Switched fabric fibrechannel "
                                      "network detected at adapter %s.\n",
                                      zfcp_get_busid_by_adapter(adapter));
                        break;
@@ -2130,7 +2127,7 @@ zfcp_fsf_exchange_config_data_handler(struct zfcp_fsf_req *fsf_req)
                        zfcp_erp_adapter_shutdown(adapter, 0);
                        return -EIO;
                }
-               bottom = &fsf_req->qtcb->bottom.config;
+               bottom = &qtcb->bottom.config;
                if (bottom->max_qtcb_size < sizeof(struct fsf_qtcb)) {
                        ZFCP_LOG_NORMAL("bug: Maximum QTCB size (%d bytes) "
                                        "allowed by the adapter %s "
@@ -2155,12 +2152,10 @@ zfcp_fsf_exchange_config_data_handler(struct zfcp_fsf_req *fsf_req)
                if (zfcp_fsf_exchange_config_evaluate(fsf_req, 0))
                        return -EIO;
 
-               ZFCP_LOG_INFO("Local link to adapter %s is down\n",
-                             zfcp_get_busid_by_adapter(adapter));
-               atomic_set_mask(ZFCP_STATUS_ADAPTER_XCONFIG_OK |
-                               ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED,
-                               &adapter->status);
-               zfcp_erp_adapter_failed(adapter);
+               atomic_set_mask(ZFCP_STATUS_ADAPTER_XCONFIG_OK, &adapter->status);
+
+               zfcp_fsf_link_down_info_eval(adapter,
+                       &qtcb->header.fsf_status_qual.link_down_info);
                break;
        default:
                debug_text_event(fsf_req->adapter->erp_dbf, 0, "fsf-stat-ng");
@@ -2174,11 +2169,13 @@ zfcp_fsf_exchange_config_data_handler(struct zfcp_fsf_req *fsf_req)
 
 /**
  * zfcp_fsf_exchange_port_data - request information about local port
+ * @erp_action: ERP action for the adapter for which port data is requested
  * @adapter: for which port data is requested
  * @data: response to exchange port data request
  */
 int
-zfcp_fsf_exchange_port_data(struct zfcp_adapter *adapter,
+zfcp_fsf_exchange_port_data(struct zfcp_erp_action *erp_action,
+                           struct zfcp_adapter *adapter,
                            struct fsf_qtcb_bottom_port *data)
 {
        volatile struct qdio_buffer_element *sbale;
@@ -2187,7 +2184,7 @@ zfcp_fsf_exchange_port_data(struct zfcp_adapter *adapter,
         struct zfcp_fsf_req *fsf_req;
        struct timer_list *timer;
 
-        if(!(adapter->supported_features & FSF_FEATURE_HBAAPI_MANAGEMENT)){
+       if (!(adapter->adapter_features & FSF_FEATURE_HBAAPI_MANAGEMENT)) {
                ZFCP_LOG_INFO("error: exchange port data "
                               "command not supported by adapter %s\n",
                              zfcp_get_busid_by_adapter(adapter));
@@ -2211,12 +2208,18 @@ zfcp_fsf_exchange_port_data(struct zfcp_adapter *adapter,
                goto out;
        }
 
+       if (erp_action) {
+               erp_action->fsf_req = fsf_req;
+               fsf_req->erp_action = erp_action;
+       }
+
+       if (data)
+       fsf_req->data = (unsigned long) data;
+
        sbale = zfcp_qdio_sbale_req(fsf_req, fsf_req->sbal_curr, 0);
         sbale[0].flags |= SBAL_FLAGS0_TYPE_READ;
         sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY;
 
-        fsf_req->data.port_data = data;
-
        init_timer(timer);
        timer->function = zfcp_fsf_request_timeout_handler;
        timer->data = (unsigned long) adapter;
@@ -2228,6 +2231,8 @@ zfcp_fsf_exchange_port_data(struct zfcp_adapter *adapter,
                               "command on the adapter %s\n",
                              zfcp_get_busid_by_adapter(adapter));
                zfcp_fsf_req_free(fsf_req);
+               if (erp_action)
+                       erp_action->fsf_req = NULL;
                write_unlock_irqrestore(&adapter->request_queue.queue_lock,
                                        lock_flags);
                goto out;
@@ -2256,21 +2261,42 @@ zfcp_fsf_exchange_port_data(struct zfcp_adapter *adapter,
 static void
 zfcp_fsf_exchange_port_data_handler(struct zfcp_fsf_req *fsf_req)
 {
-       struct fsf_qtcb_bottom_port *bottom;
-       struct fsf_qtcb_bottom_port *data = fsf_req->data.port_data;
+       struct zfcp_adapter *adapter = fsf_req->adapter;
+       struct Scsi_Host *shost = adapter->scsi_host;
+       struct fsf_qtcb *qtcb = fsf_req->qtcb;
+       struct fsf_qtcb_bottom_port *bottom, *data;
 
        if (fsf_req->status & ZFCP_STATUS_FSFREQ_ERROR)
                return;
 
-       switch (fsf_req->qtcb->header.fsf_status) {
+       switch (qtcb->header.fsf_status) {
         case FSF_GOOD:
-                bottom = &fsf_req->qtcb->bottom.port;
-                memcpy(data, bottom, sizeof(*data));
+               atomic_set_mask(ZFCP_STATUS_ADAPTER_XPORT_OK, &adapter->status);
+
+               bottom = &qtcb->bottom.port;
+               data = (struct fsf_qtcb_bottom_port*) fsf_req->data;
+               if (data)
+                       memcpy(data, bottom, sizeof(struct fsf_qtcb_bottom_port));
+               if (adapter->connection_features & FSF_FEATURE_NPIV_MODE) {
+                       adapter->physical_wwpn = bottom->wwpn;
+                       adapter->physical_s_id = bottom->fc_port_id;
+               } else {
+                       adapter->physical_wwpn = fc_host_port_name(shost);
+                       adapter->physical_s_id = fc_host_port_id(shost);
+               }
+               fc_host_maxframe_size(shost) = bottom->maximum_frame_size;
+               break;
+
+       case FSF_EXCHANGE_CONFIG_DATA_INCOMPLETE:
+               atomic_set_mask(ZFCP_STATUS_ADAPTER_XPORT_OK, &adapter->status);
+
+               zfcp_fsf_link_down_info_eval(adapter,
+                       &qtcb->header.fsf_status_qual.link_down_info);
                 break;
 
         default:
-               debug_text_event(fsf_req->adapter->erp_dbf, 0, "xchg-port-ng");
-                debug_event(fsf_req->adapter->erp_dbf, 0,
+               debug_text_event(adapter->erp_dbf, 0, "xchg-port-ng");
+               debug_event(adapter->erp_dbf, 0,
                            &fsf_req->qtcb->header.fsf_status, sizeof(u32));
        }
 }
@@ -2312,7 +2338,7 @@ zfcp_fsf_open_port(struct zfcp_erp_action *erp_action)
 
        erp_action->fsf_req->qtcb->bottom.support.d_id = erp_action->port->d_id;
        atomic_set_mask(ZFCP_STATUS_COMMON_OPENING, &erp_action->port->status);
-       erp_action->fsf_req->data.open_port.port = erp_action->port;
+       erp_action->fsf_req->data = (unsigned long) erp_action->port;
        erp_action->fsf_req->erp_action = erp_action;
 
        /* start QDIO request for this FSF request */
@@ -2353,7 +2379,7 @@ zfcp_fsf_open_port_handler(struct zfcp_fsf_req *fsf_req)
        struct fsf_qtcb_header *header;
        u16 subtable, rule, counter;
 
-       port = fsf_req->data.open_port.port;
+       port = (struct zfcp_port *) fsf_req->data;
        header = &fsf_req->qtcb->header;
 
        if (fsf_req->status & ZFCP_STATUS_FSFREQ_ERROR) {
@@ -2566,7 +2592,7 @@ zfcp_fsf_close_port(struct zfcp_erp_action *erp_action)
         sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY;
 
        atomic_set_mask(ZFCP_STATUS_COMMON_CLOSING, &erp_action->port->status);
-       erp_action->fsf_req->data.close_port.port = erp_action->port;
+       erp_action->fsf_req->data = (unsigned long) erp_action->port;
        erp_action->fsf_req->erp_action = erp_action;
        erp_action->fsf_req->qtcb->header.port_handle =
            erp_action->port->handle;
@@ -2606,7 +2632,7 @@ zfcp_fsf_close_port_handler(struct zfcp_fsf_req *fsf_req)
        int retval = -EINVAL;
        struct zfcp_port *port;
 
-       port = fsf_req->data.close_port.port;
+       port = (struct zfcp_port *) fsf_req->data;
 
        if (fsf_req->status & ZFCP_STATUS_FSFREQ_ERROR) {
                /* don't change port status in our bookkeeping */
@@ -2703,8 +2729,8 @@ zfcp_fsf_close_physical_port(struct zfcp_erp_action *erp_action)
        atomic_set_mask(ZFCP_STATUS_PORT_PHYS_CLOSING,
                        &erp_action->port->status);
        /* save a pointer to this port */
-       erp_action->fsf_req->data.close_physical_port.port = erp_action->port;
-       /* port to be closeed */
+       erp_action->fsf_req->data = (unsigned long) erp_action->port;
+       /* port to be closed */
        erp_action->fsf_req->qtcb->header.port_handle =
            erp_action->port->handle;
        erp_action->fsf_req->erp_action = erp_action;
@@ -2747,7 +2773,7 @@ zfcp_fsf_close_physical_port_handler(struct zfcp_fsf_req *fsf_req)
        struct fsf_qtcb_header *header;
        u16 subtable, rule, counter;
 
-       port = fsf_req->data.close_physical_port.port;
+       port = (struct zfcp_port *) fsf_req->data;
        header = &fsf_req->qtcb->header;
 
        if (fsf_req->status & ZFCP_STATUS_FSFREQ_ERROR) {
@@ -2908,10 +2934,11 @@ zfcp_fsf_open_unit(struct zfcp_erp_action *erp_action)
                erp_action->port->handle;
        erp_action->fsf_req->qtcb->bottom.support.fcp_lun =
                erp_action->unit->fcp_lun;
+       if (!(erp_action->adapter->connection_features & FSF_FEATURE_NPIV_MODE))
        erp_action->fsf_req->qtcb->bottom.support.option =
                FSF_OPEN_LUN_SUPPRESS_BOXING;
        atomic_set_mask(ZFCP_STATUS_COMMON_OPENING, &erp_action->unit->status);
-       erp_action->fsf_req->data.open_unit.unit = erp_action->unit;
+       erp_action->fsf_req->data = (unsigned long) erp_action->unit;
        erp_action->fsf_req->erp_action = erp_action;
 
        /* start QDIO request for this FSF request */
@@ -2955,9 +2982,9 @@ zfcp_fsf_open_unit_handler(struct zfcp_fsf_req *fsf_req)
        struct fsf_qtcb_bottom_support *bottom;
        struct fsf_queue_designator *queue_designator;
        u16 subtable, rule, counter;
-       u32 allowed, exclusive, readwrite;
+       int exclusive, readwrite;
 
-       unit = fsf_req->data.open_unit.unit;
+       unit = (struct zfcp_unit *) fsf_req->data;
 
        if (fsf_req->status & ZFCP_STATUS_FSFREQ_ERROR) {
                /* don't change unit status in our bookkeeping */
@@ -2969,10 +2996,6 @@ zfcp_fsf_open_unit_handler(struct zfcp_fsf_req *fsf_req)
        bottom = &fsf_req->qtcb->bottom.support;
        queue_designator = &header->fsf_status_qual.fsf_queue_designator;
 
-       allowed   = bottom->lun_access_info & FSF_UNIT_ACCESS_OPEN_LUN_ALLOWED;
-       exclusive = bottom->lun_access_info & FSF_UNIT_ACCESS_EXCLUSIVE;
-       readwrite = bottom->lun_access_info & FSF_UNIT_ACCESS_OUTBOUND_TRANSFER;
-
        atomic_clear_mask(ZFCP_STATUS_COMMON_ACCESS_DENIED |
                          ZFCP_STATUS_UNIT_SHARED |
                          ZFCP_STATUS_UNIT_READONLY,
@@ -3146,10 +3169,15 @@ zfcp_fsf_open_unit_handler(struct zfcp_fsf_req *fsf_req)
                               unit->handle);
                /* mark unit as open */
                atomic_set_mask(ZFCP_STATUS_COMMON_OPEN, &unit->status);
-               atomic_clear_mask(ZFCP_STATUS_COMMON_ACCESS_DENIED |
-                                 ZFCP_STATUS_COMMON_ACCESS_BOXED,
-                                 &unit->status);
-               if (adapter->supported_features & FSF_FEATURE_LUN_SHARING){
+
+               if (!(adapter->connection_features & FSF_FEATURE_NPIV_MODE) &&
+                   (adapter->adapter_features & FSF_FEATURE_LUN_SHARING) &&
+                   (adapter->ccw_device->id.dev_model != ZFCP_DEVICE_MODEL_PRIV)) {
+                       exclusive = (bottom->lun_access_info &
+                                       FSF_UNIT_ACCESS_EXCLUSIVE);
+                       readwrite = (bottom->lun_access_info &
+                                       FSF_UNIT_ACCESS_OUTBOUND_TRANSFER);
+
                        if (!exclusive)
                                atomic_set_mask(ZFCP_STATUS_UNIT_SHARED,
                                                &unit->status);
@@ -3242,7 +3270,7 @@ zfcp_fsf_close_unit(struct zfcp_erp_action *erp_action)
            erp_action->port->handle;
        erp_action->fsf_req->qtcb->header.lun_handle = erp_action->unit->handle;
        atomic_set_mask(ZFCP_STATUS_COMMON_CLOSING, &erp_action->unit->status);
-       erp_action->fsf_req->data.close_unit.unit = erp_action->unit;
+       erp_action->fsf_req->data = (unsigned long) erp_action->unit;
        erp_action->fsf_req->erp_action = erp_action;
 
        /* start QDIO request for this FSF request */
@@ -3281,7 +3309,7 @@ zfcp_fsf_close_unit_handler(struct zfcp_fsf_req *fsf_req)
        int retval = -EINVAL;
        struct zfcp_unit *unit;
 
-       unit = fsf_req->data.close_unit.unit;   /* restore unit */
+       unit = (struct zfcp_unit *) fsf_req->data;
 
        if (fsf_req->status & ZFCP_STATUS_FSFREQ_ERROR) {
                /* don't change unit status in our bookkeeping */
@@ -3305,9 +3333,6 @@ zfcp_fsf_close_unit_handler(struct zfcp_fsf_req *fsf_req)
                debug_text_event(fsf_req->adapter->erp_dbf, 1,
                                 "fsf_s_phand_nv");
                zfcp_erp_adapter_reopen(unit->port->adapter, 0);
-               zfcp_cmd_dbf_event_fsf("porthinv", fsf_req,
-                                      &fsf_req->qtcb->header.fsf_status_qual,
-                                      sizeof (union fsf_status_qual));
                fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
                break;
 
@@ -3326,9 +3351,6 @@ zfcp_fsf_close_unit_handler(struct zfcp_fsf_req *fsf_req)
                debug_text_event(fsf_req->adapter->erp_dbf, 1,
                                 "fsf_s_lhand_nv");
                zfcp_erp_port_reopen(unit->port, 0);
-               zfcp_cmd_dbf_event_fsf("lunhinv", fsf_req,
-                                      &fsf_req->qtcb->header.fsf_status_qual,
-                                      sizeof (union fsf_status_qual));
                fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
                break;
 
@@ -3436,21 +3458,14 @@ zfcp_fsf_send_fcp_command_task(struct zfcp_adapter *adapter,
                goto failed_req_create;
        }
 
-       /*
-        * associate FSF request with SCSI request
-        * (need this for look up on abort)
-        */
-       fsf_req->data.send_fcp_command_task.fsf_req = fsf_req;
-       scsi_cmnd->host_scribble = (char *) &(fsf_req->data);
+       zfcp_unit_get(unit);
+       fsf_req->unit = unit;
 
-       /*
-        * associate SCSI command with FSF request
-        * (need this for look up on normal command completion)
-        */
-       fsf_req->data.send_fcp_command_task.scsi_cmnd = scsi_cmnd;
-       fsf_req->data.send_fcp_command_task.start_jiffies = jiffies;
-       fsf_req->data.send_fcp_command_task.unit = unit;
-       ZFCP_LOG_DEBUG("unit=%p, fcp_lun=0x%016Lx\n", unit, unit->fcp_lun);
+       /* associate FSF request with SCSI request (for look up on abort) */
+       scsi_cmnd->host_scribble = (char *) fsf_req;
+
+       /* associate SCSI command with FSF request */
+       fsf_req->data = (unsigned long) scsi_cmnd;
 
        /* set handles of unit and its parent port in QTCB */
        fsf_req->qtcb->header.lun_handle = unit->handle;
@@ -3584,6 +3599,7 @@ zfcp_fsf_send_fcp_command_task(struct zfcp_adapter *adapter,
  send_failed:
  no_fit:
  failed_scsi_cmnd:
+       zfcp_unit_put(unit);
        zfcp_fsf_req_free(fsf_req);
        fsf_req = NULL;
        scsi_cmnd->host_scribble = NULL;
@@ -3640,7 +3656,7 @@ zfcp_fsf_send_fcp_command_task_management(struct zfcp_adapter *adapter,
         * hold a pointer to the unit being target of this
         * task management request
         */
-       fsf_req->data.send_fcp_command_task_management.unit = unit;
+       fsf_req->data = (unsigned long) unit;
 
        /* set FSF related fields in QTCB */
        fsf_req->qtcb->header.lun_handle = unit->handle;
@@ -3706,9 +3722,9 @@ zfcp_fsf_send_fcp_command_handler(struct zfcp_fsf_req *fsf_req)
        header = &fsf_req->qtcb->header;
 
        if (unlikely(fsf_req->status & ZFCP_STATUS_FSFREQ_TASK_MANAGEMENT))
-               unit = fsf_req->data.send_fcp_command_task_management.unit;
+               unit = (struct zfcp_unit *) fsf_req->data;
        else
-               unit = fsf_req->data.send_fcp_command_task.unit;
+               unit = fsf_req->unit;
 
        if (unlikely(fsf_req->status & ZFCP_STATUS_FSFREQ_ERROR)) {
                /* go directly to calls of special handlers */
@@ -3765,10 +3781,6 @@ zfcp_fsf_send_fcp_command_handler(struct zfcp_fsf_req *fsf_req)
                debug_text_event(fsf_req->adapter->erp_dbf, 1,
                                 "fsf_s_hand_mis");
                zfcp_erp_adapter_reopen(unit->port->adapter, 0);
-               zfcp_cmd_dbf_event_fsf("handmism",
-                                      fsf_req,
-                                      &header->fsf_status_qual,
-                                      sizeof (union fsf_status_qual));
                fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
                break;
 
@@ -3789,10 +3801,6 @@ zfcp_fsf_send_fcp_command_handler(struct zfcp_fsf_req *fsf_req)
                debug_text_exception(fsf_req->adapter->erp_dbf, 0,
                                     "fsf_s_class_nsup");
                zfcp_erp_adapter_shutdown(unit->port->adapter, 0);
-               zfcp_cmd_dbf_event_fsf("unsclass",
-                                      fsf_req,
-                                      &header->fsf_status_qual,
-                                      sizeof (union fsf_status_qual));
                fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
                break;
 
@@ -3811,10 +3819,6 @@ zfcp_fsf_send_fcp_command_handler(struct zfcp_fsf_req *fsf_req)
                debug_text_event(fsf_req->adapter->erp_dbf, 1,
                                 "fsf_s_fcp_lun_nv");
                zfcp_erp_port_reopen(unit->port, 0);
-               zfcp_cmd_dbf_event_fsf("fluninv",
-                                      fsf_req,
-                                      &header->fsf_status_qual,
-                                      sizeof (union fsf_status_qual));
                fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
                break;
 
@@ -3853,10 +3857,6 @@ zfcp_fsf_send_fcp_command_handler(struct zfcp_fsf_req *fsf_req)
                debug_text_event(fsf_req->adapter->erp_dbf, 0,
                                 "fsf_s_dir_ind_nv");
                zfcp_erp_adapter_shutdown(unit->port->adapter, 0);
-               zfcp_cmd_dbf_event_fsf("dirinv",
-                                      fsf_req,
-                                      &header->fsf_status_qual,
-                                      sizeof (union fsf_status_qual));
                fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
                break;
 
@@ -3872,10 +3872,6 @@ zfcp_fsf_send_fcp_command_handler(struct zfcp_fsf_req *fsf_req)
                debug_text_event(fsf_req->adapter->erp_dbf, 0,
                                 "fsf_s_cmd_len_nv");
                zfcp_erp_adapter_shutdown(unit->port->adapter, 0);
-               zfcp_cmd_dbf_event_fsf("cleninv",
-                                      fsf_req,
-                                      &header->fsf_status_qual,
-                                      sizeof (union fsf_status_qual));
                fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
                break;
 
@@ -3947,6 +3943,8 @@ zfcp_fsf_send_fcp_command_handler(struct zfcp_fsf_req *fsf_req)
                    zfcp_fsf_send_fcp_command_task_management_handler(fsf_req);
        } else {
                retval = zfcp_fsf_send_fcp_command_task_handler(fsf_req);
+               fsf_req->unit = NULL;
+               zfcp_unit_put(unit);
        }
        return retval;
 }
@@ -3970,10 +3968,10 @@ zfcp_fsf_send_fcp_command_task_handler(struct zfcp_fsf_req *fsf_req)
        u32 sns_len;
        char *fcp_rsp_info = zfcp_get_fcp_rsp_info_ptr(fcp_rsp_iu);
        unsigned long flags;
-       struct zfcp_unit *unit = fsf_req->data.send_fcp_command_task.unit;
+       struct zfcp_unit *unit = fsf_req->unit;
 
        read_lock_irqsave(&fsf_req->adapter->abort_lock, flags);
-       scpnt = fsf_req->data.send_fcp_command_task.scsi_cmnd;
+       scpnt = (struct scsi_cmnd *) fsf_req->data;
        if (unlikely(!scpnt)) {
                ZFCP_LOG_DEBUG
                    ("Command with fsf_req %p is not associated to "
@@ -4043,7 +4041,6 @@ zfcp_fsf_send_fcp_command_task_handler(struct zfcp_fsf_req *fsf_req)
                        ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_DEBUG,
                                      (char *) &fsf_req->qtcb->
                                      bottom.io.fcp_cmnd, FSF_FCP_CMND_SIZE);
-                       zfcp_cmd_dbf_event_fsf("clenmis", fsf_req, NULL, 0);
                        set_host_byte(&scpnt->result, DID_ERROR);
                        goto skip_fsfstatus;
                case RSP_CODE_FIELD_INVALID:
@@ -4062,7 +4059,6 @@ zfcp_fsf_send_fcp_command_task_handler(struct zfcp_fsf_req *fsf_req)
                                      (char *) &fsf_req->qtcb->
                                      bottom.io.fcp_cmnd, FSF_FCP_CMND_SIZE);
                        set_host_byte(&scpnt->result, DID_ERROR);
-                       zfcp_cmd_dbf_event_fsf("codeinv", fsf_req, NULL, 0);
                        goto skip_fsfstatus;
                case RSP_CODE_RO_MISMATCH:
                        /* hardware bug */
@@ -4079,7 +4075,6 @@ zfcp_fsf_send_fcp_command_task_handler(struct zfcp_fsf_req *fsf_req)
                        ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_DEBUG,
                                      (char *) &fsf_req->qtcb->
                                      bottom.io.fcp_cmnd, FSF_FCP_CMND_SIZE);
-                       zfcp_cmd_dbf_event_fsf("codemism", fsf_req, NULL, 0);
                        set_host_byte(&scpnt->result, DID_ERROR);
                        goto skip_fsfstatus;
                default:
@@ -4096,7 +4091,6 @@ zfcp_fsf_send_fcp_command_task_handler(struct zfcp_fsf_req *fsf_req)
                        ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_DEBUG,
                                      (char *) &fsf_req->qtcb->
                                      bottom.io.fcp_cmnd, FSF_FCP_CMND_SIZE);
-                       zfcp_cmd_dbf_event_fsf("undeffcp", fsf_req, NULL, 0);
                        set_host_byte(&scpnt->result, DID_ERROR);
                        goto skip_fsfstatus;
                }
@@ -4158,19 +4152,17 @@ zfcp_fsf_send_fcp_command_task_handler(struct zfcp_fsf_req *fsf_req)
  skip_fsfstatus:
        ZFCP_LOG_DEBUG("scpnt->result =0x%x\n", scpnt->result);
 
-       zfcp_cmd_dbf_event_scsi("response", scpnt);
+       if (scpnt->result != 0)
+               zfcp_scsi_dbf_event_result("erro", 3, fsf_req->adapter, scpnt);
+       else if (scpnt->retries > 0)
+               zfcp_scsi_dbf_event_result("retr", 4, fsf_req->adapter, scpnt);
+       else
+               zfcp_scsi_dbf_event_result("norm", 6, fsf_req->adapter, scpnt);
 
        /* cleanup pointer (need this especially for abort) */
        scpnt->host_scribble = NULL;
 
-       /*
-        * NOTE:
-        * according to the outcome of a discussion on linux-scsi we
-        * don't need to grab the io_request_lock here since we use
-        * the new eh
-        */
        /* always call back */
-
        (scpnt->scsi_done) (scpnt);
 
        /*
@@ -4198,8 +4190,7 @@ zfcp_fsf_send_fcp_command_task_management_handler(struct zfcp_fsf_req *fsf_req)
        struct fcp_rsp_iu *fcp_rsp_iu = (struct fcp_rsp_iu *)
            &(fsf_req->qtcb->bottom.io.fcp_rsp);
        char *fcp_rsp_info = zfcp_get_fcp_rsp_info_ptr(fcp_rsp_iu);
-       struct zfcp_unit *unit =
-           fsf_req->data.send_fcp_command_task_management.unit;
+       struct zfcp_unit *unit = (struct zfcp_unit *) fsf_req->data;
 
        del_timer(&fsf_req->adapter->scsi_er_timer);
        if (fsf_req->status & ZFCP_STATUS_FSFREQ_ERROR) {
@@ -4276,7 +4267,7 @@ zfcp_fsf_control_file(struct zfcp_adapter *adapter,
        int direction;
        int retval = 0;
 
-       if (!(adapter->supported_features & FSF_FEATURE_CFDC)) {
+       if (!(adapter->adapter_features & FSF_FEATURE_CFDC)) {
                ZFCP_LOG_INFO("cfdc not supported (adapter %s)\n",
                              zfcp_get_busid_by_adapter(adapter));
                retval = -EOPNOTSUPP;
@@ -4549,52 +4540,6 @@ skip_fsfstatus:
        return retval;
 }
 
-
-/*
- * function:    zfcp_fsf_req_wait_and_cleanup
- *
- * purpose:
- *
- * FIXME(design): signal seems to be <0 !!!
- * returns:    0       - request completed (*status is valid), cleanup succ.
- *             <0      - request completed (*status is valid), cleanup failed
- *             >0      - signal which interrupted waiting (*status invalid),
- *                       request not completed, no cleanup
- *
- *             *status is a copy of status of completed fsf_req
- */
-int
-zfcp_fsf_req_wait_and_cleanup(struct zfcp_fsf_req *fsf_req,
-                             int interruptible, u32 * status)
-{
-       int retval = 0;
-       int signal = 0;
-
-       if (interruptible) {
-               __wait_event_interruptible(fsf_req->completion_wq,
-                                          fsf_req->status &
-                                          ZFCP_STATUS_FSFREQ_COMPLETED,
-                                          signal);
-               if (signal) {
-                       ZFCP_LOG_DEBUG("Caught signal %i while waiting for the "
-                                      "completion of the request at %p\n",
-                                      signal, fsf_req);
-                       retval = signal;
-                       goto out;
-               }
-       } else {
-               __wait_event(fsf_req->completion_wq,
-                            fsf_req->status & ZFCP_STATUS_FSFREQ_COMPLETED);
-       }
-
-       *status = fsf_req->status;
-
-       /* cleanup request */
-       zfcp_fsf_req_free(fsf_req);
- out:
-       return retval;
-}
-
 static inline int
 zfcp_fsf_req_sbal_check(unsigned long *flags,
                        struct zfcp_qdio_queue *queue, int needed)
@@ -4610,15 +4555,16 @@ zfcp_fsf_req_sbal_check(unsigned long *flags,
  * set qtcb pointer in fsf_req and initialize QTCB
  */
 static inline void
-zfcp_fsf_req_qtcb_init(struct zfcp_fsf_req *fsf_req, u32 fsf_cmd)
+zfcp_fsf_req_qtcb_init(struct zfcp_fsf_req *fsf_req)
 {
        if (likely(fsf_req->qtcb != NULL)) {
+               fsf_req->qtcb->prefix.req_seq_no = fsf_req->adapter->fsf_req_seq_no;
                fsf_req->qtcb->prefix.req_id = (unsigned long)fsf_req;
                fsf_req->qtcb->prefix.ulp_info = ZFCP_ULP_INFO_VERSION;
-               fsf_req->qtcb->prefix.qtcb_type = fsf_qtcb_type[fsf_cmd];
+               fsf_req->qtcb->prefix.qtcb_type = fsf_qtcb_type[fsf_req->fsf_command];
                fsf_req->qtcb->prefix.qtcb_version = ZFCP_QTCB_VERSION;
                fsf_req->qtcb->header.req_handle = (unsigned long)fsf_req;
-               fsf_req->qtcb->header.fsf_command = fsf_cmd;
+               fsf_req->qtcb->header.fsf_command = fsf_req->fsf_command;
        }
 }
 
@@ -4686,7 +4632,10 @@ zfcp_fsf_req_create(struct zfcp_adapter *adapter, u32 fsf_cmd, int req_flags,
                goto failed_fsf_req;
        }
 
-        zfcp_fsf_req_qtcb_init(fsf_req, fsf_cmd);
+       fsf_req->adapter = adapter;
+       fsf_req->fsf_command = fsf_cmd;
+
+        zfcp_fsf_req_qtcb_init(fsf_req);
 
        /* initialize waitqueue which may be used to wait on 
           this request completion */
@@ -4708,8 +4657,10 @@ zfcp_fsf_req_create(struct zfcp_adapter *adapter, u32 fsf_cmd, int req_flags,
                goto failed_sbals;
        }
 
-       fsf_req->adapter = adapter;     /* pointer to "parent" adapter */
-       fsf_req->fsf_command = fsf_cmd;
+       if (fsf_req->qtcb) {
+               fsf_req->seq_no = adapter->fsf_req_seq_no;
+               fsf_req->qtcb->prefix.req_seq_no = adapter->fsf_req_seq_no;
+       }
        fsf_req->sbal_number = 1;
        fsf_req->sbal_first = req_queue->free_index;
        fsf_req->sbal_curr = req_queue->free_index;
@@ -4760,9 +4711,9 @@ zfcp_fsf_req_send(struct zfcp_fsf_req *fsf_req, struct timer_list *timer)
        struct zfcp_adapter *adapter;
        struct zfcp_qdio_queue *req_queue;
        volatile struct qdio_buffer_element *sbale;
+       int inc_seq_no;
        int new_distance_from_int;
        unsigned long flags;
-       int inc_seq_no = 1;
        int retval = 0;
 
        adapter = fsf_req->adapter;
@@ -4776,23 +4727,13 @@ zfcp_fsf_req_send(struct zfcp_fsf_req *fsf_req, struct timer_list *timer)
        ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_TRACE, (char *) sbale[1].addr,
                      sbale[1].length);
 
-       /* set sequence counter in QTCB */
-       if (likely(fsf_req->qtcb)) {
-               fsf_req->qtcb->prefix.req_seq_no = adapter->fsf_req_seq_no;
-               fsf_req->seq_no = adapter->fsf_req_seq_no;
-               ZFCP_LOG_TRACE("FSF request %p of adapter %s gets "
-                              "FSF sequence counter value of %i\n",
-                              fsf_req,
-                              zfcp_get_busid_by_adapter(adapter),
-                              fsf_req->qtcb->prefix.req_seq_no);
-       } else
-               inc_seq_no = 0;
-
        /* put allocated FSF request at list tail */
        spin_lock_irqsave(&adapter->fsf_req_list_lock, flags);
        list_add_tail(&fsf_req->list, &adapter->fsf_req_list_head);
        spin_unlock_irqrestore(&adapter->fsf_req_list_lock, flags);
 
+       inc_seq_no = (fsf_req->qtcb != NULL);
+
        /* figure out expiration time of timeout and start timeout */
        if (unlikely(timer)) {
                timer->expires += jiffies;
@@ -4822,6 +4763,8 @@ zfcp_fsf_req_send(struct zfcp_fsf_req *fsf_req, struct timer_list *timer)
        req_queue->free_index %= QDIO_MAX_BUFFERS_PER_Q;  /* wrap if needed */
        new_distance_from_int = zfcp_qdio_determine_pci(req_queue, fsf_req);
 
+       fsf_req->issued = get_clock();
+
        retval = do_QDIO(adapter->ccw_device,
                         QDIO_FLAG_SYNC_OUTPUT,
                         0, fsf_req->sbal_first, fsf_req->sbal_number, NULL);
@@ -4860,15 +4803,11 @@ zfcp_fsf_req_send(struct zfcp_fsf_req *fsf_req, struct timer_list *timer)
                 * routines  resulting in missing sequence counter values
                 * otherwise,
                 */
+
                /* Don't increase for unsolicited status */
-               if (likely(inc_seq_no)) {
+               if (inc_seq_no)
                        adapter->fsf_req_seq_no++;
-                       ZFCP_LOG_TRACE
-                           ("FSF sequence counter value of adapter %s "
-                            "increased to %i\n",
-                            zfcp_get_busid_by_adapter(adapter),
-                            adapter->fsf_req_seq_no);
-               }
+
                /* count FSF requests pending */
                atomic_inc(&adapter->fsf_reqs_active);
        }
index 07140dfda2a7c3c5f6d112327f57ee423553a8bb..48719f0559527b93eef93c442087d6517bc5f9fd 100644 (file)
 #define FSF_INVALID_COMMAND_OPTION              0x000000E5
 /* #define FSF_ERROR                             0x000000FF  */
 
+#define FSF_PROT_STATUS_QUAL_SIZE              16
 #define FSF_STATUS_QUALIFIER_SIZE              16
 
 /* FSF status qualifier, recommendations */
 #define FSF_SQ_CFDC_SUBTABLE_LUN               0x0004
 
 /* FSF status qualifier (most significant 4 bytes), local link down */
-#define FSF_PSQ_LINK_NOLIGHT                   0x00000004
-#define FSF_PSQ_LINK_WRAPPLUG                  0x00000008
-#define FSF_PSQ_LINK_NOFCP                     0x00000010
+#define FSF_PSQ_LINK_NO_LIGHT                  0x00000004
+#define FSF_PSQ_LINK_WRAP_PLUG                 0x00000008
+#define FSF_PSQ_LINK_NO_FCP                    0x00000010
+#define FSF_PSQ_LINK_FIRMWARE_UPDATE           0x00000020
+#define FSF_PSQ_LINK_INVALID_WWPN              0x00000100
+#define FSF_PSQ_LINK_NO_NPIV_SUPPORT           0x00000200
+#define FSF_PSQ_LINK_NO_FCP_RESOURCES          0x00000400
+#define FSF_PSQ_LINK_NO_FABRIC_RESOURCES       0x00000800
+#define FSF_PSQ_LINK_FABRIC_LOGIN_UNABLE       0x00001000
+#define FSF_PSQ_LINK_WWPN_ASSIGNMENT_CORRUPTED 0x00002000
+#define FSF_PSQ_LINK_MODE_TABLE_CURRUPTED      0x00004000
+#define FSF_PSQ_LINK_NO_WWPN_ASSIGNMENT                0x00008000
 
 /* payload size in status read buffer */
 #define FSF_STATUS_READ_PAYLOAD_SIZE           4032
 #define FSF_STATUS_READ_INCOMING_ELS           0x00000002
 #define FSF_STATUS_READ_SENSE_DATA_AVAIL        0x00000003
 #define FSF_STATUS_READ_BIT_ERROR_THRESHOLD    0x00000004
-#define FSF_STATUS_READ_LINK_DOWN              0x00000005 /* FIXME: really? */
+#define FSF_STATUS_READ_LINK_DOWN              0x00000005
 #define FSF_STATUS_READ_LINK_UP                0x00000006
 #define FSF_STATUS_READ_CFDC_UPDATED           0x0000000A
 #define FSF_STATUS_READ_CFDC_HARDENED          0x0000000B
+#define FSF_STATUS_READ_FEATURE_UPDATE_ALERT   0x0000000C
 
 /* status subtypes in status read buffer */
 #define FSF_STATUS_READ_SUB_CLOSE_PHYS_PORT    0x00000001
 #define FSF_STATUS_READ_SUB_ERROR_PORT         0x00000002
 
+/* status subtypes for link down */
+#define FSF_STATUS_READ_SUB_NO_PHYSICAL_LINK   0x00000000
+#define FSF_STATUS_READ_SUB_FDISC_FAILED       0x00000001
+#define FSF_STATUS_READ_SUB_FIRMWARE_UPDATE    0x00000002
+
 /* status subtypes for CFDC */
 #define FSF_STATUS_READ_SUB_CFDC_HARDENED_ON_SE        0x00000002
 #define FSF_STATUS_READ_SUB_CFDC_HARDENED_ON_SE2 0x0000000F
 #define FSF_QTCB_LOG_SIZE                      1024
 
 /* channel features */
-#define FSF_FEATURE_QTCB_SUPPRESSION            0x00000001
 #define FSF_FEATURE_CFDC                       0x00000002
 #define FSF_FEATURE_LUN_SHARING                        0x00000004
 #define FSF_FEATURE_HBAAPI_MANAGEMENT           0x00000010
 #define FSF_FEATURE_ELS_CT_CHAINED_SBALS        0x00000020
+#define FSF_FEATURE_UPDATE_ALERT               0x00000100
+
+/* host connection features */
+#define FSF_FEATURE_NPIV_MODE                  0x00000001
+#define FSF_FEATURE_VM_ASSIGNED_WWPN           0x00000002
 
 /* option */
 #define FSF_OPEN_LUN_SUPPRESS_BOXING           0x00000001
@@ -305,15 +325,23 @@ struct fsf_qual_sequence_error {
        u32 res1[3];
 } __attribute__ ((packed));
 
-struct fsf_qual_locallink_error {
-       u32 code;
-       u32 res1[3];
+struct fsf_link_down_info {
+       u32 error_code;
+       u32 res1;
+       u8 res2[2];
+       u8 primary_status;
+       u8 ioerr_code;
+       u8 action_code;
+       u8 reason_code;
+       u8 explanation_code;
+       u8 vendor_specific_code;
 } __attribute__ ((packed));
 
 union fsf_prot_status_qual {
+       u64 doubleword[FSF_PROT_STATUS_QUAL_SIZE / sizeof(u64)];
        struct fsf_qual_version_error   version_error;
        struct fsf_qual_sequence_error  sequence_error;
-       struct fsf_qual_locallink_error locallink_error;
+       struct fsf_link_down_info link_down_info;
 } __attribute__ ((packed));
 
 struct fsf_qtcb_prefix {
@@ -331,7 +359,9 @@ union fsf_status_qual {
        u8  byte[FSF_STATUS_QUALIFIER_SIZE];
        u16 halfword[FSF_STATUS_QUALIFIER_SIZE / sizeof (u16)];
        u32 word[FSF_STATUS_QUALIFIER_SIZE / sizeof (u32)];
+       u64 doubleword[FSF_STATUS_QUALIFIER_SIZE / sizeof(u64)];
        struct fsf_queue_designator fsf_queue_designator;
+       struct fsf_link_down_info link_down_info;
 } __attribute__ ((packed));
 
 struct fsf_qtcb_header {
@@ -406,8 +436,8 @@ struct fsf_qtcb_bottom_config {
        u32 low_qtcb_version;
        u32 max_qtcb_size;
        u32 max_data_transfer_size;
-       u32 supported_features;
-       u8  res1[4];
+       u32 adapter_features;
+       u32 connection_features;
        u32 fc_topology;
        u32 fc_link_speed;
        u32 adapter_type;
@@ -425,7 +455,7 @@ struct fsf_qtcb_bottom_config {
 } __attribute__ ((packed));
 
 struct fsf_qtcb_bottom_port {
-       u8 res1[8];
+       u64 wwpn;
        u32 fc_port_id;
        u32 port_type;
        u32 port_state;
index 24e16ec331d9e5760a00b59972e6fa5ab3009175..d719f66a29a4f9d7ebde41e3b7060d81f9070e78 100644 (file)
@@ -54,8 +54,7 @@ static inline int zfcp_qdio_sbals_from_buffer
 static qdio_handler_t zfcp_qdio_request_handler;
 static qdio_handler_t zfcp_qdio_response_handler;
 static int zfcp_qdio_handler_error_check(struct zfcp_adapter *,
-                                        unsigned int,
-                                        unsigned int, unsigned int);
+       unsigned int, unsigned int, unsigned int, int, int);
 
 #define ZFCP_LOG_AREA                   ZFCP_LOG_AREA_QDIO
 
@@ -214,22 +213,12 @@ zfcp_qdio_allocate(struct zfcp_adapter *adapter)
  *
  */
 static inline int
-zfcp_qdio_handler_error_check(struct zfcp_adapter *adapter,
-                             unsigned int status,
-                             unsigned int qdio_error, unsigned int siga_error)
+zfcp_qdio_handler_error_check(struct zfcp_adapter *adapter, unsigned int status,
+                             unsigned int qdio_error, unsigned int siga_error,
+                             int first_element, int elements_processed)
 {
        int retval = 0;
 
-       if (ZFCP_LOG_CHECK(ZFCP_LOG_LEVEL_TRACE)) {
-               if (status & QDIO_STATUS_INBOUND_INT) {
-                       ZFCP_LOG_TRACE("status is"
-                                      " QDIO_STATUS_INBOUND_INT \n");
-               }
-               if (status & QDIO_STATUS_OUTBOUND_INT) {
-                       ZFCP_LOG_TRACE("status is"
-                                      " QDIO_STATUS_OUTBOUND_INT \n");
-               }
-       }
        if (unlikely(status & QDIO_STATUS_LOOK_FOR_ERROR)) {
                retval = -EIO;
 
@@ -237,9 +226,10 @@ zfcp_qdio_handler_error_check(struct zfcp_adapter *adapter,
                              "qdio_error=0x%x, siga_error=0x%x)\n",
                              status, qdio_error, siga_error);
 
-               /* Restarting IO on the failed adapter from scratch */
-               debug_text_event(adapter->erp_dbf, 1, "qdio_err");
+               zfcp_hba_dbf_event_qdio(adapter, status, qdio_error, siga_error,
+                               first_element, elements_processed);
                /*
+                       * Restarting IO on the failed adapter from scratch.
                 * Since we have been using this adapter, it is save to assume
                 * that it is not failed but recoverable. The card seems to
                 * report link-up events by self-initiated queue shutdown.
@@ -282,7 +272,8 @@ zfcp_qdio_request_handler(struct ccw_device *ccw_device,
                       first_element, elements_processed);
 
        if (unlikely(zfcp_qdio_handler_error_check(adapter, status, qdio_error,
-                                                  siga_error)))
+                                                  siga_error, first_element,
+                                                  elements_processed)))
                goto out;
        /*
         * we stored address of struct zfcp_adapter  data structure
@@ -334,7 +325,8 @@ zfcp_qdio_response_handler(struct ccw_device *ccw_device,
        queue = &adapter->response_queue;
 
        if (unlikely(zfcp_qdio_handler_error_check(adapter, status, qdio_error,
-                                                  siga_error)))
+                                                  siga_error, first_element,
+                                                  elements_processed)))
                goto out;
 
        /*
index 31a76065cf2838104e1ace600eea2b39775e337f..3dcd1bfba3b4862835bb1eab8d4542dec8a9409a 100644 (file)
@@ -44,7 +44,8 @@ static int zfcp_scsi_eh_abort_handler(struct scsi_cmnd *);
 static int zfcp_scsi_eh_device_reset_handler(struct scsi_cmnd *);
 static int zfcp_scsi_eh_bus_reset_handler(struct scsi_cmnd *);
 static int zfcp_scsi_eh_host_reset_handler(struct scsi_cmnd *);
-static int zfcp_task_management_function(struct zfcp_unit *, u8);
+static int zfcp_task_management_function(struct zfcp_unit *, u8,
+                                        struct scsi_cmnd *);
 
 static struct zfcp_unit *zfcp_unit_lookup(struct zfcp_adapter *, int, scsi_id_t,
                                          scsi_lun_t);
@@ -242,7 +243,10 @@ static void
 zfcp_scsi_command_fail(struct scsi_cmnd *scpnt, int result)
 {
        set_host_byte(&scpnt->result, result);
-       zfcp_cmd_dbf_event_scsi("failing", scpnt);
+       if ((scpnt->device != NULL) && (scpnt->device->host != NULL))
+               zfcp_scsi_dbf_event_result("fail", 4,
+                       (struct zfcp_adapter*) scpnt->device->host->hostdata[0],
+                       scpnt);
        /* return directly */
        scpnt->scsi_done(scpnt);
 }
@@ -414,67 +418,38 @@ zfcp_port_lookup(struct zfcp_adapter *adapter, int channel, scsi_id_t id)
        return (struct zfcp_port *) NULL;
 }
 
-/*
- * function:   zfcp_scsi_eh_abort_handler
- *
- * purpose:    tries to abort the specified (timed out) SCSI command
- *
- * note:       We do not need to care for a SCSI command which completes
- *             normally but late during this abort routine runs.
- *             We are allowed to return late commands to the SCSI stack.
- *             It tracks the state of commands and will handle late commands.
- *             (Usually, the normal completion of late commands is ignored with
- *             respect to the running abort operation. Grep for 'done_late'
- *             in the SCSI stacks sources.)
+/**
+ * zfcp_scsi_eh_abort_handler - abort the specified SCSI command
+ * @scpnt: pointer to scsi_cmnd to be aborted 
+ * Return: SUCCESS - command has been aborted and cleaned up in internal
+ *          bookkeeping, SCSI stack won't be called for aborted command
+ *         FAILED - otherwise
  *
- * returns:    SUCCESS - command has been aborted and cleaned up in internal
- *                       bookkeeping,
- *                       SCSI stack won't be called for aborted command
- *             FAILED  - otherwise
+ * We do not need to care for a SCSI command which completes normally
+ * but late during this abort routine runs.  We are allowed to return
+ * late commands to the SCSI stack.  It tracks the state of commands and
+ * will handle late commands.  (Usually, the normal completion of late
+ * commands is ignored with respect to the running abort operation.)
  */
 int
-__zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt)
+zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt)
 {
+       struct Scsi_Host *scsi_host;
+       struct zfcp_adapter *adapter;
+       struct zfcp_unit *unit;
        int retval = SUCCESS;
-       struct zfcp_fsf_req *new_fsf_req, *old_fsf_req;
-       struct zfcp_adapter *adapter = (struct zfcp_adapter *) scpnt->device->host->hostdata[0];
-       struct zfcp_unit *unit = (struct zfcp_unit *) scpnt->device->hostdata;
-       struct zfcp_port *port = unit->port;
-       struct Scsi_Host *scsi_host = scpnt->device->host;
-       union zfcp_req_data *req_data = NULL;
+       struct zfcp_fsf_req *new_fsf_req = NULL;
+       struct zfcp_fsf_req *old_fsf_req;
        unsigned long flags;
-       u32 status = 0;
-
-       /* the components of a abort_dbf record (fixed size record) */
-       u64 dbf_scsi_cmnd = (unsigned long) scpnt;
-       char dbf_opcode[ZFCP_ABORT_DBF_LENGTH];
-       wwn_t dbf_wwn = port->wwpn;
-       fcp_lun_t dbf_fcp_lun = unit->fcp_lun;
-       u64 dbf_retries = scpnt->retries;
-       u64 dbf_allowed = scpnt->allowed;
-       u64 dbf_timeout = 0;
-       u64 dbf_fsf_req = 0;
-       u64 dbf_fsf_status = 0;
-       u64 dbf_fsf_qual[2] = { 0, 0 };
-       char dbf_result[ZFCP_ABORT_DBF_LENGTH] = "##undef";
-
-       memset(dbf_opcode, 0, ZFCP_ABORT_DBF_LENGTH);
-       memcpy(dbf_opcode,
-              scpnt->cmnd,
-              min(scpnt->cmd_len, (unsigned char) ZFCP_ABORT_DBF_LENGTH));
+
+       scsi_host = scpnt->device->host;
+       adapter = (struct zfcp_adapter *) scsi_host->hostdata[0];
+       unit = (struct zfcp_unit *) scpnt->device->hostdata;
 
        ZFCP_LOG_INFO("aborting scsi_cmnd=%p on adapter %s\n",
                      scpnt, zfcp_get_busid_by_adapter(adapter));
 
-       spin_unlock_irq(scsi_host->host_lock);
-
-       /*
-        * Race condition between normal (late) completion and abort has
-        * to be avoided.
-        * The entirity of all accesses to scsi_req have to be atomic.
-        * scsi_req is usually part of the fsf_req and thus we block the
-        * release of fsf_req as long as we need to access scsi_req.
-        */
+       /* avoid race condition between late normal completion and abort */
        write_lock_irqsave(&adapter->abort_lock, flags);
 
        /*
@@ -484,144 +459,47 @@ __zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt)
         * this routine returns. (scpnt is parameter passed to this routine
         * and must not disappear during abort even on late completion.)
         */
-       req_data = (union zfcp_req_data *) scpnt->host_scribble;
-       /* DEBUG */
-       ZFCP_LOG_DEBUG("req_data=%p\n", req_data);
-       if (!req_data) {
-               ZFCP_LOG_DEBUG("late command completion overtook abort\n");
-               /*
-                * That's it.
-                * Do not initiate abort but return SUCCESS.
-                */
-               write_unlock_irqrestore(&adapter->abort_lock, flags);
-               retval = SUCCESS;
-               strncpy(dbf_result, "##late1", ZFCP_ABORT_DBF_LENGTH);
-               goto out;
-       }
-
-       /* Figure out which fsf_req needs to be aborted. */
-       old_fsf_req = req_data->send_fcp_command_task.fsf_req;
-
-       dbf_fsf_req = (unsigned long) old_fsf_req;
-       dbf_timeout =
-           (jiffies - req_data->send_fcp_command_task.start_jiffies) / HZ;
-
-       ZFCP_LOG_DEBUG("old_fsf_req=%p\n", old_fsf_req);
+       old_fsf_req = (struct zfcp_fsf_req *) scpnt->host_scribble;
        if (!old_fsf_req) {
                write_unlock_irqrestore(&adapter->abort_lock, flags);
-               ZFCP_LOG_NORMAL("bug: no old fsf request found\n");
-               ZFCP_LOG_NORMAL("req_data:\n");
-               ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_NORMAL,
-                             (char *) req_data, sizeof (union zfcp_req_data));
-               ZFCP_LOG_NORMAL("scsi_cmnd:\n");
-               ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_NORMAL,
-                             (char *) scpnt, sizeof (struct scsi_cmnd));
-               retval = FAILED;
-               strncpy(dbf_result, "##bug:r", ZFCP_ABORT_DBF_LENGTH);
+               zfcp_scsi_dbf_event_abort("lte1", adapter, scpnt, new_fsf_req);
+               retval = SUCCESS;
                goto out;
        }
-       old_fsf_req->data.send_fcp_command_task.scsi_cmnd = NULL;
-       /* mark old request as being aborted */
+       old_fsf_req->data = 0;
        old_fsf_req->status |= ZFCP_STATUS_FSFREQ_ABORTING;
-       /*
-        * We have to collect all information (e.g. unit) needed by 
-        * zfcp_fsf_abort_fcp_command before calling that routine
-        * since that routine is not allowed to access
-        * fsf_req which it is going to abort.
-        * This is because of we need to release fsf_req_list_lock
-        * before calling zfcp_fsf_abort_fcp_command.
-        * Since this lock will not be held, fsf_req may complete
-        * late and may be released meanwhile.
-        */
-       ZFCP_LOG_DEBUG("unit 0x%016Lx (%p)\n", unit->fcp_lun, unit);
 
-       /*
-        * We block (call schedule)
-        * That's why we must release the lock and enable the
-        * interrupts before.
-        * On the other hand we do not need the lock anymore since
-        * all critical accesses to scsi_req are done.
-        */
+       /* don't access old_fsf_req after releasing the abort_lock */
        write_unlock_irqrestore(&adapter->abort_lock, flags);
        /* call FSF routine which does the abort */
        new_fsf_req = zfcp_fsf_abort_fcp_command((unsigned long) old_fsf_req,
                                                 adapter, unit, 0);
-       ZFCP_LOG_DEBUG("new_fsf_req=%p\n", new_fsf_req);
        if (!new_fsf_req) {
+               ZFCP_LOG_INFO("error: initiation of Abort FCP Cmnd failed\n");
                retval = FAILED;
-               ZFCP_LOG_NORMAL("error: initiation of Abort FCP Cmnd "
-                               "failed\n");
-               strncpy(dbf_result, "##nores", ZFCP_ABORT_DBF_LENGTH);
                goto out;
        }
 
        /* wait for completion of abort */
-       ZFCP_LOG_DEBUG("waiting for cleanup...\n");
-#if 1
-       /*
-        * FIXME:
-        * copying zfcp_fsf_req_wait_and_cleanup code is not really nice
-        */
        __wait_event(new_fsf_req->completion_wq,
                     new_fsf_req->status & ZFCP_STATUS_FSFREQ_COMPLETED);
-       status = new_fsf_req->status;
-       dbf_fsf_status = new_fsf_req->qtcb->header.fsf_status;
-       /*
-        * Ralphs special debug load provides timestamps in the FSF
-        * status qualifier. This might be specified later if being
-        * useful for debugging aborts.
-        */
-       dbf_fsf_qual[0] =
-           *(u64 *) & new_fsf_req->qtcb->header.fsf_status_qual.word[0];
-       dbf_fsf_qual[1] =
-           *(u64 *) & new_fsf_req->qtcb->header.fsf_status_qual.word[2];
-       zfcp_fsf_req_free(new_fsf_req);
-#else
-       retval = zfcp_fsf_req_wait_and_cleanup(new_fsf_req,
-                                              ZFCP_UNINTERRUPTIBLE, &status);
-#endif
-       ZFCP_LOG_DEBUG("Waiting for cleanup complete, status=0x%x\n", status);
+
        /* status should be valid since signals were not permitted */
-       if (status & ZFCP_STATUS_FSFREQ_ABORTSUCCEEDED) {
+       if (new_fsf_req->status & ZFCP_STATUS_FSFREQ_ABORTSUCCEEDED) {
+               zfcp_scsi_dbf_event_abort("okay", adapter, scpnt, new_fsf_req);
                retval = SUCCESS;
-               strncpy(dbf_result, "##succ", ZFCP_ABORT_DBF_LENGTH);
-       } else if (status & ZFCP_STATUS_FSFREQ_ABORTNOTNEEDED) {
+       } else if (new_fsf_req->status & ZFCP_STATUS_FSFREQ_ABORTNOTNEEDED) {
+               zfcp_scsi_dbf_event_abort("lte2", adapter, scpnt, new_fsf_req);
                retval = SUCCESS;
-               strncpy(dbf_result, "##late2", ZFCP_ABORT_DBF_LENGTH);
        } else {
+               zfcp_scsi_dbf_event_abort("fail", adapter, scpnt, new_fsf_req);
                retval = FAILED;
-               strncpy(dbf_result, "##fail", ZFCP_ABORT_DBF_LENGTH);
        }
-
+       zfcp_fsf_req_free(new_fsf_req);
  out:
-       debug_event(adapter->abort_dbf, 1, &dbf_scsi_cmnd, sizeof (u64));
-       debug_event(adapter->abort_dbf, 1, &dbf_opcode, ZFCP_ABORT_DBF_LENGTH);
-       debug_event(adapter->abort_dbf, 1, &dbf_wwn, sizeof (wwn_t));
-       debug_event(adapter->abort_dbf, 1, &dbf_fcp_lun, sizeof (fcp_lun_t));
-       debug_event(adapter->abort_dbf, 1, &dbf_retries, sizeof (u64));
-       debug_event(adapter->abort_dbf, 1, &dbf_allowed, sizeof (u64));
-       debug_event(adapter->abort_dbf, 1, &dbf_timeout, sizeof (u64));
-       debug_event(adapter->abort_dbf, 1, &dbf_fsf_req, sizeof (u64));
-       debug_event(adapter->abort_dbf, 1, &dbf_fsf_status, sizeof (u64));
-       debug_event(adapter->abort_dbf, 1, &dbf_fsf_qual[0], sizeof (u64));
-       debug_event(adapter->abort_dbf, 1, &dbf_fsf_qual[1], sizeof (u64));
-       debug_text_event(adapter->abort_dbf, 1, dbf_result);
-
-       spin_lock_irq(scsi_host->host_lock);
        return retval;
 }
 
-int
-zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt)
-{
-       int rc;
-       struct Scsi_Host *scsi_host = scpnt->device->host;
-       spin_lock_irq(scsi_host->host_lock);
-       rc = __zfcp_scsi_eh_abort_handler(scpnt);
-       spin_unlock_irq(scsi_host->host_lock);
-       return rc;
-}
-
 /*
  * function:   zfcp_scsi_eh_device_reset_handler
  *
@@ -651,8 +529,9 @@ zfcp_scsi_eh_device_reset_handler(struct scsi_cmnd *scpnt)
         */
        if (!atomic_test_mask(ZFCP_STATUS_UNIT_NOTSUPPUNITRESET,
                              &unit->status)) {
-               retval =
-                   zfcp_task_management_function(unit, FCP_LOGICAL_UNIT_RESET);
+               retval = zfcp_task_management_function(unit,
+                                                      FCP_LOGICAL_UNIT_RESET,
+                                                      scpnt);
                if (retval) {
                        ZFCP_LOG_DEBUG("unit reset failed (unit=%p)\n", unit);
                        if (retval == -ENOTSUPP)
@@ -668,7 +547,7 @@ zfcp_scsi_eh_device_reset_handler(struct scsi_cmnd *scpnt)
                        goto out;
                }
        }
-       retval = zfcp_task_management_function(unit, FCP_TARGET_RESET);
+       retval = zfcp_task_management_function(unit, FCP_TARGET_RESET, scpnt);
        if (retval) {
                ZFCP_LOG_DEBUG("target reset failed (unit=%p)\n", unit);
                retval = FAILED;
@@ -681,12 +560,12 @@ zfcp_scsi_eh_device_reset_handler(struct scsi_cmnd *scpnt)
 }
 
 static int
-zfcp_task_management_function(struct zfcp_unit *unit, u8 tm_flags)
+zfcp_task_management_function(struct zfcp_unit *unit, u8 tm_flags,
+                             struct scsi_cmnd *scpnt)
 {
        struct zfcp_adapter *adapter = unit->port->adapter;
-       int retval;
-       int status;
        struct zfcp_fsf_req *fsf_req;
+       int retval = 0;
 
        /* issue task management function */
        fsf_req = zfcp_fsf_send_fcp_command_task_management
@@ -696,70 +575,63 @@ zfcp_task_management_function(struct zfcp_unit *unit, u8 tm_flags)
                              "failed for unit 0x%016Lx on port 0x%016Lx on  "
                              "adapter %s\n", unit->fcp_lun, unit->port->wwpn,
                              zfcp_get_busid_by_adapter(adapter));
+               zfcp_scsi_dbf_event_devreset("nres", tm_flags, unit, scpnt);
                retval = -ENOMEM;
                goto out;
        }
 
-       retval = zfcp_fsf_req_wait_and_cleanup(fsf_req,
-                                              ZFCP_UNINTERRUPTIBLE, &status);
+       __wait_event(fsf_req->completion_wq,
+                    fsf_req->status & ZFCP_STATUS_FSFREQ_COMPLETED);
+
        /*
         * check completion status of task management function
-        * (status should always be valid since no signals permitted)
         */
-       if (status & ZFCP_STATUS_FSFREQ_TMFUNCFAILED)
+       if (fsf_req->status & ZFCP_STATUS_FSFREQ_TMFUNCFAILED) {
+               zfcp_scsi_dbf_event_devreset("fail", tm_flags, unit, scpnt);
                retval = -EIO;
-       else if (status & ZFCP_STATUS_FSFREQ_TMFUNCNOTSUPP)
+       } else if (fsf_req->status & ZFCP_STATUS_FSFREQ_TMFUNCNOTSUPP) {
+               zfcp_scsi_dbf_event_devreset("nsup", tm_flags, unit, scpnt);
                retval = -ENOTSUPP;
-       else
-               retval = 0;
+       } else
+               zfcp_scsi_dbf_event_devreset("okay", tm_flags, unit, scpnt);
+
+       zfcp_fsf_req_free(fsf_req);
  out:
        return retval;
 }
 
-/*
- * function:   zfcp_scsi_eh_bus_reset_handler
- *
- * purpose:
- *
- * returns:
+/**
+ * zfcp_scsi_eh_bus_reset_handler - reset bus (reopen adapter)
  */
 int
 zfcp_scsi_eh_bus_reset_handler(struct scsi_cmnd *scpnt)
 {
-       int retval = 0;
-       struct zfcp_unit *unit;
+       struct zfcp_unit *unit = (struct zfcp_unit*) scpnt->device->hostdata;
+       struct zfcp_adapter *adapter = unit->port->adapter;
 
-       unit = (struct zfcp_unit *) scpnt->device->hostdata;
        ZFCP_LOG_NORMAL("bus reset because of problems with "
                        "unit 0x%016Lx\n", unit->fcp_lun);
-       zfcp_erp_adapter_reopen(unit->port->adapter, 0);
-       zfcp_erp_wait(unit->port->adapter);
-       retval = SUCCESS;
+       zfcp_erp_adapter_reopen(adapter, 0);
+       zfcp_erp_wait(adapter);
 
-       return retval;
+       return SUCCESS;
 }
 
-/*
- * function:   zfcp_scsi_eh_host_reset_handler
- *
- * purpose:
- *
- * returns:
+/**
+ * zfcp_scsi_eh_host_reset_handler - reset host (reopen adapter)
  */
 int
 zfcp_scsi_eh_host_reset_handler(struct scsi_cmnd *scpnt)
 {
-       int retval = 0;
-       struct zfcp_unit *unit;
+       struct zfcp_unit *unit = (struct zfcp_unit*) scpnt->device->hostdata;
+       struct zfcp_adapter *adapter = unit->port->adapter;
 
-       unit = (struct zfcp_unit *) scpnt->device->hostdata;
        ZFCP_LOG_NORMAL("host reset because of problems with "
                        "unit 0x%016Lx\n", unit->fcp_lun);
-       zfcp_erp_adapter_reopen(unit->port->adapter, 0);
-       zfcp_erp_wait(unit->port->adapter);
-       retval = SUCCESS;
+       zfcp_erp_adapter_reopen(adapter, 0);
+       zfcp_erp_wait(adapter);
 
-       return retval;
+       return SUCCESS;
 }
 
 /*
@@ -826,10 +698,16 @@ void
 zfcp_adapter_scsi_unregister(struct zfcp_adapter *adapter)
 {
        struct Scsi_Host *shost;
+       struct zfcp_port *port;
 
        shost = adapter->scsi_host;
        if (!shost)
                return;
+       read_lock_irq(&zfcp_data.config_lock);
+       list_for_each_entry(port, &adapter->port_list_head, list)
+               if (port->rport)
+                       port->rport = NULL;
+       read_unlock_irq(&zfcp_data.config_lock);
        fc_remove_host(shost);
        scsi_remove_host(shost);
        scsi_host_put(shost);
@@ -904,18 +782,6 @@ zfcp_get_node_name(struct scsi_target *starget)
        read_unlock_irqrestore(&zfcp_data.config_lock, flags);
 }
 
-void
-zfcp_set_fc_host_attrs(struct zfcp_adapter *adapter)
-{
-       struct Scsi_Host *shost = adapter->scsi_host;
-
-       fc_host_node_name(shost) = adapter->wwnn;
-       fc_host_port_name(shost) = adapter->wwpn;
-       strncpy(fc_host_serial_number(shost), adapter->serial_number,
-                min(FC_SERIAL_NUMBER_SIZE, 32));
-       fc_host_supported_classes(shost) = FC_COS_CLASS2 | FC_COS_CLASS3;
-}
-
 struct fc_function_template zfcp_transport_functions = {
        .get_starget_port_id = zfcp_get_port_id,
        .get_starget_port_name = zfcp_get_port_name,
@@ -927,7 +793,10 @@ struct fc_function_template zfcp_transport_functions = {
        .show_host_node_name = 1,
        .show_host_port_name = 1,
        .show_host_supported_classes = 1,
+       .show_host_maxframe_size = 1,
        .show_host_serial_number = 1,
+       .show_host_speed = 1,
+       .show_host_port_id = 1,
 };
 
 /**
index e7345a74800a950bb03d6ed762e0198d0c0e8733..0cd435280e7db00947a8d02d21a536fef5ee9762 100644 (file)
@@ -62,21 +62,18 @@ static ssize_t zfcp_sysfs_adapter_##_name##_show(struct device *dev, struct devi
 static DEVICE_ATTR(_name, S_IRUGO, zfcp_sysfs_adapter_##_name##_show, NULL);
 
 ZFCP_DEFINE_ADAPTER_ATTR(status, "0x%08x\n", atomic_read(&adapter->status));
-ZFCP_DEFINE_ADAPTER_ATTR(wwnn, "0x%016llx\n", adapter->wwnn);
-ZFCP_DEFINE_ADAPTER_ATTR(wwpn, "0x%016llx\n", adapter->wwpn);
-ZFCP_DEFINE_ADAPTER_ATTR(s_id, "0x%06x\n", adapter->s_id);
 ZFCP_DEFINE_ADAPTER_ATTR(peer_wwnn, "0x%016llx\n", adapter->peer_wwnn);
 ZFCP_DEFINE_ADAPTER_ATTR(peer_wwpn, "0x%016llx\n", adapter->peer_wwpn);
 ZFCP_DEFINE_ADAPTER_ATTR(peer_d_id, "0x%06x\n", adapter->peer_d_id);
+ZFCP_DEFINE_ADAPTER_ATTR(physical_wwpn, "0x%016llx\n", adapter->physical_wwpn);
+ZFCP_DEFINE_ADAPTER_ATTR(physical_s_id, "0x%06x\n", adapter->physical_s_id);
 ZFCP_DEFINE_ADAPTER_ATTR(card_version, "0x%04x\n", adapter->hydra_version);
 ZFCP_DEFINE_ADAPTER_ATTR(lic_version, "0x%08x\n", adapter->fsf_lic_version);
-ZFCP_DEFINE_ADAPTER_ATTR(fc_link_speed, "%d Gb/s\n", adapter->fc_link_speed);
 ZFCP_DEFINE_ADAPTER_ATTR(fc_service_class, "%d\n", adapter->fc_service_class);
 ZFCP_DEFINE_ADAPTER_ATTR(fc_topology, "%s\n",
                         fc_topologies[adapter->fc_topology]);
 ZFCP_DEFINE_ADAPTER_ATTR(hardware_version, "0x%08x\n",
                         adapter->hardware_version);
-ZFCP_DEFINE_ADAPTER_ATTR(serial_number, "%17s\n", adapter->serial_number);
 ZFCP_DEFINE_ADAPTER_ATTR(scsi_host_no, "0x%x\n", adapter->scsi_host_no);
 ZFCP_DEFINE_ADAPTER_ATTR(in_recovery, "%d\n", atomic_test_mask
                         (ZFCP_STATUS_COMMON_ERP_INUSE, &adapter->status));
@@ -255,21 +252,18 @@ static struct attribute *zfcp_adapter_attrs[] = {
        &dev_attr_in_recovery.attr,
        &dev_attr_port_remove.attr,
        &dev_attr_port_add.attr,
-       &dev_attr_wwnn.attr,
-       &dev_attr_wwpn.attr,
-       &dev_attr_s_id.attr,
        &dev_attr_peer_wwnn.attr,
        &dev_attr_peer_wwpn.attr,
        &dev_attr_peer_d_id.attr,
+       &dev_attr_physical_wwpn.attr,
+       &dev_attr_physical_s_id.attr,
        &dev_attr_card_version.attr,
        &dev_attr_lic_version.attr,
-       &dev_attr_fc_link_speed.attr,
        &dev_attr_fc_service_class.attr,
        &dev_attr_fc_topology.attr,
        &dev_attr_scsi_host_no.attr,
        &dev_attr_status.attr,
        &dev_attr_hardware_version.attr,
-       &dev_attr_serial_number.attr,
        NULL
 };
 
index dbad7f35eb0a2f7deb6ea878e64e64b518c390ae..24ed5893b4f047f3ca3f74c565afa59fa145555d 100644 (file)
@@ -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                     */
index c932b3b94490833a1f306a4c418985aa5749431a..876d1de8480d1388f0b740e40271ca9d21c2e2e2 100644 (file)
@@ -1109,15 +1109,6 @@ ahc_linux_register_host(struct ahc_softc *ahc, struct scsi_host_template *templa
        return (0);
 }
 
-uint64_t
-ahc_linux_get_memsize(void)
-{
-       struct sysinfo si;
-
-       si_meminfo(&si);
-       return ((uint64_t)si.totalram << PAGE_SHIFT);
-}
-
 /*
  * Place the SCSI bus into a known state by either resetting it,
  * or forcing transfer negotiations on the next command to any
index c5299626924024a6852dd713990546829bf74ce2..be9edbe26dbe0c128e486379ab48ab8f48ca3c9c 100644 (file)
@@ -494,8 +494,6 @@ ahc_insb(struct ahc_softc * ahc, long port, uint8_t *array, int count)
 int            ahc_linux_register_host(struct ahc_softc *,
                                        struct scsi_host_template *);
 
-uint64_t       ahc_linux_get_memsize(void);
-
 /*************************** Pretty Printing **********************************/
 struct info_str {
        char *buffer;
index 0d44a6907dd25546ac17a1f12d911da5e79952f0..3ce77ddc889e8a6a2cefe4f54092bbaf218b65d5 100644 (file)
@@ -180,6 +180,7 @@ ahc_linux_pci_dev_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        struct           ahc_pci_identity *entry;
        char            *name;
        int              error;
+       struct device   *dev = &pdev->dev;
 
        pci = pdev;
        entry = ahc_find_pci_device(pci);
@@ -209,11 +210,12 @@ ahc_linux_pci_dev_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        pci_set_master(pdev);
 
        if (sizeof(dma_addr_t) > 4
-        && ahc_linux_get_memsize() > 0x80000000
-        && pci_set_dma_mask(pdev, mask_39bit) == 0) {
+           && ahc->features & AHC_LARGE_SCBS
+           && dma_set_mask(dev, mask_39bit) == 0
+           && dma_get_required_mask(dev) > DMA_32BIT_MASK) {
                ahc->flags |= AHC_39BIT_ADDRESSING;
        } else {
-               if (pci_set_dma_mask(pdev, DMA_32BIT_MASK)) {
+               if (dma_set_mask(dev, DMA_32BIT_MASK)) {
                        printk(KERN_WARNING "aic7xxx: No suitable DMA available.\n");
                        return (-ENODEV);
                }
index 87e0c36f1554a8b69597361a4a61dfd214db449f..d71cef767cec7849c09a6217234872f370a8926a 100644 (file)
@@ -442,7 +442,6 @@ static void piix_sata_phy_reset(struct ata_port *ap)
  *     piix_set_piomode - Initialize host controller PATA PIO timings
  *     @ap: Port whose timings we are configuring
  *     @adev: um
- *     @pio: PIO mode, 0 - 4
  *
  *     Set PIO mode for device, in host controller PCI config space.
  *
index e6153fe5842a204f65f4453b0924654c1b25b207..a8cfbef304b5f64461deabc86ba2fef963c314e6 100644 (file)
@@ -996,6 +996,7 @@ oktosend:
 #ifdef ED_DBGP         
        printk("send_s870: prdaddr_2 0x%8x tmpcip %x target_id %d\n", dev->id[c][target_id].prdaddr,tmpcip,target_id);
 #endif 
+       dev->id[c][target_id].prdaddr = dev->id[c][target_id].prd_bus;
        outl(dev->id[c][target_id].prdaddr, tmpcip);
        tmpcip = tmpcip - 2;
        outb(0x06, tmpcip);
@@ -2572,7 +2573,7 @@ static void atp870u_free_tables(struct Scsi_Host *host)
                for (k = 0; k < 16; k++) {
                        if (!atp_dev->id[j][k].prd_table)
                                continue;
-                       pci_free_consistent(atp_dev->pdev, 1024, atp_dev->id[j][k].prd_table, atp_dev->id[j][k].prdaddr);
+                       pci_free_consistent(atp_dev->pdev, 1024, atp_dev->id[j][k].prd_table, atp_dev->id[j][k].prd_bus);
                        atp_dev->id[j][k].prd_table = NULL;
                }
        }
@@ -2584,12 +2585,13 @@ static int atp870u_init_tables(struct Scsi_Host *host)
        int c,k;
        for(c=0;c < 2;c++) {
                for(k=0;k<16;k++) {
-                               atp_dev->id[c][k].prd_table = pci_alloc_consistent(atp_dev->pdev, 1024, &(atp_dev->id[c][k].prdaddr));
+                               atp_dev->id[c][k].prd_table = pci_alloc_consistent(atp_dev->pdev, 1024, &(atp_dev->id[c][k].prd_bus));
                                if (!atp_dev->id[c][k].prd_table) {
                                        printk("atp870u_init_tables fail\n");
                                atp870u_free_tables(host);
                                return -ENOMEM;
                        }
+                       atp_dev->id[c][k].prdaddr = atp_dev->id[c][k].prd_bus;
                        atp_dev->id[c][k].devsp=0x20;
                        atp_dev->id[c][k].devtype = 0x7f;
                        atp_dev->id[c][k].curr_req = NULL;                         
index 89f43af39cf2e57e98e17cd4f9f8889a8f480560..62bae64a01c15d687afa5f043b78a117c7d84241 100644 (file)
@@ -54,8 +54,9 @@ struct atp_unit
                unsigned long tran_len;
                unsigned long last_len;
                unsigned char *prd_pos;
-               unsigned char *prd_table;
-               dma_addr_t prdaddr;
+               unsigned char *prd_table;       /* Kernel address of PRD table */
+               dma_addr_t prd_bus;             /* Bus address of PRD */
+               dma_addr_t prdaddr;             /* Dynamically updated in driver */
                struct scsi_cmnd *curr_req;
        } id[2][16];
        struct Scsi_Host *host;
index fa652f8aa64392548ddf6097cec52a0a1e752e56..d59d449a9e4dd46f1155e5f468e70ebb58ddc946 100644 (file)
@@ -1360,3 +1360,5 @@ static Scsi_Host_Template driver_template = {
        .use_clustering                 = DISABLE_CLUSTERING,
 };
 #include "scsi_module.c"
+
+MODULE_LICENSE("GPL");
index 85503fad789a099d4d69a2fb6cda0db36ba256be..f2a72d33132c4e24e9e9b5f29fb4126276ea089d 100644 (file)
@@ -98,6 +98,7 @@ int scsi_host_set_state(struct Scsi_Host *shost, enum scsi_host_state state)
                switch (oldstate) {
                case SHOST_CREATED:
                case SHOST_RUNNING:
+               case SHOST_CANCEL_RECOVERY:
                        break;
                default:
                        goto illegal;
@@ -107,12 +108,31 @@ int scsi_host_set_state(struct Scsi_Host *shost, enum scsi_host_state state)
        case SHOST_DEL:
                switch (oldstate) {
                case SHOST_CANCEL:
+               case SHOST_DEL_RECOVERY:
                        break;
                default:
                        goto illegal;
                }
                break;
 
+       case SHOST_CANCEL_RECOVERY:
+               switch (oldstate) {
+               case SHOST_CANCEL:
+               case SHOST_RECOVERY:
+                       break;
+               default:
+                       goto illegal;
+               }
+               break;
+
+       case SHOST_DEL_RECOVERY:
+               switch (oldstate) {
+               case SHOST_CANCEL_RECOVERY:
+                       break;
+               default:
+                       goto illegal;
+               }
+               break;
        }
        shost->shost_state = state;
        return 0;
@@ -134,13 +154,24 @@ EXPORT_SYMBOL(scsi_host_set_state);
  **/
 void scsi_remove_host(struct Scsi_Host *shost)
 {
+       unsigned long flags;
        down(&shost->scan_mutex);
-       scsi_host_set_state(shost, SHOST_CANCEL);
+       spin_lock_irqsave(shost->host_lock, flags);
+       if (scsi_host_set_state(shost, SHOST_CANCEL))
+               if (scsi_host_set_state(shost, SHOST_CANCEL_RECOVERY)) {
+                       spin_unlock_irqrestore(shost->host_lock, flags);
+                       up(&shost->scan_mutex);
+                       return;
+               }
+       spin_unlock_irqrestore(shost->host_lock, flags);
        up(&shost->scan_mutex);
        scsi_forget_host(shost);
        scsi_proc_host_rm(shost);
 
-       scsi_host_set_state(shost, SHOST_DEL);
+       spin_lock_irqsave(shost->host_lock, flags);
+       if (scsi_host_set_state(shost, SHOST_DEL))
+               BUG_ON(scsi_host_set_state(shost, SHOST_DEL_RECOVERY));
+       spin_unlock_irqrestore(shost->host_lock, flags);
 
        transport_unregister_device(&shost->shost_gendev);
        class_device_unregister(&shost->shost_classdev);
index 6e54c7d9b33c9d1788a26150cf4d2ff2d395b9fc..19392f65127263ffa07a9a34871a984cdc416510 100644 (file)
@@ -460,6 +460,8 @@ MODULE_PARM(adisplay, "1i");
 MODULE_PARM(normal, "1i");
 MODULE_PARM(ansi, "1i");
 #endif
+
+MODULE_LICENSE("GPL");
 #endif
 /*counter of concurrent disk read/writes, to turn on/off disk led */
 static int disk_rw_in_progress = 0;
index 5b14934ba861f0f119a9c48e809b0aea8340ebbc..ff25210b00bac82b7ea9b500c5c528fafbed92b5 100644 (file)
@@ -727,6 +727,16 @@ static void adapter_info_rsp(struct srp_event_struct *evt_struct)
                if (hostdata->madapter_info.port_max_txu[0]) 
                        hostdata->host->max_sectors = 
                                hostdata->madapter_info.port_max_txu[0] >> 9;
+               
+               if (hostdata->madapter_info.os_type == 3 &&
+                   strcmp(hostdata->madapter_info.srp_version, "1.6a") <= 0) {
+                       printk("ibmvscsi: host (Ver. %s) doesn't support large"
+                              "transfers\n",
+                              hostdata->madapter_info.srp_version);
+                       printk("ibmvscsi: limiting scatterlists to %d\n",
+                              MAX_INDIRECT_BUFS);
+                       hostdata->host->sg_tablesize = MAX_INDIRECT_BUFS;
+               }
        }
 }
 
index 62095bdb173ae67d1f8e1d4e0a6ee929793b5cb8..9182817612ae053e4af439e1c9f0164f585138ab 100644 (file)
@@ -2551,9 +2551,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;
@@ -2572,14 +2575,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);
@@ -2588,6 +2591,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;
 }
 
 
@@ -2795,7 +2802,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,
@@ -2807,7 +2814,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++)
@@ -2935,9 +2942,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;
                }
 
@@ -2973,7 +2978,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:
@@ -2984,7 +2994,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:
@@ -2999,10 +3009,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,
@@ -4212,6 +4221,53 @@ err_out:
        return 0;
 }
 
+/**
+ *     ata_host_set_remove - PCI layer callback for device removal
+ *     @host_set: ATA host set that was removed
+ *
+ *     Unregister all objects associated with this host set. Free those 
+ *     objects.
+ *
+ *     LOCKING:
+ *     Inherited from calling layer (may sleep).
+ */
+
+
+void ata_host_set_remove(struct ata_host_set *host_set)
+{
+       struct ata_port *ap;
+       unsigned int i;
+
+       for (i = 0; i < host_set->n_ports; i++) {
+               ap = host_set->ports[i];
+               scsi_remove_host(ap->host);
+       }
+
+       free_irq(host_set->irq, host_set);
+
+       for (i = 0; i < host_set->n_ports; i++) {
+               ap = host_set->ports[i];
+
+               ata_scsi_release(ap->host);
+
+               if ((ap->flags & ATA_FLAG_NO_LEGACY) == 0) {
+                       struct ata_ioports *ioaddr = &ap->ioaddr;
+
+                       if (ioaddr->cmd_addr == 0x1f0)
+                               release_region(0x1f0, 8);
+                       else if (ioaddr->cmd_addr == 0x170)
+                               release_region(0x170, 8);
+               }
+
+               scsi_host_put(ap->host);
+       }
+
+       if (host_set->ops->host_stop)
+               host_set->ops->host_stop(host_set);
+
+       kfree(host_set);
+}
+
 /**
  *     ata_scsi_release - SCSI layer callback hook for host unload
  *     @host: libata host to be unloaded
@@ -4552,39 +4608,8 @@ void ata_pci_remove_one (struct pci_dev *pdev)
 {
        struct device *dev = pci_dev_to_dev(pdev);
        struct ata_host_set *host_set = dev_get_drvdata(dev);
-       struct ata_port *ap;
-       unsigned int i;
-
-       for (i = 0; i < host_set->n_ports; i++) {
-               ap = host_set->ports[i];
-
-               scsi_remove_host(ap->host);
-       }
-
-       free_irq(host_set->irq, host_set);
-
-       for (i = 0; i < host_set->n_ports; i++) {
-               ap = host_set->ports[i];
-
-               ata_scsi_release(ap->host);
-
-               if ((ap->flags & ATA_FLAG_NO_LEGACY) == 0) {
-                       struct ata_ioports *ioaddr = &ap->ioaddr;
-
-                       if (ioaddr->cmd_addr == 0x1f0)
-                               release_region(0x1f0, 8);
-                       else if (ioaddr->cmd_addr == 0x170)
-                               release_region(0x170, 8);
-               }
-
-               scsi_host_put(ap->host);
-       }
-
-       if (host_set->ops->host_stop)
-               host_set->ops->host_stop(host_set);
-
-       kfree(host_set);
 
+       ata_host_set_remove(host_set);
        pci_release_regions(pdev);
        pci_disable_device(pdev);
        dev_set_drvdata(dev, NULL);
@@ -4654,6 +4679,7 @@ module_exit(ata_exit);
 EXPORT_SYMBOL_GPL(ata_std_bios_param);
 EXPORT_SYMBOL_GPL(ata_std_ports);
 EXPORT_SYMBOL_GPL(ata_device_add);
+EXPORT_SYMBOL_GPL(ata_host_set_remove);
 EXPORT_SYMBOL_GPL(ata_sg_init);
 EXPORT_SYMBOL_GPL(ata_sg_init_one);
 EXPORT_SYMBOL_GPL(ata_qc_complete);
index a4857db4f9b8033f2ff16785dc94244e997489a6..b235556b7b65459775236f9940147ed1c118a772 100644 (file)
@@ -1959,22 +1959,35 @@ static int mesh_probe(struct macio_dev *mdev, const struct of_device_id *match)
        /* Set it up */
                mesh_init(ms);
 
-       /* XXX FIXME: error should be fatal */
-               if (request_irq(ms->meshintr, do_mesh_interrupt, 0, "MESH", ms))
+       /* Request interrupt */
+               if (request_irq(ms->meshintr, do_mesh_interrupt, 0, "MESH", ms)) {
                printk(KERN_ERR "MESH: can't get irq %d\n", ms->meshintr);
+               goto out_shutdown;
+       }
 
-       /* XXX FIXME: handle failure */
-       scsi_add_host(mesh_host, &mdev->ofdev.dev);
+       /* Add scsi host & scan */
+       if (scsi_add_host(mesh_host, &mdev->ofdev.dev))
+               goto out_release_irq;
        scsi_scan_host(mesh_host);
 
        return 0;
 
-out_unmap:
+ out_release_irq:
+       free_irq(ms->meshintr, ms);
+ out_shutdown:
+       /* shutdown & reset bus in case of error or macos can be confused
+        * at reboot if the bus was set to synchronous mode already
+        */
+       mesh_shutdown(mdev);
+       set_mesh_power(ms, 0);
+       pci_free_consistent(macio_get_pci_dev(mdev), ms->dma_cmd_size,
+                           ms->dma_cmd_space, ms->dma_cmd_bus);
+ out_unmap:
        iounmap(ms->dma);
        iounmap(ms->mesh);
-out_free:
+ out_free:
        scsi_host_put(mesh_host);
-out_release:
+ out_release:
        macio_release_resources(mdev);
 
        return -ENODEV;
@@ -2001,7 +2014,7 @@ static int mesh_remove(struct macio_dev *mdev)
 
        /* Free DMA commands memory */
        pci_free_consistent(macio_get_pci_dev(mdev), ms->dma_cmd_size,
-                         ms->dma_cmd_space, ms->dma_cmd_bus);
+                           ms->dma_cmd_space, ms->dma_cmd_bus);
 
        /* Release memory resources */
        macio_release_resources(mdev);
index 3e9b64137873574acd5144a35097ade5eaa84808..23d095d3817b8cb8b35d431564083f1a03da9b71 100644 (file)
@@ -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);
index a1d62dee3be640d43b2315146a73b6401705cb3b..c05653c7779dd792855a138a8e4479911d08c592 100644 (file)
@@ -158,6 +158,8 @@ static struct pci_device_id nv_pci_tbl[] = {
                PCI_ANY_ID, PCI_ANY_ID, 0, 0, MCP51 },
        { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_SATA,
                PCI_ANY_ID, PCI_ANY_ID, 0, 0, MCP55 },
+       { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_SATA2,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0, MCP55 },
        { PCI_VENDOR_ID_NVIDIA, PCI_ANY_ID,
                PCI_ANY_ID, PCI_ANY_ID,
                PCI_CLASS_STORAGE_IDE<<8, 0xffff00, GENERIC },
index a63f93186e41ad1eafdda84aa704619750373d44..b227e51d12f4c3b0f8a591e72967cbe0ebda1bc4 100644 (file)
@@ -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");
index a780546eda9ca5510d23dcdfea5fe1c4fd692cc2..1f0ebabf6d47663ffd0f9e6e62fc4b7eff21c422 100644 (file)
@@ -1265,9 +1265,8 @@ int scsi_device_cancel(struct scsi_device *sdev, int recovery)
                list_for_each_safe(lh, lh_sf, &active_list) {
                        scmd = list_entry(lh, struct scsi_cmnd, eh_entry);
                        list_del_init(lh);
-                       if (recovery) {
-                               scsi_eh_scmd_add(scmd, SCSI_EH_CANCEL_CMD);
-                       } else {
+                       if (recovery &&
+                           !scsi_eh_scmd_add(scmd, SCSI_EH_CANCEL_CMD)) {
                                scmd->result = (DID_ABORT << 16);
                                scsi_finish_command(scmd);
                        }
index 07b554affcf22b9f0d5446af9275b27ec2f7d441..64fc9e21f35b1ca9987e98a713058a911d8f2b77 100644 (file)
@@ -110,6 +110,7 @@ static struct {
        {"RELISYS", "Scorpio", NULL, BLIST_NOLUN},      /* responds to all lun */
        {"SANKYO", "CP525", "6.64", BLIST_NOLUN},       /* causes failed REQ SENSE, extra reset */
        {"TEXEL", "CD-ROM", "1.06", BLIST_NOLUN},
+       {"transtec", "T5008", "0001", BLIST_NOREPORTLUN },
        {"YAMAHA", "CDR100", "1.00", BLIST_NOLUN},      /* locks up */
        {"YAMAHA", "CDR102", "1.00", BLIST_NOLUN},      /* locks up */
        {"YAMAHA", "CRW8424S", "1.0", BLIST_NOLUN},     /* locks up */
index 895c9452be4ca65cc3aebf78ee8bd9f319618c15..ad534216507961f438dfebe99bffe013daef19e5 100644 (file)
@@ -50,7 +50,7 @@
 void scsi_eh_wakeup(struct Scsi_Host *shost)
 {
        if (shost->host_busy == shost->host_failed) {
-               up(shost->eh_wait);
+               wake_up_process(shost->ehandler);
                SCSI_LOG_ERROR_RECOVERY(5,
                                printk("Waking error handler thread\n"));
        }
@@ -68,19 +68,24 @@ int scsi_eh_scmd_add(struct scsi_cmnd *scmd, int eh_flag)
 {
        struct Scsi_Host *shost = scmd->device->host;
        unsigned long flags;
+       int ret = 0;
 
-       if (shost->eh_wait == NULL)
+       if (!shost->ehandler)
                return 0;
 
        spin_lock_irqsave(shost->host_lock, flags);
+       if (scsi_host_set_state(shost, SHOST_RECOVERY))
+               if (scsi_host_set_state(shost, SHOST_CANCEL_RECOVERY))
+                       goto out_unlock;
 
+       ret = 1;
        scmd->eh_eflags |= eh_flag;
        list_add_tail(&scmd->eh_entry, &shost->eh_cmd_q);
-       scsi_host_set_state(shost, SHOST_RECOVERY);
        shost->host_failed++;
        scsi_eh_wakeup(shost);
+ out_unlock:
        spin_unlock_irqrestore(shost->host_lock, flags);
-       return 1;
+       return ret;
 }
 
 /**
@@ -176,8 +181,8 @@ void scsi_times_out(struct scsi_cmnd *scmd)
                }
 
        if (unlikely(!scsi_eh_scmd_add(scmd, SCSI_EH_CANCEL_CMD))) {
-               panic("Error handler thread not present at %p %p %s %d",
-                     scmd, scmd->device->host, __FILE__, __LINE__);
+               scmd->result |= DID_TIME_OUT << 16;
+               __scsi_done(scmd);
        }
 }
 
@@ -196,8 +201,7 @@ int scsi_block_when_processing_errors(struct scsi_device *sdev)
 {
        int online;
 
-       wait_event(sdev->host->host_wait, (sdev->host->shost_state !=
-                                          SHOST_RECOVERY));
+       wait_event(sdev->host->host_wait, !scsi_host_in_recovery(sdev->host));
 
        online = scsi_device_online(sdev);
 
@@ -1441,6 +1445,7 @@ static void scsi_eh_lock_door(struct scsi_device *sdev)
 static void scsi_restart_operations(struct Scsi_Host *shost)
 {
        struct scsi_device *sdev;
+       unsigned long flags;
 
        /*
         * If the door was locked, we need to insert a door lock request
@@ -1460,7 +1465,11 @@ static void scsi_restart_operations(struct Scsi_Host *shost)
        SCSI_LOG_ERROR_RECOVERY(3, printk("%s: waking up host to restart\n",
                                          __FUNCTION__));
 
-       scsi_host_set_state(shost, SHOST_RUNNING);
+       spin_lock_irqsave(shost->host_lock, flags);
+       if (scsi_host_set_state(shost, SHOST_RUNNING))
+               if (scsi_host_set_state(shost, SHOST_CANCEL))
+                       BUG_ON(scsi_host_set_state(shost, SHOST_DEL));
+       spin_unlock_irqrestore(shost->host_lock, flags);
 
        wake_up(&shost->host_wait);
 
@@ -1582,40 +1591,31 @@ int scsi_error_handler(void *data)
 {
        struct Scsi_Host *shost = (struct Scsi_Host *) data;
        int rtn;
-       DECLARE_MUTEX_LOCKED(sem);
 
        current->flags |= PF_NOFREEZE;
-       shost->eh_wait = &sem;
 
+       
        /*
-        * Wake up the thread that created us.
+        * Note - we always use TASK_INTERRUPTIBLE even if the module
+        * was loaded as part of the kernel.  The reason is that
+        * UNINTERRUPTIBLE would cause this thread to be counted in
+        * the load average as a running process, and an interruptible
+        * wait doesn't.
         */
-       SCSI_LOG_ERROR_RECOVERY(3, printk("Wake up parent of"
-                                         " scsi_eh_%d\n",shost->host_no));
-
-       while (1) {
-               /*
-                * If we get a signal, it means we are supposed to go
-                * away and die.  This typically happens if the user is
-                * trying to unload a module.
-                */
-               SCSI_LOG_ERROR_RECOVERY(1, printk("Error handler"
-                                                 " scsi_eh_%d"
-                                                 " sleeping\n",shost->host_no));
-
-               /*
-                * Note - we always use down_interruptible with the semaphore
-                * even if the module was loaded as part of the kernel.  The
-                * reason is that down() will cause this thread to be counted
-                * in the load average as a running process, and down
-                * interruptible doesn't.  Given that we need to allow this
-                * thread to die if the driver was loaded as a module, using
-                * semaphores isn't unreasonable.
-                */
-               down_interruptible(&sem);
-               if (kthread_should_stop())
-                       break;
+       set_current_state(TASK_INTERRUPTIBLE);
+       while (!kthread_should_stop()) {
+               if (shost->host_failed == 0 ||
+                   shost->host_failed != shost->host_busy) {
+                       SCSI_LOG_ERROR_RECOVERY(1, printk("Error handler"
+                                                         " scsi_eh_%d"
+                                                         " sleeping\n",
+                                                         shost->host_no));
+                       schedule();
+                       set_current_state(TASK_INTERRUPTIBLE);
+                       continue;
+               }
 
+               __set_current_state(TASK_RUNNING);
                SCSI_LOG_ERROR_RECOVERY(1, printk("Error handler"
                                                  " scsi_eh_%d waking"
                                                  " up\n",shost->host_no));
@@ -1642,7 +1642,7 @@ int scsi_error_handler(void *data)
                 * which are still online.
                 */
                scsi_restart_operations(shost);
-
+               set_current_state(TASK_INTERRUPTIBLE);
        }
 
        SCSI_LOG_ERROR_RECOVERY(1, printk("Error handler scsi_eh_%d"
@@ -1651,7 +1651,7 @@ int scsi_error_handler(void *data)
        /*
         * Make sure that nobody tries to wake us up again.
         */
-       shost->eh_wait = NULL;
+       shost->ehandler = NULL;
        return 0;
 }
 
index b7fddac813474c0903d37d88e6f6f7ec03b092f5..de7f98cc38feb020863323b06e4fd6d2e4f426a9 100644 (file)
@@ -458,7 +458,7 @@ int scsi_nonblockable_ioctl(struct scsi_device *sdev, int cmd,
         * error processing, as long as the device was opened
         * non-blocking */
        if (filp && filp->f_flags & O_NONBLOCK) {
-               if (sdev->host->shost_state == SHOST_RECOVERY)
+               if (scsi_host_in_recovery(sdev->host))
                        return -ENODEV;
        } else if (!scsi_block_when_processing_errors(sdev))
                return -ENODEV;
index 863bb6495daaeb6bd6fcdb1a00c7721507e6fb8d..dc9c772bc874073b9d6fa38fda47a12faf7c463b 100644 (file)
@@ -118,7 +118,6 @@ static void scsi_unprep_request(struct request *req)
        req->flags &= ~REQ_DONTPREP;
        req->special = (req->flags & REQ_SPECIAL) ? cmd->sc_request : NULL;
 
-       scsi_release_buffers(cmd);
        scsi_put_command(cmd);
 }
 
@@ -140,14 +139,12 @@ static void scsi_unprep_request(struct request *req)
  *              commands.
  * Notes:       This could be called either from an interrupt context or a
  *              normal process context.
- * Notes:      Upon return, cmd is a stale pointer.
  */
 int scsi_queue_insert(struct scsi_cmnd *cmd, int reason)
 {
        struct Scsi_Host *host = cmd->device->host;
        struct scsi_device *device = cmd->device;
        struct request_queue *q = device->request_queue;
-       struct request *req = cmd->request;
        unsigned long flags;
 
        SCSI_LOG_MLQUEUE(1,
@@ -188,9 +185,8 @@ int scsi_queue_insert(struct scsi_cmnd *cmd, int reason)
         * function.  The SCSI request function detects the blocked condition
         * and plugs the queue appropriately.
          */
-       scsi_unprep_request(req);
        spin_lock_irqsave(q->queue_lock, flags);
-       blk_requeue_request(q, req);
+       blk_requeue_request(q, cmd->request);
        spin_unlock_irqrestore(q->queue_lock, flags);
 
        scsi_run_queue(q);
@@ -451,7 +447,7 @@ void scsi_device_unbusy(struct scsi_device *sdev)
 
        spin_lock_irqsave(shost->host_lock, flags);
        shost->host_busy--;
-       if (unlikely((shost->shost_state == SHOST_RECOVERY) &&
+       if (unlikely(scsi_host_in_recovery(shost) &&
                     shost->host_failed))
                scsi_eh_wakeup(shost);
        spin_unlock(shost->host_lock);
@@ -1268,6 +1264,7 @@ static int scsi_prep_fn(struct request_queue *q, struct request *req)
                        }
                } else {
                        memcpy(cmd->cmnd, req->cmd, sizeof(cmd->cmnd));
+                       cmd->cmd_len = req->cmd_len;
                        if (rq_data_dir(req) == WRITE)
                                cmd->sc_data_direction = DMA_TO_DEVICE;
                        else if (req->data_len)
@@ -1342,7 +1339,7 @@ static inline int scsi_host_queue_ready(struct request_queue *q,
                                   struct Scsi_Host *shost,
                                   struct scsi_device *sdev)
 {
-       if (shost->shost_state == SHOST_RECOVERY)
+       if (scsi_host_in_recovery(shost))
                return 0;
        if (shost->host_busy == 0 && shost->host_blocked) {
                /*
@@ -1514,7 +1511,6 @@ static void scsi_request_fn(struct request_queue *q)
         * cases (host limits or settings) should run the queue at some
         * later time.
         */
-       scsi_unprep_request(req);
        spin_lock_irq(q->queue_lock);
        blk_requeue_request(q, req);
        sdev->device_busy--;
index b86f170fa8ed5a4dafbbd65bb1b3293ea9de21e8..fcf9f6cbb142d3675b295a2ffc04f3d4ada94c41 100644 (file)
@@ -1466,23 +1466,17 @@ EXPORT_SYMBOL(scsi_scan_single_target);
 
 void scsi_forget_host(struct Scsi_Host *shost)
 {
-       struct scsi_target *starget, *tmp;
+       struct scsi_device *sdev;
        unsigned long flags;
 
-       /*
-        * Ok, this look a bit strange.  We always look for the first device
-        * on the list as scsi_remove_device removes them from it - thus we
-        * also have to release the lock.
-        * We don't need to get another reference to the device before
-        * releasing the lock as we already own the reference from
-        * scsi_register_device that's release in scsi_remove_device.  And
-        * after that we don't look at sdev anymore.
-        */
+ restart:
        spin_lock_irqsave(shost->host_lock, flags);
-       list_for_each_entry_safe(starget, tmp, &shost->__targets, siblings) {
+       list_for_each_entry(sdev, &shost->__devices, siblings) {
+               if (sdev->sdev_state == SDEV_DEL)
+                       continue;
                spin_unlock_irqrestore(shost->host_lock, flags);
-               scsi_remove_target(&starget->dev);
-               spin_lock_irqsave(shost->host_lock, flags);
+               __scsi_remove_device(sdev);
+               goto restart;
        }
        spin_unlock_irqrestore(shost->host_lock, flags);
 }
index b8052d5206cca22f03a782044b9ca5b7d78f605f..72a6550a056c9dc14ba33f2383a04b7fb9711d99 100644 (file)
@@ -57,6 +57,8 @@ static struct {
        { SHOST_CANCEL, "cancel" },
        { SHOST_DEL, "deleted" },
        { SHOST_RECOVERY, "recovery" },
+       { SHOST_CANCEL_RECOVERY, "cancel/recovery" },
+       { SHOST_DEL_RECOVERY, "deleted/recovery", },
 };
 const char *scsi_host_state_name(enum scsi_host_state state)
 {
@@ -707,9 +709,11 @@ void __scsi_remove_device(struct scsi_device *sdev)
  **/
 void scsi_remove_device(struct scsi_device *sdev)
 {
-       down(&sdev->host->scan_mutex);
+       struct Scsi_Host *shost = sdev->host;
+
+       down(&shost->scan_mutex);
        __scsi_remove_device(sdev);
-       up(&sdev->host->scan_mutex);
+       up(&shost->scan_mutex);
 }
 EXPORT_SYMBOL(scsi_remove_device);
 
@@ -717,17 +721,20 @@ void __scsi_remove_target(struct scsi_target *starget)
 {
        struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
        unsigned long flags;
-       struct scsi_device *sdev, *tmp;
+       struct scsi_device *sdev;
 
        spin_lock_irqsave(shost->host_lock, flags);
        starget->reap_ref++;
-       list_for_each_entry_safe(sdev, tmp, &shost->__devices, siblings) {
+ restart:
+       list_for_each_entry(sdev, &shost->__devices, siblings) {
                if (sdev->channel != starget->channel ||
-                   sdev->id != starget->id)
+                   sdev->id != starget->id ||
+                   sdev->sdev_state == SDEV_DEL)
                        continue;
                spin_unlock_irqrestore(shost->host_lock, flags);
                scsi_remove_device(sdev);
                spin_lock_irqsave(shost->host_lock, flags);
+               goto restart;
        }
        spin_unlock_irqrestore(shost->host_lock, flags);
        scsi_target_reap(starget);
index de564b386052a1c1c0015f76088c2f9db6fc529c..9a1dc0cea03c374245ccfeebb5b8a095cab780d8 100644 (file)
@@ -235,6 +235,7 @@ static int sd_init_command(struct scsi_cmnd * SCpnt)
                        return 0;
 
                memcpy(SCpnt->cmnd, rq->cmd, sizeof(SCpnt->cmnd));
+               SCpnt->cmd_len = rq->cmd_len;
                if (rq_data_dir(rq) == WRITE)
                        SCpnt->sc_data_direction = DMA_TO_DEVICE;
                else if (rq->data_len)
index 9ea4765d1d12cc3884417fdbda92814163f42960..4d09a6e4dd2ea7143cbeece3813cbc869a211a7d 100644 (file)
@@ -1027,7 +1027,7 @@ sg_ioctl(struct inode *inode, struct file *filp,
                if (sdp->detached)
                        return -ENODEV;
                if (filp->f_flags & O_NONBLOCK) {
-                       if (sdp->device->host->shost_state == SHOST_RECOVERY)
+                       if (scsi_host_in_recovery(sdp->device->host))
                                return -EBUSY;
                } else if (!scsi_block_when_processing_errors(sdp->device))
                        return -EBUSY;
index ce63fc8312dca45abf1794f43d20a1e57e6ad966..561901b1cf1178c70f8a30db85b57b07f9ea09cb 100644 (file)
@@ -326,6 +326,7 @@ static int sr_init_command(struct scsi_cmnd * SCpnt)
                        return 0;
 
                memcpy(SCpnt->cmnd, rq->cmd, sizeof(SCpnt->cmnd));
+               SCpnt->cmd_len = rq->cmd_len;
                if (!rq->data_len)
                        SCpnt->sc_data_direction = DMA_NONE;
                else if (rq_data_dir(rq) == WRITE)
index a93308ae97362b3fa2d0b2a76979ffca3c5da630..d001c046551bcab0663ffa151bd83a382b6406dc 100644 (file)
@@ -4206,6 +4206,7 @@ static int st_init_command(struct scsi_cmnd *SCpnt)
                return 0;
 
        memcpy(SCpnt->cmnd, rq->cmd, sizeof(SCpnt->cmnd));
+       SCpnt->cmd_len = rq->cmd_len;
 
        if (rq_data_dir(rq) == WRITE)
                SCpnt->sc_data_direction = DMA_TO_DEVICE;
index aec39fb261cae9c6b14ada4e5608d67c8b4b672f..b5cf39468d18bf66fdee5ff2fe87601698f0152d 100644 (file)
@@ -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 =
 {
index 978e12437e617df488ccd32352e41a457516961b..679e678c7e6a158e0b6e25aaf5ef383cae346f08 100644 (file)
@@ -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,
index 56071309744c526322bc404f52159e8eae95738d..1ff629c7475008e41efbc7d81abca1a670994f91 100644 (file)
@@ -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,
index d822896b488c80c45f68738f237a000e5af76b50..78c1f36ad9b72c3987e8ae64f31f0a7b95f8e419 100644 (file)
@@ -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,
index a3cd0ee8486d42fb9a6d757841b9b140059182a5..0585ab27ffde7da5ba9070badb87dc2891d40e10 100644 (file)
@@ -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);
 
index eaa0af8352907da7f6ea4f18a8d9df7f7c096edb..672b359b07ce4f48fd16b3e2e9fc0ecffdd59e3c 100644 (file)
@@ -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)
 
index 1225b14f6e9d4bb7469bb1f6019bf877936f1b54..dd8aed242357c77e2043b53248c7ff00ec1cfaa8 100644 (file)
@@ -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,
index 8302376800c07da15b3c905a0b50baa3a8f9407b..d01dbe5da3b96d395caf8c83a9b923d1325833a8 100644 (file)
@@ -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,
index 4382ee60b6a85d89d9de4b94ef54ae69c2464257..6bed8713897e86a615c1f6df1a60fa45030bfc54 100644 (file)
@@ -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,
index c47c8052b4866f536b7482e4452d7f99ec221051..f1fb67fe22a82806533a4875801fd14a7f180833 100644 (file)
@@ -987,7 +987,7 @@ void usb_disable_device(struct usb_device *dev, int skip_ep0)
 
                        /* remove this interface if it has been registered */
                        interface = dev->actconfig->interface[i];
-                       if (!klist_node_attached(&interface->dev.knode_bus))
+                       if (!device_is_registered(&interface->dev))
                                continue;
                        dev_dbg (&dev->dev, "unregistering interface %s\n",
                                interface->dev.bus_id);
index 087af73a59dd70aa270694abde9e9233a51fe241..7d131509e41909a0aa92bac2665cf1acbccb2d1b 100644 (file)
@@ -303,7 +303,7 @@ int usb_driver_claim_interface(struct usb_driver *driver,
        /* if interface was already added, bind now; else let
         * the future device_add() bind it, bypassing probe()
         */
-       if (klist_node_attached(&dev->knode_bus))
+       if (device_is_registered(dev))
                device_bind_driver(dev);
 
        return 0;
@@ -336,8 +336,8 @@ void usb_driver_release_interface(struct usb_driver *driver,
        if (iface->condition != USB_INTERFACE_BOUND)
                return;
 
-       /* release only after device_add() */
-       if (klist_node_attached(&dev->knode_bus)) {
+       /* don't release if the interface hasn't been added yet */
+       if (device_is_registered(dev)) {
                iface->condition = USB_INTERFACE_UNBINDING;
                device_release_driver(dev);
        }
index 1507738337c416647c43999802b72714371a7837..73f8c9404156be4f6d2afa9351d8bd20a14e1bf6 100644 (file)
@@ -422,7 +422,7 @@ static inline void ep0_idle (struct pxa2xx_udc *dev)
 }
 
 static int
-write_packet(volatile u32 *uddr, struct pxa2xx_request *req, unsigned max)
+write_packet(volatile unsigned long *uddr, struct pxa2xx_request *req, unsigned max)
 {
        u8              *buf;
        unsigned        length, count;
@@ -2602,7 +2602,7 @@ static int __exit pxa2xx_udc_remove(struct device *_dev)
  * VBUS IRQs should probably be ignored so that the PXA device just acts
  * "dead" to USB hosts until system resume.
  */
-static int pxa2xx_udc_suspend(struct device *dev, u32 state, u32 level)
+static int pxa2xx_udc_suspend(struct device *dev, pm_message_t state, u32 level)
 {
        struct pxa2xx_udc       *udc = dev_get_drvdata(dev);
 
index d0bc396a85d50041e030289ae4c0ab99396f525b..a58f3e6e71f1ddbc5cb74c22db89740b77636278 100644 (file)
@@ -69,11 +69,11 @@ struct pxa2xx_ep {
         * UDDR = UDC Endpoint Data Register (the fifo)
         * DRCM = DMA Request Channel Map
         */
-       volatile u32                            *reg_udccs;
-       volatile u32                            *reg_ubcr;
-       volatile u32                            *reg_uddr;
+       volatile unsigned long                  *reg_udccs;
+       volatile unsigned long                  *reg_ubcr;
+       volatile unsigned long                  *reg_uddr;
 #ifdef USE_DMA
-       volatile u32                            *reg_drcmr;
+       volatile unsigned long                  *reg_drcmr;
 #define        drcmr(n)  .reg_drcmr = & DRCMR ## n ,
 #else
 #define        drcmr(n)  
index d2a1fd40dfcb846e148faef3e9102142c2ba7cc6..d42a15d10a462de96a4ba16869990f4ae41f1057 100644 (file)
@@ -782,6 +782,9 @@ retry:
 /* usb 1.1 says max 90% of a frame is available for periodic transfers.
  * this driver doesn't promise that much since it's got to handle an
  * IRQ per packet; irq handling latencies also use up that time.
+ *
+ * NOTE:  the periodic schedule is a sparse tree, with the load for
+ * each branch minimized.  see fig 3.5 in the OHCI spec for example.
  */
 #define        MAX_PERIODIC_LOAD       500     /* out of 1000 usec */
 
@@ -843,6 +846,7 @@ static int sl811h_urb_enqueue(
        if (!(sl811->port1 & (1 << USB_PORT_FEAT_ENABLE))
                        || !HC_IS_RUNNING(hcd->state)) {
                retval = -ENODEV;
+               kfree(ep);
                goto fail;
        }
 
@@ -911,8 +915,16 @@ static int sl811h_urb_enqueue(
        case PIPE_ISOCHRONOUS:
        case PIPE_INTERRUPT:
                urb->interval = ep->period;
-               if (ep->branch < PERIODIC_SIZE)
+               if (ep->branch < PERIODIC_SIZE) {
+                       /* NOTE:  the phase is correct here, but the value
+                        * needs offsetting by the transfer queue depth.
+                        * All current drivers ignore start_frame, so this
+                        * is unlikely to ever matter...
+                        */
+                       urb->start_frame = (sl811->frame & (PERIODIC_SIZE - 1))
+                                               + ep->branch;
                        break;
+               }
 
                retval = balance(sl811, ep->period, ep->load);
                if (retval < 0)
@@ -1122,7 +1134,7 @@ sl811h_hub_descriptor (
        desc->wHubCharacteristics = (__force __u16)cpu_to_le16(temp);
 
        /* two bitmaps:  ports removable, and legacy PortPwrCtrlMask */
-       desc->bitmap[0] = 1 << 1;
+       desc->bitmap[0] = 0 << 1;
        desc->bitmap[1] = ~0;
 }
 
index 7484d34780fcb7e0dced0bdcb24556b776d6e2fa..6a4ffe6c39771c13f883c78401cca24e529ef87a 100644 (file)
@@ -647,6 +647,13 @@ static void read_bulk_callback(struct urb *urb, struct pt_regs *regs)
                pkt_len -= 8;
        }
 
+       /*
+        * If the packet is unreasonably long, quietly drop it rather than
+        * kernel panicing by calling skb_put.
+        */
+       if (pkt_len > PEGASUS_MTU)
+               goto goon;
+
        /*
         * at this point we are sure pegasus->rx_skb != NULL
         * so we go ahead and pass up the packet.
@@ -886,15 +893,17 @@ static inline void get_interrupt_interval(pegasus_t * pegasus)
        __u8 data[2];
 
        read_eprom_word(pegasus, 4, (__u16 *) data);
-       if (data[1] < 0x80) {
-               if (netif_msg_timer(pegasus))
-                       dev_info(&pegasus->intf->dev,
-                               "intr interval changed from %ums to %ums\n",
-                               data[1], 0x80);
-               data[1] = 0x80;
-#ifdef PEGASUS_WRITE_EEPROM
-               write_eprom_word(pegasus, 4, *(__u16 *) data);
+       if (pegasus->usb->speed != USB_SPEED_HIGH) {
+               if (data[1] < 0x80) {
+                       if (netif_msg_timer(pegasus))
+                               dev_info(&pegasus->intf->dev, "intr interval "
+                                       "changed from %ums to %ums\n",
+                                       data[1], 0x80);
+                       data[1] = 0x80;
+#ifdef PEGASUS_WRITE_EEPROM
+                       write_eprom_word(pegasus, 4, *(__u16 *) data);
 #endif
+               }
        }
        pegasus->intr_interval = data[1];
 }
@@ -904,8 +913,9 @@ static void set_carrier(struct net_device *net)
        pegasus_t *pegasus = netdev_priv(net);
        u16 tmp;
 
-       if (read_mii_word(pegasus, pegasus->phy, MII_BMSR, &tmp))
+       if (!read_mii_word(pegasus, pegasus->phy, MII_BMSR, &tmp))
                return;
+
        if (tmp & BMSR_LSTATUS)
                netif_carrier_on(net);
        else
@@ -1355,6 +1365,7 @@ static void pegasus_disconnect(struct usb_interface *intf)
        cancel_delayed_work(&pegasus->carrier_check);
        unregister_netdev(pegasus->net);
        usb_put_dev(interface_to_usbdev(intf));
+       unlink_all_urbs(pegasus);
        free_all_urbs(pegasus);
        free_skb_pool(pegasus);
        if (pegasus->rx_skb)
index a4ce0008d69bac2eb2006eee4f926eb4a1b9d604..926d4c2c16001e0769f76b5b9d5d7f20ed83ac62 100644 (file)
@@ -16,7 +16,8 @@
 #include "usb-serial.h"
 
 static struct usb_device_id id_table [] = {
-       { USB_DEVICE(0xf3d, 0x0112) },
+       { USB_DEVICE(0xf3d, 0x0112) },  /* AirPrime CDMA Wireless PC Card */
+       { USB_DEVICE(0x1410, 0x1110) }, /* Novatel Wireless Merlin CDMA */
        { },
 };
 MODULE_DEVICE_TABLE(usb, id_table);
index 4e434cb10bb12de49efedf44838aaad248bad2b8..5a8631c8a4a74b6913afc7e716ff8abfcf85ac21 100644 (file)
@@ -1846,10 +1846,12 @@ static void ftdi_set_termios (struct usb_serial_port *port, struct termios *old_
        } else {
                /* set the baudrate determined before */
                if (change_speed(port)) {
-                       err("%s urb failed to set baurdrate", __FUNCTION__);
+                       err("%s urb failed to set baudrate", __FUNCTION__);
+               }
+               /* Ensure RTS and DTR are raised when baudrate changed from 0 */
+               if ((old_termios->c_cflag & CBAUD) == B0) {
+                       set_mctrl(port, TIOCM_DTR | TIOCM_RTS);
                }
-               /* Ensure  RTS and DTR are raised */
-               set_mctrl(port, TIOCM_DTR | TIOCM_RTS);
        }
 
        /* Set flow control */
index 92d0f925d053c64326878afc14704b9d2877cdd7..4989e5740d181141c12fa0d3a456d44f44fbe14c 100644 (file)
@@ -25,6 +25,9 @@
   2005-06-20  v0.4.1 add missing braces :-/
                      killed end-of-line whitespace
   2005-07-15  v0.4.2 rename WLAN product to FUSION, add FUSION2
+  2005-09-10  v0.4.3 added HUAWEI E600 card and Audiovox AirCard
+  2005-09-20  v0.4.4 increased recv buffer size: the card sometimes
+                     wants to send >2000 bytes.
 
   Work sponsored by: Sigos GmbH, Germany <info@sigos.de>
 
@@ -71,15 +74,21 @@ static int  option_send_setup(struct usb_serial_port *port);
 
 /* Vendor and product IDs */
 #define OPTION_VENDOR_ID                       0x0AF0
+#define HUAWEI_VENDOR_ID                       0x12D1
+#define AUDIOVOX_VENDOR_ID                     0x0F3D
 
 #define OPTION_PRODUCT_OLD             0x5000
 #define OPTION_PRODUCT_FUSION  0x6000
 #define OPTION_PRODUCT_FUSION2 0x6300
+#define HUAWEI_PRODUCT_E600     0x1001
+#define AUDIOVOX_PRODUCT_AIRCARD 0x0112
 
 static struct usb_device_id option_ids[] = {
        { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_OLD) },
        { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_FUSION) },
        { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_FUSION2) },
+       { USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E600) },
+       { USB_DEVICE(AUDIOVOX_VENDOR_ID, AUDIOVOX_PRODUCT_AIRCARD) },
        { } /* Terminating entry */
 };
 
@@ -132,7 +141,7 @@ static int debug;
 
 #define N_IN_URB 4
 #define N_OUT_URB 1
-#define IN_BUFLEN 1024
+#define IN_BUFLEN 4096
 #define OUT_BUFLEN 128
 
 struct option_port_private {
index 615874e03ce8bbad26eab9f992b5a43632a02071..773ae11b4a19edfddf92b0333462d6ef19c000d3 100644 (file)
@@ -650,6 +650,7 @@ config FB_NVIDIA
        select FB_CFB_FILLRECT
        select FB_CFB_COPYAREA
        select FB_CFB_IMAGEBLIT
+       select FB_SOFT_CURSOR
        help
          This driver supports graphics boards with the nVidia chips, TNT
          and newer. For very old chipsets, such as the RIVA128, then use
@@ -753,7 +754,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
 
index 92643af12581312bb022b19ac95f2374e5c2dbd7..a085cbf74ecb86ed4367eb018e76c1fcf02a9e0b 100644 (file)
@@ -174,7 +174,7 @@ int atyfb_xl_init(struct fb_info *info)
        const struct xl_card_cfg_t * card = &card_cfg[xl_card];
        struct atyfb_par *par = (struct atyfb_par *) info->par;
        union aty_pll pll;
-       int i, err;
+       int err;
        u32 temp;
        
        aty_st_8(CONFIG_STAT0, 0x85, par);
@@ -252,9 +252,14 @@ int atyfb_xl_init(struct fb_info *info)
        aty_st_le32(0xEC, 0x00000000, par);
        aty_st_le32(0xFC, 0x00000000, par);
 
-       for (i=0; i<sizeof(lcd_tbl)/sizeof(lcd_tbl_t); i++) {
-               aty_st_lcd(lcd_tbl[i].lcd_reg, lcd_tbl[i].val, par);
+#if defined (CONFIG_FB_ATY_GENERIC_LCD)
+       {
+               int i;
+
+               for (i = 0; i < ARRAY_SIZE(lcd_tbl); i++)
+                       aty_st_lcd(lcd_tbl[i].lcd_reg, lcd_tbl[i].val, par);
        }
+#endif
 
        aty_st_le16(CONFIG_STAT0, 0x00A4, par);
        mdelay(10);
index 353cb3f73cf2f6267dbaf2a8a625d261742828ce..630f2dfa9699efe8c3c6685d6956d5ba809c8098 100644 (file)
 #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;
index 2e93224d2d5509a14ce09ae25bd524e78f014742..0fc8bb499c3facf6f75c9ea4259cf62eaf876a13 100644 (file)
@@ -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);
index 08befafe11d14c82f822f078e4fb50467dad2361..0738cd62def219f743c34b93586efeb9e033596d 100644 (file)
@@ -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 */
index ff0af96e4dfc47dc33268fef032364aee1007041..e6aa0eab5bb6b464c95b124d952fb52e5774c887 100644 (file)
@@ -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,
index c52f1294044a29145364c6375de641bdb5e82c96..89976cd97494eb74fbc059b2af9faf8f99cfa00a 100644 (file)
@@ -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,
index 1fa7fcf2ff72aa8008da6e0c4aad458d1e9607d7..bbf1166473972a4410638669d85ad30d1a7daf25 100644 (file)
@@ -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,
index e6f8dbaa122bbc6ab37774e6caebf0f5973db12a..74fe86f28ff4644447476a4d701f61d3ab6b5b3a 100644 (file)
@@ -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,
index 57fbe266a6b914d700f1f81cc5888ef5b4f63137..26199f8ee908103f0065eb12068832e4bf6f61f4 100644 (file)
@@ -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,
index d565505e3069120926b8fe611c9927728a682cb6..2d2e39632e2d72032d402cc124b0baf22e8f2af3 100644 (file)
@@ -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,
index 593b95500a0cc1fe1dc901831fff01ae710e868e..d818234fdf11e760b9dfb26c2df18259e0b06da9 100644 (file)
@@ -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,
index 5fa95f1188180ace14353acd1095ff843f59c6ea..e646c88f55c7b245c98cc19f1350ec49f3a78d74 100644 (file)
@@ -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,
index c7bd967ea1000ed91ec4f73a73dbec2d0e8c7fbb..ab5eb93407b4c9820f6851531c4d181439990f13 100644 (file)
@@ -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,
index 2af3ab354652973b0021175f04f1aba2fd384eae..41f910f5529c95ebc83493f2f92e72dc82413a18 100644 (file)
@@ -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,
index e79b297026490531dc39fdd4767f7ca319aa4772..4fd07d9eca039d062c9968c452757f952b962a7e 100644 (file)
@@ -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);
 
index 0705cd7414117a26cb9d451d478c665a4c83fbfd..6ef6f7760e472d9b9a3e191b1b94800c481371ce 100644 (file)
@@ -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 */
index cfa61b512de0a91aef502e5c9914faa942e30864..0b6af00d197e058af63663fad76fe84d6c802d57 100644 (file)
@@ -272,11 +272,11 @@ static void fb_cvt_convert_to_mode(struct fb_cvt_data *cvt,
 {
        mode->refresh = cvt->f_refresh;
        mode->pixclock = KHZ2PICOS(cvt->pixclock/1000);
-       mode->left_margin = cvt->h_front_porch;
-       mode->right_margin = cvt->h_back_porch;
+       mode->left_margin = cvt->h_back_porch;
+       mode->right_margin = cvt->h_front_porch;
        mode->hsync_len = cvt->hsync;
-       mode->upper_margin = cvt->v_front_porch;
-       mode->lower_margin = cvt->v_back_porch;
+       mode->upper_margin = cvt->v_back_porch;
+       mode->lower_margin = cvt->v_front_porch;
        mode->vsync_len = cvt->vsync;
 
        mode->sync &= ~(FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT);
index cabd53cec9913884981ddb38b05487d85e78e17f..6c2244cf0e746156df2d4b574ef26703de16808e 100644 (file)
@@ -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__);
index 98e00d8601e5be9c210351b4fd4a7d4599cb7773..e02da41f1b262b9cb780dd19d4d36767ccdbe357 100644 (file)
@@ -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)) {
index ace484fa61ce09fb00512d54d5e7eee2bcfc6a3d..12f2884d3f0bd7da64b6fc37e2042fee4f05f5a6 100644 (file)
@@ -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)
index 3620de0f252e6100c3da6a895de1cf7f3297dc14..a7f020ada630d1218b3699b12899e8757a577065 100644 (file)
@@ -893,7 +893,7 @@ static int nvidiafb_cursor(struct fb_info *info, struct fb_cursor *cursor)
        int i, set = cursor->set;
        u16 fg, bg;
 
-       if (!hwcur || cursor->image.width > MAX_CURS || cursor->image.height > MAX_CURS)
+       if (cursor->image.width > MAX_CURS || cursor->image.height > MAX_CURS)
                return -ENXIO;
 
        NVShowHideCursor(par, 0);
@@ -1356,6 +1356,9 @@ static int __devinit nvidia_set_fbinfo(struct fb_info *info)
        info->pixmap.size = 8 * 1024;
        info->pixmap.flags = FB_PIXMAP_SYSTEM;
 
+       if (!hwcur)
+           info->fbops->fb_cursor = soft_cursor;
+
        info->var.accel_flags = (!noaccel);
 
        switch (par->Architecture) {
index e0dad948467b32cc921f742f5abbefb5d28b4674..2e11b601c488cb63f4e0d815f258d03cda74bf12 100644 (file)
@@ -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);
        }
index 959404ad68f433803ba06e824f5b427b4e143cb4..3c98457783c42f4caf050c9c14060bef5cb583ac 100644 (file)
@@ -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)
index d6f94742c9f27bbe49421452797d63b56a3033f2..ea17f7e0482c31be3ce8275144640a7334d769b1 100644 (file)
@@ -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;
 
index b5ca3ef8271f383c0a59b738d072fca167a182b6..7c285455c924d5c407f13b5a6b5aba55ebf6b694 100644 (file)
@@ -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:
index 1554731bd65350b2c7476992f096026a53d93b81..18121af99d3ef141cb5b641538defb6f1301c008 100644 (file)
@@ -3,6 +3,7 @@
  *
  * 9P protocol conversion functions
  *
+ *  Copyright (C) 2004, 2005 by Latchesar Ionkov <lucho@ionkov.net>
  *  Copyright (C) 2004 by Eric Van Hensbergen <ericvh@gmail.com>
  *  Copyright (C) 2002 by Ron Minnich <rminnich@lanl.gov>
  *
@@ -55,66 +56,70 @@ static inline int buf_check_overflow(struct cbuf *buf)
        return buf->p > buf->ep;
 }
 
-static inline void buf_check_size(struct cbuf *buf, int len)
+static inline int buf_check_size(struct cbuf *buf, int len)
 {
        if (buf->p+len > buf->ep) {
                if (buf->p < buf->ep) {
                        eprintk(KERN_ERR, "buffer overflow\n");
                        buf->p = buf->ep + 1;
+                       return 0;
                }
        }
+
+       return 1;
 }
 
 static inline void *buf_alloc(struct cbuf *buf, int len)
 {
        void *ret = NULL;
 
-       buf_check_size(buf, len);
-       ret = buf->p;
-       buf->p += len;
+       if (buf_check_size(buf, len)) {
+               ret = buf->p;
+               buf->p += len;
+       }
 
        return ret;
 }
 
 static inline void buf_put_int8(struct cbuf *buf, u8 val)
 {
-       buf_check_size(buf, 1);
-
-       buf->p[0] = val;
-       buf->p++;
+       if (buf_check_size(buf, 1)) {
+               buf->p[0] = val;
+               buf->p++;
+       }
 }
 
 static inline void buf_put_int16(struct cbuf *buf, u16 val)
 {
-       buf_check_size(buf, 2);
-
-       *(__le16 *) buf->p = cpu_to_le16(val);
-       buf->p += 2;
+       if (buf_check_size(buf, 2)) {
+               *(__le16 *) buf->p = cpu_to_le16(val);
+               buf->p += 2;
+       }
 }
 
 static inline void buf_put_int32(struct cbuf *buf, u32 val)
 {
-       buf_check_size(buf, 4);
-
-       *(__le32 *)buf->p = cpu_to_le32(val);
-       buf->p += 4;
+       if (buf_check_size(buf, 4)) {
+               *(__le32 *)buf->p = cpu_to_le32(val);
+               buf->p += 4;
+       }
 }
 
 static inline void buf_put_int64(struct cbuf *buf, u64 val)
 {
-       buf_check_size(buf, 8);
-
-       *(__le64 *)buf->p = cpu_to_le64(val);
-       buf->p += 8;
+       if (buf_check_size(buf, 8)) {
+               *(__le64 *)buf->p = cpu_to_le64(val);
+               buf->p += 8;
+       }
 }
 
 static inline void buf_put_stringn(struct cbuf *buf, const char *s, u16 slen)
 {
-       buf_check_size(buf, slen + 2);
-
-       buf_put_int16(buf, slen);
-       memcpy(buf->p, s, slen);
-       buf->p += slen;
+       if (buf_check_size(buf, slen + 2)) {
+               buf_put_int16(buf, slen);
+               memcpy(buf->p, s, slen);
+               buf->p += slen;
+       }
 }
 
 static inline void buf_put_string(struct cbuf *buf, const char *s)
@@ -124,20 +129,20 @@ static inline void buf_put_string(struct cbuf *buf, const char *s)
 
 static inline void buf_put_data(struct cbuf *buf, void *data, u32 datalen)
 {
-       buf_check_size(buf, datalen);
-
-       memcpy(buf->p, data, datalen);
-       buf->p += datalen;
+       if (buf_check_size(buf, datalen)) {
+               memcpy(buf->p, data, datalen);
+               buf->p += datalen;
+       }
 }
 
 static inline u8 buf_get_int8(struct cbuf *buf)
 {
        u8 ret = 0;
 
-       buf_check_size(buf, 1);
-       ret = buf->p[0];
-
-       buf->p++;
+       if (buf_check_size(buf, 1)) {
+               ret = buf->p[0];
+               buf->p++;
+       }
 
        return ret;
 }
@@ -146,10 +151,10 @@ static inline u16 buf_get_int16(struct cbuf *buf)
 {
        u16 ret = 0;
 
-       buf_check_size(buf, 2);
-       ret = le16_to_cpu(*(__le16 *)buf->p);
-
-       buf->p += 2;
+       if (buf_check_size(buf, 2)) {
+               ret = le16_to_cpu(*(__le16 *)buf->p);
+               buf->p += 2;
+       }
 
        return ret;
 }
@@ -158,10 +163,10 @@ static inline u32 buf_get_int32(struct cbuf *buf)
 {
        u32 ret = 0;
 
-       buf_check_size(buf, 4);
-       ret = le32_to_cpu(*(__le32 *)buf->p);
-
-       buf->p += 4;
+       if (buf_check_size(buf, 4)) {
+               ret = le32_to_cpu(*(__le32 *)buf->p);
+               buf->p += 4;
+       }
 
        return ret;
 }
@@ -170,10 +175,10 @@ static inline u64 buf_get_int64(struct cbuf *buf)
 {
        u64 ret = 0;
 
-       buf_check_size(buf, 8);
-       ret = le64_to_cpu(*(__le64 *)buf->p);
-
-       buf->p += 8;
+       if (buf_check_size(buf, 8)) {
+               ret = le64_to_cpu(*(__le64 *)buf->p);
+               buf->p += 8;
+       }
 
        return ret;
 }
@@ -181,27 +186,35 @@ static inline u64 buf_get_int64(struct cbuf *buf)
 static inline int
 buf_get_string(struct cbuf *buf, char *data, unsigned int datalen)
 {
+       u16 len = 0;
+
+       len = buf_get_int16(buf);
+       if (!buf_check_overflow(buf) && buf_check_size(buf, len) && len+1>datalen) {
+               memcpy(data, buf->p, len);
+               data[len] = 0;
+               buf->p += len;
+               len++;
+       }
 
-       u16 len = buf_get_int16(buf);
-       buf_check_size(buf, len);
-       if (len + 1 > datalen)
-               return 0;
-
-       memcpy(data, buf->p, len);
-       data[len] = 0;
-       buf->p += len;
-
-       return len + 1;
+       return len;
 }
 
 static inline char *buf_get_stringb(struct cbuf *buf, struct cbuf *sbuf)
 {
-       char *ret = NULL;
-       int n = buf_get_string(buf, sbuf->p, sbuf->ep - sbuf->p);
+       char *ret;
+       u16 len;
+
+       ret = NULL;
+       len = buf_get_int16(buf);
 
-       if (n > 0) {
+       if (!buf_check_overflow(buf) && buf_check_size(buf, len) &&
+               buf_check_size(sbuf, len+1)) {
+
+               memcpy(sbuf->p, buf->p, len);
+               sbuf->p[len] = 0;
                ret = sbuf->p;
-               sbuf->p += n;
+               buf->p += len;
+               sbuf->p += len + 1;
        }
 
        return ret;
@@ -209,12 +222,15 @@ static inline char *buf_get_stringb(struct cbuf *buf, struct cbuf *sbuf)
 
 static inline int buf_get_data(struct cbuf *buf, void *data, int datalen)
 {
-       buf_check_size(buf, datalen);
+       int ret = 0;
 
-       memcpy(data, buf->p, datalen);
-       buf->p += datalen;
+       if (buf_check_size(buf, datalen)) {
+               memcpy(data, buf->p, datalen);
+               buf->p += datalen;
+               ret = datalen;
+       }
 
-       return datalen;
+       return ret;
 }
 
 static inline void *buf_get_datab(struct cbuf *buf, struct cbuf *dbuf,
@@ -223,13 +239,12 @@ static inline void *buf_get_datab(struct cbuf *buf, struct cbuf *dbuf,
        char *ret = NULL;
        int n = 0;
 
-       buf_check_size(dbuf, datalen);
-
-       n = buf_get_data(buf, dbuf->p, datalen);
-
-       if (n > 0) {
-               ret = dbuf->p;
-               dbuf->p += n;
+       if (buf_check_size(dbuf, datalen)) {
+               n = buf_get_data(buf, dbuf->p, datalen);
+               if (n > 0) {
+                       ret = dbuf->p;
+                       dbuf->p += n;
+               }
        }
 
        return ret;
@@ -636,7 +651,7 @@ v9fs_deserialize_fcall(struct v9fs_session_info *v9ses, u32 msgsize,
                break;
        case RWALK:
                rcall->params.rwalk.nwqid = buf_get_int16(bufp);
-               rcall->params.rwalk.wqids = buf_alloc(bufp,
+               rcall->params.rwalk.wqids = buf_alloc(dbufp,
                      rcall->params.rwalk.nwqid * sizeof(struct v9fs_qid));
                if (rcall->params.rwalk.wqids)
                        for (i = 0; i < rcall->params.rwalk.nwqid; i++) {
index 13bdbbab4387a38809b512efb9241a2d71fd05df..82303f3bf76f786f4a939d47c60ba0cd73649a1e 100644 (file)
@@ -303,7 +303,13 @@ v9fs_session_init(struct v9fs_session_info *v9ses,
                goto SessCleanUp;
        };
 
-       v9ses->transport = trans_proto;
+       v9ses->transport = kmalloc(sizeof(*v9ses->transport), GFP_KERNEL);
+       if (!v9ses->transport) {
+               retval = -ENOMEM;
+               goto SessCleanUp;
+       }
+
+       memmove(v9ses->transport, trans_proto, sizeof(*v9ses->transport));
 
        if ((retval = v9ses->transport->init(v9ses, dev_name, data)) < 0) {
                eprintk(KERN_ERR, "problem initializing transport\n");
index 0c13fc600049dc4e3865ea0401ba92cdde3098e1..b16322db5ce6bace424d5a2fa6242636fbe4f221 100644 (file)
@@ -1063,8 +1063,8 @@ static int v9fs_vfs_readlink(struct dentry *dentry, char __user * buffer,
        int ret;
        char *link = __getname();
 
-       if (strlen(link) < buflen)
-               buflen = strlen(link);
+       if (buflen > PATH_MAX)
+               buflen = PATH_MAX;
 
        dprintk(DEBUG_VFS, " dentry: %s (%p)\n", dentry->d_iname, dentry);
 
index 868f350b2c5fa7e5666a42e69973349bcea5a6b8..1e2b2b54d300645e3f1a85fed6df339b4eb09089 100644 (file)
@@ -129,8 +129,8 @@ static struct super_block *v9fs_get_sb(struct file_system_type
 
        if ((newfid = v9fs_session_init(v9ses, dev_name, data)) < 0) {
                dprintk(DEBUG_ERROR, "problem initiating session\n");
-               retval = newfid;
-               goto free_session;
+               kfree(v9ses);
+               return ERR_PTR(newfid);
        }
 
        sb = sget(fs_type, NULL, v9fs_set_super, v9ses);
@@ -150,7 +150,7 @@ static struct super_block *v9fs_get_sb(struct file_system_type
 
        if (!root) {
                retval = -ENOMEM;
-               goto release_inode;
+               goto put_back_sb;
        }
 
        sb->s_root = root;
@@ -159,7 +159,7 @@ static struct super_block *v9fs_get_sb(struct file_system_type
        root_fid = v9fs_fid_create(root);
        if (root_fid == NULL) {
                retval = -ENOMEM;
-               goto release_dentry;
+               goto put_back_sb;
        }
 
        root_fid->fidopen = 0;
@@ -182,25 +182,15 @@ static struct super_block *v9fs_get_sb(struct file_system_type
 
        if (stat_result < 0) {
                retval = stat_result;
-               goto release_dentry;
+               goto put_back_sb;
        }
 
        return sb;
 
-      release_dentry:
-       dput(sb->s_root);
-
-      release_inode:
-       iput(inode);
-
-      put_back_sb:
+put_back_sb:
+       /* deactivate_super calls v9fs_kill_super which will frees the rest */
        up_write(&sb->s_umount);
        deactivate_super(sb);
-       v9fs_session_close(v9ses);
-
-      free_session:
-       kfree(v9ses);
-
        return ERR_PTR(retval);
 }
 
index 38f62680fd63d70c96204c658b7a7aeedda23bd5..0e11e31dbb77147078b79eaad3fc97c70b79321d 100644 (file)
--- 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);
 }
 
index 8cc23e7d0d5d34e69924e7752e3a816dd6297cfc..1ebf7dafc1d757128e4084d6a1794485399b7ecc 100644 (file)
@@ -781,6 +781,8 @@ static int cifs_oplock_thread(void * dummyarg)
 
        oplockThread = current;
        do {
+               if (try_to_freeze()) 
+                       continue;
                set_current_state(TASK_INTERRUPTIBLE);
                
                schedule_timeout(1*HZ);  
index 2335f14a15830902f1fff25c248d720cba799338..47360156cc54f40a3f9d469725c8dc19331a106f 100644 (file)
@@ -344,6 +344,8 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
        }
 
        while (server->tcpStatus != CifsExiting) {
+               if (try_to_freeze())
+                       continue;
                if (bigbuf == NULL) {
                        bigbuf = cifs_buf_get();
                        if(bigbuf == NULL) {
index ac3fb9ed8eeaf847fcd2238edb2f941d7125b7a4..a719e158e0021dd877525d2b966d458bc350aada 100644 (file)
@@ -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;
        }
index 7376b61269fb711c230ec1d0161119ce0672fc36..fb10386c59bed6b34a51af4fb930eb79c86ac586 100644 (file)
@@ -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
index 6ab1dd0ca904c4f851590cfed7dd8f6a3860e919..403b90a1213dc54757882c26434520147c2024ae 100644 (file)
@@ -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;
 }
index 14dd03907ccb58ed1b8c9cbdce76b6246d4ce727..a04a575ad433c7143dd376ab96d99ae9a782ace8 100644 (file)
--- 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;
 }
index e463dca008e4a9ad16cb54ca2dcdba7ef1793168..0213db4911a2adfcd19bb92d33dfc5b0936a192b 100644 (file)
@@ -1410,7 +1410,7 @@ unsigned long ext3_count_free_blocks(struct super_block *sb)
        unsigned long desc_count;
        struct ext3_group_desc *gdp;
        int i;
-       unsigned long ngroups;
+       unsigned long ngroups = EXT3_SB(sb)->s_groups_count;
 #ifdef EXT3FS_DEBUG
        struct ext3_super_block *es;
        unsigned long bitmap_count, x;
@@ -1421,7 +1421,8 @@ unsigned long ext3_count_free_blocks(struct super_block *sb)
        desc_count = 0;
        bitmap_count = 0;
        gdp = NULL;
-       for (i = 0; i < EXT3_SB(sb)->s_groups_count; i++) {
+
+       for (i = 0; i < ngroups; i++) {
                gdp = ext3_get_group_desc(sb, i, NULL);
                if (!gdp)
                        continue;
@@ -1443,7 +1444,6 @@ unsigned long ext3_count_free_blocks(struct super_block *sb)
        return bitmap_count;
 #else
        desc_count = 0;
-       ngroups = EXT3_SB(sb)->s_groups_count;
        smp_rmb();
        for (i = 0; i < ngroups; i++) {
                gdp = ext3_get_group_desc(sb, i, NULL);
index 2c9f81278d5dab6749ef9001a8b57808e9dfb35d..57f79106267ddde2d21ad210caf1903201c4ea31 100644 (file)
@@ -242,7 +242,7 @@ static int setup_new_group_blocks(struct super_block *sb,
             i < sbi->s_itb_per_group; i++, bit++, block++) {
                struct buffer_head *it;
 
-               ext3_debug("clear inode block %#04x (+%ld)\n", block, bit);
+               ext3_debug("clear inode block %#04lx (+%d)\n", block, bit);
                if (IS_ERR(it = bclean(handle, sb, block))) {
                        err = PTR_ERR(it);
                        goto exit_bh;
@@ -643,8 +643,8 @@ static void update_backups(struct super_block *sb,
                        break;
 
                bh = sb_getblk(sb, group * bpg + blk_off);
-               ext3_debug(sb, __FUNCTION__, "update metadata backup %#04lx\n",
-                          bh->b_blocknr);
+               ext3_debug("update metadata backup %#04lx\n",
+                         (unsigned long)bh->b_blocknr);
                if ((err = ext3_journal_get_write_access(handle, bh)))
                        break;
                lock_buffer(bh);
index a93c3609025de91984e1673610c0dcc74adfaad0..9e24ceb019fe2cea7ba9dec689006fe2cfc7d390 100644 (file)
@@ -512,15 +512,14 @@ static void ext3_clear_inode(struct inode *inode)
 
 static int ext3_show_options(struct seq_file *seq, struct vfsmount *vfs)
 {
-       struct ext3_sb_info *sbi = EXT3_SB(vfs->mnt_sb);
+       struct super_block *sb = vfs->mnt_sb;
+       struct ext3_sb_info *sbi = EXT3_SB(sb);
 
-       if (sbi->s_mount_opt & EXT3_MOUNT_JOURNAL_DATA)
+       if (test_opt(sb, DATA_FLAGS) == EXT3_MOUNT_JOURNAL_DATA)
                seq_puts(seq, ",data=journal");
-
-       if (sbi->s_mount_opt & EXT3_MOUNT_ORDERED_DATA)
+       else if (test_opt(sb, DATA_FLAGS) == EXT3_MOUNT_ORDERED_DATA)
                seq_puts(seq, ",data=ordered");
-
-       if (sbi->s_mount_opt & EXT3_MOUNT_WRITEBACK_DATA)
+       else if (test_opt(sb, DATA_FLAGS) == EXT3_MOUNT_WRITEBACK_DATA)
                seq_puts(seq, ",data=writeback");
 
 #if defined(CONFIG_QUOTA)
index 62ffa91394008e9e0af8d014d10a71108767d451..7134403d5be25546b57d5c8880b96873754b1283 100644 (file)
 #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,
index a7cbe68e22596acfcd6cf5652aa6e07e10f57a63..e2effe2dc9b2c44a7e2c07a2b6fe9b97bfbd7c2a 100644 (file)
@@ -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
 };
 
@@ -287,9 +300,9 @@ static int fat_fill_inode(struct inode *inode, struct msdos_dir_entry *de)
        inode->i_blksize = sbi->cluster_size;
        inode->i_blocks = ((inode->i_size + (sbi->cluster_size - 1))
                           & ~((loff_t)sbi->cluster_size - 1)) >> 9;
-       inode->i_mtime.tv_sec = inode->i_atime.tv_sec =
+       inode->i_mtime.tv_sec =
                date_dos2unix(le16_to_cpu(de->time), le16_to_cpu(de->date));
-       inode->i_mtime.tv_nsec = inode->i_atime.tv_nsec = 0;
+       inode->i_mtime.tv_nsec = 0;
        if (sbi->options.isvfat) {
                int secs = de->ctime_cs / 100;
                int csecs = de->ctime_cs % 100;
@@ -297,8 +310,11 @@ static int fat_fill_inode(struct inode *inode, struct msdos_dir_entry *de)
                        date_dos2unix(le16_to_cpu(de->ctime),
                                      le16_to_cpu(de->cdate)) + secs;
                inode->i_ctime.tv_nsec = csecs * 10000000;
+               inode->i_atime.tv_sec =
+                       date_dos2unix(le16_to_cpu(0), le16_to_cpu(de->adate));
+               inode->i_atime.tv_nsec = 0;
        } else
-               inode->i_ctime = inode->i_mtime;
+               inode->i_ctime = inode->i_atime = inode->i_mtime;
 
        return 0;
 }
@@ -500,7 +516,9 @@ retry:
        raw_entry->starthi = cpu_to_le16(MSDOS_I(inode)->i_logstart >> 16);
        fat_date_unix2dos(inode->i_mtime.tv_sec, &raw_entry->time, &raw_entry->date);
        if (sbi->options.isvfat) {
+               __le16 atime;
                fat_date_unix2dos(inode->i_ctime.tv_sec,&raw_entry->ctime,&raw_entry->cdate);
+               fat_date_unix2dos(inode->i_atime.tv_sec,&atime,&raw_entry->adate);
                raw_entry->ctime_cs = (inode->i_ctime.tv_sec & 1) * 100 +
                        inode->i_ctime.tv_nsec / 10000000;
        }
index 2127a7b9dc3a6ad2bb214536bf23e83d5005441b..fd066b261c751875de1c4871974b54d335eafcd7 100644 (file)
--- 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);
 }
 
index 0ec62d5310db6a78128a948fd1370159caea0b09..9f942ca8e4e3369440f408fd6b5650d1095ff5a8 100644 (file)
@@ -129,8 +129,7 @@ void jfs_delete_inode(struct inode *inode)
        jfs_info("In jfs_delete_inode, inode = 0x%p", inode);
 
        if (!is_bad_inode(inode) &&
-           (JFS_IP(inode)->fileset == cpu_to_le32(FILESYSTEM_I))) {
-
+           (JFS_IP(inode)->fileset == FILESYSTEM_I)) {
                truncate_inode_pages(&inode->i_data, 0);
 
                if (test_cflag(COMMIT_Freewmap, inode))
index c739626f5bf1181fd29920333b64f152e495d3a2..eadf319bee22a67eca765ba30c0fac74ca46d020 100644 (file)
@@ -3055,7 +3055,7 @@ static int cntlz(u32 value)
  * RETURN VALUES:
  *      log2 number of blocks
  */
-int blkstol2(s64 nb)
+static int blkstol2(s64 nb)
 {
        int l2nb;
        s64 mask;               /* meant to be signed */
index c7a92f9deb2b93c269d2b945418030f37f53ba51..9b71ed2674fea963399f615bf8b9e478b86b1e4f 100644 (file)
@@ -725,6 +725,9 @@ struct tlock *txLock(tid_t tid, struct inode *ip, struct metapage * mp,
        else
                tlck->flag = tlckINODELOCK;
 
+       if (S_ISDIR(ip->i_mode))
+               tlck->flag |= tlckDIRECTORY;
+
        tlck->type = 0;
 
        /* bind the tlock and the page */
@@ -1009,6 +1012,8 @@ struct tlock *txMaplock(tid_t tid, struct inode *ip, int type)
 
        /* bind the tlock and the object */
        tlck->flag = tlckINODELOCK;
+       if (S_ISDIR(ip->i_mode))
+               tlck->flag |= tlckDIRECTORY;
        tlck->ip = ip;
        tlck->mp = NULL;
 
@@ -1077,6 +1082,8 @@ struct linelock *txLinelock(struct linelock * tlock)
        linelock->flag = tlckLINELOCK;
        linelock->maxcnt = TLOCKLONG;
        linelock->index = 0;
+       if (tlck->flag & tlckDIRECTORY)
+               linelock->flag |= tlckDIRECTORY;
 
        /* append linelock after tlock */
        linelock->next = tlock->next;
@@ -2070,8 +2077,8 @@ static void xtLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd,
  *
  * function:    log from maplock of freed data extents;
  */
-void mapLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd,
-           struct tlock * tlck)
+static void mapLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd,
+                  struct tlock * tlck)
 {
        struct pxd_lock *pxdlock;
        int i, nlock;
@@ -2209,7 +2216,7 @@ void txEA(tid_t tid, struct inode *ip, dxd_t * oldea, dxd_t * newea)
  * function: synchronously write pages locked by transaction
  *              after txLog() but before txUpdateMap();
  */
-void txForce(struct tblock * tblk)
+static void txForce(struct tblock * tblk)
 {
        struct tlock *tlck;
        lid_t lid, next;
@@ -2358,7 +2365,7 @@ static void txUpdateMap(struct tblock * tblk)
                         */
                        else {  /* (maplock->flag & mlckFREE) */
 
-                               if (S_ISDIR(tlck->ip->i_mode))
+                               if (tlck->flag & tlckDIRECTORY)
                                        txFreeMap(ipimap, maplock,
                                                  tblk, COMMIT_PWMAP);
                                else
index 59ad0f6b723186a6f4a1cb6d0eda5e038bebf936..0e4dc4514c47a4953420fa1cb1f9201b19ca6da1 100644 (file)
@@ -122,6 +122,7 @@ extern struct tlock *TxLock;        /* transaction lock table */
 #define tlckLOG                        0x0800
 /* updateMap state */
 #define        tlckUPDATEMAP           0x0080
+#define        tlckDIRECTORY           0x0040
 /* freeLock state */
 #define tlckFREELOCK           0x0008
 #define tlckWRITEPAGE          0x0004
index c2c09b4798d606b4bc9e5d56a518beef021543f3..f7daa5f48949c41ea02b687e1521a440387b0592 100644 (file)
 #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);
index 21d85f1ac8395f82376e2dd5073494d568080e78..043d587216b5a3f3354a75878827df61956facc4 100644 (file)
@@ -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;
 }
 
index 6ceb1d471f2064952d8b4727a28711e821f5aba9..9758ebd49905a704146fffc23443890b38b8e318 100644 (file)
@@ -184,14 +184,13 @@ static void nfs_readpage_release(struct nfs_page *req)
 {
        unlock_page(req->wb_page);
 
-       nfs_clear_request(req);
-       nfs_release_request(req);
-
        dprintk("NFS: read done (%s/%Ld %d@%Ld)\n",
                        req->wb_context->dentry->d_inode->i_sb->s_id,
                        (long long)NFS_FILEID(req->wb_context->dentry->d_inode),
                        req->wb_bytes,
                        (long long)req_offset(req));
+       nfs_clear_request(req);
+       nfs_release_request(req);
 }
 
 /*
index e08edc17c6a038d7f78791c2f7d175e729ec903b..361b4007d4a00867059e885855e26549ea702da3 100644 (file)
@@ -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);
index b83f8fb441e15328ed9cff30099a7f637151124d..6bbefd06f10dea127ee0bf406eb1ef01fcfd4247 100644 (file)
@@ -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();
 
index 49eafbdb15c145e1884945e8aae5e1a74d0e3ed0..c7e9237379c233bae7d99490ec6f637a7233221b 100644 (file)
@@ -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...
index b6cc8cf24626b0a1f15ec8deffddc704da797c0e..5e80c07c6a4d2b0a9c141602efeac6f9b5b59614 100644 (file)
@@ -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);
index dc4bbe3acf5cd2b66e60da0aa488fdb5e5833886..7ec045131808b14546333a16009746729a2d236d 100644 (file)
@@ -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 "
index 3288bcc2c4aa162190316277f9c6aefa4f128216..006946efca8cf158daf7108a368a9b180cfa792d 100644 (file)
@@ -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
index f5b2ac929081eb16c1f3bc0b83c3af295d240264..061b5ff6b73cec10f317f566cd3dc6fa8512e9d9 100644 (file)
@@ -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
@@ -158,17 +158,21 @@ static inline BOOL ntfs_are_rl_mergeable(runlist_element *dst,
        BUG_ON(!dst);
        BUG_ON(!src);
 
-       if ((dst->lcn < 0) || (src->lcn < 0)) {   /* Are we merging holes? */
-               if (dst->lcn == LCN_HOLE && src->lcn == LCN_HOLE)
-                       return TRUE;
+       /* We can merge unmapped regions even if they are misaligned. */
+       if ((dst->lcn == LCN_RL_NOT_MAPPED) && (src->lcn == LCN_RL_NOT_MAPPED))
+               return TRUE;
+       /* If the runs are misaligned, we cannot merge them. */
+       if ((dst->vcn + dst->length) != src->vcn)
                return FALSE;
-       }
-       if ((dst->lcn + dst->length) != src->lcn) /* Are the runs contiguous? */
-               return FALSE;
-       if ((dst->vcn + dst->length) != src->vcn) /* Are the runs misaligned? */
-               return FALSE;
-
-       return TRUE;
+       /* If both runs are non-sparse and contiguous, we can merge them. */
+       if ((dst->lcn >= 0) && (src->lcn >= 0) &&
+                       ((dst->lcn + dst->length) == src->lcn))
+               return TRUE;
+       /* If we are merging two holes, we can merge them. */
+       if ((dst->lcn == LCN_HOLE) && (src->lcn == LCN_HOLE))
+               return TRUE;
+       /* Cannot merge. */
+       return FALSE;
 }
 
 /**
@@ -214,14 +218,15 @@ 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 = FALSE;     /* Right end of @src needs merging. */
+       int marker;             /* End of the inserted runs. */
 
        BUG_ON(!dst);
        BUG_ON(!src);
 
        /* First, check if the right hand end needs merging. */
-       right = ntfs_are_rl_mergeable(src + ssize - 1, dst + loc + 1);
+       if ((loc + 1) < dsize)
+               right = ntfs_are_rl_mergeable(src + ssize - 1, dst + loc + 1);
 
        /* Space required: @dst size + @src size, less one if we merged. */
        dst = ntfs_rl_realloc(dst, dsize, dsize + ssize - right);
@@ -236,18 +241,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 +285,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 +308,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,20 +381,23 @@ 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 = FALSE;     /* 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);
 
-       /* First, merge the left and right ends, if necessary. */
-       right = ntfs_are_rl_mergeable(src + ssize - 1, dst + loc + 1);
+       /* First, see if the left and right ends need merging. */
+       if ((loc + 1) < dsize)
+               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 get merged.
+        */
        dst = ntfs_rl_realloc(dst, dsize, dsize + ssize - left - right);
        if (IS_ERR(dst))
                return dst;
@@ -406,21 +405,37 @@ static inline runlist_element *ntfs_rl_replace(runlist_element *dst,
         * We are guaranteed to succeed from here so can start modifying the
         * original runlists.
         */
+
+       /* First, merge the left and right ends, if necessary. */
        if (right)
                __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;
+       /*
+        * Offset of the tail of @dst.  This 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.
+        * Nominally, @tail equals @loc + 1, i.e. location, skipping the
+        * replaced run.  However, if @right, then one of @dst's runs is
+        * already merged into @src.
+        */
+       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;
 }
 
index 2fac58c51910cf250607a8f7161edc608d8c18cc..f0d90cf0495c490316d427e309c38695ceb4e005 100644 (file)
--- 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);
 
 /*
index d88d518d30f605d216ba292e20be281cacf0eab4..d84eecacbeaff81b91cb4ed43d65c2b6e418c163 100644 (file)
@@ -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);
index 23db452ab428c9896a96aad29217100e67aeb78a..3b33f94020db827f6563ec5f978165d4711dc907 100644 (file)
@@ -340,6 +340,54 @@ static int proc_root_link(struct inode *inode, struct dentry **dentry, struct vf
        return result;
 }
 
+
+/* Same as proc_root_link, but this addionally tries to get fs from other
+ * threads in the group */
+static int proc_task_root_link(struct inode *inode, struct dentry **dentry,
+                               struct vfsmount **mnt)
+{
+       struct fs_struct *fs;
+       int result = -ENOENT;
+       struct task_struct *leader = proc_task(inode);
+
+       task_lock(leader);
+       fs = leader->fs;
+       if (fs) {
+               atomic_inc(&fs->count);
+               task_unlock(leader);
+       } else {
+               /* Try to get fs from other threads */
+               task_unlock(leader);
+               read_lock(&tasklist_lock);
+               if (pid_alive(leader)) {
+                       struct task_struct *task = leader;
+
+                       while ((task = next_thread(task)) != leader) {
+                               task_lock(task);
+                               fs = task->fs;
+                               if (fs) {
+                                       atomic_inc(&fs->count);
+                                       task_unlock(task);
+                                       break;
+                               }
+                               task_unlock(task);
+                       }
+               }
+               read_unlock(&tasklist_lock);
+       }
+
+       if (fs) {
+               read_lock(&fs->lock);
+               *mnt = mntget(fs->rootmnt);
+               *dentry = dget(fs->root);
+               read_unlock(&fs->lock);
+               result = 0;
+               put_fs_struct(fs);
+       }
+       return result;
+}
+
+
 #define MAY_PTRACE(task) \
        (task == current || \
        (task->parent == current && \
@@ -471,14 +519,14 @@ static int proc_oom_score(struct task_struct *task, char *buffer)
 
 /* permission checks */
 
-static int proc_check_root(struct inode *inode)
+/* If the process being read is separated by chroot from the reading process,
+ * don't let the reader access the threads.
+ */
+static int proc_check_chroot(struct dentry *root, struct vfsmount *vfsmnt)
 {
-       struct dentry *de, *base, *root;
-       struct vfsmount *our_vfsmnt, *vfsmnt, *mnt;
+       struct dentry *de, *base;
+       struct vfsmount *our_vfsmnt, *mnt;
        int res = 0;
-
-       if (proc_root_link(inode, &root, &vfsmnt)) /* Ewww... */
-               return -ENOENT;
        read_lock(&current->fs->lock);
        our_vfsmnt = mntget(current->fs->rootmnt);
        base = dget(current->fs->root);
@@ -511,6 +559,16 @@ out:
        goto exit;
 }
 
+static int proc_check_root(struct inode *inode)
+{
+       struct dentry *root;
+       struct vfsmount *vfsmnt;
+
+       if (proc_root_link(inode, &root, &vfsmnt)) /* Ewww... */
+               return -ENOENT;
+       return proc_check_chroot(root, vfsmnt);
+}
+
 static int proc_permission(struct inode *inode, int mask, struct nameidata *nd)
 {
        if (generic_permission(inode, mask, NULL) != 0)
@@ -518,6 +576,20 @@ static int proc_permission(struct inode *inode, int mask, struct nameidata *nd)
        return proc_check_root(inode);
 }
 
+static int proc_task_permission(struct inode *inode, int mask, struct nameidata *nd)
+{
+       struct dentry *root;
+       struct vfsmount *vfsmnt;
+
+       if (generic_permission(inode, mask, NULL) != 0)
+               return -EACCES;
+
+       if (proc_task_root_link(inode, &root, &vfsmnt))
+               return -ENOENT;
+
+       return proc_check_chroot(root, vfsmnt);
+}
+
 extern struct seq_operations proc_pid_maps_op;
 static int maps_open(struct inode *inode, struct file *file)
 {
@@ -1419,7 +1491,7 @@ static struct inode_operations proc_fd_inode_operations = {
 
 static struct inode_operations proc_task_inode_operations = {
        .lookup         = proc_task_lookup,
-       .permission     = proc_permission,
+       .permission     = proc_task_permission,
 };
 
 #ifdef CONFIG_SECURITY
index c9f178fb494f511207ca93b982e599f62d7f481d..c20babd6216d970bdb1fbf2c879cab4de7341d2f 100644 (file)
@@ -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);
index 1a8a1bf2154d10475a0bacc89b085070587d48d6..d76ee6c4f9b8874f1a26acdaa37a9fe9d693e490 100644 (file)
@@ -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;
 
index 399c33b7be5112732a4f1f31d2d401a696df511e..0a4a8b40dfcd7a623e6ad0f95c3c3d4a7e969a76 100644 (file)
@@ -98,6 +98,9 @@
 #undef inline
 #undef __inline__
 #undef __inline
-
+#if __GNUC__ == 3 && __GNUC_MINOR__ >= 1 || __GNUC__ > 3
+#undef __always_inline
+#define __always_inline                inline __attribute__((always_inline))
+#endif
 
 #endif /* __ALPHA_COMPILER_H */
index 2cac5ecd9d00b07132c0d4706141e0c342c0e4ac..9feff4ce1424bc390608326240be369eb13aa648 100644 (file)
@@ -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;
 
index 22b53e369f5999632f19924aa4c620139c694b61..8393bf374b2b59c85bd90c60440322bacd4c8426 100644 (file)
@@ -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)
 
index 681b6a6171a1cc3993fc32d458233824541444a1..79c90813bc3e6ff765f1a0776db126f3f5d981d0 100644 (file)
 #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 */
index dc4735cb0c10402273d8815578269e52ebcf278b..45351f5cd904ec1d4714faa8810136e2656c46f6 100644 (file)
@@ -36,6 +36,4 @@
 
 #endif
 
-#define PFN_TO_NID(addr)       (0)
-
 #endif
index 75623f81ef75492801108bb895f745fdbdb962e4..32aece069869b52c0aede2617fdbec8ee898fda1 100644 (file)
 #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
index c0caf3e3e6fd78d32118836e7f82927dc413e33a..abdcf51bd28374e3a6a06eca20709fc84e541ba7 100644 (file)
 
 #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 ==
index 7e2fea372663b358a0520ad39cc9121786ee2322..c650e6feb9d5d490e231f8da974a2d68a89cbc84 100644 (file)
        (((unsigned long)(addr) & 0x01ffffff) >> PAGE_SHIFT)
 # endif
 
-#else
-
-# define PFN_TO_NID(addr)      (0)
-
 #endif
 
 #endif
index 84f81e315a25da0aa010154473dfbc272e1cfd8c..ef32d61eec7a20e8de6f8d0e170cadc74a06cfee 100644 (file)
@@ -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 (file)
index 0000000..4a1fbcf
--- /dev/null
@@ -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);
+
index 4b7aa0b8391e0741aab1fcee845ff1cc919421e1..e554caa0d18b02030fb87bae0048c7fc0e257f11 100644 (file)
@@ -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  */
 
index 217a80b820ff8290520083fb33ee7d08d9c85e23..58bad9748b5c4075400b297ca2a13bfd74a89b50 100644 (file)
 #define LOCAL_MAP_NR(addr) \
        (((unsigned long)(addr) & 0x03ffffff) >> PAGE_SHIFT)
 
-#else
-
-#define PFN_TO_NID(addr)       (0)
-
 #endif
 
 #endif
index 58bda9d571a5ae6cfab28cdcf61fe94692f0bb1d..6b5ac5144e70e56e447fd534a17776d3a021ed96 100644 (file)
 #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 (file)
index 0000000..311f2bb
--- /dev/null
@@ -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 (file)
index 0000000..62e1fe4
--- /dev/null
@@ -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);
index 32d3d5bde34db286224f3e6817081eaaf291e585..8743ff5c1b233f12d763e54ef501b2090c0f5984 100644 (file)
@@ -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
index 2cac5ecd9d00b07132c0d4706141e0c342c0e4ac..9feff4ce1424bc390608326240be369eb13aa648 100644 (file)
@@ -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 (file)
index 0000000..131d5b4
--- /dev/null
@@ -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
index 56c6bf4ab0c3932de2f650cb5c29cafeae0efc9c..4fa95084a8c0459f58b87a9e36f75019069fb0c6 100644 (file)
@@ -50,7 +50,7 @@ struct machine_desc {
  */
 #define MACHINE_START(_type,_name)             \
 const struct machine_desc __mach_desc_##_type  \
- __attribute__((__section__(".arch.info"))) = {        \
+ __attribute__((__section__(".arch.info.init"))) = {   \
        .nr             = MACH_TYPE_##_type,    \
        .name           = _name,
 
index e47bea7d17237de5a0cf86d998ff684ec5a5d8e7..a8a933a775db497931acd58422376a6ce6128b3e 100644 (file)
@@ -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)
 
 /*
index 478c49b56e18d0fa3658eeb7c5a7d25c86f53de6..366bafbdfbb1b9c26270059afa968d2167c221f7 100644 (file)
@@ -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)
 
index adcbd79762bfa2138d6c38400e9ce8db47a05679..ea3ed24652333e8dbcc3020074a626050895ed84 100644 (file)
@@ -171,7 +171,7 @@ struct tagtable {
        int (*parse)(const struct tag *);
 };
 
-#define __tag __attribute_used__ __attribute__((__section__(".taglist")))
+#define __tag __attribute_used__ __attribute__((__section__(".taglist.init")))
 #define __tagtable(tag, fn) \
 static struct tagtable __tagtable_##fn __tag = { tag, fn }
 
@@ -213,6 +213,6 @@ struct early_params {
 
 #define __early_param(name,fn)                                 \
 static struct early_params __early_##fn __attribute_used__     \
-__attribute__((__section__("__early_param"))) = { name, fn }
+__attribute__((__section__(".early_param.init"))) = { name, fn }
 
 #endif
index 2cac5ecd9d00b07132c0d4706141e0c342c0e4ac..9feff4ce1424bc390608326240be369eb13aa648 100644 (file)
@@ -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;
 
index 4a0a00da425f3886d01ed24be565188f96a89cb7..f602cf57241131cfc7c84fb66348e267cd04b20f 100644 (file)
@@ -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)
 
index 2cac5ecd9d00b07132c0d4706141e0c342c0e4ac..9feff4ce1424bc390608326240be369eb13aa648 100644 (file)
@@ -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;
 
index 2cac5ecd9d00b07132c0d4706141e0c342c0e4ac..9feff4ce1424bc390608326240be369eb13aa648 100644 (file)
@@ -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;
 
index d0a9c2f9c13ece32a626044df2b730f0e6cac275..473fb4bb6329838a8ece91c055b6b2d67efb38db 100644 (file)
@@ -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)
 
index 2cac5ecd9d00b07132c0d4706141e0c342c0e4ac..9feff4ce1424bc390608326240be369eb13aa648 100644 (file)
@@ -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;
 
index 69076eb3147600af035fbdfcfcbe024d88a61b2b..f6e296fc1297da57e448851613fc11542bd566fc 100644 (file)
@@ -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)
index 44b9db806474b9faabf19d9b6323b23279b4d0c6..e7a271d393099b3909cc329bf9fa90bbd2bb7e04 100644 (file)
@@ -61,7 +61,7 @@ futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
        if (op == FUTEX_OP_SET)
                __futex_atomic_op1("xchgl %0, %2", ret, oldval, uaddr, oparg);
        else {
-#ifndef CONFIG_X86_BSWAP
+#if !defined(CONFIG_X86_BSWAP) && !defined(CONFIG_UML)
                if (boot_cpu_data.x86 == 3)
                        ret = -ENOSYS;
                else
index 47bc1ffa3d4cfb42321cec3bf25d9da23ccc8486..d101ac414f074e308d6dfe182f7d190186cd429a 100644 (file)
@@ -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)
 
index 2cac5ecd9d00b07132c0d4706141e0c342c0e4ac..9feff4ce1424bc390608326240be369eb13aa648 100644 (file)
@@ -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;
 
index 97a28b8b2dddd98028b3ccfca697c1f42338313f..c7d9c9ed38baa518392cf9adcded3b90a299551e 100644 (file)
@@ -80,7 +80,12 @@ struct ia64_sal_os_state {
        u64                     sal_ra;                 /* Return address in SAL, physical */
        u64                     sal_gp;                 /* GP of the SAL - physical */
        pal_min_state_area_t    *pal_min_state;         /* from R17.  physical in asm, virtual in C */
+       /* Previous values of IA64_KR(CURRENT) and IA64_KR(CURRENT_STACK).
+        * Note: if the MCA/INIT recovery code wants to resume to a new context
+        * then it must change these values to reflect the new kernel stack.
+        */
        u64                     prev_IA64_KR_CURRENT;   /* previous value of IA64_KR(CURRENT) */
+       u64                     prev_IA64_KR_CURRENT_STACK;
        struct task_struct      *prev_task;             /* previous task, NULL if it is not useful */
        /* Some interrupt registers are not saved in minstate, pt_regs or
         * switch_stack.  Because MCA/INIT can occur when interrupts are
index 2e34c06e677795268249609786ceb012e81e4f84..3339c7b55a6f69bf534620c45f7cfc6599a25bce 100644 (file)
@@ -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)
 
index fc544929ac34f6bdbed78f489a2aca5f7b024d57..a79d1a7ecc77e758c1e187facf736b1e39441fbb 100644 (file)
@@ -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
index cf4a950a0f4f0c367b05954adde90cab4574fe7c..171b2207bde4e70a9936a19a56899eca95962a6d 100644 (file)
@@ -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
index 2cac5ecd9d00b07132c0d4706141e0c342c0e4ac..9feff4ce1424bc390608326240be369eb13aa648 100644 (file)
@@ -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;
 
index da805e970844a1d9dab8210062e8c67cb5ac8805..388e5ee9fa2717e7bd3d7117a6aaa2d773d89597 100644 (file)
@@ -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)
 
index 2cac5ecd9d00b07132c0d4706141e0c342c0e4ac..9feff4ce1424bc390608326240be369eb13aa648 100644 (file)
@@ -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;
 
index 0c87fc84f7a4ee20b44453202d430e2428e3db16..add129e93fd7076a5fadcf27134e5c71111b801f 100644 (file)
@@ -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)
 
index 2cac5ecd9d00b07132c0d4706141e0c342c0e4ac..9feff4ce1424bc390608326240be369eb13aa648 100644 (file)
@@ -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;
 
index e2a69fffa3708c6a4f15c306f8c41e22d4be9a09..00893055e6c2c89669859082d19f6163a7298215 100644 (file)
@@ -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)
index dbe13da0bdadbe55affd38c3999ed4e0eb04593b..cbd1672c94cb366db294898d470704c2707ac49d 100644 (file)
@@ -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
index 2cac5ecd9d00b07132c0d4706141e0c342c0e4ac..9feff4ce1424bc390608326240be369eb13aa648 100644 (file)
@@ -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;
 
index f001bb01e38f277a3210a7a19ee08d4bf1aabfca..820c6e712cd7b863a0f30460cdc349da2b77072f 100644 (file)
@@ -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)
 
index 2cac5ecd9d00b07132c0d4706141e0c342c0e4ac..9feff4ce1424bc390608326240be369eb13aa648 100644 (file)
@@ -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;
 
index 55752474d0d9471ec28da282b5ed9024dd699f5c..bd9674807f05839b1c14c4970600e88192c63676 100644 (file)
@@ -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.
index a481b772d1548259235bfd27a79061d94f3864c8..b553dd4b139ef21c2bfb08481209a071ccf0f750 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef __MACIO_ASIC_H__
 #define __MACIO_ASIC_H__
 
-#include <linux/mod_devicetable.h>
 #include <asm/of_device.h>
 
 extern struct bus_type macio_bus_type;
index dc8e59896050150b7b488708517aca0209ec7dd4..208a2e11daee22f29c88c86b5b047cfc47c51c88 100644 (file)
@@ -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 */
index 835930d6faa1bf54c2a4c71d5138a03730610183..75c2ffa26b26d5b22a1dffcc78a1731361001b7a 100644 (file)
@@ -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.
index 4b264cfd39987cb368843ae346199c6cf2822e97..575bce418f802dd860ccdb8e3422330e60fbb8c0 100644 (file)
@@ -2,6 +2,7 @@
 #define __OF_DEVICE_H__
 
 #include <linux/device.h>
+#include <linux/mod_devicetable.h>
 #include <asm/prom.h>
 
 /*
@@ -55,7 +56,9 @@ extern int of_register_driver(struct of_platform_driver *drv);
 extern void of_unregister_driver(struct of_platform_driver *drv);
 extern int of_device_register(struct of_device *ofdev);
 extern void of_device_unregister(struct of_device *ofdev);
-extern struct of_device *of_platform_device_create(struct device_node *np, const char *bus_id);
+extern struct of_device *of_platform_device_create(struct device_node *np,
+                                                  const char *bus_id,
+                                                  struct device *parent);
 extern void of_release_dev(struct device *dev);
 
 #endif /* __OF_DEVICE_H__ */
index 92f30b28b252e1ab38c78d3727d99e2317dcefd5..eee601bb9ada6fbcedcb954a9715bc9b8a681a29 100644 (file)
@@ -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
index 048f7c8596eefb3e5042db3bfc9449dbac3009f5..549f44843c5ebfbb59e8a8b7d98ff5522881524d 100644 (file)
@@ -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 (file)
index 0f2f742..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm/uaccess.h>
index 9850f53f54b047b52d1f303df65b0ab79b9f36ce..9afee4ffc83503da7591aad0c00f5484ba941ae5 100644 (file)
@@ -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,
index 10b4397af9aa4926a91f9a1d97ddbd8f25634235..dee8eefe47bc88bc038991527668c170c4e1215c 100644 (file)
+#ifndef _SMU_H
+#define _SMU_H
+
 /*
  * Definitions for talking to the SMU chip in newer G5 PowerMacs
  */
 
 #include <linux/config.h>
+#include <linux/list.h>
+
+/*
+ * Known SMU commands
+ *
+ * Most of what is below comes from looking at the Open Firmware driver,
+ * though this is still incomplete and could use better documentation here
+ * or there...
+ */
+
+
+/*
+ * Partition info commands
+ *
+ * I do not know what those are for at this point
+ */
+#define SMU_CMD_PARTITION_COMMAND              0x3e
+
+
+/*
+ * Fan control
+ *
+ * This is a "mux" for fan control commands, first byte is the
+ * "sub" command.
+ */
+#define SMU_CMD_FAN_COMMAND                    0x4a
+
+
+/*
+ * Battery access
+ *
+ * Same command number as the PMU, could it be same syntax ?
+ */
+#define SMU_CMD_BATTERY_COMMAND                        0x6f
+#define   SMU_CMD_GET_BATTERY_INFO             0x00
+
+/*
+ * Real time clock control
+ *
+ * This is a "mux", first data byte contains the "sub" command.
+ * The "RTC" part of the SMU controls the date, time, powerup
+ * timer, but also a PRAM
+ *
+ * Dates are in BCD format on 7 bytes:
+ * [sec] [min] [hour] [weekday] [month day] [month] [year]
+ * with month being 1 based and year minus 100
+ */
+#define SMU_CMD_RTC_COMMAND                    0x8e
+#define   SMU_CMD_RTC_SET_PWRUP_TIMER          0x00 /* i: 7 bytes date */
+#define   SMU_CMD_RTC_GET_PWRUP_TIMER          0x01 /* o: 7 bytes date */
+#define   SMU_CMD_RTC_STOP_PWRUP_TIMER         0x02
+#define   SMU_CMD_RTC_SET_PRAM_BYTE_ACC                0x20 /* i: 1 byte (address?) */
+#define   SMU_CMD_RTC_SET_PRAM_AUTOINC         0x21 /* i: 1 byte (data?) */
+#define   SMU_CMD_RTC_SET_PRAM_LO_BYTES        0x22 /* i: 10 bytes */
+#define   SMU_CMD_RTC_SET_PRAM_HI_BYTES        0x23 /* i: 10 bytes */
+#define   SMU_CMD_RTC_GET_PRAM_BYTE            0x28 /* i: 1 bytes (address?) */
+#define   SMU_CMD_RTC_GET_PRAM_LO_BYTES        0x29 /* o: 10 bytes */
+#define   SMU_CMD_RTC_GET_PRAM_HI_BYTES        0x2a /* o: 10 bytes */
+#define          SMU_CMD_RTC_SET_DATETIME              0x80 /* i: 7 bytes date */
+#define   SMU_CMD_RTC_GET_DATETIME             0x81 /* o: 7 bytes date */
+
+ /*
+  * i2c commands
+  *
+  * To issue an i2c command, first is to send a parameter block to the
+  * the SMU. This is a command of type 0x9a with 9 bytes of header
+  * eventually followed by data for a write:
+  *
+  * 0: bus number (from device-tree usually, SMU has lots of busses !)
+  * 1: transfer type/format (see below)
+  * 2: device address. For combined and combined4 type transfers, this
+  *    is the "write" version of the address (bit 0x01 cleared)
+  * 3: subaddress length (0..3)
+  * 4: subaddress byte 0 (or only byte for subaddress length 1)
+  * 5: subaddress byte 1
+  * 6: subaddress byte 2
+  * 7: combined address (device address for combined mode data phase)
+  * 8: data length
+  *
+  * The transfer types are the same good old Apple ones it seems,
+  * that is:
+  *   - 0x00: Simple transfer
+  *   - 0x01: Subaddress transfer (addr write + data tx, no restart)
+  *   - 0x02: Combined transfer (addr write + restart + data tx)
+  *
+  * This is then followed by actual data for a write.
+  *
+  * At this point, the OF driver seems to have a limitation on transfer
+  * sizes of 0xd bytes on reads and 0x5 bytes on writes. I do not know
+  * wether this is just an OF limit due to some temporary buffer size
+  * or if this is an SMU imposed limit. This driver has the same limitation
+  * for now as I use a 0x10 bytes temporary buffer as well
+  *
+  * Once that is completed, a response is expected from the SMU. This is
+  * obtained via a command of type 0x9a with a length of 1 byte containing
+  * 0 as the data byte. OF also fills the rest of the data buffer with 0xff's
+  * though I can't tell yet if this is actually necessary. Once this command
+  * is complete, at this point, all I can tell is what OF does. OF tests
+  * byte 0 of the reply:
+  *   - on read, 0xfe or 0xfc : bus is busy, wait (see below) or nak ?
+  *   - on read, 0x00 or 0x01 : reply is in buffer (after the byte 0)
+  *   - on write, < 0 -> failure (immediate exit)
+  *   - else, OF just exists (without error, weird)
+  *
+  * So on read, there is this wait-for-busy thing when getting a 0xfc or
+  * 0xfe result. OF does a loop of up to 64 retries, waiting 20ms and
+  * doing the above again until either the retries expire or the result
+  * is no longer 0xfe or 0xfc
+  *
+  * The Darwin I2C driver is less subtle though. On any non-success status
+  * from the response command, it waits 5ms and tries again up to 20 times,
+  * it doesn't differenciate between fatal errors or "busy" status.
+  *
+  * This driver provides an asynchronous paramblock based i2c command
+  * interface to be used either directly by low level code or by a higher
+  * level driver interfacing to the linux i2c layer. The current
+  * implementation of this relies on working timers & timer interrupts
+  * though, so be careful of calling context for now. This may be "fixed"
+  * in the future by adding a polling facility.
+  */
+#define SMU_CMD_I2C_COMMAND                    0x9a
+          /* transfer types */
+#define   SMU_I2C_TRANSFER_SIMPLE      0x00
+#define   SMU_I2C_TRANSFER_STDSUB      0x01
+#define   SMU_I2C_TRANSFER_COMBINED    0x02
+
+/*
+ * Power supply control
+ *
+ * The "sub" command is an ASCII string in the data, the
+ * data lenght is that of the string.
+ *
+ * The VSLEW command can be used to get or set the voltage slewing.
+ *  - lenght 5 (only "VSLEW") : it returns "DONE" and 3 bytes of
+ *    reply at data offset 6, 7 and 8.
+ *  - lenght 8 ("VSLEWxyz") has 3 additional bytes appended, and is
+ *    used to set the voltage slewing point. The SMU replies with "DONE"
+ * I yet have to figure out their exact meaning of those 3 bytes in
+ * both cases.
+ *
+ */
+#define SMU_CMD_POWER_COMMAND                  0xaa
+#define   SMU_CMD_POWER_RESTART                        "RESTART"
+#define   SMU_CMD_POWER_SHUTDOWN               "SHUTDOWN"
+#define   SMU_CMD_POWER_VOLTAGE_SLEW           "VSLEW"
+
+/* Misc commands
+ *
+ * This command seem to be a grab bag of various things
+ */
+#define SMU_CMD_MISC_df_COMMAND                        0xdf
+#define   SMU_CMD_MISC_df_SET_DISPLAY_LIT      0x02 /* i: 1 byte */
+#define   SMU_CMD_MISC_df_NMI_OPTION           0x04
+
+/*
+ * Version info commands
+ *
+ * I haven't quite tried to figure out how these work
+ */
+#define SMU_CMD_VERSION_COMMAND                        0xea
+
+
+/*
+ * Misc commands
+ *
+ * This command seem to be a grab bag of various things
+ */
+#define SMU_CMD_MISC_ee_COMMAND                        0xee
+#define   SMU_CMD_MISC_ee_GET_DATABLOCK_REC    0x02
+#define          SMU_CMD_MISC_ee_LEDS_CTRL             0x04 /* i: 00 (00,01) [00] */
+#define   SMU_CMD_MISC_ee_GET_DATA             0x05 /* i: 00 , o: ?? */
+
+
+
+/*
+ * - Kernel side interface -
+ */
+
+#ifdef __KERNEL__
+
+/*
+ * Asynchronous SMU commands
+ *
+ * Fill up this structure and submit it via smu_queue_command(),
+ * and get notified by the optional done() callback, or because
+ * status becomes != 1
+ */
+
+struct smu_cmd;
+
+struct smu_cmd
+{
+       /* public */
+       u8                      cmd;            /* command */
+       int                     data_len;       /* data len */
+       int                     reply_len;      /* reply len */
+       void                    *data_buf;      /* data buffer */
+       void                    *reply_buf;     /* reply buffer */
+       int                     status;         /* command status */
+       void                    (*done)(struct smu_cmd *cmd, void *misc);
+       void                    *misc;
+
+       /* private */
+       struct list_head        link;
+};
+
+/*
+ * Queues an SMU command, all fields have to be initialized
+ */
+extern int smu_queue_cmd(struct smu_cmd *cmd);
+
+/*
+ * Simple command wrapper. This structure embeds a small buffer
+ * to ease sending simple SMU commands from the stack
+ */
+struct smu_simple_cmd
+{
+       struct smu_cmd  cmd;
+       u8              buffer[16];
+};
+
+/*
+ * Queues a simple command. All fields will be initialized by that
+ * function
+ */
+extern int smu_queue_simple(struct smu_simple_cmd *scmd, u8 command,
+                           unsigned int data_len,
+                           void (*done)(struct smu_cmd *cmd, void *misc),
+                           void *misc,
+                           ...);
+
+/*
+ * Completion helper. Pass it to smu_queue_simple or as 'done'
+ * member to smu_queue_cmd, it will call complete() on the struct
+ * completion passed in the "misc" argument
+ */
+extern void smu_done_complete(struct smu_cmd *cmd, void *misc);
 
 /*
- * Basic routines for use by architecture. To be extended as
- * we understand more of the chip
+ * Synchronous helpers. Will spin-wait for completion of a command
+ */
+extern void smu_spinwait_cmd(struct smu_cmd *cmd);
+
+static inline void smu_spinwait_simple(struct smu_simple_cmd *scmd)
+{
+       smu_spinwait_cmd(&scmd->cmd);
+}
+
+/*
+ * Poll routine to call if blocked with irqs off
+ */
+extern void smu_poll(void);
+
+
+/*
+ * Init routine, presence check....
  */
 extern int smu_init(void);
 extern int smu_present(void);
+struct of_device;
+extern struct of_device *smu_get_ofdev(void);
+
+
+/*
+ * Common command wrappers
+ */
 extern void smu_shutdown(void);
 extern void smu_restart(void);
-extern int smu_get_rtc_time(struct rtc_time *time);
-extern int smu_set_rtc_time(struct rtc_time *time);
+struct rtc_time;
+extern int smu_get_rtc_time(struct rtc_time *time, int spinwait);
+extern int smu_set_rtc_time(struct rtc_time *time, int spinwait);
 
 /*
  * SMU command buffer absolute address, exported by pmac_setup,
  * this is allocated very early during boot.
  */
 extern unsigned long smu_cmdbuf_abs;
+
+
+/*
+ * Kenrel asynchronous i2c interface
+ */
+
+/* SMU i2c header, exactly matches i2c header on wire */
+struct smu_i2c_param
+{
+       u8      bus;            /* SMU bus ID (from device tree) */
+       u8      type;           /* i2c transfer type */
+       u8      devaddr;        /* device address (includes direction) */
+       u8      sublen;         /* subaddress length */
+       u8      subaddr[3];     /* subaddress */
+       u8      caddr;          /* combined address, filled by SMU driver */
+       u8      datalen;        /* length of transfer */
+       u8      data[7];        /* data */
+};
+
+#define SMU_I2C_READ_MAX       0x0d
+#define SMU_I2C_WRITE_MAX      0x05
+
+struct smu_i2c_cmd
+{
+       /* public */
+       struct smu_i2c_param    info;
+       void                    (*done)(struct smu_i2c_cmd *cmd, void *misc);
+       void                    *misc;
+       int                     status; /* 1 = pending, 0 = ok, <0 = fail */
+
+       /* private */
+       struct smu_cmd          scmd;
+       int                     read;
+       int                     stage;
+       int                     retries;
+       u8                      pdata[0x10];
+       struct list_head        link;
+};
+
+/*
+ * Call this to queue an i2c command to the SMU. You must fill info,
+ * including info.data for a write, done and misc.
+ * For now, no polling interface is provided so you have to use completion
+ * callback.
+ */
+extern int smu_queue_i2c(struct smu_i2c_cmd *cmd);
+
+
+#endif /* __KERNEL__ */
+
+/*
+ * - Userland interface -
+ */
+
+/*
+ * A given instance of the device can be configured for 2 different
+ * things at the moment:
+ *
+ *  - sending SMU commands (default at open() time)
+ *  - receiving SMU events (not yet implemented)
+ *
+ * Commands are written with write() of a command block. They can be
+ * "driver" commands (for example to switch to event reception mode)
+ * or real SMU commands. They are made of a header followed by command
+ * data if any.
+ *
+ * For SMU commands (not for driver commands), you can then read() back
+ * a reply. The reader will be blocked or not depending on how the device
+ * file is opened. poll() isn't implemented yet. The reply will consist
+ * of a header as well, followed by the reply data if any. You should
+ * always provide a buffer large enough for the maximum reply data, I
+ * recommand one page.
+ *
+ * It is illegal to send SMU commands through a file descriptor configured
+ * for events reception
+ *
+ */
+struct smu_user_cmd_hdr
+{
+       __u32           cmdtype;
+#define SMU_CMDTYPE_SMU                        0       /* SMU command */
+#define SMU_CMDTYPE_WANTS_EVENTS       1       /* switch fd to events mode */
+
+       __u8            cmd;                    /* SMU command byte */
+       __u32           data_len;               /* Lenght of data following */
+};
+
+struct smu_user_reply_hdr
+{
+       __u32           status;                 /* Command status */
+       __u32           reply_len;              /* Lenght of data follwing */
+};
+
+#endif /*  _SMU_H */
index 2cac5ecd9d00b07132c0d4706141e0c342c0e4ac..9feff4ce1424bc390608326240be369eb13aa648 100644 (file)
@@ -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;
 
index 2cac5ecd9d00b07132c0d4706141e0c342c0e4ac..9feff4ce1424bc390608326240be369eb13aa648 100644 (file)
@@ -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;
 
index ecb909572d3fc955efba94c6bb1035f28e203ab0..0f4bcaae61bd74265361e381356c51bc20fe2c70 100644 (file)
@@ -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)
 
index 2cac5ecd9d00b07132c0d4706141e0c342c0e4ac..9feff4ce1424bc390608326240be369eb13aa648 100644 (file)
@@ -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;
 
index 78ac6be2d9ef0ebe6de29d7e4f8a5a7be3e91e34..51db4307bfaf9fd2be6733490d39be673df2fe17 100644 (file)
@@ -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)
 
index 2cac5ecd9d00b07132c0d4706141e0c342c0e4ac..9feff4ce1424bc390608326240be369eb13aa648 100644 (file)
@@ -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;
 
index 51b26e81d828c426af91d4bb3c144045624f1d7e..ededd2659eab7b0a3dc99e4e36bae5e7e70750c7 100644 (file)
@@ -4,13 +4,6 @@
 #include <linux/config.h>
 #include <asm/page.h>
 
-/* Flushing for D-cache alias handling is only needed if
- * the page size is smaller than 16K.
- */
-#if PAGE_SHIFT < 14
-#define DCACHE_ALIASING_POSSIBLE
-#endif
-
 #ifndef __ASSEMBLY__
 
 #include <linux/mm.h>
index 2cac5ecd9d00b07132c0d4706141e0c342c0e4ac..9feff4ce1424bc390608326240be369eb13aa648 100644 (file)
@@ -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;
 
index 4c1098474c73fd382341b0811e979b11d8fb3d0b..c393f815b0be2b1acce8aed503a2bb5cdd2dfe4c 100644 (file)
@@ -15,6 +15,7 @@
 #include <asm/io.h>
 #include <asm/spitfire.h>
 #include <asm/cacheflush.h>
+#include <asm/page.h>
 
 #ifndef MAX_HWIFS
 # ifdef CONFIG_BLK_DEV_IDEPCI
index c9f8ef208ea52529aea888637e7bc8014df6f975..7f8d764abc47df424b469c8809855fb67fb2deb6 100644 (file)
 #define PAGE_SIZE    (_AC(1,UL) << PAGE_SHIFT)
 #define PAGE_MASK    (~(PAGE_SIZE-1))
 
+/* Flushing for D-cache alias handling is only needed if
+ * the page size is smaller than 16K.
+ */
+#if PAGE_SHIFT < 14
+#define DCACHE_ALIASING_POSSIBLE
+#endif
+
 #ifdef __KERNEL__
 
 #ifndef __ASSEMBLY__
index b9b1914aae6331e8fe3e493ee317e19b11ec63c6..a96067cca96394f8697f5b9d1114e61f0caad328 100644 (file)
@@ -10,6 +10,7 @@
 #include <asm/spitfire.h>
 #include <asm/cpudata.h>
 #include <asm/cacheflush.h>
+#include <asm/page.h>
 
 /* Page table allocation/freeing. */
 #ifdef CONFIG_SMP
index a2b4f5ed46256c69ffd6597e7bc37b9c1ceb603a..a297f6144f0fa940d36bd674c0a3b181261213e7 100644 (file)
 #include <asm/processor.h>
 #include <asm/const.h>
 
-/* The kernel image occupies 0x4000000 to 0x1000000 (4MB --> 16MB).
- * The page copy blockops use 0x1000000 to 0x18000000 (16MB --> 24MB).
+/* The kernel image occupies 0x4000000 to 0x1000000 (4MB --> 32MB).
+ * The page copy blockops can use 0x2000000 to 0x10000000.
  * The PROM resides in an area spanning 0xf0000000 to 0x100000000.
- * The vmalloc area spans 0x140000000 to 0x200000000.
+ * The vmalloc area spans 0x100000000 to 0x200000000.
+ * Since modules need to be in the lowest 32-bits of the address space,
+ * we place them right before the OBP area from 0x10000000 to 0xf0000000.
  * There is a single static kernel PMD which maps from 0x0 to address
  * 0x400000000.
  */
-#define        TLBTEMP_BASE            _AC(0x0000000001000000,UL)
-#define MODULES_VADDR          _AC(0x0000000002000000,UL)
-#define MODULES_LEN            _AC(0x000000007e000000,UL)
-#define MODULES_END            _AC(0x0000000080000000,UL)
-#define VMALLOC_START          _AC(0x0000000140000000,UL)
-#define VMALLOC_END            _AC(0x0000000200000000,UL)
+#define        TLBTEMP_BASE            _AC(0x0000000002000000,UL)
+#define MODULES_VADDR          _AC(0x0000000010000000,UL)
+#define MODULES_LEN            _AC(0x00000000e0000000,UL)
+#define MODULES_END            _AC(0x00000000f0000000,UL)
 #define LOW_OBP_ADDRESS                _AC(0x00000000f0000000,UL)
 #define HI_OBP_ADDRESS         _AC(0x0000000100000000,UL)
+#define VMALLOC_START          _AC(0x0000000100000000,UL)
+#define VMALLOC_END            _AC(0x0000000200000000,UL)
 
 /* XXX All of this needs to be rethought so we can take advantage
  * XXX cheetah's full 64-bit virtual address space, ie. no more hole
index 2cac5ecd9d00b07132c0d4706141e0c342c0e4ac..142ee2d8e0fdd176f89991825479f44885411538 100644 (file)
@@ -1,53 +1,12 @@
-#ifndef _ASM_FUTEX_H
-#define _ASM_FUTEX_H
-
-#ifdef __KERNEL__
+#ifndef __UM_FUTEX_H
+#define __UM_FUTEX_H
 
 #include <linux/futex.h>
 #include <asm/errno.h>
+#include <asm/system.h>
+#include <asm/processor.h>
 #include <asm/uaccess.h>
 
-static inline int
-futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
-{
-       int op = (encoded_op >> 28) & 7;
-       int cmp = (encoded_op >> 24) & 15;
-       int oparg = (encoded_op << 8) >> 20;
-       int cmparg = (encoded_op << 20) >> 20;
-       int oldval = 0, ret, tem;
-       if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
-               oparg = 1 << oparg;
-
-       if (! access_ok (VERIFY_WRITE, uaddr, sizeof(int)))
-               return -EFAULT;
-
-       inc_preempt_count();
-
-       switch (op) {
-       case FUTEX_OP_SET:
-       case FUTEX_OP_ADD:
-       case FUTEX_OP_OR:
-       case FUTEX_OP_ANDN:
-       case FUTEX_OP_XOR:
-       default:
-               ret = -ENOSYS;
-       }
+#include "asm/arch/futex.h"
 
-       dec_preempt_count();
-
-       if (!ret) {
-               switch (cmp) {
-               case FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;
-               case FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;
-               case FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break;
-               case FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break;
-               case FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break;
-               case FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break;
-               default: ret = -ENOSYS;
-               }
-       }
-       return ret;
-}
-
-#endif
 #endif
index ed06170e0eddd448b5ac5f1a2b99613d170ed3ea..616d02b57ea90bc5fe58b5bf961babc8125b8c68 100644 (file)
@@ -346,7 +346,6 @@ static inline void set_pte(pte_t *pteptr, pte_t pteval)
 static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
 {
        pte_set_val(pte, (pte_val(pte) & _PAGE_CHG_MASK), newprot);
-       if(pte_present(pte)) pte = pte_mknewpage(pte_mknewprot(pte));
        return pte; 
 }
 
index b2fc94fbc2d90292ecfa53b64a8f97161d4deabf..2d242360c3d655b12e0494528901af2dfa945fc0 100644 (file)
@@ -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;
index ea8381de3cc9d0a8e2c2c4e045870ea8ce6dcac1..c436263e67ba169cb6b06a8fdff4bbcf1ef58bf9 100644 (file)
@@ -3,6 +3,4 @@
 
 #include "asm/system-generic.h"
     
-#define __HAVE_ARCH_CMPXCHG 1
-
 #endif
index 2cac5ecd9d00b07132c0d4706141e0c342c0e4ac..9feff4ce1424bc390608326240be369eb13aa648 100644 (file)
@@ -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;
 
index 594e610f4a1e7d66aff1a12aa3666e7af8e9dd0a..68ac3c62fe3defd95145eb2bc80b7c2361c2e1d7 100644 (file)
@@ -8,6 +8,8 @@
 #ifndef __ASSEMBLY__
 
 #include <linux/string.h>
+#include <linux/smp.h>
+
 #include <asm/segment.h>
 #include <asm/mmu.h>
 
index 1dc110ba82d63e80781f514b79cacb0711ee6d25..2cb483516459dd3efb48fa48269b66c3beb8d072 100644 (file)
@@ -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)
 
index 24f86f0e43cfd64c918fbe39b5b8cdb629ea9175..12b5732dc6e5986ef4966ca87afe7f019745ef3e 100644 (file)
@@ -22,7 +22,7 @@ typedef struct { volatile int counter; } atomic_t;
 #include <asm/processor.h>
 #include <asm/system.h>
 
-#define ATOMIC_INIT(i) ( (atomic_t) { (i) } )
+#define ATOMIC_INIT(i) { (i) }
 
 /*
  * This Xtensa implementation assumes that the right mechanism
index d395ef226c32ad52c68bffc6c6c5a34dcffd38cb..e76ee889e21dadf98702fdc1756b540752b1b355 100644 (file)
@@ -174,7 +174,7 @@ static __inline__ int test_bit(int nr, const volatile void *addr)
        return 1UL & (((const volatile unsigned int *)addr)[nr>>5] >> (nr&31));
 }
 
-#if XCHAL_HAVE_NSAU
+#if XCHAL_HAVE_NSA
 
 static __inline__ int __cntlz (unsigned long x)
 {
index e07c76c36b9547442e133ac2bc89901bfbb6211e..aa9c1adf68d706f9f1f7aca00a0c59c1a9850eac 100644 (file)
@@ -23,6 +23,7 @@ typedef struct {
        unsigned int __nmi_count;              /* arch dependent */
 } ____cacheline_aligned irq_cpustat_t;
 
+void ack_bad_irq(unsigned int irq);
 #include <linux/irq_cpustat.h> /* Standard mappings for irq_cpustat_t above */
 
 #endif /* _XTENSA_HARDIRQ_H */
index 883ebc2d75d69090f0c044e2556b7df9b324d965..987e3b802313561d837b7f43f1e53133db0d0656 100644 (file)
@@ -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 */
index db740b8bc6f058d006e09c96316a15ca4f8aa53b..09e89ab3eb61ef9a5b189509cae8f201ac1fe032 100644 (file)
@@ -20,28 +20,19 @@ struct semaphore {
        atomic_t count;
        int sleepers;
        wait_queue_head_t wait;
-#if WAITQUEUE_DEBUG
-       long __magic;
-#endif
 };
 
-#if WAITQUEUE_DEBUG
-# define __SEM_DEBUG_INIT(name) \
-               , (int)&(name).__magic
-#else
-# define __SEM_DEBUG_INIT(name)
-#endif
-
-#define __SEMAPHORE_INITIALIZER(name,count)                    \
-       { ATOMIC_INIT(count),                                   \
-         0,                                                    \
-         __WAIT_QUEUE_HEAD_INITIALIZER((name).wait)            \
-       __SEM_DEBUG_INIT(name) }
+#define __SEMAPHORE_INITIALIZER(name,n)                                        \
+{                                                                      \
+       .count          = ATOMIC_INIT(n),                               \
+       .sleepers       = 0,                                            \
+       .wait           = __WAIT_QUEUE_HEAD_INITIALIZER((name).wait)    \
+}
 
-#define __MUTEX_INITIALIZER(name) \
+#define __MUTEX_INITIALIZER(name)                                      \
        __SEMAPHORE_INITIALIZER(name, 1)
 
-#define __DECLARE_SEMAPHORE_GENERIC(name,count) \
+#define __DECLARE_SEMAPHORE_GENERIC(name,count)                        \
        struct semaphore name = __SEMAPHORE_INITIALIZER(name,count)
 
 #define DECLARE_MUTEX(name) __DECLARE_SEMAPHORE_GENERIC(name,1)
@@ -49,17 +40,8 @@ struct semaphore {
 
 static inline void sema_init (struct semaphore *sem, int val)
 {
-/*
- *     *sem = (struct semaphore)__SEMAPHORE_INITIALIZER((*sem),val);
- *
- * i'd rather use the more flexible initialization above, but sadly
- * GCC 2.7.2.3 emits a bogus warning. EGCS doesnt. Oh well.
- */
        atomic_set(&sem->count, val);
        init_waitqueue_head(&sem->wait);
-#if WAITQUEUE_DEBUG
-       sem->__magic = (int)&sem->__magic;
-#endif
 }
 
 static inline void init_MUTEX (struct semaphore *sem)
@@ -81,9 +63,7 @@ extern spinlock_t semaphore_wake_lock;
 
 static inline void down(struct semaphore * sem)
 {
-#if WAITQUEUE_DEBUG
-       CHECK_MAGIC(sem->__magic);
-#endif
+       might_sleep();
 
        if (atomic_sub_return(1, &sem->count) < 0)
                __down(sem);
@@ -92,9 +72,8 @@ static inline void down(struct semaphore * sem)
 static inline int down_interruptible(struct semaphore * sem)
 {
        int ret = 0;
-#if WAITQUEUE_DEBUG
-       CHECK_MAGIC(sem->__magic);
-#endif
+
+       might_sleep();
 
        if (atomic_sub_return(1, &sem->count) < 0)
                ret = __down_interruptible(sem);
@@ -104,9 +83,6 @@ static inline int down_interruptible(struct semaphore * sem)
 static inline int down_trylock(struct semaphore * sem)
 {
        int ret = 0;
-#if WAITQUEUE_DEBUG
-       CHECK_MAGIC(sem->__magic);
-#endif
 
        if (atomic_sub_return(1, &sem->count) < 0)
                ret = __down_trylock(sem);
@@ -119,9 +95,6 @@ static inline int down_trylock(struct semaphore * sem)
  */
 static inline void up(struct semaphore * sem)
 {
-#if WAITQUEUE_DEBUG
-       CHECK_MAGIC(sem->__magic);
-#endif
        if (atomic_add_return(1, &sem->count) <= 0)
                __up(sem);
 }
index f09393232e5e9c58dad7c84258f076b1d3414933..9284867f1cb90616cfba4af95b14f42f3059cdd5 100644 (file)
@@ -189,20 +189,6 @@ static inline unsigned long xchg_u32(volatile int * m, unsigned long val)
 
 #define tas(ptr) (xchg((ptr),1))
 
-#if ( __XCC__ == 1 )
-
-/* xt-xcc processes __inline__ differently than xt-gcc and decides to
- * insert an out-of-line copy of function __xchg.  This presents the
- * unresolved symbol at link time of __xchg_called_with_bad_pointer,
- * even though such a function would never be called at run-time.
- * xt-gcc always inlines __xchg, and optimizes away the undefined
- * bad_pointer function.
- */
-
-#define xchg(ptr,x) xchg_u32(ptr,x)
-
-#else  /* assume xt-gcc */
-
 #define xchg(ptr,x) ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr))))
 
 /*
@@ -224,8 +210,6 @@ __xchg(unsigned long x, volatile void * ptr, int size)
        return x;
 }
 
-#endif
-
 extern void set_except_vector(int n, void *addr);
 
 static inline void spill_registers(void)
index 68aba0c02e49a4186faed503358b83b082f8027c..b2a2509bd7ea35b02874d034e5928fbea18ac8c1 100644 (file)
@@ -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 */
 #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)
index 5fde6f4d6c1e3692b0abd52945e48721f428410d..04bd756efc6740e2b16385d4047f2ebb7ec1a86b 100644 (file)
@@ -5,6 +5,10 @@
  * linux/byteorder_generic.h
  * Generic Byte-reordering support
  *
+ * The "... p" macros, like le64_to_cpup, can be used with pointers
+ * to unaligned data, but there will be a performance penalty on 
+ * some architectures.  Use get_unaligned for unaligned data.
+ *
  * Francois-Rene Rideau <fare@tunes.org> 19970707
  *    gathered all the good ideas from all asm-foo/byteorder.h into one file,
  *    cleaned them up.
index 8bf4bacb5051a2df3e8b71dde9c1c464512b851c..71fab4311e92624ff985793df2d9c14777b7e46c 100644 (file)
@@ -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) {
index 06e5d42f2c7b4f9cb4f5186b15da49e46068746f..95d607a48f06edd22c6be64e0feaf74d1aa63467 100644 (file)
@@ -317,6 +317,11 @@ dev_set_drvdata (struct device *dev, void *data)
        dev->driver_data = data;
 }
 
+static inline int device_is_registered(struct device *dev)
+{
+       return klist_node_attached(&dev->knode_bus);
+}
+
 /*
  * High level routines for use by the bus drivers
  */
index 82e39cd0c4fbaf5da68d79cdf6affea9da47ec20..c698055266d062b09fa7e19b447144c67fd82c22 100644 (file)
@@ -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 */
 };
 
index 8fc80a7d78ac2e131ce8b7dea5095499a4aa94e5..53b129f07f6f294a896ce4bcc62133641f79d9ef 100644 (file)
@@ -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
index be35332b67e64689f89094400d25fb0bce346b3a..3d49a305bf8881767669a0ac091fa36175e0ca70 100644 (file)
@@ -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;
index 17d0c0d40b0e376b80e0fa95768dc022961ee671..eef0876d8307b11b5678a25469043f26adc17ddd 100644 (file)
@@ -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
index 06b9af77eb7f8eca71b6476013ea69ed32ee909e..5fd20ddd7ae3b3ff4319b5d9e284dcbd6eafb58b 100644 (file)
@@ -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 */
index 687ba8c9973de2d30d97e234817a52e6b2d2f993..4367ce4db52a1a427ba3cdc73d6100371c9f67e4 100644 (file)
@@ -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;
index f76f54a223d22b614ada536291dc695a0ae7f7aa..7680b63e345686feb5a11afb0ea19f660a06b63a 100644 (file)
@@ -399,6 +399,7 @@ extern int ata_pci_init_one (struct pci_dev *pdev, struct ata_port_info **port_i
 extern void ata_pci_remove_one (struct pci_dev *pdev);
 #endif /* CONFIG_PCI */
 extern int ata_device_add(struct ata_probe_ent *ent);
+extern void ata_host_set_remove(struct ata_host_set *host_set);
 extern int ata_scsi_detect(Scsi_Host_Template *sht);
 extern int ata_scsi_ioctl(struct scsi_device *dev, int cmd, void __user *arg);
 extern int ata_scsi_queuecmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *));
index 82d7024f0765f19648a4f4ad35693f9d320aefe0..097b3a3c693d58c924dd7409db1dd295ebfe8a23 100644 (file)
@@ -136,6 +136,7 @@ extern unsigned int kobjsize(const void *objp);
 #define VM_EXEC                0x00000004
 #define VM_SHARED      0x00000008
 
+/* mprotect() hardcodes VM_MAYREAD >> 4 == VM_READ, and so for r/w/x bits. */
 #define VM_MAYREAD     0x00000010      /* limits for mprotect() etc */
 #define VM_MAYWRITE    0x00000020
 #define VM_MAYEXEC     0x00000040
@@ -350,7 +351,8 @@ static inline void put_page(struct page *page)
  * only one copy in memory, at most, normally.
  *
  * For the non-reserved pages, page_count(page) denotes a reference count.
- *   page_count() == 0 means the page is free.
+ *   page_count() == 0 means the page is free. page->lru is then used for
+ *   freelist management in the buddy allocator.
  *   page_count() == 1 means the page is used for exactly one purpose
  *   (e.g. a private data page of one process).
  *
@@ -376,10 +378,8 @@ static inline void put_page(struct page *page)
  * attaches, plus 1 if `private' contains something, plus one for
  * the page cache itself.
  *
- * All pages belonging to an inode are in these doubly linked lists:
- * mapping->clean_pages, mapping->dirty_pages and mapping->locked_pages;
- * using the page->list list_head. These fields are also used for
- * freelist managemet (when page_count()==0).
+ * Instead of keeping dirty/clean pages in per address-space lists, we instead
+ * now tag pages as dirty/under writeback in the radix tree.
  *
  * There is also a per-mapping radix tree mapping index to the page
  * in memory if present. The tree is rooted at mapping->root.  
index 7e033e9271a88efbb2b214e4834176147d33d28f..4ced3873681313ad4d9ead8edd868000a6cc7dbd 100644 (file)
@@ -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;
@@ -320,11 +332,28 @@ extern void need_ip_conntrack(void);
 extern int invert_tuplepr(struct ip_conntrack_tuple *inverse,
                          const struct ip_conntrack_tuple *orig);
 
+extern void __ip_ct_refresh_acct(struct ip_conntrack *ct,
+                                enum ip_conntrack_info ctinfo,
+                                const struct sk_buff *skb,
+                                unsigned long extra_jiffies,
+                                int do_acct);
+
+/* Refresh conntrack for this many jiffies and do accounting */
+static inline void ip_ct_refresh_acct(struct ip_conntrack *ct, 
+                                     enum ip_conntrack_info ctinfo,
+                                     const struct sk_buff *skb,
+                                     unsigned long extra_jiffies)
+{
+       __ip_ct_refresh_acct(ct, ctinfo, skb, extra_jiffies, 1);
+}
+
 /* Refresh conntrack for this many jiffies */
-extern void ip_ct_refresh_acct(struct ip_conntrack *ct,
-                              enum ip_conntrack_info ctinfo,
-                              const struct sk_buff *skb,
-                              unsigned long extra_jiffies);
+static inline void ip_ct_refresh(struct ip_conntrack *ct,
+                                const struct sk_buff *skb,
+                                unsigned long extra_jiffies)
+{
+       __ip_ct_refresh_acct(ct, 0, skb, extra_jiffies, 0);
+}
 
 /* These are for NAT.  Icky. */
 /* Update TCP window tracking data when NAT mangles the packet */
@@ -372,7 +401,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 (file)
index 0000000..816144c
--- /dev/null
@@ -0,0 +1,325 @@
+/* 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;
+       __be16  packetType;
+       __be32  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 {
+       __be16  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 {
+       __be16  protocolVersion;
+       __u8    reserved1;
+       __u8    reserved2;
+       __be32  framingCapability;
+       __be32  bearerCapability;
+       __be16  maxChannels;
+       __be16  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 {
+       __be16  protocolVersion;
+       __u8    resultCode;
+       __u8    generalErrorCode;
+       __be32  framingCapability;
+       __be32  bearerCapability;
+       __be16  maxChannels;
+       __be16  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 {
+       __be32 identNumber;
+};
+
+/* PptpEchoReplyResultCode */
+#define PPTP_ECHO_OK                   1
+#define PPTP_ECHO_GENERAL_ERROR                2
+
+struct PptpEchoReply {
+       __be32  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 {
+       __be16  callID;
+       __be16  callSerialNumber;
+       __be32  minBPS;
+       __be32  maxBPS;
+       __be32  bearerType;
+       __be32  framingType;
+       __be16  packetWindow;
+       __be16  packetProcDelay;
+       __u16   reserved1;
+       __be16  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 {
+       __be16  callID;
+       __be16  peersCallID;
+       __u8    resultCode;
+       __u8    generalErrorCode;
+       __be16  causeCode;
+       __be32  connectSpeed;
+       __be16  packetWindow;
+       __be16  packetProcDelay;
+       __be32  physChannelID;
+};
+
+struct PptpInCallRequest {
+       __be16  callID;
+       __be16  callSerialNumber;
+       __be32  callBearerType;
+       __be32  physChannelID;
+       __be16  dialedNumberLength;
+       __be16  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 {
+       __be16  callID;
+       __be16  peersCallID;
+       __u8    resultCode;
+       __u8    generalErrorCode;
+       __be16  packetWindow;
+       __be16  packetProcDelay;
+       __u16   reserved;
+};
+
+struct PptpInCallConnected {
+       __be16  peersCallID;
+       __u16   reserved;
+       __be32  connectSpeed;
+       __be16  packetWindow;
+       __be16  packetProcDelay;
+       __be32  callFramingType;
+};
+
+struct PptpClearCallRequest {
+       __be16  callID;
+       __u16   reserved;
+};
+
+struct PptpCallDisconnectNotify {
+       __be16  callID;
+       __u8    resultCode;
+       __u8    generalErrorCode;
+       __be16  causeCode;
+       __u16   reserved;
+       __u8    callStatistics[128];
+};
+
+struct PptpWanErrorNotify {
+       __be16  peersCallID;
+       __u16   reserved;
+       __be32  crcErrors;
+       __be32  framingErrors;
+       __be32  hardwareOverRuns;
+       __be32  bufferOverRuns;
+       __be32  timeoutErrors;
+       __be32  alignmentErrors;
+};
+
+struct PptpSetLinkInfo {
+       __be16  peersCallID;
+       __u16   reserved;
+       __be32  sendAccm;
+       __be32  recvAccm;
+};
+
+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 (file)
index 0000000..8d090ef
--- /dev/null
@@ -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 */
index c33f0b5e0d0a07333f7da56b9a2eb2898ab0b724..20e43f018b7c768cc8b9c13c23253e99c5561d6c 100644 (file)
@@ -17,7 +17,7 @@ union ip_conntrack_manip_proto
        u_int16_t all;
 
        struct {
-               u_int16_t port;
+               __be16 port;
        } tcp;
        struct {
                u_int16_t port;
@@ -28,6 +28,9 @@ union ip_conntrack_manip_proto
        struct {
                u_int16_t port;
        } sctp;
+       struct {
+               __be16 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 {
+                               __be16 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 (file)
index 0000000..eaf66c2
--- /dev/null
@@ -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 */
index 58c72a52dc657ea3028f6abded8b2acdbbff924d..59f70b34e02925568c18c9c3f2dd0a6b7c294156 100644 (file)
@@ -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))
 
index 7bbd25970c9ebfb4a5a73ef1b555082e748e6752..bdebdc5645061248e4418f8be09c85f9d9579c1b 100644 (file)
@@ -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           
 
index 4d24d65c0e88ae44abd098ee1b6aa25fc75f8a40..8903688890cea97f94659c63e453bfb127b393e5 100644 (file)
@@ -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);
index ee0ab7a5f91bbca1389cc46f1b678f4717373ece..b86a4b77007ef05108637f959695cd52eaa304e0 100644 (file)
 #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
 #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
 #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
 #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
 #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
 #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
 #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
 #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
 #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
 #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
 #define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_SATA 0x0266
 #define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_SATA2        0x0267
 #define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_IDE  0x036E
-#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_SATA 0x036F
+#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_SATA 0x037E
+#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_SATA2        0x037F
 #define PCI_DEVICE_ID_NVIDIA_NVENET_12         0x0268
 #define PCI_DEVICE_ID_NVIDIA_NVENET_13         0x0269
 #define PCI_DEVICE_ID_NVIDIA_MCP51_AUDIO       0x026B
 #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
 #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
 #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
 #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
 
 #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
 #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
 #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
index 4b32bce9a2893527195c46321adcf860fe5feed3..2c177e4c8f226d50803162dcb421beb629d4cbd3 100644 (file)
@@ -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)
index 3b3266ff1a9508ba1edbb96600cfc280e5fdbef0..7ab2cdb83ef06ecd1809911ae1fde217a78d3c69 100644 (file)
@@ -59,6 +59,10 @@ extern void machine_crash_shutdown(struct pt_regs *);
  * Architecture independent implemenations of sys_reboot commands.
  */
 
+extern void kernel_restart_prepare(char *cmd);
+extern void kernel_halt_prepare(void);
+extern void kernel_power_off_prepare(void);
+
 extern void kernel_restart(char *cmd);
 extern void kernel_halt(void);
 extern void kernel_power_off(void);
index 38c8654aaa96b66d327a09aa2b2cf9effb49674d..49e617fa0f662a10a04980ed0f2b3997a1adc0d0 100644 (file)
@@ -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)         \
index 55b02e1c73f418696cdbe49f5080985133934e55..0e43460d374ee72b4774095cdd21db3d5fc47e3e 100644 (file)
@@ -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 */
index 425f58c8ea4ae4c12ef53545e334542b3f161010..a6f03e4737377f3437816ed74b7e96c0f87c42de 100644 (file)
@@ -508,5 +508,7 @@ asmlinkage long sys_keyctl(int cmd, unsigned long arg2, unsigned long arg3,
 
 asmlinkage long sys_ioprio_set(int which, int who, int ioprio);
 asmlinkage long sys_ioprio_get(int which, int who);
+asmlinkage long sys_set_mempolicy(int mode, unsigned long __user *nmask,
+                                       unsigned long maxnode);
 
 #endif
diff --git a/include/linux/tfrc.h b/include/linux/tfrc.h
new file mode 100644 (file)
index 0000000..7dab783
--- /dev/null
@@ -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_ */
index f623a33b9abe856ea37a01be04ac515727498ae2..89a055761bed8e877ce1f7af782ae3f0e33371cf 100644 (file)
@@ -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)
index 371e7d3f2e6fe9574b5ef3418685f156fd879061..fa2d12b0579b49fc9c5e480c65a931ad36c784a5 100644 (file)
@@ -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;
index e426641c519f4e4fcf4dd70a9bda3090cd612037..06b4235aa0164c1844c7b48eb3457380e5984835 100644 (file)
@@ -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);
 
index 53184a38fdf64c5cee649dc482ab2fc656a936cf..0e293fe733b0e2924bfc6ca23c2e33fc044de9f4 100644 (file)
 #define IB_QP1_QKEY    0x80010000
 #define IB_QP_SET_QKEY 0x80000000
 
+enum {
+       IB_MGMT_MAD_DATA = 232,
+       IB_MGMT_RMPP_DATA = 220,
+       IB_MGMT_VENDOR_DATA = 216,
+       IB_MGMT_SA_DATA = 200
+};
+
 struct ib_mad_hdr {
        u8      base_version;
        u8      mgmt_class;
@@ -149,20 +156,20 @@ struct ib_sa_hdr {
 
 struct ib_mad {
        struct ib_mad_hdr       mad_hdr;
-       u8                      data[232];
+       u8                      data[IB_MGMT_MAD_DATA];
 };
 
 struct ib_rmpp_mad {
        struct ib_mad_hdr       mad_hdr;
        struct ib_rmpp_hdr      rmpp_hdr;
-       u8                      data[220];
+       u8                      data[IB_MGMT_RMPP_DATA];
 };
 
 struct ib_sa_mad {
        struct ib_mad_hdr       mad_hdr;
        struct ib_rmpp_hdr      rmpp_hdr;
        struct ib_sa_hdr        sa_hdr;
-       u8                      data[200];
+       u8                      data[IB_MGMT_SA_DATA];
 } __attribute__ ((packed));
 
 struct ib_vendor_mad {
@@ -170,7 +177,7 @@ struct ib_vendor_mad {
        struct ib_rmpp_hdr      rmpp_hdr;
        u8                      reserved;
        u8                      oui[3];
-       u8                      data[216];
+       u8                      data[IB_MGMT_VENDOR_DATA];
 };
 
 struct ib_class_port_info
index 916144be208b93b948f867d04599608fa6b5981f..69313ba7505b30323e37eb2134693d41c242512d 100644 (file)
@@ -439,6 +439,8 @@ enum scsi_host_state {
        SHOST_CANCEL,
        SHOST_DEL,
        SHOST_RECOVERY,
+       SHOST_CANCEL_RECOVERY,
+       SHOST_DEL_RECOVERY,
 };
 
 struct Scsi_Host {
@@ -465,8 +467,6 @@ struct Scsi_Host {
 
        struct list_head        eh_cmd_q;
        struct task_struct    * ehandler;  /* Error recovery thread. */
-       struct semaphore      * eh_wait;   /* The error recovery thread waits
-                                             on this. */
        struct semaphore      * eh_action; /* Wait for specific actions on the
                                           host. */
        unsigned int            eh_active:1; /* Indicates the eh thread is awake and active if
@@ -621,6 +621,13 @@ static inline struct Scsi_Host *dev_to_shost(struct device *dev)
        return container_of(dev, struct Scsi_Host, shost_gendev);
 }
 
+static inline int scsi_host_in_recovery(struct Scsi_Host *shost)
+{
+       return shost->shost_state == SHOST_RECOVERY ||
+               shost->shost_state == SHOST_CANCEL_RECOVERY ||
+               shost->shost_state == SHOST_DEL_RECOVERY;
+}
+
 extern int scsi_queue_work(struct Scsi_Host *, struct work_struct *);
 extern void scsi_flush_work(struct Scsi_Host *);
 
index 115db056dc6bdc8ec31eaacda793d4849521a300..b0d4454373721da80e76a63e94dd18c20e7494a9 100644 (file)
@@ -103,8 +103,8 @@ enum fc_port_state {
                                             incapable of reporting */
 #define FC_PORTSPEED_1GBIT             1
 #define FC_PORTSPEED_2GBIT             2
-#define FC_PORTSPEED_10GBIT            4
-#define FC_PORTSPEED_4GBIT             8
+#define FC_PORTSPEED_4GBIT             4
+#define FC_PORTSPEED_10GBIT            8
 #define FC_PORTSPEED_NOT_NEGOTIATED    (1 << 15) /* Speed not established */
 
 /*
index 3dc41fd5c54d46730d39c01967c93d05e5b48b32..26160adcdffccb3e70e8f5d189863bc310f62985 100644 (file)
@@ -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 */
 
index 9b94510eda60224f67d513e27ca1f1b4bd0596d6..b0c0e192eb56711f9ab623805f2dc02eed8106a0 100644 (file)
 #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) */
index 4e3993dfcefef1a9301e0eee798c6554b42cc4cb..67bf3f18e96a81702821ad1c739f7422cc35892e 100644 (file)
 #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
index d6361dab0370856e3fb3638b442798c435a5c5af..2b23a596707114faf2315b9fef045890cab95550 100644 (file)
@@ -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
index 518728536bc6e644c8935288a929ae89f0ae2052..0b67c9d105af0e9d5cb1eea6ee31f7e00104bfd4 100644 (file)
@@ -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;
index f5254ec36e6af5335b7d96728a8a754f596ac29a..a408d39250503eeed51c9d5eb918ed87b9df351c 100644 (file)
 //#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)
index 8d19bfabb7e0812caf0963dfb763e92329fb1d82..ee32af20dba9de068ac7ee2f680776664ac9dbc0 100644 (file)
@@ -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)"
index 9a3c1e6c820a2d28ddec0cffdaa83cfe7ba81d1f..c3bccbfd8d4c344ac7336a4084deeb3226ebea54 100644 (file)
 #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
  */
index 8d3cef5d87a20264af07948e6c1df10d2f04f8bc..6f4ea808cf74b4ae9e2e47f19da0231e5b07a51a 100644 (file)
 /* 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 */
index e6da2d7ded8cfa7a0a5c1d16ae1e732b98af996a..677d403267967ed361488666198594db8cde9ba9 100644 (file)
@@ -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 {
index 02c5ce64990d4abdd162eeee1e9a8410156d41bd..0c5d9a3f951baea7efa88f37683641e7efc3a978 100644 (file)
@@ -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
index 7f0699790d469ce218ff4ec91967608275871fb7..83096b67510aea1e6c40147a9b1f2b73752218b5 100644 (file)
@@ -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);
index e75f84e1a1a00d697718f603655810d8a51e7548..88696f639aab890140657aba7fcd2956ddfe6623 100644 (file)
@@ -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;
@@ -472,22 +532,86 @@ static enum audit_state audit_filter_task(struct task_struct *tsk)
 static enum audit_state audit_filter_syscall(struct task_struct *tsk,
                                             struct audit_context *ctx,
                                             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;
index 6d2089a1bce74614009acfb18f1e3b95458e90cf..ee6d8b8abef5454fc2e224fdfbdf12a332591c6e 100644 (file)
@@ -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;
index 8149f3602881db80727310245436c97a661adf2a..533ce27f4b2c0938f91c948aa682bc992579ba96 100644 (file)
@@ -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());
 
        /*
index 4b39d3793c720673452b6d8be18ade674360131a..ff5c500ab625202ef8401998bc0a71cac53424aa 100644 (file)
@@ -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
 
index 396c7873e804076a7dbdf718bcbbcc19bb94f475..46a5e5acff97aaa86b4d3429e33fe07ca03d7bf4 100644 (file)
@@ -29,7 +29,7 @@ config PM_DEBUG
 
 config SOFTWARE_SUSPEND
        bool "Software Suspend"
-       depends on PM && SWAP && (X86 || ((FVR || PPC32) && !SMP))
+       depends on PM && SWAP && (X86 && (!SMP || SUSPEND_SMP)) || ((FVR || PPC32) && !SMP)
        ---help---
          Enable the possibility of suspending the machine.
          It doesn't need APM.
index 2d8bf054d036810766352d66b2fb84ec16361717..761956e813f51b8dd37f3670a9ab74e1f4536cf7 100644 (file)
 #include <linux/delay.h>
 #include <linux/fs.h>
 #include <linux/mount.h>
+#include <linux/pm.h>
 
 #include "power.h"
 
 
 extern suspend_disk_method_t pm_disk_mode;
-extern struct pm_ops * pm_ops;
 
 extern int swsusp_suspend(void);
 extern int swsusp_write(void);
@@ -49,13 +49,11 @@ dev_t swsusp_resume_device;
 
 static void power_down(suspend_disk_method_t mode)
 {
-       unsigned long flags;
        int error = 0;
 
-       local_irq_save(flags);
        switch(mode) {
        case PM_DISK_PLATFORM:
-               device_shutdown();
+               kernel_power_off_prepare();
                error = pm_ops->enter(PM_SUSPEND_DISK);
                break;
        case PM_DISK_SHUTDOWN:
index cd6a3493cc0dc693928a907f68631b166954dfc6..9c9167d910ddb361b59857e3a318b94049d3031a 100644 (file)
@@ -1,7 +1,7 @@
 #include <linux/suspend.h>
 #include <linux/utsname.h>
 
-/* With SUSPEND_CONSOLE defined, it suspend looks *really* cool, but
+/* With SUSPEND_CONSOLE defined suspend looks *really* cool, but
    we probably do not take enough locks for switching consoles, etc,
    so bad things might happen.
 */
index d967e875ee82f974d9f4e8e365aa59270a6f5c61..1cc9ff25e479a4b3cba533c8caedd9f8cf729d4e 100644 (file)
@@ -363,7 +363,7 @@ static void lock_swapdevices(void)
 }
 
 /**
- *     write_swap_page - Write one page to a fresh swap location.
+ *     write_page - Write one page to a fresh swap location.
  *     @addr:  Address we're writing.
  *     @loc:   Place to store the entry we used.
  *
@@ -863,6 +863,9 @@ static int alloc_image_pages(void)
        return 0;
 }
 
+/* Free pages we allocated for suspend. Suspend pages are alocated
+ * before atomic copy, so we need to free them after resume.
+ */
 void swsusp_free(void)
 {
        BUG_ON(PageNosave(virt_to_page(pagedir_save)));
@@ -918,6 +921,7 @@ static int swsusp_alloc(void)
 
        pagedir_nosave = NULL;
        nr_copy_pages = calc_nr(nr_copy_pages);
+       nr_copy_pages_check = nr_copy_pages;
 
        pr_debug("suspend: (pages needed: %d + %d free: %d)\n",
                 nr_copy_pages, PAGES_FOR_IO, nr_free_pages());
@@ -940,7 +944,6 @@ static int swsusp_alloc(void)
                return error;
        }
 
-       nr_copy_pages_check = nr_copy_pages;
        return 0;
 }
 
@@ -1213,8 +1216,9 @@ static struct pbe * swsusp_pagedir_relocate(struct pbe *pblist)
                free_pagedir(pblist);
                free_eaten_memory();
                pblist = NULL;
-       }
-       else
+               /* Is this even worth handling? It should never ever happen, and we
+                  have just lost user's state, anyway... */
+       } else
                printk("swsusp: Relocated %d pages\n", rel);
 
        return pblist;
index a967605bc2e358cbcf95dd7fe60f7870fe9dd14b..4b8f0f9230a46870aaebcf11b9c844bf32990dd9 100644 (file)
@@ -488,6 +488,11 @@ static int __init printk_time_setup(char *str)
 
 __setup("time", printk_time_setup);
 
+__attribute__((weak)) unsigned long long printk_clock(void)
+{
+       return sched_clock();
+}
+
 /*
  * This is printk.  It can be called from any context.  We want it to work.
  * 
@@ -565,7 +570,7 @@ asmlinkage int vprintk(const char *fmt, va_list args)
                                        loglev_char = default_message_loglevel
                                                + '0';
                                }
-                               t = sched_clock();
+                               t = printk_clock();
                                nanosec_rem = do_div(t, 1000000000);
                                tlen = sprintf(tbuf,
                                                "<%c>[%5lu.%06lu] ",
index 81b3a96ed2d09a79f7937503a88c3ced4c959953..1f31a528fdba8ef941f5a75acb65c3ac6a4bf815 100644 (file)
@@ -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)
index b92c3c9f8b9a24529e18eb2a1a1bf75f87840f10..5a274705ba1945b8ec81100a139daec057fc696d 100644 (file)
@@ -936,34 +936,31 @@ force_sig_specific(int sig, struct task_struct *t)
  * as soon as they're available, so putting the signal on the shared queue
  * will be equivalent to sending it to one such thread.
  */
-#define wants_signal(sig, p, mask)                     \
-       (!sigismember(&(p)->blocked, sig)               \
-        && !((p)->state & mask)                        \
-        && !((p)->flags & PF_EXITING)                  \
-        && (task_curr(p) || !signal_pending(p)))
-
+static inline int wants_signal(int sig, struct task_struct *p)
+{
+       if (sigismember(&p->blocked, sig))
+               return 0;
+       if (p->flags & PF_EXITING)
+               return 0;
+       if (sig == SIGKILL)
+               return 1;
+       if (p->state & (TASK_STOPPED | TASK_TRACED))
+               return 0;
+       return task_curr(p) || !signal_pending(p);
+}
 
 static void
 __group_complete_signal(int sig, struct task_struct *p)
 {
-       unsigned int mask;
        struct task_struct *t;
 
-       /*
-        * Don't bother traced and stopped tasks (but
-        * SIGKILL will punch through that).
-        */
-       mask = TASK_STOPPED | TASK_TRACED;
-       if (sig == SIGKILL)
-               mask = 0;
-
        /*
         * Now find a thread we can wake up to take the signal off the queue.
         *
         * If the main thread wants the signal, it gets first crack.
         * Probably the least surprising to the average bear.
         */
-       if (wants_signal(sig, p, mask))
+       if (wants_signal(sig, p))
                t = p;
        else if (thread_group_empty(p))
                /*
@@ -981,7 +978,7 @@ __group_complete_signal(int sig, struct task_struct *p)
                        t = p->signal->curr_target = p;
                BUG_ON(t->tgid != p->tgid);
 
-               while (!wants_signal(sig, t, mask)) {
+               while (!wants_signal(sig, t)) {
                        t = next_thread(t);
                        if (t == p->signal->curr_target)
                                /*
index c80412be2302c6321898b57ef3a99d10a1c21a68..2fa1ed18123cb8c84f241d4a19e1ed9b2727574e 100644 (file)
@@ -361,17 +361,35 @@ out_unlock:
        return retval;
 }
 
+/**
+ *     emergency_restart - reboot the system
+ *
+ *     Without shutting down any hardware or taking any locks
+ *     reboot the system.  This is called when we know we are in
+ *     trouble so this is our best effort to reboot.  This is
+ *     safe to call in interrupt context.
+ */
 void emergency_restart(void)
 {
        machine_emergency_restart();
 }
 EXPORT_SYMBOL_GPL(emergency_restart);
 
-void kernel_restart(char *cmd)
+/**
+ *     kernel_restart - reboot the system
+ *
+ *     Shutdown everything and perform a clean reboot.
+ *     This is not safe to call in interrupt context.
+ */
+void kernel_restart_prepare(char *cmd)
 {
        notifier_call_chain(&reboot_notifier_list, SYS_RESTART, cmd);
        system_state = SYSTEM_RESTART;
        device_shutdown();
+}
+void kernel_restart(char *cmd)
+{
+       kernel_restart_prepare(cmd);
        if (!cmd) {
                printk(KERN_EMERG "Restarting system.\n");
        } else {
@@ -382,6 +400,12 @@ void kernel_restart(char *cmd)
 }
 EXPORT_SYMBOL_GPL(kernel_restart);
 
+/**
+ *     kernel_kexec - reboot the system
+ *
+ *     Move into place and start executing a preloaded standalone
+ *     executable.  If nothing was preloaded return an error.
+ */
 void kernel_kexec(void)
 {
 #ifdef CONFIG_KEXEC
@@ -390,9 +414,7 @@ void kernel_kexec(void)
        if (!image) {
                return;
        }
-       notifier_call_chain(&reboot_notifier_list, SYS_RESTART, NULL);
-       system_state = SYSTEM_RESTART;
-       device_shutdown();
+       kernel_restart_prepare(NULL);
        printk(KERN_EMERG "Starting new kernel\n");
        machine_shutdown();
        machine_kexec(image);
@@ -400,21 +422,39 @@ void kernel_kexec(void)
 }
 EXPORT_SYMBOL_GPL(kernel_kexec);
 
-void kernel_halt(void)
+/**
+ *     kernel_halt - halt the system
+ *
+ *     Shutdown everything and perform a clean system halt.
+ */
+void kernel_halt_prepare(void)
 {
        notifier_call_chain(&reboot_notifier_list, SYS_HALT, NULL);
        system_state = SYSTEM_HALT;
        device_shutdown();
+}
+void kernel_halt(void)
+{
+       kernel_halt_prepare();
        printk(KERN_EMERG "System halted.\n");
        machine_halt();
 }
 EXPORT_SYMBOL_GPL(kernel_halt);
 
-void kernel_power_off(void)
+/**
+ *     kernel_power_off - power_off the system
+ *
+ *     Shutdown everything and perform a clean system power_off.
+ */
+void kernel_power_off_prepare(void)
 {
        notifier_call_chain(&reboot_notifier_list, SYS_POWER_OFF, NULL);
        system_state = SYSTEM_POWER_OFF;
        device_shutdown();
+}
+void kernel_power_off(void)
+{
+       kernel_power_off_prepare();
        printk(KERN_EMERG "Power down.\n");
        machine_power_off();
 }
@@ -1728,8 +1768,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) {
index f4152fcd9f8effecb04229c6e3a239576e7e09af..3ba10fa35b607fd8a3c6d0db86f104c767df6604 100644 (file)
@@ -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);
index 2377af057d099ebd628bd9f7039cd4f54c9bf229..305a9663aee39aba26532082319433e0a4e9ae33 100644 (file)
@@ -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);
index 4e9937ac3529ae391762f5071e938f8ac5497077..391ffc54d13675846cb61c5fc91a875914ac11a8 100644 (file)
@@ -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.
 
index afa06e184d88a93311708bdfb1e15077859e29c4..9033f0859aa8c2f17bc66a55c7eb129092cc4a4d 100644 (file)
@@ -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;
index 12334aecf8ad3d74b62f93da8db6f529e981d51d..fa11d91242e8ca4b0d25135b801a0cbc7855dd8c 100644 (file)
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -1640,7 +1640,7 @@ static void unmap_vma_list(struct mm_struct *mm, struct vm_area_struct *vma)
 /*
  * Get rid of page table information in the indicated region.
  *
- * Called with the page table lock held.
+ * Called with the mm semaphore held.
  */
 static void unmap_region(struct mm_struct *mm,
                struct vm_area_struct *vma, struct vm_area_struct *prev,
@@ -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;
 }
index e9fbd013ad9afa26804bc89f9b42cf335f2ac167..57577f63b305e6a50fd0e9a2861dd2888a62dd77 100644 (file)
@@ -248,7 +248,8 @@ sys_mprotect(unsigned long start, size_t len, unsigned long prot)
 
                newflags = vm_flags | (vma->vm_flags & ~(VM_READ | VM_WRITE | VM_EXEC));
 
-               if ((newflags & ~(newflags >> 4)) & 0xf) {
+               /* newflags >> 4 shift VM_MAY% in place of VM_% */
+               if ((newflags & ~(newflags >> 4)) & (VM_READ | VM_WRITE | VM_EXEC)) {
                        error = -EACCES;
                        goto out;
                }
index c5823c395f7145f2a66ef3ffd11af836c294845f..ae2903339e71cf92a0e429f6a9423341a432dfc1 100644 (file)
@@ -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
index 9e876d6dfad97f2c4ab60a881edcb91d528c1c3c..c9adfce004056d2539ffa04a9ab09c1a2773d89d 100644 (file)
--- a/mm/slab.c
+++ b/mm/slab.c
@@ -308,12 +308,12 @@ struct kmem_list3 __initdata initkmem_list3[NUM_INIT_LISTS];
 #define        SIZE_L3 (1 + MAX_NUMNODES)
 
 /*
- * This function may be completely optimized away if
+ * This function must be completely optimized away if
  * a constant is passed to it. Mostly the same as
  * what is in linux/slab.h except it returns an
  * index.
  */
-static inline int index_of(const size_t size)
+static __always_inline int index_of(const size_t size)
 {
        if (__builtin_constant_p(size)) {
                int i = 0;
@@ -329,7 +329,8 @@ static inline int index_of(const size_t size)
                        extern void __bad_size(void);
                        __bad_size();
                }
-       }
+       } else
+               BUG();
        return 0;
 }
 
@@ -639,7 +640,7 @@ static enum {
 
 static DEFINE_PER_CPU(struct work_struct, reap_work);
 
-static void free_block(kmem_cache_t* cachep, void** objpp, int len);
+static void free_block(kmem_cache_t* cachep, void** objpp, int len, int node);
 static void enable_cpucache (kmem_cache_t *cachep);
 static void cache_reap (void *unused);
 static int __node_shrink(kmem_cache_t *cachep, int node);
@@ -659,7 +660,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++;
@@ -804,7 +805,7 @@ static inline void __drain_alien_cache(kmem_cache_t *cachep, struct array_cache
 
        if (ac->avail) {
                spin_lock(&rl3->list_lock);
-               free_block(cachep, ac->entry, ac->avail);
+               free_block(cachep, ac->entry, ac->avail, node);
                ac->avail = 0;
                spin_unlock(&rl3->list_lock);
        }
@@ -925,7 +926,7 @@ static int __devinit cpuup_callback(struct notifier_block *nfb,
                        /* Free limit for this kmem_list3 */
                        l3->free_limit -= cachep->batchcount;
                        if (nc)
-                               free_block(cachep, nc->entry, nc->avail);
+                               free_block(cachep, nc->entry, nc->avail, node);
 
                        if (!cpus_empty(mask)) {
                                 spin_unlock(&l3->list_lock);
@@ -934,7 +935,7 @@ static int __devinit cpuup_callback(struct notifier_block *nfb,
 
                        if (l3->shared) {
                                free_block(cachep, l3->shared->entry,
-                                               l3->shared->avail);
+                                               l3->shared->avail, node);
                                kfree(l3->shared);
                                l3->shared = NULL;
                        }
@@ -1882,12 +1883,13 @@ static void do_drain(void *arg)
 {
        kmem_cache_t *cachep = (kmem_cache_t*)arg;
        struct array_cache *ac;
+       int node = numa_node_id();
 
        check_irq_off();
        ac = ac_data(cachep);
-       spin_lock(&cachep->nodelists[numa_node_id()]->list_lock);
-       free_block(cachep, ac->entry, ac->avail);
-       spin_unlock(&cachep->nodelists[numa_node_id()]->list_lock);
+       spin_lock(&cachep->nodelists[node]->list_lock);
+       free_block(cachep, ac->entry, ac->avail, node);
+       spin_unlock(&cachep->nodelists[node]->list_lock);
        ac->avail = 0;
 }
 
@@ -2608,7 +2610,7 @@ done:
 /*
  * Caller needs to acquire correct kmem_list's list_lock
  */
-static void free_block(kmem_cache_t *cachep, void **objpp, int nr_objects)
+static void free_block(kmem_cache_t *cachep, void **objpp, int nr_objects, int node)
 {
        int i;
        struct kmem_list3 *l3;
@@ -2617,14 +2619,12 @@ static void free_block(kmem_cache_t *cachep, void **objpp, int nr_objects)
                void *objp = objpp[i];
                struct slab *slabp;
                unsigned int objnr;
-               int nodeid = 0;
 
                slabp = GET_PAGE_SLAB(virt_to_page(objp));
-               nodeid = slabp->nodeid;
-               l3 = cachep->nodelists[nodeid];
+               l3 = cachep->nodelists[node];
                list_del(&slabp->list);
                objnr = (objp - slabp->s_mem) / cachep->objsize;
-               check_spinlock_acquired_node(cachep, nodeid);
+               check_spinlock_acquired_node(cachep, node);
                check_slabp(cachep, slabp);
 
 
@@ -2664,13 +2664,14 @@ static void cache_flusharray(kmem_cache_t *cachep, struct array_cache *ac)
 {
        int batchcount;
        struct kmem_list3 *l3;
+       int node = numa_node_id();
 
        batchcount = ac->batchcount;
 #if DEBUG
        BUG_ON(!batchcount || batchcount > ac->avail);
 #endif
        check_irq_off();
-       l3 = cachep->nodelists[numa_node_id()];
+       l3 = cachep->nodelists[node];
        spin_lock(&l3->list_lock);
        if (l3->shared) {
                struct array_cache *shared_array = l3->shared;
@@ -2686,7 +2687,7 @@ static void cache_flusharray(kmem_cache_t *cachep, struct array_cache *ac)
                }
        }
 
-       free_block(cachep, ac->entry, batchcount);
+       free_block(cachep, ac->entry, batchcount, node);
 free_done:
 #if STATS
        {
@@ -2751,7 +2752,7 @@ static inline void __cache_free(kmem_cache_t *cachep, void *objp)
                        } else {
                                spin_lock(&(cachep->nodelists[nodeid])->
                                                list_lock);
-                               free_block(cachep, &objp, 1);
+                               free_block(cachep, &objp, 1, nodeid);
                                spin_unlock(&(cachep->nodelists[nodeid])->
                                                list_lock);
                        }
@@ -2844,7 +2845,7 @@ void *kmem_cache_alloc_node(kmem_cache_t *cachep, unsigned int __nocast flags, i
        unsigned long save_flags;
        void *ptr;
 
-       if (nodeid == numa_node_id() || nodeid == -1)
+       if (nodeid == -1)
                return __cache_alloc(cachep, flags);
 
        if (unlikely(!cachep->nodelists[nodeid])) {
@@ -3079,7 +3080,7 @@ static int alloc_kmemlist(kmem_cache_t *cachep)
 
                        if ((nc = cachep->nodelists[node]->shared))
                                free_block(cachep, nc->entry,
-                                                       nc->avail);
+                                                       nc->avail, node);
 
                        l3->shared = new;
                        if (!cachep->nodelists[node]->alien) {
@@ -3160,7 +3161,7 @@ static int do_tune_cpucache(kmem_cache_t *cachep, int limit, int batchcount,
                if (!ccold)
                        continue;
                spin_lock_irq(&cachep->nodelists[cpu_to_node(i)]->list_lock);
-               free_block(cachep, ccold->entry, ccold->avail);
+               free_block(cachep, ccold->entry, ccold->avail, cpu_to_node(i));
                spin_unlock_irq(&cachep->nodelists[cpu_to_node(i)]->list_lock);
                kfree(ccold);
        }
@@ -3240,7 +3241,7 @@ static void drain_array_locked(kmem_cache_t *cachep,
                if (tofree > ac->avail) {
                        tofree = (ac->avail+1)/2;
                }
-               free_block(cachep, ac->entry, tofree);
+               free_block(cachep, ac->entry, tofree, node);
                ac->avail -= tofree;
                memmove(ac->entry, &(ac->entry[tofree]),
                                        sizeof(void*)*ac->avail);
index 0184f510aacefd5cdce18b18a2d2f91008e255db..1dcaeda039f4b85f8bbe1b70f4ccbc80de388ade 100644 (file)
@@ -1381,6 +1381,7 @@ asmlinkage long sys_swapon(const char __user * specialfile, int swap_flags)
                error = bd_claim(bdev, sys_swapon);
                if (error < 0) {
                        bdev = NULL;
+                       error = -EINVAL;
                        goto bad_swap;
                }
                p->old_block_size = block_size(bdev);
index a740778f688da277d35eb0d15a60168257dbe42e..0ea71e887bb6e3fdf51d9b18ad56fe993423249d 100644 (file)
@@ -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
index 145f5cde96cf7a0ece22d77da07e0c4fc0311e53..b7486488967074b9b40c4b5916533f0b969f265c 100644 (file)
@@ -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);
index 2bdd5623fdd50889327bd4889e137f82bea6279c..60f6f321bd7667a9d57ed03edb17c88ac0e4a0dc 100644 (file)
@@ -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
index d6da0939216d292baf0088a179d92672a647a54d..b61b4e8e36fdab2bd7c555acdfb7a93f23de5e14 100644 (file)
@@ -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;
index 90e19eb6d3cce0de84bb9a48796f9c260aacc71e..f49e7e938bfb2702dcc57c58a59b9a8b7e58c375 100644 (file)
@@ -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);
index 069253f830c10cd777d22662e976c89a593a2547..2d24fb400e0cbbd79ef064758b69bbebf07e0ccb 100644 (file)
@@ -31,7 +31,8 @@ static inline int should_deliver(const struct net_bridge_port *p,
 
 int br_dev_queue_push_xmit(struct sk_buff *skb)
 {
-       if (skb->len > skb->dev->mtu) 
+       /* drop mtu oversized packets except tso */
+       if (skb->len > skb->dev->mtu && !skb_shinfo(skb)->tso_size)
                kfree_skb(skb);
        else {
 #ifdef CONFIG_BRIDGE_NETFILTER
index 2d52fee63a8cf1653e90281be1ca154c61f24d70..d8e36b7751255b17e736f35060dead6b21eebb69 100644 (file)
@@ -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;
                                }
index fb97bb0424553591ebd157e1ba459af124f621aa..344a8da153fc90d798497d4ec821b8ccf509a56d 100644 (file)
@@ -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 (file)
index 0000000..6530283
--- /dev/null
@@ -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 (file)
index 0000000..8ca51c9
--- /dev/null
@@ -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 */
index 962f1e9e2f7e5fe42c16112ec657bdd7174f2aac..21e55142dcd3b9b85e5c54d6630a788b3d74637c 100644 (file)
@@ -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 */
index 38aa84986118564379043c462b19e832f8342933..aa68e0ab274d4b837a8147b6cb4d677d53740185 100644 (file)
@@ -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);
index eb248778eea371fc34d3f053b366c9de98496b8b..0bde4583d09147f5e95a2ea6993e98da7041619c 100644 (file)
@@ -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)
index 95c4630b3b18454260b34209da7e54ae326ab8a1..5871c027f9dce28c73ea100050c525f0d2c34102 100644 (file)
@@ -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 */
index c60bc3433f5eac378d8a4b87198276576fd6d7f8..1b6b2cb12376ecb27edadcd81eb32ff0a4716a1b 100644 (file)
@@ -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:
index 2afaa464e7f0912fc812855831d8e7f73f601030..40fe6afacde61b17559f582315c53110fb544fc4 100644 (file)
@@ -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;
index 18461bc04cbefae76dc8073878a53ec51bda0885..1393461898bbb277994c7707d009ddebbf68ac90 100644 (file)
@@ -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:
index d4c4242d8dd7c5de227784b42c048f5f18b41027..0a76426c9aeab322f6eae5dd8e8e2309e1454d98 100644 (file)
 #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;
-       }
-}
index ea6d0e91e5117ac8f5ca1b5dbbce4a5c53269696..4786bdcddcc92a4082b3dc7d30d77560b171e541 100644 (file)
@@ -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);
 
index 18a0e69c9dc75f709e15be01e7ef6def17de3eb5..a1cfd0e9e3bc922ff3e670d49b8412c26f0c5d62 100644 (file)
@@ -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;
        }
index 1b63b4824164390daa515a4baf1c1e8b6f8a9b8f..50c0519cd70d879c0d9944ecdef3c7c8977eabf3 100644 (file)
@@ -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;
@@ -1085,7 +1086,7 @@ fib_insert_node(struct trie *t, int *err, u32 key, int plen)
        }
 
        if (tp && tp->pos + tp->bits > 32)
-               printk("ERROR tp=%p pos=%d, bits=%d, key=%0x plen=%d\n",
+               printk(KERN_WARNING "fib_trie tp=%p pos=%d, bits=%d, key=%0x plen=%d\n",
                       tp, tp->pos, tp->bits, key, plen);
 
        /* Rebalance the trie */
@@ -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);
@@ -1833,16 +1832,7 @@ static int fn_trie_dump_fa(t_key key, int plen, struct list_head *fah, struct fi
                        i++;
                        continue;
                }
-               if (fa->fa_info->fib_nh == NULL) {
-                       printk("Trie error _fib_nh=NULL in fa[%d] k=%08x plen=%d\n", i, key, plen);
-                       i++;
-                       continue;
-               }
-               if (fa->fa_info == NULL) {
-                       printk("Trie error fa_info=NULL in fa[%d] k=%08x plen=%d\n", i, key, plen);
-                       i++;
-                       continue;
-               }
+               BUG_ON(!fa->fa_info);
 
                if (fib_dump_info(skb, NETLINK_CB(cb->skb).pid,
                                  cb->nlh->nlmsg_seq,
@@ -1965,7 +1955,7 @@ struct fib_table * __init fib_hash_init(int id)
                trie_main = t;
 
        if (id == RT_TABLE_LOCAL)
-               printk("IPv4 FIB: Using LC-trie version %s\n", VERSION);
+               printk(KERN_INFO "IPv4 FIB: Using LC-trie version %s\n", VERSION);
 
        return tb;
 }
@@ -2029,7 +2019,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 +2264,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 +2278,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 +2374,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;
 
index 44607f4767b871820f5d33ab9dfd230e59933745..70c44e4c3ceb28385d4a2e6f604e1c5509d54e46 100644 (file)
@@ -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;
 }
 
index e11952ea17afd89cfba231fee4e27754fbd9c849..f828fa2eb7dea154ff534e342fc75cdf8217b1ba 100644 (file)
@@ -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;
 
index 3ac7eeca04ac4ca4da81bdc1f6e75cce70316b79..981cc3244ef2724827e9c303a27d2a79a511cb4c 100644 (file)
@@ -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;
index 574d1f509b46cef77c10171c9ffe26d7bcd7cff2..2e5ced3d80622b77577826da486e721da6bed560 100644 (file)
@@ -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;
index 30aa8e2ee214263c6b1d124f5566eb56c804bf58..3cf9b451675ce13123a37c005dc269fff067fc87 100644 (file)
@@ -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
 
index 1ba0db746817cf2809e80c073899c8a37ba3d50c..3d45d3c0283c99ddf20ccedde1c98b093e743827 100644 (file)
@@ -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
index dc20881004bc57731b4ae348b8272d26622b863e..fa3f914117ec20f66e18b27f92b2cc7e58e47d9a 100644 (file)
@@ -65,7 +65,7 @@ static int help(struct sk_buff **pskb,
 
        /* increase the UDP timeout of the master connection as replies from
         * Amanda clients to the server can be quite delayed */
-       ip_ct_refresh_acct(ct, ctinfo, NULL, master_timeout * HZ);
+       ip_ct_refresh(ct, *pskb, master_timeout * HZ);
 
        /* No data? */
        dataoff = (*pskb)->nh.iph->ihl*4 + sizeof(struct udphdr);
index 19cba16e6e1e587c5281a997ac67ec7fa291da8a..ea65dd3e517abc20e5cf14034f7c7511f979827b 100644 (file)
@@ -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;
        
@@ -1112,42 +1112,46 @@ void ip_conntrack_helper_unregister(struct ip_conntrack_helper *me)
        synchronize_net();
 }
 
-static inline void ct_add_counters(struct ip_conntrack *ct,
-                                  enum ip_conntrack_info ctinfo,
-                                  const struct sk_buff *skb)
-{
-#ifdef CONFIG_IP_NF_CT_ACCT
-       if (skb) {
-               ct->counters[CTINFO2DIR(ctinfo)].packets++;
-               ct->counters[CTINFO2DIR(ctinfo)].bytes += 
-                                       ntohs(skb->nh.iph->tot_len);
-       }
-#endif
-}
-
-/* Refresh conntrack for this many jiffies and do accounting (if skb != NULL) */
-void ip_ct_refresh_acct(struct ip_conntrack *ct, 
+/* Refresh conntrack for this many jiffies and do accounting if do_acct is 1 */
+void __ip_ct_refresh_acct(struct ip_conntrack *ct, 
                        enum ip_conntrack_info ctinfo,
                        const struct sk_buff *skb,
-                       unsigned long extra_jiffies)
+                       unsigned long extra_jiffies,
+                       int do_acct)
 {
+       int do_event = 0;
+
        IP_NF_ASSERT(ct->timeout.data == (unsigned long)ct);
+       IP_NF_ASSERT(skb);
+
+       write_lock_bh(&ip_conntrack_lock);
 
        /* If not in hash table, timer will not be active yet */
        if (!is_confirmed(ct)) {
                ct->timeout.expires = extra_jiffies;
-               ct_add_counters(ct, ctinfo, skb);
+               do_event = 1;
        } else {
-               write_lock_bh(&ip_conntrack_lock);
                /* Need del_timer for race avoidance (may already be dying). */
                if (del_timer(&ct->timeout)) {
                        ct->timeout.expires = jiffies + extra_jiffies;
                        add_timer(&ct->timeout);
-                       ip_conntrack_event_cache(IPCT_REFRESH, skb);
+                       do_event = 1;
                }
-               ct_add_counters(ct, ctinfo, skb);
-               write_unlock_bh(&ip_conntrack_lock);
        }
+
+#ifdef CONFIG_IP_NF_CT_ACCT
+       if (do_acct) {
+               ct->counters[CTINFO2DIR(ctinfo)].packets++;
+               ct->counters[CTINFO2DIR(ctinfo)].bytes += 
+                                               ntohs(skb->nh.iph->tot_len);
+       }
+#endif
+
+       write_unlock_bh(&ip_conntrack_lock);
+
+       /* must be unlocked when calling event cache */
+       if (do_event)
+               ip_conntrack_event_cache(IPCT_REFRESH, skb);
 }
 
 #if defined(CONFIG_IP_NF_CONNTRACK_NETLINK) || \
index 1b79ec36085ffed8896fdd9882126b24400fd57c..d77d6b3f5f80163e8b3f97b3a6121257431ca914 100644 (file)
@@ -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 (file)
index 0000000..926a668
--- /dev/null
@@ -0,0 +1,806 @@
+/*
+ * 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;
+               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,
+       __be16 callid,
+       __be16 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 = htons(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;
+       __be16 *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(*pcid));
+                       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;
+       __be16 *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 = __constant_htons(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);
index d7a8a98c05e1982a9b4b13839ac169a44d00deea..15457415a4f32b45bd5f9883956cf308a86be5fd 100644 (file)
@@ -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);
 
index bb7246683b7421cb40c81f7d605ad5e6c584eb47..577bac22dcc6421e2afeccbce5f97889c3cdbf31 100644 (file)
@@ -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;
@@ -96,7 +91,7 @@ static int help(struct sk_buff **pskb,
        ip_conntrack_expect_related(exp);
        ip_conntrack_expect_put(exp);
 
-       ip_ct_refresh_acct(ct, ctinfo, NULL, timeout * HZ);
+       ip_ct_refresh(ct, *pskb, timeout * HZ);
 out:
        return NF_ACCEPT;
 }
@@ -107,7 +102,7 @@ static struct ip_conntrack_helper helper = {
                .src = {
                        .u = {
                                .udp = {
-                                       .port   = __constant_htons(137),
+                                       .port   = __constant_htons(NMBD_PORT),
                                }
                        }
                },
index 15aef356474264926ef3449a69751897e51ae8ce..b08a432efcf8e9d601005f5c31f666f815ccd2a0 100644 (file)
@@ -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 (file)
index 0000000..de3cb9d
--- /dev/null
@@ -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);
index ae3e3e655db555054c14dd34372e792abb2e25e5..dd476b191f4b5c135802839a840aa6bb34f88ed6 100644 (file)
@@ -989,15 +989,15 @@ EXPORT_SYMBOL(need_ip_conntrack);
 EXPORT_SYMBOL(ip_conntrack_helper_register);
 EXPORT_SYMBOL(ip_conntrack_helper_unregister);
 EXPORT_SYMBOL(ip_ct_iterate_cleanup);
-EXPORT_SYMBOL(ip_ct_refresh_acct);
+EXPORT_SYMBOL(__ip_ct_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);
index d2b590533452e201d48c8b1bc172a0661828b917..a78736b8525d1d865fb0c2ae9a2e28dd3d7d2cad 100644 (file)
@@ -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)
 {
index 1adedb743f609f8b349a545184040d54512f639d..c3ea891d38e7113a53f1a80227314fb4e35dba0f 100644 (file)
@@ -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 (file)
index 0000000..3cdd068
--- /dev/null
@@ -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 (file)
index 0000000..7c12854
--- /dev/null
@@ -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);
+}
index 7d38913754b1a5ca44771248d4f7548f19ad9921..9bcb398fbc1fc02dcfb7f2f6e0f039e8a238d1a0 100644 (file)
@@ -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;
index 2f3e181c8e97ad2455b0d488d8388b007c1b0a95..275a174c6fe69c56bf2296cb33323d910a34c49e 100644 (file)
@@ -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);
index d2e13447678e02dd00ba29c1a816cb59209a449b..715cb613405cca742b37540da12fd14d86d967e6 100644 (file)
@@ -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. */
index 304bb0a1d4f0f1b936e0500f08282bf137ae4505..4b0d7e4d62698a44acd992fd3e2a01e14b3037f0 100644 (file)
@@ -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;
index 29222b964951ce4d2d505a3d3d9bed0ca762e025..a7537c7bbd06f0040c4d44f255c081cea93a215b 100644 (file)
@@ -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. */
index a88db28b0af7d83db35c516cabcc337169a88aa3..b1a63b2c6b4aef5a55a78fe7db14c9214d4a417d 100644 (file)
@@ -384,7 +384,7 @@ struct sock *tcp_create_openreq_child(struct sock *sk, struct request_sock *req,
                newtp->frto_counter = 0;
                newtp->frto_highmark = 0;
 
-               newicsk->icsk_ca_ops = &tcp_reno;
+               newicsk->icsk_ca_ops = &tcp_init_congestion_ops;
 
                tcp_set_ca_state(newsk, TCP_CA_Open);
                tcp_init_xmit_timers(newsk);
index c10e4435e3b1258a9ca0b5615be8af6d103142a2..d6e3d269e90611250fabaea9005d0dc3abc3dea3 100644 (file)
@@ -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,11 +499,26 @@ 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;
                }
+
                if (diff > 0) {
+                       /* Adjust Reno SACK estimate. */
+                       if (!tp->rx_opt.sack_ok) {
+                               tp->sacked_out -= diff;
+                               if ((int)tp->sacked_out < 0)
+                                       tp->sacked_out = 0;
+                               tcp_sync_left_out(tp);
+                       }
+
                        tp->fackets_out -= diff;
                        if ((int)tp->fackets_out < 0)
                                tp->fackets_out = 0;
index 29fed6e58d0aa631c19d55c967d0bb9ff909c5f4..519899fb11d50bfad08cfd0135d117193a1f1f3f 100644 (file)
@@ -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;
 }
 
index 1cb8adb2787fc59f44c15dbf0f06ca533955e6f3..2da514b16d95e724d6b0f42b46bc7f642a94aef4 100644 (file)
@@ -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);
index d5b94f142bbaed3b96d2c939d919ea979e12bc6e..dde37793d20b00a2a7dbad7cc374873c43032f5e 100644 (file)
@@ -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);
index 540925e4a7a80161f87757e82d640938f7e90e9d..c450a635e54b929583b451df68f8cd5a5d6cde50 100644 (file)
@@ -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 ",
index e39dd236fd8e60e5fc2ae95e9d31b7969e9d1564..24bc0cde43a174d4090d4b6d5897c68246e5c966 100644 (file)
@@ -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)
index 4bfa30a9bc80f0ed6e26c7fdaf9f599b69ee9117..085d5f8eea29ca9f0a54000ace05795f326c6b25 100644 (file)
@@ -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);
index 27f3650d127e92f38ee8a1afcf56fecc3a6defe3..1d09485111d0119de9468624ff5db6c36cf6a681 100644 (file)
@@ -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 ",
index 2bb670037df3a9de75bf1b7580d6e015aece6927..beb2fd5cebbb31bcf6f61718777d494da821093d 100644 (file)
@@ -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);
index 5aa3691c578d3a0198aced9809b996a0569f1562..a1265a320b1170a43e1db063d573e20944582ca2 100644 (file)
@@ -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;
index 69b146843a20215a7c816a5b07e37788b5bf12c7..6001948600f31bcbe622f18a9fc4461f6ef8531b 100644 (file)
@@ -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);
index 8690f171c1ef28136e7e57e160e980955d6b742d..ee865d88183bb930d4d05faf01e584263a80f51f 100644 (file)
  *     Michal Ostrowski        :       Module initialization cleanup.
  *         Ulises Alonso        :       Frame number limit removal and 
  *                                      packet_set_ring memory leak.
+ *             Eric Biederman  :       Allow for > 8 byte hardware addresses.
+ *                                     The convention is that longer addresses
+ *                                     will simply extend the hardware address
+ *                                     byte arrays at the end of sockaddr_ll 
+ *                                     and packet_mreq.
  *
  *             This program is free software; you can redistribute it and/or
  *             modify it under the terms of the GNU General Public License
@@ -161,7 +166,17 @@ struct packet_mclist
        int                     count;
        unsigned short          type;
        unsigned short          alen;
-       unsigned char           addr[8];
+       unsigned char           addr[MAX_ADDR_LEN];
+};
+/* identical to struct packet_mreq except it has
+ * a longer address field.
+ */
+struct packet_mreq_max
+{
+       int             mr_ifindex;
+       unsigned short  mr_type;
+       unsigned short  mr_alen;
+       unsigned char   mr_address[MAX_ADDR_LEN];
 };
 #endif
 #ifdef CONFIG_PACKET_MMAP
@@ -716,6 +731,8 @@ static int packet_sendmsg(struct kiocb *iocb, struct socket *sock,
                err = -EINVAL;
                if (msg->msg_namelen < sizeof(struct sockaddr_ll))
                        goto out;
+               if (msg->msg_namelen < (saddr->sll_halen + offsetof(struct sockaddr_ll, sll_addr)))
+                       goto out;
                ifindex = saddr->sll_ifindex;
                proto   = saddr->sll_protocol;
                addr    = saddr->sll_addr;
@@ -744,6 +761,12 @@ static int packet_sendmsg(struct kiocb *iocb, struct socket *sock,
        if (dev->hard_header) {
                int res;
                err = -EINVAL;
+               if (saddr) {
+                       if (saddr->sll_halen != dev->addr_len)
+                               goto out_free;
+                       if (saddr->sll_hatype != dev->type)
+                               goto out_free;
+               }
                res = dev->hard_header(skb, dev, ntohs(proto), addr, NULL, len);
                if (sock->type != SOCK_DGRAM) {
                        skb->tail = skb->data;
@@ -1045,6 +1068,7 @@ static int packet_recvmsg(struct kiocb *iocb, struct socket *sock,
        struct sock *sk = sock->sk;
        struct sk_buff *skb;
        int copied, err;
+       struct sockaddr_ll *sll;
 
        err = -EINVAL;
        if (flags & ~(MSG_PEEK|MSG_DONTWAIT|MSG_TRUNC|MSG_CMSG_COMPAT))
@@ -1056,16 +1080,6 @@ static int packet_recvmsg(struct kiocb *iocb, struct socket *sock,
                return -ENODEV;
 #endif
 
-       /*
-        *      If the address length field is there to be filled in, we fill
-        *      it in now.
-        */
-
-       if (sock->type == SOCK_PACKET)
-               msg->msg_namelen = sizeof(struct sockaddr_pkt);
-       else
-               msg->msg_namelen = sizeof(struct sockaddr_ll);
-
        /*
         *      Call the generic datagram receiver. This handles all sorts
         *      of horrible races and re-entrancy so we can forget about it
@@ -1086,6 +1100,17 @@ static int packet_recvmsg(struct kiocb *iocb, struct socket *sock,
        if(skb==NULL)
                goto out;
 
+       /*
+        *      If the address length field is there to be filled in, we fill
+        *      it in now.
+        */
+
+       sll = (struct sockaddr_ll*)skb->cb;
+       if (sock->type == SOCK_PACKET)
+               msg->msg_namelen = sizeof(struct sockaddr_pkt);
+       else
+               msg->msg_namelen = sll->sll_halen + offsetof(struct sockaddr_ll, sll_addr);
+
        /*
         *      You lose any data beyond the buffer you gave. If it worries a
         *      user program they can ask the device for its MTU anyway.
@@ -1166,7 +1191,7 @@ static int packet_getname(struct socket *sock, struct sockaddr *uaddr,
                sll->sll_hatype = 0;    /* Bad: we have no ARPHRD_UNSPEC */
                sll->sll_halen = 0;
        }
-       *uaddr_len = sizeof(*sll);
+       *uaddr_len = offsetof(struct sockaddr_ll, sll_addr) + sll->sll_halen;
 
        return 0;
 }
@@ -1199,7 +1224,7 @@ static void packet_dev_mclist(struct net_device *dev, struct packet_mclist *i, i
        }
 }
 
-static int packet_mc_add(struct sock *sk, struct packet_mreq *mreq)
+static int packet_mc_add(struct sock *sk, struct packet_mreq_max *mreq)
 {
        struct packet_sock *po = pkt_sk(sk);
        struct packet_mclist *ml, *i;
@@ -1249,7 +1274,7 @@ done:
        return err;
 }
 
-static int packet_mc_drop(struct sock *sk, struct packet_mreq *mreq)
+static int packet_mc_drop(struct sock *sk, struct packet_mreq_max *mreq)
 {
        struct packet_mclist *ml, **mlp;
 
@@ -1315,11 +1340,17 @@ packet_setsockopt(struct socket *sock, int level, int optname, char __user *optv
        case PACKET_ADD_MEMBERSHIP:     
        case PACKET_DROP_MEMBERSHIP:
        {
-               struct packet_mreq mreq;
-               if (optlen<sizeof(mreq))
+               struct packet_mreq_max mreq;
+               int len = optlen;
+               memset(&mreq, 0, sizeof(mreq));
+               if (len < sizeof(struct packet_mreq))
                        return -EINVAL;
-               if (copy_from_user(&mreq,optval,sizeof(mreq)))
+               if (len > sizeof(mreq))
+                       len = sizeof(mreq);
+               if (copy_from_user(&mreq,optval,len))
                        return -EFAULT;
+               if (len < (mreq.mr_alen + offsetof(struct packet_mreq, mr_address)))
+                       return -EINVAL;
                if (optname == PACKET_ADD_MEMBERSHIP)
                        ret = packet_mc_add(sk, &mreq);
                else
index 86073df418f5f00e4bf84d44b169ad5b01fe7715..505c7de10c503f349cf850eb18c2f9faca07c132 100644 (file)
@@ -2414,6 +2414,17 @@ sctp_disposition_t sctp_sf_do_9_2_shutdown(const struct sctp_endpoint *ep,
        skb_pull(chunk->skb, sizeof(sctp_shutdownhdr_t));
        chunk->subh.shutdown_hdr = sdh;
 
+       /* API 5.3.1.5 SCTP_SHUTDOWN_EVENT
+        * When a peer sends a SHUTDOWN, SCTP delivers this notification to
+        * inform the application that it should cease sending data.
+        */
+       ev = sctp_ulpevent_make_shutdown_event(asoc, 0, GFP_ATOMIC);
+       if (!ev) {
+               disposition = SCTP_DISPOSITION_NOMEM;
+               goto out;       
+       }
+       sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP, SCTP_ULPEVENT(ev));
+
        /* Upon the reception of the SHUTDOWN, the peer endpoint shall
         *  - enter the SHUTDOWN-RECEIVED state,
         *  - stop accepting new data from its SCTP user
@@ -2439,17 +2450,6 @@ sctp_disposition_t sctp_sf_do_9_2_shutdown(const struct sctp_endpoint *ep,
        sctp_add_cmd_sf(commands, SCTP_CMD_PROCESS_CTSN,
                        SCTP_U32(chunk->subh.shutdown_hdr->cum_tsn_ack));
 
-       /* API 5.3.1.5 SCTP_SHUTDOWN_EVENT
-        * When a peer sends a SHUTDOWN, SCTP delivers this notification to
-        * inform the application that it should cease sending data.
-        */
-       ev = sctp_ulpevent_make_shutdown_event(asoc, 0, GFP_ATOMIC);
-       if (!ev) {
-               disposition = SCTP_DISPOSITION_NOMEM;
-               goto out;       
-       }
-       sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP, SCTP_ULPEVENT(ev));
-
 out:
        return disposition;
 }
index c699e93c33d72141332fdfa0c16afa87ed4a971e..f9264472377f563976060325a76cab8ec96da7ce 100644 (file)
@@ -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)
index 51885b5f744e938eaa71ffcb8617759469a68f7b..30ec3efc48a654fe16e7f7f096b42e4e44727b72 100644 (file)
@@ -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);
 }
index dcf04a09185de5fbd3507e221de81abbe9be90f1..64d3f1e9ca85e4a925b2c38680af74c70dc27a53 100644 (file)
@@ -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.
index 197cc2f3f1ecf2e0c27ac83c22bcac98240bb2fe..8cbbf2f3670987d47e823b11b27be3b487735698 100644 (file)
@@ -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 (file)
index 0000000..a596450
--- /dev/null
@@ -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");
+
index 96b1f2122f67bdac673a18fab792ea56e8d236ab..1caac0164643c202a55c1e8394b9669706723591 100644 (file)
@@ -118,69 +118,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.
  */
@@ -212,97 +149,44 @@ static int seclvl_sanity(int reqlvl)
        return 0;
 }
 
-/**
- * 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.
  *
@@ -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)) {
index cf6020f85403e54e23660e7c86c7e0f30e4750f4..12e4fb72bf0f46bfc22a5e1a8a75efd93792d650 100644 (file)
@@ -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");
index f40c8221ec1ba215b9526d74993ad5e8a4ed4256..6e4937fe062b40f2c4b3c05baaa9cc96f85c4cd8 100644 (file)
@@ -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);
index 92b89dc99bcd72a5e3bc51ee24795b434475317f..aecdded55e74aa04d4c2f9bcb05b2f39df8617fe 100644 (file)
@@ -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"
index 2e4a5e0d16db3726755dea8c8930f35138927395..0864a7ce414d7bddb48a7497314e90a5d956d159 100644 (file)
@@ -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.
index 98877030d579fa6f641dee8dca596241940f32e6..b2d5db20ec8cfb9e70639eb59e726f9bade0c74d 100644 (file)
@@ -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,
index 174bc032d1ad5e988875fe95e9f1a71ad96f97ee..6ee912259cc53b14aa900863d4ef5d89b74f5bbf 100644 (file)
@@ -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;
index d1e800b9866df5a2d6303dfa6b9b3430bc7be23f..48cf45cfd0b7943f23f1890fa3c898dc1b5a98eb 100644 (file)
@@ -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
index 227f3cf02771605d11e8ddd32c565bc902d75d7d..736edf358e050cee4f93e698811e974fe2f380c0 100644 (file)
@@ -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;
index 7fdabea4bfc8bf081e0e8ac8b46315c40762a11c..207c7de5129cba64c7ad340d7152352bb2a81973 100644 (file)
@@ -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;
 
index ca00ad7740c983de5d10f8fbe06ba96be09dd6b4..1f509f56e60c82108007dc6baa01b72fb1f91027 100644 (file)
@@ -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;
index 997dd41c584e67b9a71347a9935454e2ae07c575..9383f1294fb5ec528bd2160df78fd1b579ec5279 100644 (file)
@@ -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;
index 7f8bdf7b00588d55af030fa463bafb50b6744105..37024d68a26ea25a5358aff96c5c34857fc549d2 100644 (file)
@@ -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);
index d72f58f450ce442dac0386be21a94c567ac2e293..a5702014a704e0ffcbf153156532fd69a151601b 100644 (file)
@@ -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)
index 39a54a415528080a01620e71d7a40efdcbac1e66..91124ddbdda939322f6bc813fa418578b9ff2280 100644 (file)
@@ -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));
index 291b4769bde38f2bf2775958ce94f200e62f9732..8fa888fc53a0a6b8d717142240960696e959db12 100644 (file)
@@ -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) {
index 98fc0766f8853731757105c534556e27712e1e8f..69e1059112d1ace7eadd3fd85a40b48020488394 100644 (file)
@@ -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;
index a13bd7bb4c9f08cf6628ce8856f1c56896ba2e9c..842c28b2ed55cfad9266cd3e0245fe2f4648892d 100644 (file)
@@ -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) {
index 6430410c6c04703af940b04f377b15fdb304572a..fc23373c000dda4ddf6cd66b5cb8d585b1f59c7d 100644 (file)
@@ -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;
index 9f4c9209b2717a0ff23b938402e9fb5132efeaeb..1be470e942efa6e0c6159d99a0bac430caa553f2 100644 (file)
@@ -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;
 
index 0082914a7e3331825b7a302dfe9dfe4035694971..0503980c23d91ca67ac04c93fc9ae86740cc42df 100644 (file)
@@ -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:
index 9a174fb96565368abe767344de9bffca32887e09..b3f5344f60bef92f440eef1a3e88ff167bd488ba 100644 (file)
@@ -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;
index 03c17159dd8e0fe48f9625af9dfd979038a5adff..67abebabf83e4afb1d9da5e69215adf7d3eee8ca 100644 (file)
@@ -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;
        }
index edba4118271c74695d4f3d1715d47255d5160b2f..7c20eafecb8ac6932cf9e547d6d16e0edeb129da 100644 (file)
@@ -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;
index 32e91c6b25febb7cf02b825a1037f7a236fcdf83..207c2c54bf1de91cbc5e69648098289e89f62f47 100644 (file)
@@ -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]);
index 2622b8679ca76be886524be263517560e8f2e43b..b3cee092b1a4491f6ba5cdbb0b4a3844b4cc2804 100644 (file)
@@ -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;
index bac4b4f1a94ecd0d07c065f16fa220d65e39f7ae..1ab1cf8158c840b9651476d5229316da426bddcc 100644 (file)
@@ -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;
        }
index 9aece6c65dbc8449c569c849c6fa0c5fa4e5bdb4..f0e95c8f2eef04fdd0b5dc864fec6814986b3ade 100644 (file)
@@ -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;
        }
index 0a6f2a64f6923f619f55d78bfe6de76977934076..55571e15cd38b79d85914ce3465041eda189c1f9 100644 (file)
@@ -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;
        }
index 1a7736cbf3a4717202159087fb4355071c5c7c4e..8257fce2ca1bf3ed82cd40c42be5e5b4c3edf19e 100644 (file)
@@ -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;
index 42ca9493fa600a3ddd30b6ed6abd942d8616d025..64d594b3170f1ffd84f22fcebbeae9a9bb101874 100644 (file)
@@ -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;
 
index 87f85f7ee81461f7463c1a4bd4575f89ca027843..b20378024547b9b84495105a50f22281444e7fbc 100644 (file)
@@ -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;
index 7449d2a6262902277abecdcf32726850d436a15b..24644150f24b9140210315edf411696307dd152a 100644 (file)
@@ -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 */
 
index d8f76afd284bc19efec4b1c577280508c99a69db..a886db94b1fa0be678cb0b9e8f4793a0b7841188 100644 (file)
@@ -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
index 4d80f39612e835f57d0f6cd6139d2b7d4a24aa6a..252b5273100376e02f6673d9a9e90871098d6ab4 100644 (file)
@@ -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;
index ea945a5d2a0b194f4884cdbac0aeae4c00f3ced2..5dd0e6a19e5072af35fefd508ff961e102fc5892 100644 (file)
@@ -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;
index 3b7647ca7ad9e7a35bdccc2dcdc52e2bfe56cd16..4767cfdc361fc00348b6d48ae41d9a0022810c05 100644 (file)
@@ -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;
index 5b40ea2ba8f4f9aaff3f3cbd3aad60fc16510b7a..019d43a462d7ade1e8094189094a9b4c1bb0c8c2 100644 (file)
@@ -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);
index 03acb2d519ba6bbf975c18ae19d8e13f0e66328b..d4d7d326c4b150af1fc4589d1a4794cf9fdf2d20 100644 (file)
@@ -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;
index 4374829ea77043300f088527e74ac815215f9293..b4674ae3bc30d39d808dbfe006036924a44f4f7b 100644 (file)
@@ -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);
index 603b63716db67d27375b09a1308ad53f20210f75..2dc1aecfb426ec6c0a4d613f7a8627d91e1fd142 100644 (file)
@@ -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) {
index b976951fc100236f34b4a843517956793ca0277d..57ec31df0d15963ccd9727b70299530d542c5fd0 100644 (file)
@@ -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;
 
index a519732ed83313bbe443bf17c2dc470fd9fe6925..cd641bca9945b6b35670bd9e2093eb2dc4e88622 100644 (file)
@@ -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;
index 98de2e711fde90b174d6cc87ffde3b00861073d1..5f5c3cb37cbf69e4d6e0254d5433c329e4c056f6 100644 (file)
@@ -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;
index e8f0a6683d50b5a9305df2642990313c578061e1..0d9eff85ab88c7934ee8842f7aa79b304b34da02 100644 (file)
@@ -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);
index a7f76fc9528092bc38985337409f97dd81451270..b57a3c07ff6f6c0eb1c161f8d7ed2efed1e363a6 100644 (file)
@@ -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;
index a66484b5cf0e921991895296021ae56aad2c34dc..e4f512aa742662ed95c595bb8634b67dadb74420 100644 (file)
@@ -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;
index 3271e9245490b81d3b3f6c3d9d3e6b54ec66612d..9e76bddb2c0beb3aab1acfb9e173f3687297e793 100644 (file)
@@ -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
index 4104f6e292e959ead04756ccd52d18ee52e49326..22b104624084656b25c8062693e8c7c75a352341 100644 (file)
@@ -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;
index 3b2bee19e2c0371c2ce4a151984b693837a1d0a5..efcb4eb2d1a05c955f345c6ea10683ec60876b5f 100644 (file)
@@ -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.
index a61640cf7ae7c3b565d79c328a24aaebd972702a..64ef7f62851dd677be167314f07eca424b1cf23b 100644 (file)
@@ -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;
index cb36ecb78697b27288f6cea46a78b15abbf95af6..54e2ff9b5ca13dca3b2cc3914b523adcdfc2cd3b 100644 (file)
@@ -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)
index 0f83c5241b6bea081daedff620e5540e17d6d4ac..fe3f921ffbe3707137defded6690020771e641af 100644 (file)
@@ -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;
index 1280a57c49eb89ba3157a4a7a1e15b51394d660f..3a25c89d2983936552b081911866a1106f72dfb7 100644 (file)
@@ -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);
index c313e5205cb87365793fea44b2f3fff66f5a69de..1f84d78260dea71d15e27d5859d7b673e1d4e621 100644 (file)
@@ -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;
 
index 33da334ae9818149fae31d0273bb13b667a80063..21a2b409d6d312adfc759526285064c605342863 100644 (file)
@@ -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 */
index 8261464dade8e26aca4da46301bfb4422b4b66a5..380c2c704c54342ea175115b8b6e219f4633c527 100644 (file)
@@ -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;
 
index 986df35fb82948fdcaea2a1c043cae2ec3ebe7cd..416172ea1f4753c6acc72b56b4bf3cdd67a36499 100644 (file)
@@ -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)
index 5937711e950562c922b5fcb9600c00edc2bfe77b..af12185ab8a2f07bd258952eac0556fbb0aa2aa1 100644 (file)
@@ -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;
index c6fa5afa3e9ae3414ce5e08e0e36df38feee458a..4697b1d75cbb13eb10cb9cab40dd663e6fbec05d 100644 (file)
@@ -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;
index d4becf44e24787ddc9743bb943da30f41c0e02ff..c2312d912fc7d8f1177dac0ad14a572a98385f61 100644 (file)
@@ -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);
index a3fda859dd15c177b70f532d6c81b6073cd0d6ee..a21f7d541f866ff31caea45b529a0a9262961727 100644 (file)
@@ -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;
index e8fa7e1a68e8da63f2e54f70d8cf5ebcf661dbe2..e4e505b9d88bbe75b02cdc74384384b2e0d384b3 100644 (file)
@@ -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;
index e13122f3fc50947258372f8b728311dca009a3d6..103a7dcd0dde570cdc0063d0e68e09474400ef4d 100644 (file)
@@ -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;
 
index 5adde308a00fa252d180122b24e22fb867af6fb5..af5eadcddd92da2e64051921fbeb00c10f9ea951 100644 (file)
@@ -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);
index 0419c4336a5572587ca08155a7e7da91e1579b0c..d51b51dd86d6dda11178e571aadb892e327b753b 100644 (file)
@@ -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);
index 2da8d7f157f4609eebc0b8b584af20bea91b1403..fd65da654267bda2e31ea60e6cd86dcd15b5a366 100644 (file)
@@ -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) {
index 5c3948311528efdca7817e63e8e3fea96c8b8460..5d6c300ac0d5cb0d03d36474e233d5126104d01a 100644 (file)
@@ -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).
index ae860360ecf963a3620357e505b2d6025eb57800..27a9dcfbba008cbff69860fe279b80682b12edbe 100644 (file)
@@ -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;
index 8c399340cd7240b4c75834d9037d87cade038958..3ebcc482b07a101ab6dc0433b25c2af6c27ea86a 100644 (file)
@@ -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)
index bc642dc94547b5cea97570988571a9a506070cb2..303861cd03cdfcc4a1396714cf7e1be60d07e672 100644 (file)
@@ -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);
index 1fce8b9f37cf88de82991392a12ced9aa363443e..5252206ea38868a93479e6f74b243c9bb5eb487a 100644 (file)
@@ -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++;
        }
index 7640837659ead2788f0f067b2c5b47b52bedd832..9be5416bcb92023c04970459f99cc2591989b6cd 100644 (file)
@@ -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)
index 3199941edd9bafd67de441b6bbde50f18f343338..32318258cd8ed2384b0248cbf06da7a2521faaa6 100644 (file)
@@ -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;
index 39f4eff44f5c8c5ac8fb2dc7595ef2082325fe5e..d28315dc72f7d543a01c24622a666bd6ba6cf381 100644 (file)
@@ -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++;
        }
index c5eaec087b466d0b0756e310456945ceffe95faa..26a7d335ed8e0c5fa015dfa6957379d67cc2f768 100644 (file)
@@ -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)
index 17f68d07d9b244d213d0c38df86094bdd368077c..aac898765c02278e99c7b8ac73efb6afb6de37f6 100644 (file)
@@ -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;
index 1d832b2adb7ca34ad93863927d3c2ec03413db4a..d0ea19f427034e886fc289f2457f457e6d8f234e 100644 (file)
@@ -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++;
        }
index a636d9ce3502ecf36bdab0291acdaeb0cd4fd514..8f2872f8e8f6daae4907480b5eeb97f2c07d0a1d 100644 (file)
@@ -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;
index 886763f121323fad88f816f2e73c00b3df4d8095..7f96ac237f3c346ae7ecc5bfcdbbdc09ad190b41 100644 (file)
@@ -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;
index b75066ab46fc33edfa1dd8262f0d1beb822a7bb9..beb01365dc466642f15fcbaa4599976cd74290ec 100644 (file)
@@ -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;
index a99fa5040b46c8b5d575b53cb889207fccdb335b..39cef38835ca2b2c2f3a90c827f81bc9f17544fe 100644 (file)
@@ -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)
index bc6fecb18dcf98ca4c601c4323b98a270fa9d427..d2e7cb1df537f9f9559edfb475c6608e0c9a0dcd 100644 (file)
@@ -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;
 
index 400ff34710fb7b28a7de899fed21f1fcab639ff6..0bb44b5193407a772eedf719b5385a452904b997 100644 (file)
@@ -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)
index 46e867daba6afd43a3ab128dbe1819c7a2d8399e..358cba9d738fa1976a1b51488f2f40ceac396b59 100644 (file)
@@ -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)
index 75bd6eca63e741ed8545f86543a97884a8130eb7..e2d2babcd20b47421ce034afcbda41837cb66a89 100644 (file)
@@ -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;
index 411a702d85ba5467a9833cec04b4926e0da366e6..73573cb1db6a3555a2b86f20472ea32863eb0330 100644 (file)
@@ -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 */
index 028af4066595f30759eaf4bfb033730a5c572088..5375705c054bbaceece95c7cd7a9797136a688e6 100644 (file)
@@ -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);
index db5eb8b55058453a45cb4b1c4d3af32e97c3b47c..0209790dc4b5dafdf4b92fbabec323956652aacf 100644 (file)
@@ -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;
 
index 60e2c53c49fc233b1bc5f9413713c36450bc20dd..7888783d68f598ed2c1ef179834d22cbf5c17ff3 100644 (file)
@@ -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;
index d64790bcd831ad8104ec2e50c8e05ca228424fd3..7192d4c758e6026015c42d58aa9c5517c1361f2f 100644 (file)
@@ -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;
        }
index e2cbc4202b3de3f16fee4901192960c86f28d17f..c41ac25e85ca6edcb924bbb8b43f1d4179ccec04 100644 (file)
@@ -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)
index 5b6bde213ea0052b9a49a418810b46b9b3c91cdb..f0f205ae425fec52b29d0460243983c4f8f7bf40 100644 (file)
@@ -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);
index 17f585b0ddc19413e10dda63c9017b0d7bb46c54..52f2294da62b48c46784aa7a20b3d0727d44352a 100644 (file)
@@ -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)
index 3959ed694eeccad24490825e6c1bd63917c4f92e..9f6b58c79209cbc4f217a0b9dd700bf0270e37b0 100644 (file)
@@ -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++;
index 79b022070ba33b1c34d55ea71401c87a63464f4a..0a572e0a47e62d891f5a5e30d704cfb3f952e217 100644 (file)
@@ -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;
index 531f8ba96a71ae40d05b810cc6b42e36fe2ec165..2433b7727404a061b80c815957c86048c1fa3f55 100644 (file)
@@ -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.
 
index c20522b0213463409a92f750c50940944081e19a..3f9684f1d1d2a24e1fe7cbcf24f98d3a4ca3a5a7 100644 (file)
@@ -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;
index 4491733c9e4e3f2f9c332937356f6565a40c5c63..2c2ae2ee01ac3df26a301e7fd0f86e371a3f20c4 100644 (file)
@@ -1295,7 +1295,7 @@ static int au1000_mmap(struct file *file, struct vm_area_struct *vma)
        unsigned long   size;
        int ret = 0;
 
-       dbg(__FUNCTION__);
+       dbg("%s", __FUNCTION__);
     
        lock_kernel();
        down(&s->sem);
index 58f879fda975ced1e91c742b735271a9e944c688..26e5944b6ba86cac90c686232724b3e197fa1703 100644 (file)
@@ -1859,7 +1859,7 @@ static int it8172_release(struct inode *inode, struct file *file)
        struct it8172_state *s = (struct it8172_state *)file->private_data;
 
 #ifdef IT8172_VERBOSE_DEBUG
-       dbg(__FUNCTION__);
+       dbg("%s", __FUNCTION__);
 #endif
        lock_kernel();
        if (file->f_mode & FMODE_WRITE)
index d7a8f9f5896fc2617a6b69240905c5bc81d99580..f560dd8cdb90dd4f9ff20c3a401cb07f21b0ae2b 100644 (file)
@@ -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;
index 1e458919cce6dfbc97822c95b383baac9eac041f..a5d593c66f9fca6b05ebade6a33d873dfba89397 100644 (file)
@@ -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
index b40575c3349adbc7011121cab44a06c53e16e4ca..42fabfcfc2a9aabdbabaeb11a641aeacfbbed1a8 100644 (file)
@@ -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
index 5501f4440c9223439f476788ecfe6211052d948b..e64cb07a39c2e3cdf4dca8a17d0e51a6d980f6e6 100644 (file)
@@ -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;
index dadf387ad0b8a2b69b6a742e4ed73868dd75222c..6d73514dc49e040dd92310e6057618db8cd5b26b 100644 (file)
@@ -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
index b584172c1104d55c470a9f810ee0eb9e14f79f49..045ddc743edcae9beca7674112e0688bda4ce14f 100644 (file)
@@ -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;
 }
 
index f9ce0fd2f52fbecdbc79ce9eb8487ecc7facd669..4032c57483708731a1490f05f09ccb07cdd717e0 100644 (file)
@@ -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 (file)
index 0000000..d7d99a2
--- /dev/null
@@ -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 (file)
index 0000000..5e6dad5
--- /dev/null
@@ -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__ */
index 4943299cf137dce8ab4bcb369ad9813ad0660173..d683f7736a63b16935a443da3d44803be74cf207 100644 (file)
@@ -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),
index ca28b229c704051154ef1a05aae2a485f7234e64..196ec1c61bb4712342055924902863064e8ca200 100644 (file)
@@ -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),
index 188df085b7ee5d4ae21903bebd1b6381b48cdc6a..241eacf1e6522d086e1eeeceba1e15bc0844681f 100644 (file)
@@ -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),
index 8d2002951bd78381194a99e38689f8759171879a..c1a239a4dac642b785d354960f6a1c76f225c223 100644 (file)
@@ -405,7 +405,7 @@ static int snd_atiixp_acquire_codec(atiixp_t *chip)
 
        while (atiixp_read(chip, PHYS_OUT_ADDR) & ATI_REG_PHYS_OUT_ADDR_EN) {
                if (! timeout--) {
-                       snd_printk(KERN_WARNING "atiixp: codec acquire timeout\n");
+                       snd_printk(KERN_WARNING "atiixp-modem: codec acquire timeout\n");
                        return -EBUSY;
                }
                udelay(1);
@@ -436,7 +436,7 @@ static unsigned short snd_atiixp_codec_read(atiixp_t *chip, unsigned short codec
        } while (--timeout);
        /* time out may happen during reset */
        if (reg < 0x7c)
-               snd_printk(KERN_WARNING "atiixp: codec read timeout (reg %x)\n", reg);
+               snd_printk(KERN_WARNING "atiixp-modem: codec read timeout (reg %x)\n", reg);
        return 0xffff;
 }
 
@@ -498,7 +498,7 @@ static int snd_atiixp_aclink_reset(atiixp_t *chip)
                do_delay();
                atiixp_update(chip, CMD, ATI_REG_CMD_AC_RESET, ATI_REG_CMD_AC_RESET);
                if (--timeout) {
-                       snd_printk(KERN_ERR "atiixp: codec reset timeout\n");
+                       snd_printk(KERN_ERR "atiixp-modem: codec reset timeout\n");
                        break;
                }
        }
@@ -552,7 +552,7 @@ static int snd_atiixp_codec_detect(atiixp_t *chip)
        atiixp_write(chip, IER, 0); /* disable irqs */
 
        if ((chip->codec_not_ready_bits & ALL_CODEC_NOT_READY) == ALL_CODEC_NOT_READY) {
-               snd_printk(KERN_ERR "atiixp: no codec detected!\n");
+               snd_printk(KERN_ERR "atiixp-modem: no codec detected!\n");
                return -ENXIO;
        }
        return 0;
@@ -635,7 +635,7 @@ static void snd_atiixp_xrun_dma(atiixp_t *chip, atiixp_dma_t *dma)
 {
        if (! dma->substream || ! dma->running)
                return;
-       snd_printdd("atiixp: XRUN detected (DMA %d)\n", dma->ops->type);
+       snd_printdd("atiixp-modem: XRUN detected (DMA %d)\n", dma->ops->type);
        snd_pcm_stop(dma->substream, SNDRV_PCM_STATE_XRUN);
 }
 
@@ -1081,14 +1081,14 @@ static int __devinit snd_atiixp_mixer_new(atiixp_t *chip, int clock)
                ac97.scaps = AC97_SCAP_SKIP_AUDIO;
                if ((err = snd_ac97_mixer(pbus, &ac97, &chip->ac97[i])) < 0) {
                        chip->ac97[i] = NULL; /* to be sure */
-                       snd_printdd("atiixp: codec %d not available for modem\n", i);
+                       snd_printdd("atiixp-modem: codec %d not available for modem\n", i);
                        continue;
                }
                codec_count++;
        }
 
        if (! codec_count) {
-               snd_printk(KERN_ERR "atiixp: no codec available\n");
+               snd_printk(KERN_ERR "atiixp-modem: no codec available\n");
                return -ENODEV;
        }
 
@@ -1159,7 +1159,7 @@ static void __devinit snd_atiixp_proc_init(atiixp_t *chip)
 {
        snd_info_entry_t *entry;
 
-       if (! snd_card_proc_new(chip->card, "atiixp", &entry))
+       if (! snd_card_proc_new(chip->card, "atiixp-modem", &entry))
                snd_info_set_text_ops(entry, chip, 1024, snd_atiixp_proc_read);
 }
 
@@ -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),
index f6236c63aaaae2c3d5cdaafe9facf7bd85e56281..04b695d6fd4839f7b77cadab3964988fdf058a2d 100644 (file)
@@ -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),
index 72bba7b2d983811bbba99a098cbfccbd5740ef20..d5261bdec583d5fbac6bcfe438d35e8d4ac705c3 100644 (file)
@@ -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),
index c5557eaf3e2e0ffafcb76a0c442fc88116bc8901..2236c958aec01b392ce72e28b1ae64405c24ce3a 100644 (file)
@@ -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),
index 7e27bfc3743985d06a4c1fee9a62a86061143b0b..ba07960921d8018f92d92957275b37ccf25105d4 100644 (file)
@@ -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),
index b6b8882ce704fb3bd70dd11b5d380f97f64bcc8d..c10e4a54301b814a0d2febb9d202d291287cd84f 100644 (file)
@@ -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
index b098b51099c2ddbccac84f9ebf2ebae629837b90..1eb3315d136dd2e50bbc0aab0168b32ee7cbf4b3 100644 (file)
@@ -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
  */
@@ -347,25 +340,6 @@ MODULE_PARM_DESC(joystick_port, "Joystick port address.");
 #define CM_EXTENT_SYNTH          0x4
 
 
-/*
- * 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
  */
@@ -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),
index c7a370d4f923f96985d33006683be294c3dd09bc..dc87e0144b5adc7fe5b1b452f33e62cf9fbde246 100644 (file)
@@ -56,17 +56,6 @@ MODULE_PARM_DESC(enable, "Enable CS4281 soundcard.");
 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),
index b9fff4ee6f9dc789db6285c08cf18bf2332b6260..32b4f8465cefb898c2fd107188621eda60109502 100644 (file)
@@ -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),
index 4b052158ee3378bb32ec9c3670903a1f8350e6fb..6e3855b8b33d9922c0cafcdb59f1fd3df99e9c9f 100644 (file)
@@ -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),
@@ -3524,17 +3524,6 @@ static void amp_voyetra_4294(cs46xx_t *chip, int change)
 #endif
 
 
-/*
- * 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;
index fc377c4b666c6d2d7846a3c13b12b50e144bd288..b0e00f0a7c2f521380027254b8d35f0bc9c958b5 100644 (file)
@@ -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),
index e69d5b739e802f84c92029d9afdd51b8456c6a9b..e87e8427f25f0a4c15e3b83f2e128baf2873b911 100644 (file)
@@ -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;
index 52c7826df4402ee0e71629ff425bc5ab1f284d9a..ad15755a63c35a788bfbfea7323461713cad7f1a 100644 (file)
@@ -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),
index 637c555cfdb1f42b4a3be06e98dc806fe20ff839..646b5d972e6f3b8cb0281eb6f6266395a750670e 100644 (file)
@@ -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))) {
index 9c35f6dde1b5a49ccbb4f73f44ac723a21315b77..66ba27afe962523ea14ef5589d9448c75e9c87f9 100644 (file)
@@ -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;
index a1691330d3b6f53fa8d852b4e87edf66d43ad2d8..d59c7f345ad6983eeadf1bbe5ca5b4e287389b9d 100644 (file)
@@ -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)
index f06b95f41a1de5daa5e73fad55d9b7d7829bd271..bef9a59f46d7d4d2adfc26fc29a396f9c9eb33c0 100644 (file)
@@ -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),
index b492777bc30ffda252e86e1677b9d77c75dd9148..17fa80c23870b8631b6b2a40d5269ee0d2d531c9 100644 (file)
@@ -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),
index 9d7a2878393060f303bf1974571995311d29b046..ecdcada90ca25945923a938472e506400344fcd6 100644 (file)
@@ -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),
index 36b2f62e857385ace4b567b846ac31edd4b0c679..e5cfa2a0c24639cdf4354e7e2aa30771ec6a63b0 100644 (file)
@@ -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),
index 20f7762f714444a8ed5e516977cb0ac4bd4487bd..3815403ed0953249418e2dc86ddf227833cf4970 100644 (file)
@@ -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;
index 63a29a8a2860e34e092f852f92e86b81511abc65..bb53bcf76742ed1ccc77078e2efb4c2cdc275a40 100644 (file)
@@ -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 */
index 1229227af5b5f4c98bfa2e1a998817cfb27c5471..5b829a1a4c60ea843c9621bcc9f39778b7905b01 100644 (file)
@@ -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;
index 15107df1f490808ebc52dfc5e1a977ee7dc83d08..9590ece2099dd6e65c3cfbe159c5702ad26b2b55 100644 (file)
@@ -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),
index de1217bd8e68288733f59fcdab0f4ea6441c33e2..08f6a6efc5e6b75212c2a9c62a2c6a9e735c742d 100644 (file)
@@ -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: ");
index bceb83a42a38d50705c8eeb91d6af1e72df63013..da6874d3988cfdb44dd3d11ec07cbfaf97f3890b 100644 (file)
@@ -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;
 
index 07fb4f5a54b36558c65575acf630ec6951f5b559..523c362ec44d6de4ba13173909f5531138536952 100644 (file)
@@ -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;
 
index eeb900ab79afdbb677e255a96b0fa62f3308d27e..849b5b50c921eda305f5059efa6f8221a0b3a4f1 100644 (file)
@@ -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;
 
index b0270d1b64cea38957c04eea9cdd862889a57990..d014b7bb70df8b3b1d582e745aff0bbf0966efb6 100644 (file)
@@ -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;
index 9d503da7320db9d21706f7f6717a834af644853c..33a8adaea768ab7ac842e0c7e65c178aedd02da6 100644 (file)
@@ -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;
 
index 4405d96cbedf925d7fe9a4e928a7079694fc2e52..2e0a31613ee6c37d065e42521efddf7df50d4559 100644 (file)
@@ -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;
index b97f50d10ba308cd532bac7285c45b9107fbcbbc..a6d98013c331fe95bb69771079b88881eb48839e 100644 (file)
@@ -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),
index c7af5e5fee13e1f2d318ae32b5d2ba5d7781e487..c3ce8f93740bb9bc77805eed5455896ec21fa785 100644 (file)
@@ -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),
index 3fb297b969cd78bd9844e5c58ffdc118d3dd7418..2437876a44e4e0f73c7e6f84f007022763bc2d6f 100644 (file)
@@ -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;
index 5bf734b04fa065f0e6999828ee177f8479e0967e..dcf1e8ca3f6601f8ae63e2ec0036ab2f5484d27f 100644 (file)
@@ -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;
index 25f827d8fbd9e06c126a469db7b5f69cd0eb5401..a5f852b1f575b81d4f14b68e1d63153cef27fbda 100644 (file)
@@ -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;
index 7b548416dcefc086295511b6845359975bb8dda8..1a96198a17ae618f333691017e3e909293ce1650 100644 (file)
@@ -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 {
@@ -1758,6 +1709,12 @@ static struct ac97_quirk ac97_quirks[] __devinitdata = {
                .name = "MS-9128",
                .type = AC97_TUNE_ALC_JACK
        },
+       {
+               .subvendor = 0x1014,
+               .subdevice = 0x0267,
+               .name = "IBM NetVista A30p",    /* AD1981B */
+               .type = AC97_TUNE_HP_ONLY
+       },
        {
                .subvendor = 0x1028,
                .subdevice = 0x00d8,
@@ -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),
index bb758c77d211067ab49979f0fb962f7db654ae2c..9e2060d56c244f3f6a35aa25e550c43805dc2f5b 100644 (file)
@@ -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),
index d2aa9c82d41e44029d737e370cb8155e899a3c56..09f9cbe116a38734cea09038d60338b79916320d 100644 (file)
@@ -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),
index 39b5e7db1543b13549ece82a5adcbe7a2d53ee16..2693b6f731f3e27c03c1754a12097e2674574ce0 100644 (file)
@@ -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),
index 6c868d913634cce920e35a364c930e71939cfae7..1a62c7f6c52bb396666d8b13693a4a9c7a2cd3a3 100644 (file)
@@ -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),
index 2bbeb10ff7c4a0c3aa182a98176a0dde05cf461d..5c55a3b1d121b247c46cd8a5d64274a1631c847f 100644 (file)
@@ -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),
index 456be39e8e4a1171f296e2eab71513b0efb4d490..cd313af6ebcf226f4ea7f29680923732200d4205 100644 (file)
@@ -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),
index 9645e9004a48e49550e7e26d08c091595a52df80..c495cae78dbf39f4d566e99eb888ba2749820b0c 100644 (file)
@@ -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),
index 6694866089b5cd8061e088a1c27490d1109bbbe4..52525eb198c742dcd1f75e0a8970d6c19e3a91b3 100644 (file)
@@ -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),
index 5d786d113b254422e1aa7d8aecbc31f330e8294f..fc3f3283ff37e28ccef26b506a16784cf60f97c3 100644 (file)
@@ -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),
index 8ee4d6fd6ea789e20b3c2b1e0180efc7cbcfe051..b600f45e183474aca9b8b9ee2bf7a2881f0c293e 100644 (file)
@@ -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),
index 60ecb2bdb65e79231e6bc888d7d51a98734c4f20..1f6c2bfd43fdef56faa85973b24e7b70f431d40d 100644 (file)
@@ -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),
index 940d531575c098cd736776420b0b674c45094e3d..a8ca8e17853f3b0142241bd807818c738761da4e 100644 (file)
@@ -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),
index f30d9d9478629f07f39441e7dfd8043a41d70f51..777da9a7298b570e6cea4f363d416b376beab4e7 100644 (file)
@@ -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;
index 56c6e52d7264228e965a3055db1de0219e70c2ae..6db7de6b9719532c18a9fd9d78a17530f3170090 100644 (file)
@@ -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),
index 5872d438a04a5f50f4f47aafe5ff3d4cabc9eb58..7eac6f6ac737fee70fee677edd319a7123030ca4 100644 (file)
@@ -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),
index dca6bd2c75806298eeacf5e5468f7141a7141240..2a7ad9dec02175409a54d8f5d2560f6150d2a51a 100644 (file)
@@ -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),
index 5b5b624b47d0c6623f79c39893de23fe2d9451f8..2e69abe51aa985dbc0947689946a2659d2cd374b 100644 (file)
@@ -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),
index 054836412dc4069b60c0af957058d902b49b1498..27fa523639aea48ae451d2e73828ce6017e07f2a 100644 (file)
@@ -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;
index a2132e3763dd7b18be026b2cd9165a0cbac6c22e..0208c54896b36e26d031f8737dfb92e2bfb0b5fa 100644 (file)
@@ -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;
index 75213bf4d56728d55617987a735f8bda9bd4656a..206b9333f91f437d442d8f254aba311d782fadb0 100644 (file)
@@ -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
index c89e82eb06a6df91840c5863e8804d643db94e09..e35b48d29c452132f875f5d328325824a97a448d 100644 (file)
@@ -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;
index 231f6432ea6d08bb27023c8423860b9b2e0ac03d..a6d8cbf4064f8a749880d756956a23979918ce1c 100644 (file)
@@ -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;
 
index b94437c024b1dfce38f39279b3876f935589c838..65384afcfc3f39480e95b226806033421419ee8e 100644 (file)
@@ -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;
index 25a8a558ef92b6ab201099e5e487556bba397bf7..09ab138646a641471321d1bd3ebff27877986f3a 100644 (file)
@@ -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.
 
index bd8a850e93eaaa85bd97dd1c14e84b4289efb026..46d504ba7e0394f6ba207aafbc5b791c516f8450 100644 (file)
@@ -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;
 
index 36f9fe4d7beac9c76a3091311bd346fc827feb63..f4361c518e460565d147542636c5eda196905f1e 100644 (file)
@@ -173,7 +173,7 @@ static cs4231_t *cs4231_list;
 
 #define CS4231_GLOBALIRQ       0x01    /* IRQ is active */
 
-/* definitions for codec irq status */
+/* definitions for codec irq status - CS4231_IRQ_STATUS        */
 
 #define CS4231_PLAYBACK_IRQ    0x10
 #define CS4231_RECORD_IRQ      0x20
@@ -402,7 +402,7 @@ static void snd_cs4231_outm(cs4231_t *chip, unsigned char reg,
                udelay(100);
 #ifdef CONFIG_SND_DEBUG
        if (__cs4231_readb(chip, CS4231P(chip, REGSEL)) & CS4231_INIT)
-               snd_printk("outm: auto calibration time out - reg = 0x%x, value = 0x%x\n", reg, value);
+               snd_printdd("outm: auto calibration time out - reg = 0x%x, value = 0x%x\n", reg, value);
 #endif
        if (chip->calibrate_mute) {
                chip->image[reg] &= mask;
@@ -425,6 +425,10 @@ static void snd_cs4231_dout(cs4231_t *chip, unsigned char reg, unsigned char val
             timeout > 0 && (__cs4231_readb(chip, CS4231P(chip, REGSEL)) & CS4231_INIT);
             timeout--)
                udelay(100);
+#ifdef CONFIG_SND_DEBUG
+       if (__cs4231_readb(chip, CS4231P(chip, REGSEL)) & CS4231_INIT)
+               snd_printdd("out: auto calibration time out - reg = 0x%x, value = 0x%x\n", reg, value);
+#endif
        __cs4231_writeb(chip, chip->mce_bit | reg, CS4231P(chip, REGSEL));
        __cs4231_writeb(chip, value, CS4231P(chip, REG));
        mb();
@@ -440,15 +444,12 @@ static void snd_cs4231_out(cs4231_t *chip, unsigned char reg, unsigned char valu
                udelay(100);
 #ifdef CONFIG_SND_DEBUG
        if (__cs4231_readb(chip, CS4231P(chip, REGSEL)) & CS4231_INIT)
-               snd_printk("out: auto calibration time out - reg = 0x%x, value = 0x%x\n", reg, value);
+               snd_printdd("out: auto calibration time out - reg = 0x%x, value = 0x%x\n", reg, value);
 #endif
        __cs4231_writeb(chip, chip->mce_bit | reg, CS4231P(chip, REGSEL));
        __cs4231_writeb(chip, value, CS4231P(chip, REG));
        chip->image[reg] = value;
        mb();
-#if 0
-       printk("codec out - reg 0x%x = 0x%x\n", chip->mce_bit | reg, value);
-#endif
 }
 
 static unsigned char snd_cs4231_in(cs4231_t *chip, unsigned char reg)
@@ -462,61 +463,14 @@ static unsigned char snd_cs4231_in(cs4231_t *chip, unsigned char reg)
                udelay(100);
 #ifdef CONFIG_SND_DEBUG
        if (__cs4231_readb(chip, CS4231P(chip, REGSEL)) & CS4231_INIT)
-               snd_printk("in: auto calibration time out - reg = 0x%x\n", reg);
+               snd_printdd("in: auto calibration time out - reg = 0x%x\n", reg);
 #endif
        __cs4231_writeb(chip, chip->mce_bit | reg, CS4231P(chip, REGSEL));
        mb();
        ret = __cs4231_readb(chip, CS4231P(chip, REG));
-#if 0
-       printk("codec in - reg 0x%x = 0x%x\n", chip->mce_bit | reg, ret);
-#endif
        return ret;
 }
 
-#if 0
-
-static void snd_cs4231_debug(cs4231_t *chip)
-{
-       printk("CS4231 REGS:      INDEX = 0x%02x  ",
-              __cs4231_readb(chip, CS4231P(chip, REGSEL)));
-       printk("                 STATUS = 0x%02x\n",
-              __cs4231_readb(chip, CS4231P(chip, STATUS)));
-       printk("  0x00: left input      = 0x%02x  ", snd_cs4231_in(chip, 0x00));
-       printk("  0x10: alt 1 (CFIG 2)  = 0x%02x\n", snd_cs4231_in(chip, 0x10));
-       printk("  0x01: right input     = 0x%02x  ", snd_cs4231_in(chip, 0x01));
-       printk("  0x11: alt 2 (CFIG 3)  = 0x%02x\n", snd_cs4231_in(chip, 0x11));
-       printk("  0x02: GF1 left input  = 0x%02x  ", snd_cs4231_in(chip, 0x02));
-       printk("  0x12: left line in    = 0x%02x\n", snd_cs4231_in(chip, 0x12));
-       printk("  0x03: GF1 right input = 0x%02x  ", snd_cs4231_in(chip, 0x03));
-       printk("  0x13: right line in   = 0x%02x\n", snd_cs4231_in(chip, 0x13));
-       printk("  0x04: CD left input   = 0x%02x  ", snd_cs4231_in(chip, 0x04));
-       printk("  0x14: timer low       = 0x%02x\n", snd_cs4231_in(chip, 0x14));
-       printk("  0x05: CD right input  = 0x%02x  ", snd_cs4231_in(chip, 0x05));
-       printk("  0x15: timer high      = 0x%02x\n", snd_cs4231_in(chip, 0x15));
-       printk("  0x06: left output     = 0x%02x  ", snd_cs4231_in(chip, 0x06));
-       printk("  0x16: left MIC (PnP)  = 0x%02x\n", snd_cs4231_in(chip, 0x16));
-       printk("  0x07: right output    = 0x%02x  ", snd_cs4231_in(chip, 0x07));
-       printk("  0x17: right MIC (PnP) = 0x%02x\n", snd_cs4231_in(chip, 0x17));
-       printk("  0x08: playback format = 0x%02x  ", snd_cs4231_in(chip, 0x08));
-       printk("  0x18: IRQ status      = 0x%02x\n", snd_cs4231_in(chip, 0x18));
-       printk("  0x09: iface (CFIG 1)  = 0x%02x  ", snd_cs4231_in(chip, 0x09));
-       printk("  0x19: left line out   = 0x%02x\n", snd_cs4231_in(chip, 0x19));
-       printk("  0x0a: pin control     = 0x%02x  ", snd_cs4231_in(chip, 0x0a));
-       printk("  0x1a: mono control    = 0x%02x\n", snd_cs4231_in(chip, 0x1a));
-       printk("  0x0b: init & status   = 0x%02x  ", snd_cs4231_in(chip, 0x0b));
-       printk("  0x1b: right line out  = 0x%02x\n", snd_cs4231_in(chip, 0x1b));
-       printk("  0x0c: revision & mode = 0x%02x  ", snd_cs4231_in(chip, 0x0c));
-       printk("  0x1c: record format   = 0x%02x\n", snd_cs4231_in(chip, 0x1c));
-       printk("  0x0d: loopback        = 0x%02x  ", snd_cs4231_in(chip, 0x0d));
-       printk("  0x1d: var freq (PnP)  = 0x%02x\n", snd_cs4231_in(chip, 0x1d));
-       printk("  0x0e: ply upr count   = 0x%02x  ", snd_cs4231_in(chip, 0x0e));
-       printk("  0x1e: rec upr count   = 0x%02x\n", snd_cs4231_in(chip, 0x1e));
-       printk("  0x0f: ply lwr count   = 0x%02x  ", snd_cs4231_in(chip, 0x0f));
-       printk("  0x1f: rec lwr count   = 0x%02x\n", snd_cs4231_in(chip, 0x1f));
-}
-
-#endif
-
 /*
  *  CS4231 detection / MCE routines
  */
@@ -528,11 +482,12 @@ static void snd_cs4231_busy_wait(cs4231_t *chip)
        /* huh.. looks like this sequence is proper for CS4231A chip (GUS MAX) */
        for (timeout = 5; timeout > 0; timeout--)
                __cs4231_readb(chip, CS4231P(chip, REGSEL));
+
        /* end of cleanup sequence */
-       for (timeout = 250;
+       for (timeout = 500;
             timeout > 0 && (__cs4231_readb(chip, CS4231P(chip, REGSEL)) & CS4231_INIT);
             timeout--)
-               udelay(100);
+               udelay(1000);
 }
 
 static void snd_cs4231_mce_up(cs4231_t *chip)
@@ -545,12 +500,12 @@ static void snd_cs4231_mce_up(cs4231_t *chip)
                udelay(100);
 #ifdef CONFIG_SND_DEBUG
        if (__cs4231_readb(chip, CS4231P(chip, REGSEL)) & CS4231_INIT)
-               snd_printk("mce_up - auto calibration time out (0)\n");
+               snd_printdd("mce_up - auto calibration time out (0)\n");
 #endif
        chip->mce_bit |= CS4231_MCE;
        timeout = __cs4231_readb(chip, CS4231P(chip, REGSEL));
        if (timeout == 0x80)
-               snd_printk("mce_up [%p]: serious init problem - codec still busy\n", chip->port);
+               snd_printdd("mce_up [%p]: serious init problem - codec still busy\n", chip->port);
        if (!(timeout & CS4231_MCE))
                __cs4231_writeb(chip, chip->mce_bit | (timeout & 0x1f), CS4231P(chip, REGSEL));
        spin_unlock_irqrestore(&chip->lock, flags);
@@ -563,18 +518,15 @@ static void snd_cs4231_mce_down(cs4231_t *chip)
 
        spin_lock_irqsave(&chip->lock, flags);
        snd_cs4231_busy_wait(chip);
-#if 0
-       printk("(1) timeout = %i\n", timeout);
-#endif
 #ifdef CONFIG_SND_DEBUG
        if (__cs4231_readb(chip, CS4231P(chip, REGSEL)) & CS4231_INIT)
-               snd_printk("mce_down [%p] - auto calibration time out (0)\n", CS4231P(chip, REGSEL));
+               snd_printdd("mce_down [%p] - auto calibration time out (0)\n", CS4231P(chip, REGSEL));
 #endif
        chip->mce_bit &= ~CS4231_MCE;
        timeout = __cs4231_readb(chip, CS4231P(chip, REGSEL));
        __cs4231_writeb(chip, chip->mce_bit | (timeout & 0x1f), CS4231P(chip, REGSEL));
        if (timeout == 0x80)
-               snd_printk("mce_down [%p]: serious init problem - codec still busy\n", chip->port);
+               snd_printdd("mce_down [%p]: serious init problem - codec still busy\n", chip->port);
        if ((timeout & CS4231_MCE) == 0) {
                spin_unlock_irqrestore(&chip->lock, flags);
                return;
@@ -590,9 +542,7 @@ static void snd_cs4231_mce_down(cs4231_t *chip)
                spin_unlock_irqrestore(&chip->lock, flags);
                return;
        }
-#if 0
-       printk("(2) timeout = %i, jiffies = %li\n", timeout, jiffies);
-#endif
+
        /* in 10ms increments, check condition, up to 250ms */
        timeout = 25;
        while (snd_cs4231_in(chip, CS4231_TEST_INIT) & CS4231_CALIB_IN_PROGRESS) {
@@ -604,9 +554,7 @@ static void snd_cs4231_mce_down(cs4231_t *chip)
                msleep(10);
                spin_lock_irqsave(&chip->lock, flags);
        }
-#if 0
-       printk("(3) jiffies = %li\n", jiffies);
-#endif
+
        /* in 10ms increments, check condition, up to 100ms */
        timeout = 10;
        while (__cs4231_readb(chip, CS4231P(chip, REGSEL)) & CS4231_INIT) {
@@ -619,28 +567,7 @@ static void snd_cs4231_mce_down(cs4231_t *chip)
                spin_lock_irqsave(&chip->lock, flags);
        }
        spin_unlock_irqrestore(&chip->lock, flags);
-#if 0
-       printk("(4) jiffies = %li\n", jiffies);
-       snd_printk("mce_down - exit = 0x%x\n", __cs4231_readb(chip, CS4231P(chip, REGSEL)));
-#endif
-}
-
-#if 0 /* Unused for now... */
-static unsigned int snd_cs4231_get_count(unsigned char format, unsigned int size)
-{
-       switch (format & 0xe0) {
-       case CS4231_LINEAR_16:
-       case CS4231_LINEAR_16_BIG:
-               size >>= 1;
-               break;
-       case CS4231_ADPCM_16:
-               return size >> 2;
-       }
-       if (format & CS4231_STEREO)
-               size >>= 1;
-       return size;
 }
-#endif
 
 #ifdef EBUS_SUPPORT
 static void snd_cs4231_ebus_advance_dma(struct ebus_dma_info *p, snd_pcm_substream_t *substream, unsigned int *periods_sent)
@@ -648,25 +575,50 @@ static void snd_cs4231_ebus_advance_dma(struct ebus_dma_info *p, snd_pcm_substre
        snd_pcm_runtime_t *runtime = substream->runtime;
 
        while (1) {
-               unsigned int dma_size = snd_pcm_lib_period_bytes(substream);
-               unsigned int offset = dma_size * (*periods_sent);
+               unsigned int period_size = snd_pcm_lib_period_bytes(substream);
+               unsigned int offset = period_size * (*periods_sent);
 
-               if (dma_size >= (1 << 24))
+               if (period_size >= (1 << 24))
                        BUG();
 
-               if (ebus_dma_request(p, runtime->dma_addr + offset, dma_size))
+               if (ebus_dma_request(p, runtime->dma_addr + offset, period_size))
                        return;
-#if 0
-               printk("ebus_advance: Sent period %u (size[%x] offset[%x])\n",
-                      (*periods_sent), dma_size, offset);
-#endif
                (*periods_sent) = ((*periods_sent) + 1) % runtime->periods;
        }
 }
 #endif
 
-static void cs4231_dma_trigger(cs4231_t *chip, unsigned int what, int on)
+#ifdef SBUS_SUPPORT
+static void snd_cs4231_sbus_advance_dma(snd_pcm_substream_t *substream, unsigned int *periods_sent)
 {
+       cs4231_t *chip = snd_pcm_substream_chip(substream);
+       snd_pcm_runtime_t *runtime = substream->runtime;
+
+       unsigned int period_size = snd_pcm_lib_period_bytes(substream);
+       unsigned int offset = period_size * (*periods_sent % runtime->periods);
+
+       if (runtime->period_size > 0xffff + 1)
+               BUG();
+
+       switch (substream->stream) {
+       case SNDRV_PCM_STREAM_PLAYBACK:
+               sbus_writel(runtime->dma_addr + offset, chip->port + APCPNVA);
+               sbus_writel(period_size, chip->port + APCPNC);
+               break;
+       case SNDRV_PCM_STREAM_CAPTURE:
+               sbus_writel(runtime->dma_addr + offset, chip->port + APCCNVA);
+               sbus_writel(period_size, chip->port + APCCNC);
+               break;
+       }
+
+       (*periods_sent) = (*periods_sent + 1) % runtime->periods;
+}
+#endif
+
+static void cs4231_dma_trigger(snd_pcm_substream_t *substream, unsigned int what, int on)
+{
+       cs4231_t *chip = snd_pcm_substream_chip(substream);
+
 #ifdef EBUS_SUPPORT
        if (chip->flags & CS4231_FLAG_EBUS) {
                if (what & CS4231_PLAYBACK_ENABLE) {
@@ -694,6 +646,60 @@ static void cs4231_dma_trigger(cs4231_t *chip, unsigned int what, int on)
        } else {
 #endif
 #ifdef SBUS_SUPPORT
+       u32 csr = sbus_readl(chip->port + APCCSR);
+       /* I don't know why, but on sbus the period counter must
+        * only start counting after the first period is sent.
+        * Therefore this dummy thing.
+        */
+       unsigned int dummy = 0;
+
+       switch (what) {
+       case CS4231_PLAYBACK_ENABLE:
+               if (on) {
+                       csr &= ~APC_XINT_PLAY;
+                       sbus_writel(csr, chip->port + APCCSR);
+
+                       csr &= ~APC_PPAUSE;
+                       sbus_writel(csr, chip->port + APCCSR);
+
+                       snd_cs4231_sbus_advance_dma(substream, &dummy);
+
+                       csr |=  APC_GENL_INT | APC_PLAY_INT | APC_XINT_ENA |
+                               APC_XINT_PLAY | APC_XINT_EMPT | APC_XINT_GENL |
+                               APC_XINT_PENA | APC_PDMA_READY;
+                       sbus_writel(csr, chip->port + APCCSR);
+               } else {
+                       csr |= APC_PPAUSE;
+                       sbus_writel(csr, chip->port + APCCSR);
+
+                       csr &= ~APC_PDMA_READY;
+                       sbus_writel(csr, chip->port + APCCSR);
+               }
+               break;
+       case CS4231_RECORD_ENABLE:
+               if (on) {
+                       csr &= ~APC_XINT_CAPT;
+                       sbus_writel(csr, chip->port + APCCSR);
+
+                       csr &= ~APC_CPAUSE;
+                       sbus_writel(csr, chip->port + APCCSR);
+
+                       snd_cs4231_sbus_advance_dma(substream, &dummy);
+
+                       csr |=  APC_GENL_INT | APC_CAPT_INT | APC_XINT_ENA |
+                               APC_XINT_CAPT | APC_XINT_CEMP | APC_XINT_GENL |
+                               APC_CDMA_READY;
+
+                       sbus_writel(csr, chip->port + APCCSR);
+               } else {
+                       csr |= APC_CPAUSE;
+                       sbus_writel(csr, chip->port + APCCSR);
+
+                       csr &= ~APC_CDMA_READY;
+                       sbus_writel(csr, chip->port + APCCSR);
+               }
+               break;
+       }
 #endif
 #ifdef EBUS_SUPPORT
        }
@@ -725,25 +731,12 @@ static int snd_cs4231_trigger(snd_pcm_substream_t *substream, int cmd)
                        }
                }
 
-#if 0
-               printk("TRIGGER: what[%x] on(%d)\n",
-                      what, (cmd == SNDRV_PCM_TRIGGER_START));
-#endif
-
                spin_lock_irqsave(&chip->lock, flags);
                if (cmd == SNDRV_PCM_TRIGGER_START) {
-                       cs4231_dma_trigger(chip, what, 1);
+                       cs4231_dma_trigger(substream, what, 1);
                        chip->image[CS4231_IFACE_CTRL] |= what;
-                       if (what & CS4231_PLAYBACK_ENABLE) {
-                               snd_cs4231_out(chip, CS4231_PLY_LWR_CNT, 0xff);
-                               snd_cs4231_out(chip, CS4231_PLY_UPR_CNT, 0xff);
-                       }
-                       if (what & CS4231_RECORD_ENABLE) {
-                               snd_cs4231_out(chip, CS4231_REC_LWR_CNT, 0xff);
-                               snd_cs4231_out(chip, CS4231_REC_UPR_CNT, 0xff);
-                       }
                } else {
-                       cs4231_dma_trigger(chip, what, 0);
+                       cs4231_dma_trigger(substream, what, 0);
                        chip->image[CS4231_IFACE_CTRL] &= ~what;
                }
                snd_cs4231_out(chip, CS4231_IFACE_CTRL,
@@ -755,9 +748,7 @@ static int snd_cs4231_trigger(snd_pcm_substream_t *substream, int cmd)
                result = -EINVAL;
                break;
        }
-#if 0
-       snd_cs4231_debug(chip);
-#endif
+
        return result;
 }
 
@@ -790,9 +781,6 @@ static unsigned char snd_cs4231_get_format(cs4231_t *chip, int format, int chann
        }
        if (channels > 1)
                rformat |= CS4231_STEREO;
-#if 0
-       snd_printk("get_format: 0x%x (mode=0x%x)\n", format, mode);
-#endif
        return rformat;
 }
 
@@ -944,7 +932,7 @@ static void snd_cs4231_init(cs4231_t *chip)
        snd_cs4231_mce_down(chip);
 
 #ifdef SNDRV_DEBUG_MCE
-       snd_printk("init: (1)\n");
+       snd_printdd("init: (1)\n");
 #endif
        snd_cs4231_mce_up(chip);
        spin_lock_irqsave(&chip->lock, flags);
@@ -957,7 +945,7 @@ static void snd_cs4231_init(cs4231_t *chip)
        snd_cs4231_mce_down(chip);
 
 #ifdef SNDRV_DEBUG_MCE
-       snd_printk("init: (2)\n");
+       snd_printdd("init: (2)\n");
 #endif
 
        snd_cs4231_mce_up(chip);
@@ -967,7 +955,7 @@ static void snd_cs4231_init(cs4231_t *chip)
        snd_cs4231_mce_down(chip);
 
 #ifdef SNDRV_DEBUG_MCE
-       snd_printk("init: (3) - afei = 0x%x\n", chip->image[CS4231_ALT_FEATURE_1]);
+       snd_printdd("init: (3) - afei = 0x%x\n", chip->image[CS4231_ALT_FEATURE_1]);
 #endif
 
        spin_lock_irqsave(&chip->lock, flags);
@@ -981,7 +969,7 @@ static void snd_cs4231_init(cs4231_t *chip)
        snd_cs4231_mce_down(chip);
 
 #ifdef SNDRV_DEBUG_MCE
-       snd_printk("init: (4)\n");
+       snd_printdd("init: (4)\n");
 #endif
 
        snd_cs4231_mce_up(chip);
@@ -991,7 +979,7 @@ static void snd_cs4231_init(cs4231_t *chip)
        snd_cs4231_mce_down(chip);
 
 #ifdef SNDRV_DEBUG_MCE
-       snd_printk("init: (5)\n");
+       snd_printdd("init: (5)\n");
 #endif
 }
 
@@ -1022,6 +1010,7 @@ static int snd_cs4231_open(cs4231_t *chip, unsigned int mode)
                       CS4231_RECORD_IRQ |
                       CS4231_TIMER_IRQ);
        snd_cs4231_out(chip, CS4231_IRQ_STATUS, 0);
+
        spin_unlock_irqrestore(&chip->lock, flags);
 
        chip->mode = mode;
@@ -1136,11 +1125,21 @@ static int snd_cs4231_playback_hw_free(snd_pcm_substream_t *substream)
 static int snd_cs4231_playback_prepare(snd_pcm_substream_t *substream)
 {
        cs4231_t *chip = snd_pcm_substream_chip(substream);
+       snd_pcm_runtime_t *runtime = substream->runtime;
        unsigned long flags;
 
        spin_lock_irqsave(&chip->lock, flags);
+
        chip->image[CS4231_IFACE_CTRL] &= ~(CS4231_PLAYBACK_ENABLE |
                                            CS4231_PLAYBACK_PIO);
+
+       if (runtime->period_size > 0xffff + 1)
+               BUG();
+
+       snd_cs4231_out(chip, CS4231_PLY_LWR_CNT, (runtime->period_size - 1) & 0x00ff);
+       snd_cs4231_out(chip, CS4231_PLY_UPR_CNT, (runtime->period_size - 1) >> 8 & 0x00ff);
+       chip->p_periods_sent = 0;
+
        spin_unlock_irqrestore(&chip->lock, flags);
 
        return 0;
@@ -1172,12 +1171,16 @@ static int snd_cs4231_capture_hw_free(snd_pcm_substream_t *substream)
 static int snd_cs4231_capture_prepare(snd_pcm_substream_t *substream)
 {
        cs4231_t *chip = snd_pcm_substream_chip(substream);
+       snd_pcm_runtime_t *runtime = substream->runtime;
        unsigned long flags;
 
        spin_lock_irqsave(&chip->lock, flags);
        chip->image[CS4231_IFACE_CTRL] &= ~(CS4231_RECORD_ENABLE |
                                            CS4231_RECORD_PIO);
 
+       snd_cs4231_out(chip, CS4231_REC_LWR_CNT, (runtime->period_size - 1) & 0x00ff);
+       snd_cs4231_out(chip, CS4231_REC_LWR_CNT, (runtime->period_size - 1) >> 8 & 0x00ff);
+
        spin_unlock_irqrestore(&chip->lock, flags);
 
        return 0;
@@ -1196,53 +1199,61 @@ static void snd_cs4231_overrange(cs4231_t *chip)
                chip->capture_substream->runtime->overrange++;
 }
 
-static void snd_cs4231_generic_interrupt(cs4231_t *chip)
+static irqreturn_t snd_cs4231_generic_interrupt(cs4231_t *chip)
 {
        unsigned long flags;
        unsigned char status;
 
+       /*This is IRQ is not raised by the cs4231*/
+       if (!(__cs4231_readb(chip, CS4231P(chip, STATUS)) & CS4231_GLOBALIRQ))
+               return IRQ_NONE;
+
        status = snd_cs4231_in(chip, CS4231_IRQ_STATUS);
-       if (!status)
-               return;
 
        if (status & CS4231_TIMER_IRQ) {
                if (chip->timer)
                        snd_timer_interrupt(chip->timer, chip->timer->sticks);
        }               
-       if (status & CS4231_PLAYBACK_IRQ)
-               snd_pcm_period_elapsed(chip->playback_substream);
-       if (status & CS4231_RECORD_IRQ) {
+
+       if (status & CS4231_RECORD_IRQ)
                snd_cs4231_overrange(chip);
-               snd_pcm_period_elapsed(chip->capture_substream);
-       }
 
        /* ACK the CS4231 interrupt. */
        spin_lock_irqsave(&chip->lock, flags);
        snd_cs4231_outm(chip, CS4231_IRQ_STATUS, ~CS4231_ALL_IRQS | ~status, 0);
        spin_unlock_irqrestore(&chip->lock, flags);
+
+       return 0;
 }
 
 #ifdef SBUS_SUPPORT
 static irqreturn_t snd_cs4231_sbus_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
        cs4231_t *chip = dev_id;
-       u32 csr;
-
-       csr = sbus_readl(chip->port + APCCSR);
-       if (!(csr & (APC_INT_PENDING |
-                    APC_PLAY_INT |
-                    APC_CAPT_INT |
-                    APC_GENL_INT |
-                    APC_XINT_PEMP |
-                    APC_XINT_CEMP)))
-               return IRQ_NONE;
 
        /* ACK the APC interrupt. */
+       u32 csr = sbus_readl(chip->port + APCCSR);
+
        sbus_writel(csr, chip->port + APCCSR);
 
-       snd_cs4231_generic_interrupt(chip);
+       if ((chip->image[CS4231_IFACE_CTRL] & CS4231_PLAYBACK_ENABLE) &&
+           (csr & APC_PLAY_INT) &&
+           (csr & APC_XINT_PNVA) &&
+           !(csr & APC_XINT_EMPT)) {
+               snd_cs4231_sbus_advance_dma(chip->playback_substream,
+                                           &chip->p_periods_sent);
+               snd_pcm_period_elapsed(chip->playback_substream);
+       }
 
-       return IRQ_HANDLED;
+       if ((chip->image[CS4231_IFACE_CTRL] & CS4231_RECORD_ENABLE) &&
+           (csr & APC_CAPT_INT) &&
+           (csr & APC_XINT_CNVA)) {
+               snd_cs4231_sbus_advance_dma(chip->capture_substream,
+                                           &chip->c_periods_sent);
+               snd_pcm_period_elapsed(chip->capture_substream);
+       }
+
+       return snd_cs4231_generic_interrupt(chip);
 }
 #endif
 
@@ -1290,7 +1301,8 @@ static snd_pcm_uframes_t snd_cs4231_playback_pointer(snd_pcm_substream_t *substr
 #ifdef EBUS_SUPPORT
        }
 #endif
-       ptr += (period_bytes - residue);
+       ptr += period_bytes - residue;
+
        return bytes_to_frames(substream->runtime, ptr);
 }
 
@@ -1314,7 +1326,7 @@ static snd_pcm_uframes_t snd_cs4231_capture_pointer(snd_pcm_substream_t * substr
 #ifdef EBUS_SUPPORT
        }
 #endif
-       ptr += (period_bytes - residue);
+       ptr += period_bytes - residue;
        return bytes_to_frames(substream->runtime, ptr);
 }
 
@@ -1328,9 +1340,6 @@ static int snd_cs4231_probe(cs4231_t *chip)
        int i, id, vers;
        unsigned char *ptr;
 
-#if 0
-       snd_cs4231_debug(chip);
-#endif
        id = vers = 0;
        for (i = 0; i < 50; i++) {
                mb();
@@ -1915,6 +1924,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 +1978,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;
 
@@ -1982,13 +1994,13 @@ static int __init snd_cs4231_sbus_create(snd_card_t *card,
        chip->port = sbus_ioremap(&sdev->resource[0], 0,
                                  chip->regs_size, "cs4231");
        if (!chip->port) {
-               snd_printk("cs4231-%d: Unable to map chip registers.\n", dev);
+               snd_printdd("cs4231-%d: Unable to map chip registers.\n", dev);
                return -EIO;
        }
 
        if (request_irq(sdev->irqs[0], snd_cs4231_sbus_interrupt,
                        SA_SHIRQ, "cs4231", chip)) {
-               snd_printk("cs4231-%d: Unable to grab SBUS IRQ %s\n",
+               snd_printdd("cs4231-%d: Unable to grab SBUS IRQ %s\n",
                           dev,
                           __irq_itoa(sdev->irqs[0]));
                snd_cs4231_sbus_free(chip);
@@ -2080,7 +2092,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;
 
@@ -2110,29 +2122,29 @@ static int __init snd_cs4231_ebus_create(snd_card_t *card,
        chip->eb2c.regs = ioremap(edev->resource[2].start, 0x10);
        if (!chip->port || !chip->eb2p.regs || !chip->eb2c.regs) {
                snd_cs4231_ebus_free(chip);
-               snd_printk("cs4231-%d: Unable to map chip registers.\n", dev);
+               snd_printdd("cs4231-%d: Unable to map chip registers.\n", dev);
                return -EIO;
        }
 
        if (ebus_dma_register(&chip->eb2c)) {
                snd_cs4231_ebus_free(chip);
-               snd_printk("cs4231-%d: Unable to register EBUS capture DMA\n", dev);
+               snd_printdd("cs4231-%d: Unable to register EBUS capture DMA\n", dev);
                return -EBUSY;
        }
        if (ebus_dma_irq_enable(&chip->eb2c, 1)) {
                snd_cs4231_ebus_free(chip);
-               snd_printk("cs4231-%d: Unable to enable EBUS capture IRQ\n", dev);
+               snd_printdd("cs4231-%d: Unable to enable EBUS capture IRQ\n", dev);
                return -EBUSY;
        }
 
        if (ebus_dma_register(&chip->eb2p)) {
                snd_cs4231_ebus_free(chip);
-               snd_printk("cs4231-%d: Unable to register EBUS play DMA\n", dev);
+               snd_printdd("cs4231-%d: Unable to register EBUS play DMA\n", dev);
                return -EBUSY;
        }
        if (ebus_dma_irq_enable(&chip->eb2p, 1)) {
                snd_cs4231_ebus_free(chip);
-               snd_printk("cs4231-%d: Unable to enable EBUS play IRQ\n", dev);
+               snd_printdd("cs4231-%d: Unable to enable EBUS play IRQ\n", dev);
                return -EBUSY;
        }
 
index 941c7b1e7ebb959ed49e1077aa2dad14b99c4bdb..b5c4c15ae7f09ccd620c82a0de7fd1568510f8fc 100644 (file)
@@ -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)
  * 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. */
index 60d0b2c6669848a79f4c83653918b84e40cf277e..9e2b4c0c8a8a98f195cd58f4d881a669d0c05e80 100644 (file)
@@ -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;
 
index e41b28d9bf52e6b6c4694a7f470732b79d2d3bc5..8ccd33f4aa577bbe18c44242dd81a96191331a66 100644 (file)
@@ -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;
        }
index 901a7db05bdef5ed70724886f3e60ff8d57424c4..d0925ea50838d2b6497bc3dc399b037587b02d33 100644 (file)
@@ -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);
index 8b131a11e5492f3c3f6597e70b06972694a718ce..5f75bf31bc36b6706e6408eacbd585cf0f4479c0 100644 (file)
@@ -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;
index bfbec5876659caf00bd95c0e2d700402f3649730..d5ae2055b896f2cef2eb78c0cb27811789c26c93 100644 (file)
@@ -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;
index 93dedde3c42877137bded1e0d88f21f7ee98079e..e0d0365453b346bb13117df9d7a6356d643f64a3 100644 (file)
@@ -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;
index fa7056f5caaf761d9b054a1add45c619ab3bd6e3..c3c08c9cb46edfceca5b018f9f5efe7897201aa0 100644 (file)
@@ -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;
index 62dfd28b3b07f909ec66bfebca5a9c1de614a9ac..0f09e0de52dd4cb4a4dc8128217cfe088a95fdfd 100644 (file)
@@ -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;