Merge /spare/repo/linux-2.6/
authorJeff Garzik <jgarzik@pobox.com>
Thu, 22 Sep 2005 02:34:08 +0000 (22:34 -0400)
committerJeff Garzik <jgarzik@pobox.com>
Thu, 22 Sep 2005 02:34:08 +0000 (22:34 -0400)
429 files changed:
CREDITS
Documentation/CodingStyle
Documentation/DocBook/kernel-hacking.tmpl
Documentation/dell_rbu.txt
Documentation/filesystems/relayfs.txt
Documentation/ia64/mca.txt [new file with mode: 0644]
MAINTAINERS
Makefile
README
arch/alpha/kernel/osf_sys.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/semaphore.c
arch/arm/kernel/traps.c
arch/arm/kernel/vmlinux.lds.S
arch/arm/mach-ixp4xx/ixdp425-setup.c
arch/arm/mach-pxa/corgi.c
arch/arm/mach-pxa/lubbock.c
arch/arm/mach-pxa/poodle.c
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/lib/Makefile
arch/i386/lib/dec_and_lock.c [deleted file]
arch/ia64/Kconfig
arch/ia64/Makefile
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_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/lib/Makefile
arch/ppc/lib/dec_and_lock.c [deleted file]
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/open_pic2.c
arch/ppc64/Kconfig
arch/ppc64/Makefile
arch/ppc64/kernel/head.S
arch/ppc64/kernel/pSeries_iommu.c
arch/ppc64/kernel/pci.c
arch/ppc64/kernel/prom_init.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/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/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/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/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/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/um_arch.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/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
drivers/acorn/char/pcf8583.c
drivers/block/cciss.c
drivers/block/ll_rw_blk.c
drivers/block/paride/pf.c
drivers/block/scsi_ioctl.c
drivers/char/agp/hp-agp.c
drivers/char/epca.c
drivers/char/epca.h
drivers/char/hvc_console.c
drivers/char/vt.c
drivers/char/watchdog/mpcore_wdt.c
drivers/firmware/dell_rbu.c
drivers/hwmon/hdaps.c
drivers/i2c/busses/i2c-pxa.c
drivers/ide/ide-taskfile.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/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/md/raid6.h
drivers/md/raid6algos.c
drivers/md/raid6altivec.uc
drivers/md/raid6test/Makefile
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/maps/sharpsl-flash.c
drivers/mtd/nand/sharpsl.c
drivers/net/8139cp.c
drivers/net/Kconfig
drivers/net/bonding/bond_main.c
drivers/net/e100.c
drivers/net/e1000/e1000_main.c
drivers/net/ixgb/ixgb_main.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/pci/hotplug/ibmphp_pci.c
drivers/pci/hotplug/pciehp_ctrl.c
drivers/pci/hotplug/shpchp_ctrl.c
drivers/pci/pci.c
drivers/pcmcia/yenta_socket.c
drivers/s390/cio/blacklist.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/scsi/aic7xxx/aic7xxx_osm.c
drivers/scsi/aic7xxx/aic7xxx_osm.h
drivers/scsi/aic7xxx/aic7xxx_osm_pci.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/qla2xxx/qla_init.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/video/Kconfig
drivers/video/aty/xlinit.c
drivers/video/backlight/corgi_bl.c
drivers/video/console/vgacon.c
drivers/video/fbcvt.c
drivers/video/imxfb.c
drivers/video/nvidia/nv_i2c.c
drivers/video/nvidia/nvidia.c
drivers/video/savage/savagefb-i2c.c
drivers/video/savage/savagefb.h
drivers/video/savage/savagefb_driver.c
fs/aio.c
fs/compat.c
fs/dcache.c
fs/eventpoll.c
fs/exec.c
fs/fat/file.c
fs/fat/inode.c
fs/file.c
fs/locks.c
fs/ntfs/ChangeLog
fs/ntfs/aops.c
fs/ntfs/inode.c
fs/ntfs/malloc.h
fs/ntfs/runlist.c
fs/proc/array.c
fs/proc/base.c
include/asm-alpha/futex.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/memory.h
include/asm-arm/arch-pxa/poodle.h
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/setup.h
include/asm-arm26/futex.h
include/asm-cris/futex.h
include/asm-frv/futex.h
include/asm-h8300/futex.h
include/asm-i386/futex.h
include/asm-ia64/futex.h
include/asm-ia64/ptrace.h
include/asm-ia64/thread_info.h
include/asm-m32r/futex.h
include/asm-m68k/futex.h
include/asm-m68knommu/futex.h
include/asm-parisc/futex.h
include/asm-ppc/futex.h
include/asm-ppc/irq.h
include/asm-ppc/mpc8xx.h
include/asm-ppc/ppc_sys.h
include/asm-ppc/tlbflush.h
include/asm-s390/futex.h
include/asm-sh/futex.h
include/asm-sh64/futex.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/processor-generic.h
include/asm-um/system-i386.h
include/asm-v850/futex.h
include/asm-x86_64/desc.h
include/linux/byteorder/generic.h
include/linux/dccp.h
include/linux/i2c.h
include/linux/if_vlan.h
include/linux/joystick.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/pci_ids.h
include/linux/syscalls.h
include/linux/tfrc.h [new file with mode: 0644]
include/net/ip_vs.h
include/rdma/ib_mad.h
include/scsi/scsi_host.h
include/scsi/scsi_transport_fc.h
kernel/exit.c
kernel/fork.c
kernel/printk.c
kernel/sys.c
lib/dec_and_lock.c
mm/Kconfig
mm/mmap.c
mm/mprotect.c
mm/slab.c
net/8021q/vlan_dev.c
net/Kconfig
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_core.c
net/ipv4/netfilter/ip_conntrack_helper_pptp.c [new file with mode: 0644]
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_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/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/socket.c
security/seclvl.c
sound/arm/aaci.c
sound/pci/rme32.c
sound/pci/rme96.c
sound/sparc/cs4231.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 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
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 d1e0eb46d201fb8574625f587159fe991ff6e609..ade7415d2467e7725b755cce37c078a3e291a65e 100644 (file)
@@ -686,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
@@ -2259,6 +2266,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
@@ -2271,12 +2284,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..2b5844d8cfa0a117284ef5713fb0957e96fd4667 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 question 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".
+   In alternative, before compiling, edit your Makefile and change the
+   "EXTRAVERSION" line - its content is appended to the regular kernel
+   version.
 
  - 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 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 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 426c2bc517eb7ca8fd42a06fa2e6b0d971b24324..be37586cb1b062ba5ec96502b223e6e97ab4d215 100644 (file)
@@ -198,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)
@@ -259,6 +256,16 @@ 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);
@@ -285,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
@@ -332,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
@@ -345,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 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,
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 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 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 6e683745af49d1ceb128fc99ec60b61ad76a61f6..80f83d6cdbfcac4a7bf1e2f85aaefe314dce1819 100644 (file)
@@ -84,23 +84,23 @@ mca_page_isolate(unsigned long paddr)
        struct page *p;
 
        /* whether physical address is valid or not */
-       if ( !ia64_phys_addr_valid(paddr) ) 
+       if (!ia64_phys_addr_valid(paddr))
                return ISOLATE_NG;
 
        /* convert physical address to physical page number */
        p = pfn_to_page(paddr>>PAGE_SHIFT);
 
        /* check whether a page number have been already registered or not */
-       for( i = 0; i < num_page_isolate; i++ )
-               if( page_isolate[i] == p )
+       for (i = 0; i < num_page_isolate; i++)
+               if (page_isolate[i] == p)
                        return ISOLATE_OK; /* already listed */
 
        /* limitation check */
-       if( num_page_isolate == MAX_PAGE_ISOLATE ) 
+       if (num_page_isolate == MAX_PAGE_ISOLATE)
                return ISOLATE_NG;
 
        /* kick pages having attribute 'SLAB' or 'Reserved' */
-       if( PageSlab(p) || PageReserved(p) ) 
+       if (PageSlab(p) || PageReserved(p))
                return ISOLATE_NG;
 
        /* add attribute 'Reserved' and register the page */
@@ -139,10 +139,10 @@ mca_handler_bh(unsigned long paddr)
  * @peidx:     pointer to index of processor error section
  */
 
-static void 
+static void
 mca_make_peidx(sal_log_processor_info_t *slpi, peidx_table_t *peidx)
 {
-       /* 
+       /*
         * calculate the start address of
         *   "struct cpuid_info" and "sal_processor_static_info_t".
         */
@@ -164,7 +164,7 @@ mca_make_peidx(sal_log_processor_info_t *slpi, peidx_table_t *peidx)
 }
 
 /**
- * mca_make_slidx -  Make index of SAL error record 
+ * mca_make_slidx -  Make index of SAL error record
  * @buffer:    pointer to SAL error record
  * @slidx:     pointer to index of SAL error record
  *
@@ -172,12 +172,12 @@ mca_make_peidx(sal_log_processor_info_t *slpi, peidx_table_t *peidx)
  *     1 if record has platform error / 0 if not
  */
 #define LOG_INDEX_ADD_SECT_PTR(sect, ptr) \
-        { slidx_list_t *hl = &slidx_pool.buffer[slidx_pool.cur_idx]; \
-          hl->hdr = ptr; \
-          list_add(&hl->list, &(sect)); \
-          slidx_pool.cur_idx = (slidx_pool.cur_idx + 1)%slidx_pool.max_idx; }
+       {slidx_list_t *hl = &slidx_pool.buffer[slidx_pool.cur_idx]; \
+       hl->hdr = ptr; \
+       list_add(&hl->list, &(sect)); \
+       slidx_pool.cur_idx = (slidx_pool.cur_idx + 1)%slidx_pool.max_idx; }
 
-static int 
+static int
 mca_make_slidx(void *buffer, slidx_table_t *slidx)
 {
        int platform_err = 0;
@@ -214,28 +214,36 @@ mca_make_slidx(void *buffer, slidx_table_t *slidx)
                sp = (sal_log_section_hdr_t *)((char*)buffer + ercd_pos);
                if (!efi_guidcmp(sp->guid, SAL_PROC_DEV_ERR_SECT_GUID)) {
                        LOG_INDEX_ADD_SECT_PTR(slidx->proc_err, sp);
-               } else if (!efi_guidcmp(sp->guid, SAL_PLAT_MEM_DEV_ERR_SECT_GUID)) {
+               } else if (!efi_guidcmp(sp->guid,
+                               SAL_PLAT_MEM_DEV_ERR_SECT_GUID)) {
                        platform_err = 1;
                        LOG_INDEX_ADD_SECT_PTR(slidx->mem_dev_err, sp);
-               } else if (!efi_guidcmp(sp->guid, SAL_PLAT_SEL_DEV_ERR_SECT_GUID)) {
+               } else if (!efi_guidcmp(sp->guid,
+                               SAL_PLAT_SEL_DEV_ERR_SECT_GUID)) {
                        platform_err = 1;
                        LOG_INDEX_ADD_SECT_PTR(slidx->sel_dev_err, sp);
-               } else if (!efi_guidcmp(sp->guid, SAL_PLAT_PCI_BUS_ERR_SECT_GUID)) {
+               } else if (!efi_guidcmp(sp->guid,
+                               SAL_PLAT_PCI_BUS_ERR_SECT_GUID)) {
                        platform_err = 1;
                        LOG_INDEX_ADD_SECT_PTR(slidx->pci_bus_err, sp);
-               } else if (!efi_guidcmp(sp->guid, SAL_PLAT_SMBIOS_DEV_ERR_SECT_GUID)) {
+               } else if (!efi_guidcmp(sp->guid,
+                               SAL_PLAT_SMBIOS_DEV_ERR_SECT_GUID)) {
                        platform_err = 1;
                        LOG_INDEX_ADD_SECT_PTR(slidx->smbios_dev_err, sp);
-               } else if (!efi_guidcmp(sp->guid, SAL_PLAT_PCI_COMP_ERR_SECT_GUID)) {
+               } else if (!efi_guidcmp(sp->guid,
+                               SAL_PLAT_PCI_COMP_ERR_SECT_GUID)) {
                        platform_err = 1;
                        LOG_INDEX_ADD_SECT_PTR(slidx->pci_comp_err, sp);
-               } else if (!efi_guidcmp(sp->guid, SAL_PLAT_SPECIFIC_ERR_SECT_GUID)) {
+               } else if (!efi_guidcmp(sp->guid,
+                               SAL_PLAT_SPECIFIC_ERR_SECT_GUID)) {
                        platform_err = 1;
                        LOG_INDEX_ADD_SECT_PTR(slidx->plat_specific_err, sp);
-               } else if (!efi_guidcmp(sp->guid, SAL_PLAT_HOST_CTLR_ERR_SECT_GUID)) {
+               } else if (!efi_guidcmp(sp->guid,
+                               SAL_PLAT_HOST_CTLR_ERR_SECT_GUID)) {
                        platform_err = 1;
                        LOG_INDEX_ADD_SECT_PTR(slidx->host_ctlr_err, sp);
-               } else if (!efi_guidcmp(sp->guid, SAL_PLAT_BUS_ERR_SECT_GUID)) {
+               } else if (!efi_guidcmp(sp->guid,
+                               SAL_PLAT_BUS_ERR_SECT_GUID)) {
                        platform_err = 1;
                        LOG_INDEX_ADD_SECT_PTR(slidx->plat_bus_err, sp);
                } else {
@@ -253,15 +261,16 @@ mca_make_slidx(void *buffer, slidx_table_t *slidx)
  * Return value:
  *     0 on Success / -ENOMEM on Failure
  */
-static int 
+static int
 init_record_index_pools(void)
 {
        int i;
        int rec_max_size;  /* Maximum size of SAL error records */
        int sect_min_size; /* Minimum size of SAL error sections */
        /* minimum size table of each section */
-       static int sal_log_sect_min_sizes[] = { 
-               sizeof(sal_log_processor_info_t) + sizeof(sal_processor_static_info_t),
+       static int sal_log_sect_min_sizes[] = {
+               sizeof(sal_log_processor_info_t)
+               + sizeof(sal_processor_static_info_t),
                sizeof(sal_log_mem_dev_err_info_t),
                sizeof(sal_log_sel_dev_err_info_t),
                sizeof(sal_log_pci_bus_err_info_t),
@@ -294,7 +303,8 @@ init_record_index_pools(void)
 
        /* - 3 - */
        slidx_pool.max_idx = (rec_max_size/sect_min_size) * 2 + 1;
-       slidx_pool.buffer = (slidx_list_t *) kmalloc(slidx_pool.max_idx * sizeof(slidx_list_t), GFP_KERNEL);
+       slidx_pool.buffer = (slidx_list_t *)
+               kmalloc(slidx_pool.max_idx * sizeof(slidx_list_t), GFP_KERNEL);
 
        return slidx_pool.buffer ? 0 : -ENOMEM;
 }
@@ -308,6 +318,7 @@ init_record_index_pools(void)
  * is_mca_global - Check whether this MCA is global or not
  * @peidx:     pointer of index of processor error section
  * @pbci:      pointer to pal_bus_check_info_t
+ * @sos:       pointer to hand off struct between SAL and OS
  *
  * Return value:
  *     MCA_IS_LOCAL / MCA_IS_GLOBAL
@@ -317,11 +328,12 @@ static mca_type_t
 is_mca_global(peidx_table_t *peidx, pal_bus_check_info_t *pbci,
              struct ia64_sal_os_state *sos)
 {
-       pal_processor_state_info_t *psp = (pal_processor_state_info_t*)peidx_psp(peidx);
+       pal_processor_state_info_t *psp =
+               (pal_processor_state_info_t*)peidx_psp(peidx);
 
-       /* 
+       /*
         * PAL can request a rendezvous, if the MCA has a global scope.
-        * If "rz_always" flag is set, SAL requests MCA rendezvous 
+        * If "rz_always" flag is set, SAL requests MCA rendezvous
         * in spite of global MCA.
         * Therefore it is local MCA when rendezvous has not been requested.
         * Failed to rendezvous, the system must be down.
@@ -381,13 +393,15 @@ is_mca_global(peidx_table_t *peidx, pal_bus_check_info_t *pbci,
  * @slidx:     pointer of index of SAL error record
  * @peidx:     pointer of index of processor error section
  * @pbci:      pointer of pal_bus_check_info
+ * @sos:       pointer to hand off struct between SAL and OS
  *
  * Return value:
  *     1 on Success / 0 on Failure
  */
 
 static int
-recover_from_read_error(slidx_table_t *slidx, peidx_table_t *peidx, pal_bus_check_info_t *pbci,
+recover_from_read_error(slidx_table_t *slidx,
+                       peidx_table_t *peidx, pal_bus_check_info_t *pbci,
                        struct ia64_sal_os_state *sos)
 {
        sal_log_mod_error_info_t *smei;
@@ -453,24 +467,28 @@ recover_from_read_error(slidx_table_t *slidx, peidx_table_t *peidx, pal_bus_chec
  * @slidx:     pointer of index of SAL error record
  * @peidx:     pointer of index of processor error section
  * @pbci:      pointer of pal_bus_check_info
+ * @sos:       pointer to hand off struct between SAL and OS
  *
  * Return value:
  *     1 on Success / 0 on Failure
  */
 
 static int
-recover_from_platform_error(slidx_table_t *slidx, peidx_table_t *peidx, pal_bus_check_info_t *pbci,
+recover_from_platform_error(slidx_table_t *slidx, peidx_table_t *peidx,
+                           pal_bus_check_info_t *pbci,
                            struct ia64_sal_os_state *sos)
 {
        int status = 0;
-       pal_processor_state_info_t *psp = (pal_processor_state_info_t*)peidx_psp(peidx);
+       pal_processor_state_info_t *psp =
+               (pal_processor_state_info_t*)peidx_psp(peidx);
 
        if (psp->bc && pbci->eb && pbci->bsi == 0) {
                switch(pbci->type) {
                case 1: /* partial read */
                case 3: /* full line(cpu) read */
                case 9: /* I/O space read */
-                       status = recover_from_read_error(slidx, peidx, pbci, sos);
+                       status = recover_from_read_error(slidx, peidx, pbci,
+                                                        sos);
                        break;
                case 0: /* unknown */
                case 2: /* partial write */
@@ -481,7 +499,8 @@ recover_from_platform_error(slidx_table_t *slidx, peidx_table_t *peidx, pal_bus_
                case 8: /* write coalescing transactions */
                case 10: /* I/O space write */
                case 11: /* inter-processor interrupt message(IPI) */
-               case 12: /* interrupt acknowledge or external task priority cycle */
+               case 12: /* interrupt acknowledge or
+                               external task priority cycle */
                default:
                        break;
                }
@@ -496,6 +515,7 @@ recover_from_platform_error(slidx_table_t *slidx, peidx_table_t *peidx, pal_bus_
  * @slidx:     pointer of index of SAL error record
  * @peidx:     pointer of index of processor error section
  * @pbci:      pointer of pal_bus_check_info
+ * @sos:       pointer to hand off struct between SAL and OS
  *
  * Return value:
  *     1 on Success / 0 on Failure
@@ -509,15 +529,17 @@ recover_from_platform_error(slidx_table_t *slidx, peidx_table_t *peidx, pal_bus_
  */
 
 static int
-recover_from_processor_error(int platform, slidx_table_t *slidx, peidx_table_t *peidx, pal_bus_check_info_t *pbci,
+recover_from_processor_error(int platform, slidx_table_t *slidx,
+                            peidx_table_t *peidx, pal_bus_check_info_t *pbci,
                             struct ia64_sal_os_state *sos)
 {
-       pal_processor_state_info_t *psp = (pal_processor_state_info_t*)peidx_psp(peidx);
+       pal_processor_state_info_t *psp =
+               (pal_processor_state_info_t*)peidx_psp(peidx);
 
-       /* 
+       /*
         * We cannot recover errors with other than bus_check.
         */
-       if (psp->cc || psp->rc || psp->uc) 
+       if (psp->cc || psp->rc || psp->uc)
                return 0;
 
        /*
@@ -546,10 +568,10 @@ recover_from_processor_error(int platform, slidx_table_t *slidx, peidx_table_t *
         * (e.g. a load from poisoned memory)
         * This means "there are some platform errors".
         */
-       if (platform) 
+       if (platform)
                return recover_from_platform_error(slidx, peidx, pbci, sos);
-       /* 
-        * On account of strange SAL error record, we cannot recover. 
+       /*
+        * On account of strange SAL error record, we cannot recover.
         */
        return 0;
 }
@@ -557,14 +579,14 @@ recover_from_processor_error(int platform, slidx_table_t *slidx, peidx_table_t *
 /**
  * mca_try_to_recover - Try to recover from MCA
  * @rec:       pointer to a SAL error record
+ * @sos:       pointer to hand off struct between SAL and OS
  *
  * Return value:
  *     1 on Success / 0 on Failure
  */
 
 static int
-mca_try_to_recover(void *rec, 
-       struct ia64_sal_os_state *sos)
+mca_try_to_recover(void *rec, struct ia64_sal_os_state *sos)
 {
        int platform_err;
        int n_proc_err;
@@ -588,7 +610,8 @@ mca_try_to_recover(void *rec,
        }
 
        /* Make index of processor error section */
-       mca_make_peidx((sal_log_processor_info_t*)slidx_first_entry(&slidx.proc_err)->hdr, &peidx);
+       mca_make_peidx((sal_log_processor_info_t*)
+               slidx_first_entry(&slidx.proc_err)->hdr, &peidx);
 
        /* Extract Processor BUS_CHECK[0] */
        *((u64*)&pbci) = peidx_check_info(&peidx, bus_check, 0);
@@ -598,7 +621,8 @@ mca_try_to_recover(void *rec,
                return 0;
        
        /* Try to recover a processor error */
-       return recover_from_processor_error(platform_err, &slidx, &peidx, &pbci, sos);
+       return recover_from_processor_error(platform_err, &slidx, &peidx,
+                                           &pbci, sos);
 }
 
 /*
@@ -611,7 +635,7 @@ int __init mca_external_handler_init(void)
                return -ENOMEM;
 
        /* register external mca handlers */
-       if (ia64_reg_MCA_extension(mca_try_to_recover))       
+       if (ia64_reg_MCA_extension(mca_try_to_recover)) {       
                printk(KERN_ERR "ia64_reg_MCA_extension failed.\n");
                kfree(slidx_pool.buffer);
                return -EFAULT;
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 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 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 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 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 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 f0fd7fbd6531cd01fb8984d2c81e82a25825b484..8c6313e7e1453658980fa4ddb8ac0b9755216fb7 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,84 @@ 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 %x\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 %x\n", pci->phb->dma_window_size);
+
 }
 
 
@@ -446,14 +440,29 @@ 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, 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;
 
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 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 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 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 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..310c1f823f26713eb9a4d6689fd20d504b8e6fb2 100644 (file)
@@ -30,6 +30,7 @@ static struct mconsole_command commands[] = {
        { "go", mconsole_go, MCONSOLE_INTR },
        { "log", mconsole_log, MCONSOLE_INTR },
        { "proc", mconsole_proc, MCONSOLE_PROC },
+        { "stack", mconsole_stack, MCONSOLE_INTR },
 };
 
 /* Initialized in mconsole_init, which is an initcall */
@@ -172,9 +173,9 @@ int mconsole_notify(char *sock_name, int type, const void *data, int len)
        if(notify_sock < 0){
                notify_sock = socket(PF_UNIX, SOCK_DGRAM, 0);
                if(notify_sock < 0){
-                       printk("mconsole_notify - socket failed, errno = %d\n",
-                              errno);
                        err = -errno;
+                       printk("mconsole_notify - socket failed, errno = %d\n",
+                              err);
                }
        }
        unlock_notify();
@@ -197,8 +198,8 @@ int mconsole_notify(char *sock_name, int type, const void *data, int len)
        n = sendto(notify_sock, &packet, len, 0, (struct sockaddr *) &target, 
                   sizeof(target));
        if(n < 0){
-               printk("mconsole_notify - sendto failed, errno = %d\n", errno);
                err = -errno;
+               printk("mconsole_notify - sendto failed, errno = %d\n", errno);
        }
        return(err);
 }
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 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..39cf568ccfaf7b391e2527b3af518a78e76c38ae 100644 (file)
@@ -113,8 +113,23 @@ void set_current(void *t)
 
 void *_switch_to(void *prev, void *next, void *last)
 {
-       return(CHOOSE_MODE(switch_to_tt(prev, next), 
-                          switch_to_skas(prev, next)));
+        struct task_struct *from = prev;
+        struct task_struct *to= next;
+
+        to->thread.prev_sched = from;
+        set_current(to);
+
+       do {
+               current->thread.saved_task = NULL ;
+               CHOOSE_MODE_PROC(switch_to_tt, switch_to_skas, prev, next);
+               if(current->thread.saved_task)
+                       show_regs(&(current->thread.regs));
+               next= current->thread.saved_task;
+               prev= current;
+       } while(current->thread.saved_task);
+
+        return(current->thread.prev_sched);
+
 }
 
 void interrupt_end(void)
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..0a562c3c0fd85400d99a2b0131f635af41faa9b9 100644 (file)
@@ -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 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 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 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 4e34b0f9d6138bc9141fc6410ed59d6dabd14001..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>
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 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 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 c56f995aadadcee00d8a63982ccf0a16da20c97a..486b6e1c7dfb96aaa1a8e98e06169d7ce7164f27 100644 (file)
@@ -483,9 +483,6 @@ static int cciss_open(struct inode *inode, struct file *filep)
        printk(KERN_DEBUG "cciss_open %s\n", inode->i_bdev->bd_disk->disk_name);
 #endif /* CCISS_DEBUG */ 
 
-       if (host->busy_initializing)
-               return -EBUSY;
-
        if (host->busy_initializing || drv->busy_configuring)
                return -EBUSY;
        /*
@@ -2991,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]);
@@ -3033,7 +3031,6 @@ static int __devinit cciss_init_one(struct pci_dev *pdev,
                add_disk(disk);
        }
 
-       hba[i]->busy_initializing = 0;
        return(1);
 
 clean4:
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 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 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 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 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 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 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 {
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 eaebfc14c933c1f84783fcdbf401bd5bc4b2a453..4c56411f399316c8bb11833beda296a351c34537 100644 (file)
@@ -5,10 +5,10 @@
  * Copyright (C) 2005 Jesper Juhl <jesper.juhl@gmail.com>
  *
  * The HardDisk Active Protection System (hdaps) is present in the IBM ThinkPad
- * T41, T42, T43, R51, and X40, at least.  It provides a basic two-axis
- * accelerometer and other data, such as the device's temperature.
+ * T41, T42, T43, R50, R50p, R51, and X40, at least.  It provides a basic
+ * two-axis accelerometer and other data, such as the device's temperature.
  *
- * Based on the document by Mark A. Smith available at
+ * This driver is based on the document by Mark A. Smith available at
  * http://www.almaden.ibm.com/cs/people/marksmith/tpaps.html and a lot of trial
  * and error.
  *
 #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,
 };
@@ -619,7 +491,7 @@ static struct attribute_group hdaps_attribute_group = {
  * XXX: We should be able to return nonzero and halt the detection process.
  * But there is a bug in dmi_check_system() where a nonzero return from the
  * first match will result in a return of failure from dmi_check_system().
- * I fixed this; the patch is in 2.6-mm.  Once in Linus's tree we can make
+ * I fixed this; the patch is 2.6-git.  Once in a released tree, we can make
  * hdaps_dmi_match_invert() return hdaps_dmi_match(), which in turn returns 1.
  */
 static int hdaps_dmi_match(struct dmi_system_id *id)
@@ -668,6 +540,7 @@ static int __init hdaps_init(void)
                HDAPS_DMI_MATCH_NORMAL("ThinkPad T42"),
                HDAPS_DMI_MATCH_NORMAL("ThinkPad T43"),
                HDAPS_DMI_MATCH_NORMAL("ThinkPad X40"),
+               HDAPS_DMI_MATCH_NORMAL("ThinkPad X41 Tablet"),
                { .ident = NULL }
        };
 
@@ -696,8 +569,18 @@ static int __init hdaps_init(void)
        if (ret)
                goto out_device;
 
-       if (hdaps_mousedev)
-               hdaps_mousedev_enable();
+       /* initial calibrate for the input device */
+       hdaps_calibrate();
+
+       /* initialize the input class */
+       hdaps_idev.dev = &pdev->dev;
+       input_register_device(&hdaps_idev);
+
+       /* start up our timer for the input device */
+       init_timer(&hdaps_timer);
+       hdaps_timer.function = hdaps_mousedev_poll;
+       hdaps_timer.expires = jiffies + HDAPS_POLL_PERIOD;
+       add_timer(&hdaps_timer);
 
        printk(KERN_INFO "hdaps: driver successfully loaded.\n");
        return 0;
@@ -715,8 +598,8 @@ out:
 
 static void __exit hdaps_exit(void)
 {
-       hdaps_mousedev_disable();
-
+       del_timer_sync(&hdaps_timer);
+       input_unregister_device(&hdaps_idev);
        sysfs_remove_group(&pdev->dev.kobj, &hdaps_attribute_group);
        platform_device_unregister(pdev);
        driver_unregister(&hdaps_driver);
@@ -728,9 +611,6 @@ static void __exit hdaps_exit(void)
 module_init(hdaps_init);
 module_exit(hdaps_exit);
 
-module_param_named(mousedev, hdaps_mousedev, bool, 0);
-MODULE_PARM_DESC(mousedev, "enable the input class device");
-
 module_param_named(invert, hdaps_invert, bool, 0);
 MODULE_PARM_DESC(invert, "invert data along each axis");
 
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 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 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 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..0a2536d6240297e77ebaa76a7f82c1766c492f59 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;
                }
        }
 
@@ -205,7 +209,9 @@ static void st5481B_mode(struct st5481_bcs *bcs, int mode)
        bcs->mode = mode;
 
        // Cancel all USB transfers on this B channel
+       b_out->urb[0]->transfer_flags |= URB_ASYNC_UNLINK;
        usb_unlink_urb(b_out->urb[0]);
+       b_out->urb[1]->transfer_flags |= URB_ASYNC_UNLINK;
        usb_unlink_urb(b_out->urb[1]);
        b_out->busy = 0;
 
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..ffd5b2d45552641c713ec8fde152fb9f946e6ab1 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;
                }
        }
 
@@ -631,7 +645,9 @@ void st5481_in_mode(struct st5481_in *in, int mode)
 
        in->mode = mode;
 
+       in->urb[0]->transfer_flags |= URB_ASYNC_UNLINK;
        usb_unlink_urb(in->urb[0]);
+       in->urb[1]->transfer_flags |= URB_ASYNC_UNLINK;
        usb_unlink_urb(in->urb[1]);
 
        if (in->mode != L1_MODE_NULL) {
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 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 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 bd99c268e2daba16e3579246a9adf39cf71bf210..f822cd3025ff07b154e48e7cd2d226e21f4f6898 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;
@@ -1142,10 +1140,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);
 }
 
@@ -1186,7 +1180,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)
@@ -1515,13 +1508,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++) {
@@ -1531,24 +1528,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 82603e419d767e6b3b807bfc62b376910c9b988a..ff3fccd7513b59a4a39895d5f56ddc3bdda3124c 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 94c9f68dd16bacf4686eac5cb7da66062bf8df33..90449a0f2a6c4454b277d6fa333264a014940794 100644 (file)
@@ -2879,6 +2879,7 @@ static void bond_arp_send_all(struct bonding *bond, struct slave *slave)
                 * This target is not on a VLAN
                 */
                if (rt->u.dst.dev == bond->dev) {
+                       ip_rt_put(rt);
                        dprintk("basa: rtdev == bond->dev: arp_send\n");
                        bond_arp_send(slave->dev, ARPOP_REQUEST, targets[i],
                                      bond->master_ip, 0);
@@ -2898,6 +2899,7 @@ static void bond_arp_send_all(struct bonding *bond, struct slave *slave)
                }
 
                if (vlan_id) {
+                       ip_rt_put(rt);
                        bond_arp_send(slave->dev, ARPOP_REQUEST, targets[i],
                                      vlan->vlan_ip, vlan_id);
                        continue;
@@ -2909,6 +2911,7 @@ static void bond_arp_send_all(struct bonding *bond, struct slave *slave)
                               bond->dev->name, NIPQUAD(fl.fl4_dst),
                               rt->u.dst.dev ? rt->u.dst.dev->name : "NULL");
                }
+               ip_rt_put(rt);
        }
 }
 
@@ -5036,6 +5039,14 @@ static int __init bonding_init(void)
        return 0;
 
 out_err:
+       /*
+        * rtnl_unlock() will run netdev_run_todo(), putting the
+        * thus-far-registered bonding devices into a state which
+        * unregigister_netdevice() will accept
+        */
+       rtnl_unlock();
+       rtnl_lock();
+
        /* free and unregister all bonds that were successfully added */
        bond_free_all();
 
index 1c918309539f5101e87bdf5ead9f93bc1934180c..c15406d46418d4f76a3f13185b902557392d86a8 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 d02883dcc9b3f4dc9953f8d024f8368fb5f5e9b8..c062b0ad8262202b1b4fb2fbbf1cb9dab1c85852 100644 (file)
@@ -2545,7 +2545,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 5015eaf4e20a5472c594d49212b2349d2c9120f3..176680cb153e8b114797f4e6a8bad2f1837c678c 100644 (file)
@@ -1617,8 +1617,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 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 757c83387a296a556a14d5bf49ce8983ee107003..7ce734ec6ba8c94f5ebcb4cb4aebbfef3f926a21 100644 (file)
@@ -42,7 +42,7 @@
 #include "skge.h"
 
 #define DRV_NAME               "skge"
-#define DRV_VERSION            "0.9"
+#define DRV_VERSION            "1.0"
 #define PFX                    DRV_NAME " "
 
 #define DEFAULT_TX_RING_SIZE   128
@@ -669,7 +669,7 @@ static void skge_led(struct skge_port *skge, enum led_mode mode)
                                     PHY_M_LED_BLINK_RT(BLINK_84MS) |
                                     PHY_M_LEDC_TX_CTRL |
                                     PHY_M_LEDC_DP_CTRL);
-               
+
                        gm_phy_write(hw, port, PHY_MARV_LED_OVER,
                                     PHY_M_LED_MO_RX(MO_LED_OFF) |
                                     (skge->speed == SPEED_100 ?
@@ -877,7 +877,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);
@@ -988,6 +988,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 */
@@ -1022,8 +1024,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);
@@ -1107,8 +1107,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);
 
@@ -1341,6 +1339,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);
@@ -1466,7 +1466,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);
 
        /*
@@ -1579,7 +1578,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);
 
@@ -1678,9 +1676,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);
@@ -1688,10 +1688,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 |
@@ -1730,7 +1732,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);
 
@@ -1802,20 +1804,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)
@@ -1874,10 +1882,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)
@@ -1897,7 +1903,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);
@@ -2113,7 +2118,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:
@@ -2136,15 +2140,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),
@@ -2368,8 +2377,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)
@@ -2531,8 +2538,6 @@ static int skge_poll(struct net_device *dev, int *budget)
        unsigned int to_do = min(dev->quota, *budget);
        unsigned int work_done = 0;
 
-       pr_debug("skge_poll\n");
-
        for (e = ring->to_clean; work_done < to_do; e = e->next) {
                struct skge_rx_desc *rd = e->desc;
                struct sk_buff *skb;
@@ -2673,9 +2678,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)
@@ -3001,9 +3006,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)
@@ -3232,6 +3234,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);
@@ -3240,7 +3247,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);
@@ -3259,7 +3266,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..efbf98c675d2d5823acaf26fc9021e9de551b3f4 100644 (file)
@@ -2008,7 +2008,7 @@ enum {
        GM_IS_RX_FF_OR  = 1<<1, /* Receive FIFO Overrun */
        GM_IS_RX_COMPL  = 1<<0, /* Frame Reception Complete */
 
-#define GMAC_DEF_MSK   (GM_IS_TX_CO_OV | GM_IS_RX_CO_OV | GM_IS_TX_FF_UR)
+#define GMAC_DEF_MSK   (GM_IS_RX_FF_OR | GM_IS_TX_FF_UR)
 
 /*     GMAC_LINK_CTRL  16 bit  GMAC Link Control Reg (YUKON only) */
                                                /* Bits 15.. 2: reserved */
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 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 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 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 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 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 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 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 5cc53cd9323e5a9416fc7baf2ff22d8f233af653..d92273cbe0de279cdb5e9351c33a45b63fc8b397 100644 (file)
@@ -2465,9 +2465,12 @@ static unsigned long ata_pio_poll(struct ata_port *ap)
  *
  *     LOCKING:
  *     None.  (executing in kernel thread context)
+ *
+ *     RETURNS:
+ *     Non-zero if qc completed, zero otherwise.
  */
 
-static void ata_pio_complete (struct ata_port *ap)
+static int ata_pio_complete (struct ata_port *ap)
 {
        struct ata_queued_cmd *qc;
        u8 drv_stat;
@@ -2486,14 +2489,14 @@ static void ata_pio_complete (struct ata_port *ap)
                if (drv_stat & (ATA_BUSY | ATA_DRQ)) {
                        ap->pio_task_state = PIO_ST_LAST_POLL;
                        ap->pio_task_timeout = jiffies + ATA_TMOUT_PIO;
-                       return;
+                       return 0;
                }
        }
 
        drv_stat = ata_wait_idle(ap);
        if (!ata_ok(drv_stat)) {
                ap->pio_task_state = PIO_ST_ERR;
-               return;
+               return 0;
        }
 
        qc = ata_qc_from_tag(ap, ap->active_tag);
@@ -2502,6 +2505,10 @@ static void ata_pio_complete (struct ata_port *ap)
        ap->pio_task_state = PIO_ST_IDLE;
 
        ata_poll_qc_complete(qc, drv_stat);
+
+       /* another command may start at this point */
+
+       return 1;
 }
 
 
@@ -2709,7 +2716,7 @@ static void __atapi_pio_bytes(struct ata_queued_cmd *qc, unsigned int bytes)
 
 next_sg:
        if (unlikely(qc->cursg >= qc->n_elem)) {
-               /* 
+               /*
                 * The end of qc->sg is reached and the device expects
                 * more data to transfer. In order not to overrun qc->sg
                 * and fulfill length specified in the byte count register,
@@ -2721,7 +2728,7 @@ next_sg:
                unsigned int i;
 
                if (words) /* warning if bytes > 1 */
-                       printk(KERN_WARNING "ata%u: %u bytes trailing data\n", 
+                       printk(KERN_WARNING "ata%u: %u bytes trailing data\n",
                               ap->id, bytes);
 
                for (i = 0; i < words; i++)
@@ -2849,9 +2856,7 @@ static void ata_pio_block(struct ata_port *ap)
        if (is_atapi_taskfile(&qc->tf)) {
                /* no more data to transfer or unsupported ATAPI command */
                if ((status & ATA_DRQ) == 0) {
-                       ap->pio_task_state = PIO_ST_IDLE;
-
-                       ata_poll_qc_complete(qc, status);
+                       ap->pio_task_state = PIO_ST_LAST;
                        return;
                }
 
@@ -2887,7 +2892,12 @@ static void ata_pio_error(struct ata_port *ap)
 static void ata_pio_task(void *_data)
 {
        struct ata_port *ap = _data;
-       unsigned long timeout = 0;
+       unsigned long timeout;
+       int qc_completed;
+
+fsm_start:
+       timeout = 0;
+       qc_completed = 0;
 
        switch (ap->pio_task_state) {
        case PIO_ST_IDLE:
@@ -2898,7 +2908,7 @@ static void ata_pio_task(void *_data)
                break;
 
        case PIO_ST_LAST:
-               ata_pio_complete(ap);
+               qc_completed = ata_pio_complete(ap);
                break;
 
        case PIO_ST_POLL:
@@ -2913,10 +2923,9 @@ static void ata_pio_task(void *_data)
        }
 
        if (timeout)
-               queue_delayed_work(ata_wq, &ap->pio_task,
-                                  timeout);
-       else
-               queue_work(ata_wq, &ap->pio_task);
+               queue_delayed_work(ata_wq, &ap->pio_task, timeout);
+       else if (!qc_completed)
+               goto fsm_start;
 }
 
 static void atapi_request_sense(struct ata_port *ap, struct ata_device *dev,
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 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 31ee13eef7afb34eb1a4c40756108ebb1c2ad2e8..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
index 92643af12581312bb022b19ac95f2374e5c2dbd7..0bea0d8d78211a57b8d9f6d1358c343cc03715c0 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,12 @@ int atyfb_xl_init(struct fb_info *info)
        aty_st_le32(0xEC, 0x00000000, par);
        aty_st_le32(0xFC, 0x00000000, par);
 
+#if defined (CONFIG_FB_ATY_GENERIC_LCD)
+       int i;
        for (i=0; i<sizeof(lcd_tbl)/sizeof(lcd_tbl_t); 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 a32817678552f61de175cd18302343be45a725a1..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)
 {
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 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 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 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 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 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 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 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 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..fb34f88a4a747abc6251a8895c31ec13dceb3a1f 100644 (file)
@@ -340,6 +340,52 @@ 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);
+               struct task_struct *task = leader;
+               read_lock(&tasklist_lock);
+               if (pid_alive(task)) {
+                       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 +517,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 +557,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 +574,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 +1489,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 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 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
 
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
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 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 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 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 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 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 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 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 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 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 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 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)
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 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 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 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 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 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 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 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..bace72a76cc45dea47944e26679d4473bff4e627 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;
@@ -372,7 +384,7 @@ extern struct ip_conntrack_expect *
 __ip_conntrack_expect_find(const struct ip_conntrack_tuple *tuple);
 
 extern struct ip_conntrack_expect *
-ip_conntrack_expect_find_get(const struct ip_conntrack_tuple *tuple);
+ip_conntrack_expect_find(const struct ip_conntrack_tuple *tuple);
 
 extern struct ip_conntrack_tuple_hash *
 __ip_conntrack_find(const struct ip_conntrack_tuple *tuple,
diff --git a/include/linux/netfilter_ipv4/ip_conntrack_pptp.h b/include/linux/netfilter_ipv4/ip_conntrack_pptp.h
new file mode 100644 (file)
index 0000000..389e385
--- /dev/null
@@ -0,0 +1,332 @@
+/* PPTP constants and structs */
+#ifndef _CONNTRACK_PPTP_H
+#define _CONNTRACK_PPTP_H
+
+/* state of the control session */
+enum pptp_ctrlsess_state {
+       PPTP_SESSION_NONE,                      /* no session present */
+       PPTP_SESSION_ERROR,                     /* some session error */
+       PPTP_SESSION_STOPREQ,                   /* stop_sess request seen */
+       PPTP_SESSION_REQUESTED,                 /* start_sess request seen */
+       PPTP_SESSION_CONFIRMED,                 /* session established */
+};
+
+/* state of the call inside the control session */
+enum pptp_ctrlcall_state {
+       PPTP_CALL_NONE,
+       PPTP_CALL_ERROR,
+       PPTP_CALL_OUT_REQ,
+       PPTP_CALL_OUT_CONF,
+       PPTP_CALL_IN_REQ,
+       PPTP_CALL_IN_REP,
+       PPTP_CALL_IN_CONF,
+       PPTP_CALL_CLEAR_REQ,
+};
+
+
+/* conntrack private data */
+struct ip_ct_pptp_master {
+       enum pptp_ctrlsess_state sstate;        /* session state */
+
+       /* everything below is going to be per-expectation in newnat,
+        * since there could be more than one call within one session */
+       enum pptp_ctrlcall_state cstate;        /* call state */
+       u_int16_t pac_call_id;                  /* call id of PAC, host byte order */
+       u_int16_t pns_call_id;                  /* call id of PNS, host byte order */
+
+       /* in pre-2.6.11 this used to be per-expect. Now it is per-conntrack
+        * and therefore imposes a fixed limit on the number of maps */
+       struct ip_ct_gre_keymap *keymap_orig, *keymap_reply;
+};
+
+/* conntrack_expect private member */
+struct ip_ct_pptp_expect {
+       enum pptp_ctrlcall_state cstate;        /* call state */
+       u_int16_t pac_call_id;                  /* call id of PAC */
+       u_int16_t pns_call_id;                  /* call id of PNS */
+};
+
+
+#ifdef __KERNEL__
+
+#define IP_CONNTR_PPTP         PPTP_CONTROL_PORT
+
+#define PPTP_CONTROL_PORT      1723
+
+#define PPTP_PACKET_CONTROL    1
+#define PPTP_PACKET_MGMT       2
+
+#define PPTP_MAGIC_COOKIE      0x1a2b3c4d
+
+struct pptp_pkt_hdr {
+       __u16   packetLength;
+       __u16   packetType;
+       __u32   magicCookie;
+};
+
+/* PptpControlMessageType values */
+#define PPTP_START_SESSION_REQUEST     1
+#define PPTP_START_SESSION_REPLY       2
+#define PPTP_STOP_SESSION_REQUEST      3
+#define PPTP_STOP_SESSION_REPLY                4
+#define PPTP_ECHO_REQUEST              5
+#define PPTP_ECHO_REPLY                        6
+#define PPTP_OUT_CALL_REQUEST          7
+#define PPTP_OUT_CALL_REPLY            8
+#define PPTP_IN_CALL_REQUEST           9
+#define PPTP_IN_CALL_REPLY             10
+#define PPTP_IN_CALL_CONNECT           11
+#define PPTP_CALL_CLEAR_REQUEST                12
+#define PPTP_CALL_DISCONNECT_NOTIFY    13
+#define PPTP_WAN_ERROR_NOTIFY          14
+#define PPTP_SET_LINK_INFO             15
+
+#define PPTP_MSG_MAX                   15
+
+/* PptpGeneralError values */
+#define PPTP_ERROR_CODE_NONE           0
+#define PPTP_NOT_CONNECTED             1
+#define PPTP_BAD_FORMAT                        2
+#define PPTP_BAD_VALUE                 3
+#define PPTP_NO_RESOURCE               4
+#define PPTP_BAD_CALLID                        5
+#define PPTP_REMOVE_DEVICE_ERROR       6
+
+struct PptpControlHeader {
+       __u16   messageType;
+       __u16   reserved;
+};
+
+/* FramingCapability Bitmap Values */
+#define PPTP_FRAME_CAP_ASYNC           0x1
+#define PPTP_FRAME_CAP_SYNC            0x2
+
+/* BearerCapability Bitmap Values */
+#define PPTP_BEARER_CAP_ANALOG         0x1
+#define PPTP_BEARER_CAP_DIGITAL                0x2
+
+struct PptpStartSessionRequest {
+       __u16   protocolVersion;
+       __u8    reserved1;
+       __u8    reserved2;
+       __u32   framingCapability;
+       __u32   bearerCapability;
+       __u16   maxChannels;
+       __u16   firmwareRevision;
+       __u8    hostName[64];
+       __u8    vendorString[64];
+};
+
+/* PptpStartSessionResultCode Values */
+#define PPTP_START_OK                  1
+#define PPTP_START_GENERAL_ERROR       2
+#define PPTP_START_ALREADY_CONNECTED   3
+#define PPTP_START_NOT_AUTHORIZED      4
+#define PPTP_START_UNKNOWN_PROTOCOL    5
+
+struct PptpStartSessionReply {
+       __u16   protocolVersion;
+       __u8    resultCode;
+       __u8    generalErrorCode;
+       __u32   framingCapability;
+       __u32   bearerCapability;
+       __u16   maxChannels;
+       __u16   firmwareRevision;
+       __u8    hostName[64];
+       __u8    vendorString[64];
+};
+
+/* PptpStopReasons */
+#define PPTP_STOP_NONE                 1
+#define PPTP_STOP_PROTOCOL             2
+#define PPTP_STOP_LOCAL_SHUTDOWN       3
+
+struct PptpStopSessionRequest {
+       __u8    reason;
+};
+
+/* PptpStopSessionResultCode */
+#define PPTP_STOP_OK                   1
+#define PPTP_STOP_GENERAL_ERROR                2
+
+struct PptpStopSessionReply {
+       __u8    resultCode;
+       __u8    generalErrorCode;
+};
+
+struct PptpEchoRequest {
+       __u32 identNumber;
+};
+
+/* PptpEchoReplyResultCode */
+#define PPTP_ECHO_OK                   1
+#define PPTP_ECHO_GENERAL_ERROR                2
+
+struct PptpEchoReply {
+       __u32   identNumber;
+       __u8    resultCode;
+       __u8    generalErrorCode;
+       __u16   reserved;
+};
+
+/* PptpFramingType */
+#define PPTP_ASYNC_FRAMING             1
+#define PPTP_SYNC_FRAMING              2
+#define PPTP_DONT_CARE_FRAMING         3
+
+/* PptpCallBearerType */
+#define PPTP_ANALOG_TYPE               1
+#define PPTP_DIGITAL_TYPE              2
+#define PPTP_DONT_CARE_BEARER_TYPE     3
+
+struct PptpOutCallRequest {
+       __u16   callID;
+       __u16   callSerialNumber;
+       __u32   minBPS;
+       __u32   maxBPS;
+       __u32   bearerType;
+       __u32   framingType;
+       __u16   packetWindow;
+       __u16   packetProcDelay;
+       __u16   reserved1;
+       __u16   phoneNumberLength;
+       __u16   reserved2;
+       __u8    phoneNumber[64];
+       __u8    subAddress[64];
+};
+
+/* PptpCallResultCode */
+#define PPTP_OUTCALL_CONNECT           1
+#define PPTP_OUTCALL_GENERAL_ERROR     2
+#define PPTP_OUTCALL_NO_CARRIER                3
+#define PPTP_OUTCALL_BUSY              4
+#define PPTP_OUTCALL_NO_DIAL_TONE      5
+#define PPTP_OUTCALL_TIMEOUT           6
+#define PPTP_OUTCALL_DONT_ACCEPT       7
+
+struct PptpOutCallReply {
+       __u16   callID;
+       __u16   peersCallID;
+       __u8    resultCode;
+       __u8    generalErrorCode;
+       __u16   causeCode;
+       __u32   connectSpeed;
+       __u16   packetWindow;
+       __u16   packetProcDelay;
+       __u32   physChannelID;
+};
+
+struct PptpInCallRequest {
+       __u16   callID;
+       __u16   callSerialNumber;
+       __u32   callBearerType;
+       __u32   physChannelID;
+       __u16   dialedNumberLength;
+       __u16   dialingNumberLength;
+       __u8    dialedNumber[64];
+       __u8    dialingNumber[64];
+       __u8    subAddress[64];
+};
+
+/* PptpInCallResultCode */
+#define PPTP_INCALL_ACCEPT             1
+#define PPTP_INCALL_GENERAL_ERROR      2
+#define PPTP_INCALL_DONT_ACCEPT                3
+
+struct PptpInCallReply {
+       __u16   callID;
+       __u16   peersCallID;
+       __u8    resultCode;
+       __u8    generalErrorCode;
+       __u16   packetWindow;
+       __u16   packetProcDelay;
+       __u16   reserved;
+};
+
+struct PptpInCallConnected {
+       __u16   peersCallID;
+       __u16   reserved;
+       __u32   connectSpeed;
+       __u16   packetWindow;
+       __u16   packetProcDelay;
+       __u32   callFramingType;
+};
+
+struct PptpClearCallRequest {
+       __u16   callID;
+       __u16   reserved;
+};
+
+struct PptpCallDisconnectNotify {
+       __u16   callID;
+       __u8    resultCode;
+       __u8    generalErrorCode;
+       __u16   causeCode;
+       __u16   reserved;
+       __u8    callStatistics[128];
+};
+
+struct PptpWanErrorNotify {
+       __u16   peersCallID;
+       __u16   reserved;
+       __u32   crcErrors;
+       __u32   framingErrors;
+       __u32   hardwareOverRuns;
+       __u32   bufferOverRuns;
+       __u32   timeoutErrors;
+       __u32   alignmentErrors;
+};
+
+struct PptpSetLinkInfo {
+       __u16   peersCallID;
+       __u16   reserved;
+       __u32   sendAccm;
+       __u32   recvAccm;
+};
+
+
+struct pptp_priv_data {
+       __u16   call_id;
+       __u16   mcall_id;
+       __u16   pcall_id;
+};
+
+union pptp_ctrl_union {
+               struct PptpStartSessionRequest  sreq;
+               struct PptpStartSessionReply    srep;
+               struct PptpStopSessionRequest   streq;
+               struct PptpStopSessionReply     strep;
+                struct PptpOutCallRequest       ocreq;
+                struct PptpOutCallReply         ocack;
+                struct PptpInCallRequest        icreq;
+                struct PptpInCallReply          icack;
+                struct PptpInCallConnected      iccon;
+               struct PptpClearCallRequest     clrreq;
+                struct PptpCallDisconnectNotify disc;
+                struct PptpWanErrorNotify       wanerr;
+                struct PptpSetLinkInfo          setlink;
+};
+
+extern int
+(*ip_nat_pptp_hook_outbound)(struct sk_buff **pskb,
+                         struct ip_conntrack *ct,
+                         enum ip_conntrack_info ctinfo,
+                         struct PptpControlHeader *ctlh,
+                         union pptp_ctrl_union *pptpReq);
+
+extern int
+(*ip_nat_pptp_hook_inbound)(struct sk_buff **pskb,
+                         struct ip_conntrack *ct,
+                         enum ip_conntrack_info ctinfo,
+                         struct PptpControlHeader *ctlh,
+                         union pptp_ctrl_union *pptpReq);
+
+extern int
+(*ip_nat_pptp_hook_exp_gre)(struct ip_conntrack_expect *exp_orig,
+                           struct ip_conntrack_expect *exp_reply);
+
+extern void
+(*ip_nat_pptp_hook_expectfn)(struct ip_conntrack *ct,
+                            struct ip_conntrack_expect *exp);
+#endif /* __KERNEL__ */
+#endif /* _CONNTRACK_PPTP_H */
diff --git a/include/linux/netfilter_ipv4/ip_conntrack_proto_gre.h b/include/linux/netfilter_ipv4/ip_conntrack_proto_gre.h
new file mode 100644 (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..14dc0f7b655636c60d2cec9780ad642625500534 100644 (file)
@@ -28,6 +28,9 @@ union ip_conntrack_manip_proto
        struct {
                u_int16_t port;
        } sctp;
+       struct {
+               u_int16_t key;  /* key is 32bit, pptp only uses 16 */
+       } gre;
 };
 
 /* The manipulable part of the tuple. */
@@ -61,6 +64,10 @@ struct ip_conntrack_tuple
                        struct {
                                u_int16_t port;
                        } sctp;
+                       struct {
+                               u_int16_t key;  /* key is 32bit, 
+                                                * pptp only uses 16 */
+                       } gre;
                } u;
 
                /* The protocol. */
diff --git a/include/linux/netfilter_ipv4/ip_nat_pptp.h b/include/linux/netfilter_ipv4/ip_nat_pptp.h
new file mode 100644 (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 f6c1a142286ada86dedd2acf509dfc429b594186..c49d28eca561852803437ecc3555cec52bad8413 100644 (file)
 #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_RME_DIGI96       0x3fc0
 #define PCI_DEVICE_ID_RME_DIGI96_8     0x3fc1
 #define PCI_DEVICE_ID_RME_DIGI96_8_PRO 0x3fc2
-#define PCI_DEVICE_IDRME__DIGI96_8_PAD_OR_PST 0x3fc3
+#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_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
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 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 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 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 c80412be2302c6321898b57ef3a99d10a1c21a68..f723522e69868b6aadf3ad675a44c6fa62c13b04 100644 (file)
@@ -1728,8 +1728,7 @@ asmlinkage long sys_prctl(int option, unsigned long arg2, unsigned long arg3,
                        error = put_user(current->pdeath_signal, (int __user *)arg2);
                        break;
                case PR_GET_DUMPABLE:
-                       if (current->mm->dumpable)
-                               error = 1;
+                       error = current->mm->dumpable;
                        break;
                case PR_SET_DUMPABLE:
                        if (arg2 < 0 || arg2 > 2) {
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 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 9e876d6dfad97f2c4ab60a881edcb91d528c1c3c..437d3388054bbe93bd2567eb8257f6365a1c5c78 100644 (file)
--- a/mm/slab.c
+++ b/mm/slab.c
@@ -659,7 +659,7 @@ static inline kmem_cache_t *__find_general_cachep(size_t size,
        * kmem_cache_create(), or __kmalloc(), before
        * the generic caches are initialized.
        */
-       BUG_ON(csizep->cs_cachep == NULL);
+       BUG_ON(malloc_sizes[INDEX_AC].cs_cachep == NULL);
 #endif
        while (size > csizep->cs_size)
                csizep++;
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 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 c74034cf7ede15e34390531a549c4a7ce1048193..1b6b2cb12376ecb27edadcd81eb32ff0a4716a1b 100644 (file)
@@ -16,6 +16,7 @@
 
 #include <net/sock.h>
 
+#include "ackvec.h"
 #include "ccid.h"
 #include "dccp.h"
 
@@ -60,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)
@@ -164,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);
@@ -384,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,
@@ -433,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;
 
@@ -473,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;
        }
 
@@ -487,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;
        }
 
        /*
@@ -551,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);
@@ -563,13 +520,13 @@ int dccp_rcv_state_process(struct sock *sk, struct sk_buff *skb,
        }
 
        if (unlikely(dh->dccph_type == DCCP_PKT_SYNC)) {
-               dccp_send_sync(sk, DCCP_SKB_CB(skb)->dccpd_seq,
-                              DCCP_PKT_SYNCACK);
+               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 19cba16e6e1e587c5281a997ac67ec7fa291da8a..c1f82e0c81cf64d1c7f094621ff4f35fbd5b2d45 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;
        
@@ -1143,7 +1143,10 @@ void ip_ct_refresh_acct(struct ip_conntrack *ct,
                if (del_timer(&ct->timeout)) {
                        ct->timeout.expires = jiffies + extra_jiffies;
                        add_timer(&ct->timeout);
-                       ip_conntrack_event_cache(IPCT_REFRESH, skb);
+                       /* FIXME: We loose some REFRESH events if this function
+                        * is called without an skb.  I'll fix this later -HW */
+                       if (skb)
+                               ip_conntrack_event_cache(IPCT_REFRESH, skb);
                }
                ct_add_counters(ct, ctinfo, skb);
                write_unlock_bh(&ip_conntrack_lock);
diff --git a/net/ipv4/netfilter/ip_conntrack_helper_pptp.c b/net/ipv4/netfilter/ip_conntrack_helper_pptp.c
new file mode 100644 (file)
index 0000000..79db5b7
--- /dev/null
@@ -0,0 +1,805 @@
+/*
+ * ip_conntrack_pptp.c - Version 3.0
+ *
+ * Connection tracking support for PPTP (Point to Point Tunneling Protocol).
+ * PPTP is a a protocol for creating virtual private networks.
+ * It is a specification defined by Microsoft and some vendors
+ * working with Microsoft.  PPTP is built on top of a modified
+ * version of the Internet Generic Routing Encapsulation Protocol.
+ * GRE is defined in RFC 1701 and RFC 1702.  Documentation of
+ * PPTP can be found in RFC 2637
+ *
+ * (C) 2000-2005 by Harald Welte <laforge@gnumonks.org>
+ *
+ * Development of this code funded by Astaro AG (http://www.astaro.com/)
+ *
+ * Limitations:
+ *      - We blindly assume that control connections are always
+ *        established in PNS->PAC direction.  This is a violation
+ *        of RFFC2673
+ *      - We can only support one single call within each session
+ *
+ * TODO:
+ *      - testing of incoming PPTP calls 
+ *
+ * Changes: 
+ *     2002-02-05 - Version 1.3
+ *       - Call ip_conntrack_unexpect_related() from 
+ *         pptp_destroy_siblings() to destroy expectations in case
+ *         CALL_DISCONNECT_NOTIFY or tcp fin packet was seen
+ *         (Philip Craig <philipc@snapgear.com>)
+ *       - Add Version information at module loadtime
+ *     2002-02-10 - Version 1.6
+ *       - move to C99 style initializers
+ *       - remove second expectation if first arrives
+ *     2004-10-22 - Version 2.0
+ *       - merge Mandrake's 2.6.x port with recent 2.6.x API changes
+ *       - fix lots of linear skb assumptions from Mandrake's port
+ *     2005-06-10 - Version 2.1
+ *       - use ip_conntrack_expect_free() instead of kfree() on the
+ *         expect's (which are from the slab for quite some time)
+ *     2005-06-10 - Version 3.0
+ *       - port helper to post-2.6.11 API changes,
+ *         funded by Oxcoda NetBox Blue (http://www.netboxblue.com/)
+ *     2005-07-30 - Version 3.1
+ *       - port helper to 2.6.13 API changes
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/netfilter.h>
+#include <linux/ip.h>
+#include <net/checksum.h>
+#include <net/tcp.h>
+
+#include <linux/netfilter_ipv4/ip_conntrack.h>
+#include <linux/netfilter_ipv4/ip_conntrack_core.h>
+#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
+#include <linux/netfilter_ipv4/ip_conntrack_proto_gre.h>
+#include <linux/netfilter_ipv4/ip_conntrack_pptp.h>
+
+#define IP_CT_PPTP_VERSION "3.1"
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Harald Welte <laforge@gnumonks.org>");
+MODULE_DESCRIPTION("Netfilter connection tracking helper module for PPTP");
+
+static DEFINE_SPINLOCK(ip_pptp_lock);
+
+int
+(*ip_nat_pptp_hook_outbound)(struct sk_buff **pskb,
+                         struct ip_conntrack *ct,
+                         enum ip_conntrack_info ctinfo,
+                         struct PptpControlHeader *ctlh,
+                         union pptp_ctrl_union *pptpReq);
+
+int
+(*ip_nat_pptp_hook_inbound)(struct sk_buff **pskb,
+                         struct ip_conntrack *ct,
+                         enum ip_conntrack_info ctinfo,
+                         struct PptpControlHeader *ctlh,
+                         union pptp_ctrl_union *pptpReq);
+
+int
+(*ip_nat_pptp_hook_exp_gre)(struct ip_conntrack_expect *expect_orig,
+                           struct ip_conntrack_expect *expect_reply);
+
+void
+(*ip_nat_pptp_hook_expectfn)(struct ip_conntrack *ct,
+                            struct ip_conntrack_expect *exp);
+
+#if 0
+/* PptpControlMessageType names */
+const char *pptp_msg_name[] = {
+       "UNKNOWN_MESSAGE",
+       "START_SESSION_REQUEST",
+       "START_SESSION_REPLY",
+       "STOP_SESSION_REQUEST",
+       "STOP_SESSION_REPLY",
+       "ECHO_REQUEST",
+       "ECHO_REPLY",
+       "OUT_CALL_REQUEST",
+       "OUT_CALL_REPLY",
+       "IN_CALL_REQUEST",
+       "IN_CALL_REPLY",
+       "IN_CALL_CONNECT",
+       "CALL_CLEAR_REQUEST",
+       "CALL_DISCONNECT_NOTIFY",
+       "WAN_ERROR_NOTIFY",
+       "SET_LINK_INFO"
+};
+EXPORT_SYMBOL(pptp_msg_name);
+#define DEBUGP(format, args...)        printk(KERN_DEBUG "%s:%s: " format, __FILE__, __FUNCTION__, ## args)
+#else
+#define DEBUGP(format, args...)
+#endif
+
+#define SECS *HZ
+#define MINS * 60 SECS
+#define HOURS * 60 MINS
+
+#define PPTP_GRE_TIMEOUT               (10 MINS)
+#define PPTP_GRE_STREAM_TIMEOUT        (5 HOURS)
+
+static void pptp_expectfn(struct ip_conntrack *ct,
+                        struct ip_conntrack_expect *exp)
+{
+       DEBUGP("increasing timeouts\n");
+
+       /* increase timeout of GRE data channel conntrack entry */
+       ct->proto.gre.timeout = PPTP_GRE_TIMEOUT;
+       ct->proto.gre.stream_timeout = PPTP_GRE_STREAM_TIMEOUT;
+
+       /* Can you see how rusty this code is, compared with the pre-2.6.11
+        * one? That's what happened to my shiny newnat of 2002 ;( -HW */
+
+       if (!ip_nat_pptp_hook_expectfn) {
+               struct ip_conntrack_tuple inv_t;
+               struct ip_conntrack_expect *exp_other;
+
+               /* obviously this tuple inversion only works until you do NAT */
+               invert_tuplepr(&inv_t, &exp->tuple);
+               DEBUGP("trying to unexpect other dir: ");
+               DUMP_TUPLE(&inv_t);
+       
+               exp_other = ip_conntrack_expect_find(&inv_t);
+               if (exp_other) {
+                       /* delete other expectation.  */
+                       DEBUGP("found\n");
+                       ip_conntrack_unexpect_related(exp_other);
+                       ip_conntrack_expect_put(exp_other);
+               } else {
+                       DEBUGP("not found\n");
+               }
+       } else {
+               /* we need more than simple inversion */
+               ip_nat_pptp_hook_expectfn(ct, exp);
+       }
+}
+
+static int destroy_sibling_or_exp(const struct ip_conntrack_tuple *t)
+{
+       struct ip_conntrack_tuple_hash *h;
+       struct ip_conntrack_expect *exp;
+
+       DEBUGP("trying to timeout ct or exp for tuple ");
+       DUMP_TUPLE(t);
+
+       h = ip_conntrack_find_get(t, NULL);
+       if (h)  {
+               struct ip_conntrack *sibling = tuplehash_to_ctrack(h);
+               DEBUGP("setting timeout of conntrack %p to 0\n", sibling);
+               sibling->proto.gre.timeout = 0;
+               sibling->proto.gre.stream_timeout = 0;
+               /* refresh_acct will not modify counters if skb == NULL */
+               if (del_timer(&sibling->timeout))
+                       sibling->timeout.function((unsigned long)sibling);
+               ip_conntrack_put(sibling);
+               return 1;
+       } else {
+               exp = ip_conntrack_expect_find(t);
+               if (exp) {
+                       DEBUGP("unexpect_related of expect %p\n", exp);
+                       ip_conntrack_unexpect_related(exp);
+                       ip_conntrack_expect_put(exp);
+                       return 1;
+               }
+       }
+
+       return 0;
+}
+
+
+/* timeout GRE data connections */
+static void pptp_destroy_siblings(struct ip_conntrack *ct)
+{
+       struct ip_conntrack_tuple t;
+
+       /* Since ct->sibling_list has literally rusted away in 2.6.11, 
+        * we now need another way to find out about our sibling
+        * contrack and expects... -HW */
+
+       /* try original (pns->pac) tuple */
+       memcpy(&t, &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple, sizeof(t));
+       t.dst.protonum = IPPROTO_GRE;
+       t.src.u.gre.key = htons(ct->help.ct_pptp_info.pns_call_id);
+       t.dst.u.gre.key = htons(ct->help.ct_pptp_info.pac_call_id);
+
+       if (!destroy_sibling_or_exp(&t))
+               DEBUGP("failed to timeout original pns->pac ct/exp\n");
+
+       /* try reply (pac->pns) tuple */
+       memcpy(&t, &ct->tuplehash[IP_CT_DIR_REPLY].tuple, sizeof(t));
+       t.dst.protonum = IPPROTO_GRE;
+       t.src.u.gre.key = htons(ct->help.ct_pptp_info.pac_call_id);
+       t.dst.u.gre.key = htons(ct->help.ct_pptp_info.pns_call_id);
+
+       if (!destroy_sibling_or_exp(&t))
+               DEBUGP("failed to timeout reply pac->pns ct/exp\n");
+}
+
+/* expect GRE connections (PNS->PAC and PAC->PNS direction) */
+static inline int
+exp_gre(struct ip_conntrack *master,
+       u_int32_t seq,
+       u_int16_t callid,
+       u_int16_t peer_callid)
+{
+       struct ip_conntrack_tuple inv_tuple;
+       struct ip_conntrack_tuple exp_tuples[] = {
+               /* tuple in original direction, PNS->PAC */
+               { .src = { .ip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip,
+                          .u = { .gre = { .key = peer_callid } }
+                        },
+                 .dst = { .ip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip,
+                          .u = { .gre = { .key = callid } },
+                          .protonum = IPPROTO_GRE
+                        },
+                },
+               /* tuple in reply direction, PAC->PNS */
+               { .src = { .ip = master->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip,
+                          .u = { .gre = { .key = callid } }
+                        },
+                 .dst = { .ip = master->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip,
+                          .u = { .gre = { .key = peer_callid } },
+                          .protonum = IPPROTO_GRE
+                        },
+                }
+       };
+       struct ip_conntrack_expect *exp_orig, *exp_reply;
+       int ret = 1;
+
+       exp_orig = ip_conntrack_expect_alloc(master);
+       if (exp_orig == NULL)
+               goto out;
+
+       exp_reply = ip_conntrack_expect_alloc(master);
+       if (exp_reply == NULL)
+               goto out_put_orig;
+
+       memcpy(&exp_orig->tuple, &exp_tuples[0], sizeof(exp_orig->tuple));
+
+       exp_orig->mask.src.ip = 0xffffffff;
+       exp_orig->mask.src.u.all = 0;
+       exp_orig->mask.dst.u.all = 0;
+       exp_orig->mask.dst.u.gre.key = 0xffff;
+       exp_orig->mask.dst.ip = 0xffffffff;
+       exp_orig->mask.dst.protonum = 0xff;
+               
+       exp_orig->master = master;
+       exp_orig->expectfn = pptp_expectfn;
+       exp_orig->flags = 0;
+
+       exp_orig->dir = IP_CT_DIR_ORIGINAL;
+
+       /* both expectations are identical apart from tuple */
+       memcpy(exp_reply, exp_orig, sizeof(*exp_reply));
+       memcpy(&exp_reply->tuple, &exp_tuples[1], sizeof(exp_reply->tuple));
+
+       exp_reply->dir = !exp_orig->dir;
+
+       if (ip_nat_pptp_hook_exp_gre)
+               ret = ip_nat_pptp_hook_exp_gre(exp_orig, exp_reply);
+       else {
+
+               DEBUGP("calling expect_related PNS->PAC");
+               DUMP_TUPLE(&exp_orig->tuple);
+
+               if (ip_conntrack_expect_related(exp_orig) != 0) {
+                       DEBUGP("cannot expect_related()\n");
+                       goto out_put_both;
+               }
+
+               DEBUGP("calling expect_related PAC->PNS");
+               DUMP_TUPLE(&exp_reply->tuple);
+
+               if (ip_conntrack_expect_related(exp_reply) != 0) {
+                       DEBUGP("cannot expect_related()\n");
+                       goto out_unexpect_orig;
+               }
+
+               /* Add GRE keymap entries */
+               if (ip_ct_gre_keymap_add(master, &exp_reply->tuple, 0) != 0) {
+                       DEBUGP("cannot keymap_add() exp\n");
+                       goto out_unexpect_both;
+               }
+
+               invert_tuplepr(&inv_tuple, &exp_reply->tuple);
+               if (ip_ct_gre_keymap_add(master, &inv_tuple, 1) != 0) {
+                       ip_ct_gre_keymap_destroy(master);
+                       DEBUGP("cannot keymap_add() exp_inv\n");
+                       goto out_unexpect_both;
+               }
+               ret = 0;
+       }
+
+out_put_both:
+       ip_conntrack_expect_put(exp_reply);
+out_put_orig:
+       ip_conntrack_expect_put(exp_orig);
+out:
+       return ret;
+
+out_unexpect_both:
+       ip_conntrack_unexpect_related(exp_reply);
+out_unexpect_orig:
+       ip_conntrack_unexpect_related(exp_orig);
+       goto out_put_both;
+}
+
+static inline int 
+pptp_inbound_pkt(struct sk_buff **pskb,
+                struct tcphdr *tcph,
+                unsigned int nexthdr_off,
+                unsigned int datalen,
+                struct ip_conntrack *ct,
+                enum ip_conntrack_info ctinfo)
+{
+       struct PptpControlHeader _ctlh, *ctlh;
+       unsigned int reqlen;
+       union pptp_ctrl_union _pptpReq, *pptpReq;
+       struct ip_ct_pptp_master *info = &ct->help.ct_pptp_info;
+       u_int16_t msg, *cid, *pcid;
+       u_int32_t seq;  
+
+       ctlh = skb_header_pointer(*pskb, nexthdr_off, sizeof(_ctlh), &_ctlh);
+       if (!ctlh) {
+               DEBUGP("error during skb_header_pointer\n");
+               return NF_ACCEPT;
+       }
+       nexthdr_off += sizeof(_ctlh);
+       datalen -= sizeof(_ctlh);
+
+       reqlen = datalen;
+       if (reqlen > sizeof(*pptpReq))
+               reqlen = sizeof(*pptpReq);
+       pptpReq = skb_header_pointer(*pskb, nexthdr_off, reqlen, &_pptpReq);
+       if (!pptpReq) {
+               DEBUGP("error during skb_header_pointer\n");
+               return NF_ACCEPT;
+       }
+
+       msg = ntohs(ctlh->messageType);
+       DEBUGP("inbound control message %s\n", pptp_msg_name[msg]);
+
+       switch (msg) {
+       case PPTP_START_SESSION_REPLY:
+               if (reqlen < sizeof(_pptpReq.srep)) {
+                       DEBUGP("%s: short packet\n", pptp_msg_name[msg]);
+                       break;
+               }
+
+               /* server confirms new control session */
+               if (info->sstate < PPTP_SESSION_REQUESTED) {
+                       DEBUGP("%s without START_SESS_REQUEST\n",
+                               pptp_msg_name[msg]);
+                       break;
+               }
+               if (pptpReq->srep.resultCode == PPTP_START_OK)
+                       info->sstate = PPTP_SESSION_CONFIRMED;
+               else 
+                       info->sstate = PPTP_SESSION_ERROR;
+               break;
+
+       case PPTP_STOP_SESSION_REPLY:
+               if (reqlen < sizeof(_pptpReq.strep)) {
+                       DEBUGP("%s: short packet\n", pptp_msg_name[msg]);
+                       break;
+               }
+
+               /* server confirms end of control session */
+               if (info->sstate > PPTP_SESSION_STOPREQ) {
+                       DEBUGP("%s without STOP_SESS_REQUEST\n",
+                               pptp_msg_name[msg]);
+                       break;
+               }
+               if (pptpReq->strep.resultCode == PPTP_STOP_OK)
+                       info->sstate = PPTP_SESSION_NONE;
+               else
+                       info->sstate = PPTP_SESSION_ERROR;
+               break;
+
+       case PPTP_OUT_CALL_REPLY:
+               if (reqlen < sizeof(_pptpReq.ocack)) {
+                       DEBUGP("%s: short packet\n", pptp_msg_name[msg]);
+                       break;
+               }
+
+               /* server accepted call, we now expect GRE frames */
+               if (info->sstate != PPTP_SESSION_CONFIRMED) {
+                       DEBUGP("%s but no session\n", pptp_msg_name[msg]);
+                       break;
+               }
+               if (info->cstate != PPTP_CALL_OUT_REQ &&
+                   info->cstate != PPTP_CALL_OUT_CONF) {
+                       DEBUGP("%s without OUTCALL_REQ\n", pptp_msg_name[msg]);
+                       break;
+               }
+               if (pptpReq->ocack.resultCode != PPTP_OUTCALL_CONNECT) {
+                       info->cstate = PPTP_CALL_NONE;
+                       break;
+               }
+
+               cid = &pptpReq->ocack.callID;
+               pcid = &pptpReq->ocack.peersCallID;
+
+               info->pac_call_id = ntohs(*cid);
+               
+               if (htons(info->pns_call_id) != *pcid) {
+                       DEBUGP("%s for unknown callid %u\n",
+                               pptp_msg_name[msg], ntohs(*pcid));
+                       break;
+               }
+
+               DEBUGP("%s, CID=%X, PCID=%X\n", pptp_msg_name[msg], 
+                       ntohs(*cid), ntohs(*pcid));
+               
+               info->cstate = PPTP_CALL_OUT_CONF;
+
+               seq = ntohl(tcph->seq) + sizeof(struct pptp_pkt_hdr)
+                                      + sizeof(struct PptpControlHeader)
+                                      + ((void *)pcid - (void *)pptpReq);
+                       
+               if (exp_gre(ct, seq, *cid, *pcid) != 0)
+                       printk("ip_conntrack_pptp: error during exp_gre\n");
+               break;
+
+       case PPTP_IN_CALL_REQUEST:
+               if (reqlen < sizeof(_pptpReq.icack)) {
+                       DEBUGP("%s: short packet\n", pptp_msg_name[msg]);
+                       break;
+               }
+
+               /* server tells us about incoming call request */
+               if (info->sstate != PPTP_SESSION_CONFIRMED) {
+                       DEBUGP("%s but no session\n", pptp_msg_name[msg]);
+                       break;
+               }
+               pcid = &pptpReq->icack.peersCallID;
+               DEBUGP("%s, PCID=%X\n", pptp_msg_name[msg], ntohs(*pcid));
+               info->cstate = PPTP_CALL_IN_REQ;
+               info->pac_call_id = ntohs(*pcid);
+               break;
+
+       case PPTP_IN_CALL_CONNECT:
+               if (reqlen < sizeof(_pptpReq.iccon)) {
+                       DEBUGP("%s: short packet\n", pptp_msg_name[msg]);
+                       break;
+               }
+
+               /* server tells us about incoming call established */
+               if (info->sstate != PPTP_SESSION_CONFIRMED) {
+                       DEBUGP("%s but no session\n", pptp_msg_name[msg]);
+                       break;
+               }
+               if (info->sstate != PPTP_CALL_IN_REP
+                   && info->sstate != PPTP_CALL_IN_CONF) {
+                       DEBUGP("%s but never sent IN_CALL_REPLY\n",
+                               pptp_msg_name[msg]);
+                       break;
+               }
+
+               pcid = &pptpReq->iccon.peersCallID;
+               cid = &info->pac_call_id;
+
+               if (info->pns_call_id != ntohs(*pcid)) {
+                       DEBUGP("%s for unknown CallID %u\n", 
+                               pptp_msg_name[msg], ntohs(*cid));
+                       break;
+               }
+
+               DEBUGP("%s, PCID=%X\n", pptp_msg_name[msg], ntohs(*pcid));
+               info->cstate = PPTP_CALL_IN_CONF;
+
+               /* we expect a GRE connection from PAC to PNS */
+               seq = ntohl(tcph->seq) + sizeof(struct pptp_pkt_hdr)
+                                      + sizeof(struct PptpControlHeader)
+                                      + ((void *)pcid - (void *)pptpReq);
+                       
+               if (exp_gre(ct, seq, *cid, *pcid) != 0)
+                       printk("ip_conntrack_pptp: error during exp_gre\n");
+
+               break;
+
+       case PPTP_CALL_DISCONNECT_NOTIFY:
+               if (reqlen < sizeof(_pptpReq.disc)) {
+                       DEBUGP("%s: short packet\n", pptp_msg_name[msg]);
+                       break;
+               }
+
+               /* server confirms disconnect */
+               cid = &pptpReq->disc.callID;
+               DEBUGP("%s, CID=%X\n", pptp_msg_name[msg], ntohs(*cid));
+               info->cstate = PPTP_CALL_NONE;
+
+               /* untrack this call id, unexpect GRE packets */
+               pptp_destroy_siblings(ct);
+               break;
+
+       case PPTP_WAN_ERROR_NOTIFY:
+               break;
+
+       case PPTP_ECHO_REQUEST:
+       case PPTP_ECHO_REPLY:
+               /* I don't have to explain these ;) */
+               break;
+       default:
+               DEBUGP("invalid %s (TY=%d)\n", (msg <= PPTP_MSG_MAX)
+                       ? pptp_msg_name[msg]:pptp_msg_name[0], msg);
+               break;
+       }
+
+
+       if (ip_nat_pptp_hook_inbound)
+               return ip_nat_pptp_hook_inbound(pskb, ct, ctinfo, ctlh,
+                                               pptpReq);
+
+       return NF_ACCEPT;
+
+}
+
+static inline int
+pptp_outbound_pkt(struct sk_buff **pskb,
+                 struct tcphdr *tcph,
+                 unsigned int nexthdr_off,
+                 unsigned int datalen,
+                 struct ip_conntrack *ct,
+                 enum ip_conntrack_info ctinfo)
+{
+       struct PptpControlHeader _ctlh, *ctlh;
+       unsigned int reqlen;
+       union pptp_ctrl_union _pptpReq, *pptpReq;
+       struct ip_ct_pptp_master *info = &ct->help.ct_pptp_info;
+       u_int16_t msg, *cid, *pcid;
+
+       ctlh = skb_header_pointer(*pskb, nexthdr_off, sizeof(_ctlh), &_ctlh);
+       if (!ctlh)
+               return NF_ACCEPT;
+       nexthdr_off += sizeof(_ctlh);
+       datalen -= sizeof(_ctlh);
+       
+       reqlen = datalen;
+       if (reqlen > sizeof(*pptpReq))
+               reqlen = sizeof(*pptpReq);
+       pptpReq = skb_header_pointer(*pskb, nexthdr_off, reqlen, &_pptpReq);
+       if (!pptpReq)
+               return NF_ACCEPT;
+
+       msg = ntohs(ctlh->messageType);
+       DEBUGP("outbound control message %s\n", pptp_msg_name[msg]);
+
+       switch (msg) {
+       case PPTP_START_SESSION_REQUEST:
+               /* client requests for new control session */
+               if (info->sstate != PPTP_SESSION_NONE) {
+                       DEBUGP("%s but we already have one",
+                               pptp_msg_name[msg]);
+               }
+               info->sstate = PPTP_SESSION_REQUESTED;
+               break;
+       case PPTP_STOP_SESSION_REQUEST:
+               /* client requests end of control session */
+               info->sstate = PPTP_SESSION_STOPREQ;
+               break;
+
+       case PPTP_OUT_CALL_REQUEST:
+               if (reqlen < sizeof(_pptpReq.ocreq)) {
+                       DEBUGP("%s: short packet\n", pptp_msg_name[msg]);
+                       /* FIXME: break; */
+               }
+
+               /* client initiating connection to server */
+               if (info->sstate != PPTP_SESSION_CONFIRMED) {
+                       DEBUGP("%s but no session\n",
+                               pptp_msg_name[msg]);
+                       break;
+               }
+               info->cstate = PPTP_CALL_OUT_REQ;
+               /* track PNS call id */
+               cid = &pptpReq->ocreq.callID;
+               DEBUGP("%s, CID=%X\n", pptp_msg_name[msg], ntohs(*cid));
+               info->pns_call_id = ntohs(*cid);
+               break;
+       case PPTP_IN_CALL_REPLY:
+               if (reqlen < sizeof(_pptpReq.icack)) {
+                       DEBUGP("%s: short packet\n", pptp_msg_name[msg]);
+                       break;
+               }
+
+               /* client answers incoming call */
+               if (info->cstate != PPTP_CALL_IN_REQ
+                   && info->cstate != PPTP_CALL_IN_REP) {
+                       DEBUGP("%s without incall_req\n", 
+                               pptp_msg_name[msg]);
+                       break;
+               }
+               if (pptpReq->icack.resultCode != PPTP_INCALL_ACCEPT) {
+                       info->cstate = PPTP_CALL_NONE;
+                       break;
+               }
+               pcid = &pptpReq->icack.peersCallID;
+               if (info->pac_call_id != ntohs(*pcid)) {
+                       DEBUGP("%s for unknown call %u\n", 
+                               pptp_msg_name[msg], ntohs(*pcid));
+                       break;
+               }
+               DEBUGP("%s, CID=%X\n", pptp_msg_name[msg], ntohs(*pcid));
+               /* part two of the three-way handshake */
+               info->cstate = PPTP_CALL_IN_REP;
+               info->pns_call_id = ntohs(pptpReq->icack.callID);
+               break;
+
+       case PPTP_CALL_CLEAR_REQUEST:
+               /* client requests hangup of call */
+               if (info->sstate != PPTP_SESSION_CONFIRMED) {
+                       DEBUGP("CLEAR_CALL but no session\n");
+                       break;
+               }
+               /* FUTURE: iterate over all calls and check if
+                * call ID is valid.  We don't do this without newnat,
+                * because we only know about last call */
+               info->cstate = PPTP_CALL_CLEAR_REQ;
+               break;
+       case PPTP_SET_LINK_INFO:
+               break;
+       case PPTP_ECHO_REQUEST:
+       case PPTP_ECHO_REPLY:
+               /* I don't have to explain these ;) */
+               break;
+       default:
+               DEBUGP("invalid %s (TY=%d)\n", (msg <= PPTP_MSG_MAX)? 
+                       pptp_msg_name[msg]:pptp_msg_name[0], msg);
+               /* unknown: no need to create GRE masq table entry */
+               break;
+       }
+       
+       if (ip_nat_pptp_hook_outbound)
+               return ip_nat_pptp_hook_outbound(pskb, ct, ctinfo, ctlh,
+                                                pptpReq);
+
+       return NF_ACCEPT;
+}
+
+
+/* track caller id inside control connection, call expect_related */
+static int 
+conntrack_pptp_help(struct sk_buff **pskb,
+                   struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
+
+{
+       struct pptp_pkt_hdr _pptph, *pptph;
+       struct tcphdr _tcph, *tcph;
+       u_int32_t tcplen = (*pskb)->len - (*pskb)->nh.iph->ihl * 4;
+       u_int32_t datalen;
+       int dir = CTINFO2DIR(ctinfo);
+       struct ip_ct_pptp_master *info = &ct->help.ct_pptp_info;
+       unsigned int nexthdr_off;
+
+       int oldsstate, oldcstate;
+       int ret;
+
+       /* don't do any tracking before tcp handshake complete */
+       if (ctinfo != IP_CT_ESTABLISHED 
+           && ctinfo != IP_CT_ESTABLISHED+IP_CT_IS_REPLY) {
+               DEBUGP("ctinfo = %u, skipping\n", ctinfo);
+               return NF_ACCEPT;
+       }
+       
+       nexthdr_off = (*pskb)->nh.iph->ihl*4;
+       tcph = skb_header_pointer(*pskb, nexthdr_off, sizeof(_tcph), &_tcph);
+       BUG_ON(!tcph);
+       nexthdr_off += tcph->doff * 4;
+       datalen = tcplen - tcph->doff * 4;
+
+       if (tcph->fin || tcph->rst) {
+               DEBUGP("RST/FIN received, timeouting GRE\n");
+               /* can't do this after real newnat */
+               info->cstate = PPTP_CALL_NONE;
+
+               /* untrack this call id, unexpect GRE packets */
+               pptp_destroy_siblings(ct);
+       }
+
+       pptph = skb_header_pointer(*pskb, nexthdr_off, sizeof(_pptph), &_pptph);
+       if (!pptph) {
+               DEBUGP("no full PPTP header, can't track\n");
+               return NF_ACCEPT;
+       }
+       nexthdr_off += sizeof(_pptph);
+       datalen -= sizeof(_pptph);
+
+       /* if it's not a control message we can't do anything with it */
+       if (ntohs(pptph->packetType) != PPTP_PACKET_CONTROL ||
+           ntohl(pptph->magicCookie) != PPTP_MAGIC_COOKIE) {
+               DEBUGP("not a control packet\n");
+               return NF_ACCEPT;
+       }
+
+       oldsstate = info->sstate;
+       oldcstate = info->cstate;
+
+       spin_lock_bh(&ip_pptp_lock);
+
+       /* FIXME: We just blindly assume that the control connection is always
+        * established from PNS->PAC.  However, RFC makes no guarantee */
+       if (dir == IP_CT_DIR_ORIGINAL)
+               /* client -> server (PNS -> PAC) */
+               ret = pptp_outbound_pkt(pskb, tcph, nexthdr_off, datalen, ct,
+                                       ctinfo);
+       else
+               /* server -> client (PAC -> PNS) */
+               ret = pptp_inbound_pkt(pskb, tcph, nexthdr_off, datalen, ct,
+                                      ctinfo);
+       DEBUGP("sstate: %d->%d, cstate: %d->%d\n",
+               oldsstate, info->sstate, oldcstate, info->cstate);
+       spin_unlock_bh(&ip_pptp_lock);
+
+       return ret;
+}
+
+/* control protocol helper */
+static struct ip_conntrack_helper pptp = { 
+       .list = { NULL, NULL },
+       .name = "pptp", 
+       .me = THIS_MODULE,
+       .max_expected = 2,
+       .timeout = 5 * 60,
+       .tuple = { .src = { .ip = 0, 
+                           .u = { .tcp = { .port =  
+                                   __constant_htons(PPTP_CONTROL_PORT) } } 
+                         }, 
+                  .dst = { .ip = 0, 
+                           .u = { .all = 0 },
+                           .protonum = IPPROTO_TCP
+                         } 
+                },
+       .mask = { .src = { .ip = 0, 
+                          .u = { .tcp = { .port = 0xffff } } 
+                        }, 
+                 .dst = { .ip = 0, 
+                          .u = { .all = 0 },
+                          .protonum = 0xff 
+                        } 
+               },
+       .help = conntrack_pptp_help
+};
+
+extern void __exit ip_ct_proto_gre_fini(void);
+extern int __init ip_ct_proto_gre_init(void);
+
+/* ip_conntrack_pptp initialization */
+static int __init init(void)
+{
+       int retcode;
+       retcode = ip_ct_proto_gre_init();
+       if (retcode < 0)
+               return retcode;
+
+       DEBUGP(" registering helper\n");
+       if ((retcode = ip_conntrack_helper_register(&pptp))) {
+               printk(KERN_ERR "Unable to register conntrack application "
+                               "helper for pptp: %d\n", retcode);
+               ip_ct_proto_gre_fini();
+               return retcode;
+       }
+
+       printk("ip_conntrack_pptp version %s loaded\n", IP_CT_PPTP_VERSION);
+       return 0;
+}
+
+static void __exit fini(void)
+{
+       ip_conntrack_helper_unregister(&pptp);
+       ip_ct_proto_gre_fini();
+       printk("ip_conntrack_pptp version %s unloaded\n", IP_CT_PPTP_VERSION);
+}
+
+module_init(init);
+module_exit(fini);
+
+EXPORT_SYMBOL(ip_nat_pptp_hook_outbound);
+EXPORT_SYMBOL(ip_nat_pptp_hook_inbound);
+EXPORT_SYMBOL(ip_nat_pptp_hook_exp_gre);
+EXPORT_SYMBOL(ip_nat_pptp_hook_expectfn);
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..d3c7808010ec0db617de4c089146206f51aad118 100644 (file)
@@ -993,11 +993,11 @@ EXPORT_SYMBOL(ip_ct_refresh_acct);
 
 EXPORT_SYMBOL(ip_conntrack_expect_alloc);
 EXPORT_SYMBOL(ip_conntrack_expect_put);
-EXPORT_SYMBOL_GPL(ip_conntrack_expect_find_get);
+EXPORT_SYMBOL_GPL(__ip_conntrack_expect_find);
+EXPORT_SYMBOL_GPL(ip_conntrack_expect_find);
 EXPORT_SYMBOL(ip_conntrack_expect_related);
 EXPORT_SYMBOL(ip_conntrack_unexpect_related);
 EXPORT_SYMBOL_GPL(ip_conntrack_expect_list);
-EXPORT_SYMBOL_GPL(__ip_conntrack_expect_find);
 EXPORT_SYMBOL_GPL(ip_ct_unlink_expect);
 
 EXPORT_SYMBOL(ip_conntrack_tuple_taken);
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 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..5dd6dd7d091e18d20823bbd11320fe06e370aa14 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,6 +499,12 @@ int tcp_fragment(struct sock *sk, struct sk_buff *skb, u32 len, unsigned int mss
                        tcp_skb_pcount(buff);
 
                tp->packets_out -= diff;
+
+               if (TCP_SKB_CB(skb)->sacked & TCPCB_SACKED_ACKED)
+                       tp->sacked_out -= diff;
+               if (TCP_SKB_CB(skb)->sacked & TCPCB_SACKED_RETRANS)
+                       tp->retrans_out -= diff;
+
                if (TCP_SKB_CB(skb)->sacked & TCPCB_LOST) {
                        tp->lost_out -= diff;
                        tp->left_out -= diff;
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 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 dc4e17b6eaf6623c1547363d0b22ee660a556508..1caac0164643c202a55c1e8394b9669706723591 100644 (file)
@@ -252,10 +252,9 @@ passwd_write_file(struct file * file, const char __user * buf,
        }
 
        if (count < 0 || count >= PAGE_SIZE)
-               return -ENOMEM;
-       if (*ppos != 0) {
                return -EINVAL;
-       }
+       if (*ppos != 0)
+               return -EINVAL;
        page = (char *)get_zeroed_page(GFP_KERNEL);
        if (!page)
                return -ENOMEM;
@@ -265,9 +264,8 @@ passwd_write_file(struct file * file, const char __user * buf,
        
        len = strlen(page);
        /* ``echo "secret" > seclvl/passwd'' includes a newline */
-       if (page[len - 1] == '\n') {
+       if (page[len - 1] == '\n')
                len--;
-       }
        /* Hash the password, then compare the hashed values */
        if ((rc = plaintext_to_sha1(tmp, page, len))) {
                seclvl_printk(0, KERN_ERR, "Error hashing password: rc = "
@@ -275,9 +273,8 @@ passwd_write_file(struct file * file, const char __user * buf,
                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");
@@ -482,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);
@@ -638,9 +634,8 @@ static int __init seclvl_init(void)
 static void __exit seclvl_exit(void)
 {
        securityfs_remove(seclvl_ino);
-       if (*passwd || *sha1_passwd) {
+       if (*passwd || *sha1_passwd)
                securityfs_remove(passwd_ino);
-       }
        securityfs_remove(dir_ino);
        if (secondary == 1) {
                mod_unreg_security(MY_NAME, &seclvl_ops);
index 34195b7486082f6550997947459a38b554800ea9..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;
index 3daeecb9eb0e6a0b4a4da6712470354efa7bec7a..cd313af6ebcf226f4ea7f29680923732200d4205 100644 (file)
@@ -228,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,}
 };
@@ -240,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);
 
@@ -527,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) | 
@@ -881,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;
        }
@@ -1408,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;
        }
@@ -1639,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:
@@ -1670,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:
@@ -1697,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:
@@ -1982,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;
        }
index 9983b66dc56448c2600f3f89a9459c7bd7d2744a..c495cae78dbf39f4d566e99eb888ba2749820b0c 100644 (file)
@@ -233,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, }
 };
@@ -248,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
@@ -830,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 */
@@ -1598,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 {
@@ -1858,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;
@@ -1895,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) {
@@ -1932,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 {
@@ -1953,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;
                }
@@ -2375,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");
index 2fb27c4e951fcac586724b51f571715966f37fbc..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,54 +567,58 @@ 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)
 {
        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();
@@ -1985,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);
@@ -2113,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;
        }