Merge branch 'upstream-linus' of master.kernel.org:/pub/scm/linux/kernel/git/jgarzik...
authorLinus Torvalds <torvalds@g5.osdl.org>
Sat, 29 Oct 2005 18:25:16 +0000 (11:25 -0700)
committerLinus Torvalds <torvalds@g5.osdl.org>
Sat, 29 Oct 2005 18:25:16 +0000 (11:25 -0700)
304 files changed:
Documentation/DocBook/kernel-api.tmpl
Documentation/DocBook/usb.tmpl
Documentation/input/yealink.txt
Documentation/kernel-parameters.txt
Documentation/networking/ip-sysctl.txt
MAINTAINERS
arch/arm/boot/compressed/misc.c
arch/frv/kernel/time.c
arch/i386/pci/fixup.c
arch/ia64/Kconfig
arch/ia64/configs/bigsur_defconfig
arch/ia64/configs/gensparse_defconfig [new file with mode: 0644]
arch/ia64/configs/tiger_defconfig
arch/ia64/configs/zx1_defconfig
arch/ia64/defconfig
arch/ia64/hp/common/hwsw_iommu.c
arch/ia64/hp/common/sba_iommu.c
arch/ia64/hp/sim/simscsi.c
arch/ia64/kernel/acpi.c
arch/ia64/kernel/efi.c
arch/ia64/kernel/irq.c
arch/ia64/kernel/mca.c
arch/ia64/kernel/module.c
arch/ia64/kernel/patch.c
arch/ia64/kernel/ptrace.c
arch/ia64/kernel/setup.c
arch/ia64/kernel/smp.c
arch/ia64/kernel/smpboot.c
arch/ia64/kernel/uncached.c
arch/ia64/lib/swiotlb.c
arch/ia64/mm/Makefile
arch/ia64/mm/contig.c
arch/ia64/mm/discontig.c
arch/ia64/mm/init.c
arch/ia64/mm/numa.c
arch/ia64/mm/tlb.c
arch/ia64/pci/pci.c
arch/ia64/sn/kernel/bte.c
arch/ia64/sn/kernel/io_init.c
arch/ia64/sn/kernel/setup.c
arch/ia64/sn/kernel/sn2/sn2_smp.c
arch/ia64/sn/kernel/sn2/sn_hwperf.c
arch/ia64/sn/kernel/tiocx.c
arch/ia64/sn/kernel/xpc.h
arch/ia64/sn/kernel/xpc_channel.c
arch/ia64/sn/kernel/xpc_main.c
arch/ia64/sn/kernel/xpc_partition.c
arch/ia64/sn/pci/pci_dma.c
arch/ia64/sn/pci/pcibr/pcibr_reg.c
arch/ia64/sn/pci/tioca_provider.c
arch/ia64/sn/pci/tioce_provider.c
arch/sh64/kernel/time.c
drivers/Makefile
drivers/base/power/main.c
drivers/base/power/power.h
drivers/base/power/runtime.c
drivers/block/as-iosched.c
drivers/block/ub.c
drivers/char/agp/sgi-agp.c
drivers/char/mmtimer.c
drivers/char/snsc.c
drivers/infiniband/core/agent.c
drivers/infiniband/core/agent.h
drivers/infiniband/core/agent_priv.h [deleted file]
drivers/infiniband/core/cm.c
drivers/infiniband/core/cm_msgs.h
drivers/infiniband/core/device.c
drivers/infiniband/core/mad.c
drivers/infiniband/core/mad_priv.h
drivers/infiniband/core/mad_rmpp.c
drivers/infiniband/core/mad_rmpp.h
drivers/infiniband/core/sa_query.c
drivers/infiniband/core/smi.h
drivers/infiniband/core/sysfs.c
drivers/infiniband/core/ucm.c
drivers/infiniband/core/ucm.h [deleted file]
drivers/infiniband/core/user_mad.c
drivers/infiniband/core/uverbs.h
drivers/infiniband/core/uverbs_cmd.c
drivers/infiniband/core/uverbs_main.c
drivers/infiniband/core/verbs.c
drivers/infiniband/hw/mthca/Makefile
drivers/infiniband/hw/mthca/mthca_catas.c [new file with mode: 0644]
drivers/infiniband/hw/mthca/mthca_cmd.c
drivers/infiniband/hw/mthca/mthca_dev.h
drivers/infiniband/hw/mthca/mthca_eq.c
drivers/infiniband/hw/mthca/mthca_mad.c
drivers/infiniband/hw/mthca/mthca_main.c
drivers/infiniband/hw/mthca/mthca_mcg.c
drivers/infiniband/hw/mthca/mthca_memfree.c
drivers/infiniband/hw/mthca/mthca_memfree.h
drivers/infiniband/hw/mthca/mthca_provider.c
drivers/infiniband/hw/mthca/mthca_qp.c
drivers/infiniband/hw/mthca/mthca_srq.c
drivers/infiniband/hw/mthca/mthca_user.h
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_verbs.c
drivers/input/keyboard/amikbd.c
drivers/input/misc/sparcspkr.c
drivers/mmc/wbsd.c
drivers/pci/access.c
drivers/pci/hotplug/acpiphp_glue.c
drivers/pci/hotplug/cpcihp_zt5550.c
drivers/pci/hotplug/cpqphp_core.c
drivers/pci/hotplug/rpaphp.h
drivers/pci/hotplug/rpaphp_core.c
drivers/pci/hotplug/rpaphp_pci.c
drivers/pci/hotplug/shpchp.h
drivers/pci/hotplug/shpchp_core.c
drivers/pci/hotplug/shpchp_ctrl.c
drivers/pci/hotplug/shpchp_hpc.c
drivers/pci/hotplug/shpchp_pci.c
drivers/pci/hotplug/shpchp_sysfs.c
drivers/pci/hotplug/shpchprm.h [deleted file]
drivers/pci/hotplug/shpchprm_acpi.c
drivers/pci/hotplug/shpchprm_legacy.c
drivers/pci/hotplug/shpchprm_legacy.h [deleted file]
drivers/pci/hotplug/shpchprm_nonacpi.c
drivers/pci/hotplug/shpchprm_nonacpi.h [deleted file]
drivers/pci/msi.c
drivers/pci/pci-driver.c
drivers/pci/pci-sysfs.c
drivers/pci/pci.c
drivers/pci/pci.h
drivers/pci/probe.c
drivers/pci/proc.c
drivers/pci/quirks.c
drivers/pci/syscall.c
drivers/s390/char/vmlogrdr.c
drivers/scsi/ipr.c
drivers/scsi/megaraid/megaraid_mbox.c
drivers/scsi/sata_sil24.c
drivers/usb/Makefile
drivers/usb/class/Kconfig
drivers/usb/class/Makefile
drivers/usb/class/bluetty.c [deleted file]
drivers/usb/class/cdc-acm.c
drivers/usb/class/usblp.c
drivers/usb/core/Kconfig
drivers/usb/core/Makefile
drivers/usb/core/config.c
drivers/usb/core/devio.c
drivers/usb/core/file.c
drivers/usb/core/hcd-pci.c
drivers/usb/core/hcd.c
drivers/usb/core/hcd.h
drivers/usb/core/hub.c
drivers/usb/core/hub.h
drivers/usb/core/inode.c
drivers/usb/core/message.c
drivers/usb/core/notify.c [new file with mode: 0644]
drivers/usb/core/sysfs.c
drivers/usb/core/urb.c
drivers/usb/core/usb.c
drivers/usb/core/usb.h
drivers/usb/gadget/dummy_hcd.c
drivers/usb/gadget/ether.c
drivers/usb/gadget/file_storage.c
drivers/usb/gadget/goku_udc.c
drivers/usb/gadget/lh7a40x_udc.c
drivers/usb/gadget/net2280.c
drivers/usb/gadget/omap_udc.c
drivers/usb/gadget/pxa2xx_udc.c
drivers/usb/gadget/zero.c
drivers/usb/host/Makefile
drivers/usb/host/ehci-hcd.c
drivers/usb/host/ehci-hub.c
drivers/usb/host/ehci-pci.c [new file with mode: 0644]
drivers/usb/host/ehci.h
drivers/usb/host/isp116x-hcd.c
drivers/usb/host/isp116x.h
drivers/usb/host/ohci-au1xxx.c
drivers/usb/host/ohci-dbg.c
drivers/usb/host/ohci-hcd.c
drivers/usb/host/ohci-hub.c
drivers/usb/host/ohci-lh7a404.c
drivers/usb/host/ohci-mem.c
drivers/usb/host/ohci-omap.c
drivers/usb/host/ohci-pci.c
drivers/usb/host/ohci-ppc-soc.c
drivers/usb/host/ohci-pxa27x.c
drivers/usb/host/ohci-s3c2410.c
drivers/usb/host/ohci-sa1111.c
drivers/usb/host/ohci.h
drivers/usb/host/pci-quirks.c [new file with mode: 0644]
drivers/usb/host/sl811-hcd.c
drivers/usb/host/uhci-debug.c
drivers/usb/host/uhci-hcd.c
drivers/usb/host/uhci-hcd.h
drivers/usb/host/uhci-q.c
drivers/usb/image/mdc800.c
drivers/usb/image/microtek.c
drivers/usb/input/aiptek.c
drivers/usb/input/hid-core.c
drivers/usb/input/hiddev.c
drivers/usb/input/map_to_7segment.h
drivers/usb/input/touchkitusb.c
drivers/usb/media/dabusb.c
drivers/usb/misc/auerswald.c
drivers/usb/misc/idmouse.c
drivers/usb/misc/legousbtower.c
drivers/usb/misc/rio500.c
drivers/usb/misc/sisusbvga/sisusb.c
drivers/usb/misc/usblcd.c
drivers/usb/misc/usbtest.c
drivers/usb/mon/mon_main.c
drivers/usb/net/Kconfig
drivers/usb/net/kaweth.c
drivers/usb/net/pegasus.c
drivers/usb/net/pegasus.h
drivers/usb/net/rtl8150.c
drivers/usb/net/usbnet.c
drivers/usb/serial/ChangeLog.old [new file with mode: 0644]
drivers/usb/serial/Kconfig
drivers/usb/serial/Makefile
drivers/usb/serial/airprime.c
drivers/usb/serial/belkin_sa.c
drivers/usb/serial/bus.c
drivers/usb/serial/cp2101.c
drivers/usb/serial/cyberjack.c
drivers/usb/serial/cypress_m8.c
drivers/usb/serial/digi_acceleport.c
drivers/usb/serial/empeg.c
drivers/usb/serial/ftdi_sio.c
drivers/usb/serial/ftdi_sio.h
drivers/usb/serial/garmin_gps.c
drivers/usb/serial/generic.c
drivers/usb/serial/hp4x.c
drivers/usb/serial/io_edgeport.c
drivers/usb/serial/io_tables.h
drivers/usb/serial/io_ti.c
drivers/usb/serial/ipaq.c
drivers/usb/serial/ipw.c
drivers/usb/serial/ir-usb.c
drivers/usb/serial/keyspan.h
drivers/usb/serial/keyspan_pda.c
drivers/usb/serial/kl5kusb105.c
drivers/usb/serial/kobil_sct.c
drivers/usb/serial/mct_u232.c
drivers/usb/serial/nokia_dku2.c [new file with mode: 0644]
drivers/usb/serial/omninet.c
drivers/usb/serial/option.c
drivers/usb/serial/pl2303.c
drivers/usb/serial/safe_serial.c
drivers/usb/serial/ti_usb_3410_5052.c
drivers/usb/serial/usb-serial.c
drivers/usb/serial/usb-serial.h
drivers/usb/serial/visor.c
drivers/usb/serial/whiteheat.c
drivers/usb/storage/Kconfig
drivers/usb/storage/shuttle_usbat.c
drivers/usb/storage/shuttle_usbat.h
drivers/usb/storage/transport.c
drivers/usb/storage/transport.h
drivers/usb/storage/unusual_devs.h
drivers/usb/storage/usb.c
drivers/usb/storage/usb.h
drivers/usb/usb-skeleton.c
drivers/video/cirrusfb.c
fs/compat_ioctl.c
include/asm-i386/mach-summit/mach_mpparse.h
include/asm-ia64/machvec.h
include/asm-ia64/machvec_hpzx1.h
include/asm-ia64/machvec_hpzx1_swiotlb.h
include/asm-ia64/meminit.h
include/asm-ia64/mmzone.h
include/asm-ia64/nodedata.h
include/asm-ia64/page.h
include/asm-ia64/sn/arch.h
include/asm-ia64/sn/io.h
include/asm-ia64/sn/klconfig.h
include/asm-ia64/sn/l1.h
include/asm-ia64/sn/nodepda.h
include/asm-ia64/sn/sn_cpuid.h
include/asm-ia64/sn/sn_sal.h
include/asm-ia64/sn/tioca_provider.h
include/asm-ia64/sn/tiocx.h
include/asm-ia64/sn/xp.h
include/asm-ia64/sparsemem.h [new file with mode: 0644]
include/linux/etherdevice.h
include/linux/pci.h
include/linux/pci_ids.h
include/linux/pm.h
include/linux/usb.h
include/linux/usb_otg.h
include/linux/usbdevice_fs.h
include/net/sctp/user.h
include/rdma/ib_cm.h
include/rdma/ib_mad.h
include/rdma/ib_user_cm.h
include/rdma/ib_user_verbs.h
include/rdma/ib_verbs.h
kernel/signal.c
kernel/time.c
net/bluetooth/hidp/Kconfig
net/ethernet/eth.c
net/ipv4/fib_frontend.c
net/sctp/sm_make_chunk.c
net/sctp/socket.c
net/sctp/ulpevent.c
sound/oss/ymfpci.c
sound/pci/bt87x.c

index d650ce3..4d9b66d 100644 (file)
@@ -286,7 +286,9 @@ X!Edrivers/pci/search.c
  -->
 !Edrivers/pci/msi.c
 !Edrivers/pci/bus.c
-!Edrivers/pci/hotplug.c
+<!-- FIXME: Removed for now since no structured comments in source
+X!Edrivers/pci/hotplug.c
+-->
 !Edrivers/pci/probe.c
 !Edrivers/pci/rom.c
      </sect1>
index 705c442..15ce0f2 100644 (file)
 
 !Edrivers/usb/core/hcd.c
 !Edrivers/usb/core/hcd-pci.c
-!Edrivers/usb/core/buffer.c
+!Idrivers/usb/core/buffer.c
     </chapter>
 
     <chapter>
index 85f095a..0962c5c 100644 (file)
@@ -2,7 +2,6 @@ Driver documentation for yealink usb-p1k phones
 
 0. Status
 ~~~~~~~~~
-
 The p1k is a relatively cheap usb 1.1 phone with:
   - keyboard           full support, yealink.ko / input event API
   - LCD                        full support, yealink.ko / sysfs API
@@ -17,9 +16,8 @@ For vendor documentation see http://www.yealink.com
 
 1. Compilation (stand alone version)
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
 Currently only kernel 2.6.x.y versions are supported.
-In order to build the yealink.ko module do:
+In order to build the yealink.ko module do
 
   make
 
@@ -28,6 +26,21 @@ the Makefile is pointing to the location where your kernel sources
 are located, default /usr/src/linux.
 
 
+1.1 Troubleshooting
+~~~~~~~~~~~~~~~~~~~
+Q: Module yealink compiled and installed without any problem but phone
+   is not initialized and does not react to any actions.
+A: If you see something like:
+   hiddev0: USB HID v1.00 Device [Yealink Network Technology Ltd. VOIP USB Phone
+   in dmesg, it means that the hid driver has grabbed the device first. Try to
+   load module yealink before any other usb hid driver. Please see the
+   instructions provided by your distribution on module configuration.
+
+Q: Phone is working now (displays version and accepts keypad input) but I can't
+   find the sysfs files.
+A: The sysfs files are located on the particular usb endpoint. On most
+   distributions you can do: "find /sys/ -name get_icons" for a hint.
+
 
 2. keyboard features
 ~~~~~~~~~~~~~~~~~~~~
index 971589a..90766b7 100644 (file)
@@ -1517,8 +1517,6 @@ running once the system is up.
        uart6850=       [HW,OSS]
                        Format: <io>,<irq>
 
-       usb-handoff     [HW] Enable early USB BIOS -> OS handoff
-
        usbhid.mousepoll=
                        [USBHID] The interval which mice are to be polled at.
 
index b433c8a..65895bb 100644 (file)
@@ -309,7 +309,7 @@ tcp_tso_win_divisor - INTEGER
        can be consumed by a single TSO frame.
        The setting of this parameter is a choice between burstiness and
        building larger TSO frames.
-       Default: 8
+       Default: 3
 
 tcp_frto - BOOLEAN
        Enables F-RTO, an enhanced recovery algorithm for TCP retransmission
index a51d9cf..251a28e 100644 (file)
@@ -116,12 +116,6 @@ M: ajk@iehk.rwth-aachen.de
 L:     linux-hams@vger.kernel.org
 S:     Maintained
 
-YEALINK PHONE DRIVER
-P:     Henk Vergonet
-M:     Henk.Vergonet@gmail.com
-L:     usbb2k-api-dev@nongnu.org
-S:     Maintained
-
 8139CP 10/100 FAST ETHERNET DRIVER
 P:     Jeff Garzik
 M:     jgarzik@pobox.com
@@ -2503,14 +2497,6 @@ L:       linux-kernel@vger.kernel.org
 L:     linux-usb-devel@lists.sourceforge.net
 S:     Supported
 
-USB BLUETOOTH TTY CONVERTER DRIVER
-P:     Greg Kroah-Hartman
-M:     greg@kroah.com
-L:     linux-usb-users@lists.sourceforge.net
-L:     linux-usb-devel@lists.sourceforge.net
-S:     Maintained
-W:     http://www.kroah.com/linux-usb/
-
 USB CDC ETHERNET DRIVER
 P:     Greg Kroah-Hartman
 M:     greg@kroah.com
@@ -2871,6 +2857,12 @@ M:       jpr@f6fbb.org
 L:     linux-hams@vger.kernel.org
 S:     Maintained
 
+YEALINK PHONE DRIVER
+P:     Henk Vergonet
+M:     Henk.Vergonet@gmail.com
+L:     usbb2k-api-dev@nongnu.org
+S:     Maintained
+
 YMFPCI YAMAHA PCI SOUND (Use ALSA instead)
 P:     Pete Zaitcev
 M:     zaitcev@yahoo.com
index 23434b5..50f13ee 100644 (file)
@@ -30,7 +30,7 @@ unsigned int __machine_arch_type;
 #define putstr icedcc_putstr
 #define putc icedcc_putc
 
-extern void idedcc_putc(int ch);
+extern void icedcc_putc(int ch);
 
 static void
 icedcc_putstr(const char *ptr)
index 8d6558b..f43b734 100644 (file)
@@ -221,6 +221,7 @@ int do_settimeofday(struct timespec *tv)
        clock_was_set();
        return 0;
 }
+EXPORT_SYMBOL(do_settimeofday);
 
 /*
  * Scheduler clock - returns current time in nanosec units.
index 8e8e895..330fd2b 100644 (file)
@@ -2,6 +2,8 @@
  * Exceptions for specific devices. Usually work-arounds for fatal design flaws.
  */
 
+#include <linux/delay.h>
+#include <linux/dmi.h>
 #include <linux/pci.h>
 #include <linux/init.h>
 #include "pci.h"
@@ -384,3 +386,60 @@ static void __devinit pci_fixup_video(struct pci_dev *pdev)
        }
 }
 DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, pci_fixup_video);
+
+/*
+ * Some Toshiba laptops need extra code to enable their TI TSB43AB22/A.
+ *
+ * We pretend to bring them out of full D3 state, and restore the proper
+ * IRQ, PCI cache line size, and BARs, otherwise the device won't function
+ * properly.  In some cases, the device will generate an interrupt on
+ * the wrong IRQ line, causing any devices sharing the the line it's
+ * *supposed* to use to be disabled by the kernel's IRQ debug code.
+ */
+static u16 toshiba_line_size;
+
+static struct dmi_system_id __devinit toshiba_ohci1394_dmi_table[] = {
+       {
+               .ident = "Toshiba PS5 based laptop",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+                       DMI_MATCH(DMI_PRODUCT_VERSION, "PS5"),
+               },
+       },
+       {
+               .ident = "Toshiba PSM4 based laptop",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+                       DMI_MATCH(DMI_PRODUCT_VERSION, "PSM4"),
+               },
+       },
+       { }
+};
+
+static void __devinit pci_pre_fixup_toshiba_ohci1394(struct pci_dev *dev)
+{
+       if (!dmi_check_system(toshiba_ohci1394_dmi_table))
+               return; /* only applies to certain Toshibas (so far) */
+
+       dev->current_state = PCI_D3cold;
+       pci_read_config_word(dev, PCI_CACHE_LINE_SIZE, &toshiba_line_size);
+}
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_TI, 0x8032,
+                        pci_pre_fixup_toshiba_ohci1394);
+
+static void __devinit pci_post_fixup_toshiba_ohci1394(struct pci_dev *dev)
+{
+       if (!dmi_check_system(toshiba_ohci1394_dmi_table))
+               return; /* only applies to certain Toshibas (so far) */
+
+       /* Restore config space on Toshiba laptops */
+       mdelay(10);
+       pci_write_config_word(dev, PCI_CACHE_LINE_SIZE, toshiba_line_size);
+       pci_write_config_word(dev, PCI_INTERRUPT_LINE, dev->irq);
+       pci_write_config_dword(dev, PCI_BASE_ADDRESS_0,
+                              pci_resource_start(dev, 0));
+       pci_write_config_dword(dev, PCI_BASE_ADDRESS_1,
+                              pci_resource_start(dev, 1));
+}
+DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_TI, 0x8032,
+                        pci_post_fixup_toshiba_ohci1394);
index 945c15a..1642375 100644 (file)
@@ -63,8 +63,6 @@ config IA64_GENERIC
        select ACPI
        select NUMA
        select ACPI_NUMA
-       select VIRTUAL_MEM_MAP
-       select DISCONTIGMEM
        help
          This selects the system type of your hardware.  A "generic" kernel
          will run on any supported IA-64 system.  However, if you configure
@@ -176,40 +174,6 @@ config IA64_L1_CACHE_SHIFT
        default "6" if ITANIUM
 
 # align cache-sensitive data to 64 bytes
-config NUMA
-       bool "NUMA support"
-       depends on !IA64_HP_SIM
-       default y if IA64_SGI_SN2
-       select ACPI_NUMA
-       help
-         Say Y to compile the kernel to support NUMA (Non-Uniform Memory
-         Access).  This option is for configuring high-end multiprocessor
-         server systems.  If in doubt, say N.
-
-config VIRTUAL_MEM_MAP
-       bool "Virtual mem map"
-       default y if !IA64_HP_SIM
-       help
-         Say Y to compile the kernel with support for a virtual mem map.
-         This code also only takes effect if a memory hole of greater than
-         1 Gb is found during boot.  You must turn this option on if you
-         require the DISCONTIGMEM option for your machine. If you are
-         unsure, say Y.
-
-config HOLES_IN_ZONE
-       bool
-       default y if VIRTUAL_MEM_MAP
-
-config ARCH_DISCONTIGMEM_ENABLE
-       bool "Discontiguous memory support"
-       depends on (IA64_DIG || IA64_SGI_SN2 || IA64_GENERIC || IA64_HP_ZX1 || IA64_HP_ZX1_SWIOTLB) && NUMA && VIRTUAL_MEM_MAP
-       default y if (IA64_SGI_SN2 || IA64_GENERIC) && NUMA
-       help
-         Say Y to support efficient handling of discontiguous physical memory,
-         for architectures which are either NUMA (Non-Uniform Memory Access)
-         or have huge holes in the physical address space for other reasons.
-         See <file:Documentation/vm/numa> for more.
-
 config IA64_CYCLONE
        bool "Cyclone (EXA) Time Source support"
        help
@@ -232,8 +196,10 @@ config IA64_SGI_SN_XP
          based on a network adapter and DMA messaging.
 
 config FORCE_MAX_ZONEORDER
-       int
-       default "18"
+       int "MAX_ORDER (11 - 17)"  if !HUGETLB_PAGE
+       range 11 17  if !HUGETLB_PAGE
+       default "17" if HUGETLB_PAGE
+       default "11"
 
 config SMP
        bool "Symmetric multi-processing support"
@@ -254,8 +220,8 @@ config SMP
          If you don't know what to do here, say N.
 
 config NR_CPUS
-       int "Maximum number of CPUs (2-512)"
-       range 2 512
+       int "Maximum number of CPUs (2-1024)"
+       range 2 1024
        depends on SMP
        default "64"
        help
@@ -298,6 +264,58 @@ config PREEMPT
 
 source "mm/Kconfig"
 
+config ARCH_SELECT_MEMORY_MODEL
+       def_bool y
+
+config ARCH_DISCONTIGMEM_ENABLE
+       def_bool y
+       help
+         Say Y to support efficient handling of discontiguous physical memory,
+         for architectures which are either NUMA (Non-Uniform Memory Access)
+         or have huge holes in the physical address space for other reasons.
+         See <file:Documentation/vm/numa> for more.
+
+config ARCH_FLATMEM_ENABLE
+       def_bool y
+
+config ARCH_SPARSEMEM_ENABLE
+       def_bool y
+       depends on ARCH_DISCONTIGMEM_ENABLE
+
+config ARCH_DISCONTIGMEM_DEFAULT
+       def_bool y if (IA64_SGI_SN2 || IA64_GENERIC || IA64_HP_ZX1 || IA64_HP_ZX1_SWIOTLB)
+       depends on ARCH_DISCONTIGMEM_ENABLE
+
+config NUMA
+       bool "NUMA support"
+       depends on !IA64_HP_SIM && !FLATMEM
+       default y if IA64_SGI_SN2
+       help
+         Say Y to compile the kernel to support NUMA (Non-Uniform Memory
+         Access).  This option is for configuring high-end multiprocessor
+         server systems.  If in doubt, say N.
+
+# VIRTUAL_MEM_MAP and FLAT_NODE_MEM_MAP are functionally equivalent.
+# VIRTUAL_MEM_MAP has been retained for historical reasons.
+config VIRTUAL_MEM_MAP
+       bool "Virtual mem map"
+       depends on !SPARSEMEM
+       default y if !IA64_HP_SIM
+       help
+         Say Y to compile the kernel with support for a virtual mem map.
+         This code also only takes effect if a memory hole of greater than
+         1 Gb is found during boot.  You must turn this option on if you
+         require the DISCONTIGMEM option for your machine. If you are
+         unsure, say Y.
+
+config HOLES_IN_ZONE
+       bool
+       default y if VIRTUAL_MEM_MAP
+
+config HAVE_ARCH_EARLY_PFN_TO_NID
+       def_bool y
+       depends on NEED_MULTIPLE_NODES
+
 config IA32_SUPPORT
        bool "Support for Linux/x86 binaries"
        help
index 3b65cbb..b40672b 100644 (file)
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.10-rc2
-# Mon Nov 29 13:27:48 2004
+# Linux kernel version: 2.6.14-rc1
+# Wed Sep 14 15:18:49 2005
 #
 
 #
 CONFIG_EXPERIMENTAL=y
 CONFIG_CLEAN_COMPILE=y
 CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
 
 #
 # General setup
 #
 CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
 CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
 CONFIG_POSIX_MQUEUE=y
 # CONFIG_BSD_PROCESS_ACCT is not set
 CONFIG_SYSCTL=y
 # CONFIG_AUDIT is not set
-CONFIG_LOG_BUF_SHIFT=16
 CONFIG_HOTPLUG=y
 CONFIG_KOBJECT_UEVENT=y
 # CONFIG_IKCONFIG is not set
+# CONFIG_CPUSETS is not set
+CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_EMBEDDED is not set
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_ALL is not set
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 CONFIG_SHMEM=y
 CONFIG_CC_ALIGN_FUNCTIONS=0
 CONFIG_CC_ALIGN_LABELS=0
 CONFIG_CC_ALIGN_LOOPS=0
 CONFIG_CC_ALIGN_JUMPS=0
 # CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
 
 #
 # Loadable module support
@@ -58,12 +64,15 @@ CONFIG_IA64=y
 CONFIG_64BIT=y
 CONFIG_MMU=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_TIME_INTERPOLATION=y
 CONFIG_EFI=y
 CONFIG_GENERIC_IOMAP=y
+CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
 # CONFIG_IA64_GENERIC is not set
 CONFIG_IA64_DIG=y
 # CONFIG_IA64_HP_ZX1 is not set
+# CONFIG_IA64_HP_ZX1_SWIOTLB is not set
 # CONFIG_IA64_SGI_SN2 is not set
 # CONFIG_IA64_HP_SIM is not set
 CONFIG_ITANIUM=y
@@ -72,17 +81,30 @@ CONFIG_ITANIUM=y
 # CONFIG_IA64_PAGE_SIZE_8KB is not set
 CONFIG_IA64_PAGE_SIZE_16KB=y
 # CONFIG_IA64_PAGE_SIZE_64KB is not set
+# CONFIG_HZ_100 is not set
+CONFIG_HZ_250=y
+# CONFIG_HZ_1000 is not set
+CONFIG_HZ=250
 CONFIG_IA64_BRL_EMU=y
 CONFIG_IA64_L1_CACHE_SHIFT=6
 # CONFIG_NUMA is not set
 # CONFIG_VIRTUAL_MEM_MAP is not set
 # CONFIG_IA64_CYCLONE is not set
 CONFIG_IOSAPIC=y
+# CONFIG_IA64_SGI_SN_XP is not set
 CONFIG_FORCE_MAX_ZONEORDER=18
 CONFIG_SMP=y
 CONFIG_NR_CPUS=2
 # CONFIG_HOTPLUG_CPU is not set
+# CONFIG_SCHED_SMT is not set
 CONFIG_PREEMPT=y
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+# CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_HAVE_DEC_LOCK=y
 CONFIG_IA32_SUPPORT=y
 CONFIG_COMPAT=y
@@ -95,6 +117,7 @@ CONFIG_IA64_PALINFO=y
 #
 CONFIG_EFI_VARS=y
 CONFIG_EFI_PCDP=y
+# CONFIG_DELL_RBU is not set
 CONFIG_BINFMT_ELF=y
 CONFIG_BINFMT_MISC=m
 
@@ -102,18 +125,26 @@ CONFIG_BINFMT_MISC=m
 # Power management and ACPI
 #
 CONFIG_PM=y
-CONFIG_ACPI=y
+# CONFIG_PM_DEBUG is not set
 
 #
 # ACPI (Advanced Configuration and Power Interface) Support
 #
+CONFIG_ACPI=y
 CONFIG_ACPI_BUTTON=m
 CONFIG_ACPI_FAN=m
 CONFIG_ACPI_PROCESSOR=m
 CONFIG_ACPI_THERMAL=m
+CONFIG_ACPI_BLACKLIST_YEAR=0
 # CONFIG_ACPI_DEBUG is not set
 CONFIG_ACPI_POWER=y
 CONFIG_ACPI_SYSTEM=y
+# CONFIG_ACPI_CONTAINER is not set
+
+#
+# CPU Frequency scaling
+#
+# CONFIG_CPU_FREQ is not set
 
 #
 # Bus options (PCI, PCMCIA)
@@ -122,7 +153,7 @@ CONFIG_PCI=y
 CONFIG_PCI_DOMAINS=y
 # CONFIG_PCI_MSI is not set
 CONFIG_PCI_LEGACY_PROC=y
-CONFIG_PCI_NAMES=y
+# CONFIG_PCI_DEBUG is not set
 
 #
 # PCI Hotplug Support
@@ -135,8 +166,70 @@ CONFIG_PCI_NAMES=y
 # CONFIG_PCCARD is not set
 
 #
-# PC-card bridges
+# 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 is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_BIC=y
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP 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_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
 
 #
 # Device Drivers
@@ -150,6 +243,11 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y
 # CONFIG_FW_LOADER is not set
 # CONFIG_DEBUG_DRIVER is not set
 
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
+
 #
 # Memory Technology Devices (MTD)
 #
@@ -163,7 +261,13 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y
 #
 # Plug and Play support
 #
-# CONFIG_PNP is not set
+CONFIG_PNP=y
+# CONFIG_PNP_DEBUG is not set
+
+#
+# Protocols
+#
+CONFIG_PNPACPI=y
 
 #
 # Block devices
@@ -172,14 +276,15 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y
 # CONFIG_BLK_CPQ_CISS_DA is not set
 # CONFIG_BLK_DEV_DAC960 is not set
 # CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
 CONFIG_BLK_DEV_LOOP=m
 CONFIG_BLK_DEV_CRYPTOLOOP=m
 CONFIG_BLK_DEV_NBD=m
 # CONFIG_BLK_DEV_SX8 is not set
 # CONFIG_BLK_DEV_UB is not set
 CONFIG_BLK_DEV_RAM=m
+CONFIG_BLK_DEV_RAM_COUNT=16
 CONFIG_BLK_DEV_RAM_SIZE=4096
-CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_CDROM_PKTCDVD is not set
 
 #
@@ -189,6 +294,7 @@ CONFIG_IOSCHED_NOOP=y
 CONFIG_IOSCHED_AS=y
 CONFIG_IOSCHED_DEADLINE=y
 CONFIG_IOSCHED_CFQ=y
+# CONFIG_ATA_OVER_ETH is not set
 
 #
 # ATA/ATAPI/MFM/RLL support
@@ -211,7 +317,8 @@ CONFIG_BLK_DEV_IDEFLOPPY=m
 #
 # IDE chipset support/bugfixes
 #
-CONFIG_IDE_GENERIC=m
+# CONFIG_IDE_GENERIC is not set
+# CONFIG_BLK_DEV_IDEPNP is not set
 CONFIG_BLK_DEV_IDEPCI=y
 CONFIG_IDEPCI_SHARE_IRQ=y
 # CONFIG_BLK_DEV_OFFBOARD is not set
@@ -233,6 +340,7 @@ CONFIG_IDEDMA_PCI_AUTO=y
 # CONFIG_BLK_DEV_HPT366 is not set
 # CONFIG_BLK_DEV_SC1200 is not set
 CONFIG_BLK_DEV_PIIX=m
+# CONFIG_BLK_DEV_IT821X is not set
 # CONFIG_BLK_DEV_NS87415 is not set
 # CONFIG_BLK_DEV_PDC202XX_OLD is not set
 # CONFIG_BLK_DEV_PDC202XX_NEW is not set
@@ -250,6 +358,7 @@ CONFIG_IDEDMA_AUTO=y
 #
 # SCSI device support
 #
+# CONFIG_RAID_ATTRS is not set
 CONFIG_SCSI=y
 CONFIG_SCSI_PROC_FS=y
 
@@ -261,6 +370,7 @@ CONFIG_BLK_DEV_SD=y
 # CONFIG_CHR_DEV_OSST is not set
 # CONFIG_BLK_DEV_SR is not set
 # CONFIG_CHR_DEV_SG is not set
+# CONFIG_CHR_DEV_SCH is not set
 
 #
 # Some SCSI devices (e.g. CD jukebox) support multiple LUNs
@@ -274,6 +384,8 @@ CONFIG_SCSI_LOGGING=y
 #
 CONFIG_SCSI_SPI_ATTRS=m
 # CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_ATTRS is not set
 
 #
 # SCSI low-level drivers
@@ -288,18 +400,13 @@ CONFIG_SCSI_SPI_ATTRS=m
 # CONFIG_MEGARAID_NEWGEN is not set
 # CONFIG_MEGARAID_LEGACY is not set
 # CONFIG_SCSI_SATA is not set
-# CONFIG_SCSI_BUSLOGIC is not set
 # CONFIG_SCSI_DMX3191D is not set
-# CONFIG_SCSI_EATA is not set
-# CONFIG_SCSI_EATA_PIO is not set
 # CONFIG_SCSI_FUTURE_DOMAIN is not set
-# CONFIG_SCSI_GDTH is not set
 # CONFIG_SCSI_IPS is not set
 # CONFIG_SCSI_INITIO is not set
 # CONFIG_SCSI_INIA100 is not set
 # CONFIG_SCSI_SYM53C8XX_2 is not set
 # CONFIG_SCSI_IPR is not set
-# CONFIG_SCSI_QLOGIC_ISP is not set
 # CONFIG_SCSI_QLOGIC_FC is not set
 CONFIG_SCSI_QLOGIC_1280=y
 # CONFIG_SCSI_QLOGIC_1280_1040 is not set
@@ -309,7 +416,8 @@ CONFIG_SCSI_QLA2XXX=y
 # CONFIG_SCSI_QLA2300 is not set
 # CONFIG_SCSI_QLA2322 is not set
 # CONFIG_SCSI_QLA6312 is not set
-# CONFIG_SCSI_QLA6322 is not set
+# CONFIG_SCSI_QLA24XX is not set
+# CONFIG_SCSI_LPFC is not set
 # CONFIG_SCSI_DC395x is not set
 # CONFIG_SCSI_DC390T is not set
 # CONFIG_SCSI_DEBUG is not set
@@ -332,11 +440,14 @@ CONFIG_DM_CRYPT=m
 CONFIG_DM_SNAPSHOT=m
 CONFIG_DM_MIRROR=m
 CONFIG_DM_ZERO=m
+# CONFIG_DM_MULTIPATH is not set
 
 #
 # Fusion MPT device support
 #
 # CONFIG_FUSION is not set
+# CONFIG_FUSION_SPI is not set
+# CONFIG_FUSION_FC is not set
 
 #
 # IEEE 1394 (FireWire) support
@@ -349,78 +460,25 @@ CONFIG_DM_ZERO=m
 # CONFIG_I2O is not set
 
 #
-# Networking support
+# Network device support
 #
-CONFIG_NET=y
-
-#
-# Networking options
-#
-CONFIG_PACKET=y
-CONFIG_PACKET_MMAP=y
-# CONFIG_NETLINK_DEV is not set
-CONFIG_UNIX=y
-# CONFIG_NET_KEY is not set
-CONFIG_INET=y
-# CONFIG_IP_MULTICAST is not set
-# CONFIG_IP_ADVANCED_ROUTER is not set
-# CONFIG_IP_PNP is not set
-# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE is not set
-# CONFIG_ARPD is not set
-# CONFIG_SYN_COOKIES is not set
-# CONFIG_INET_AH is not set
-# CONFIG_INET_ESP is not set
-# CONFIG_INET_IPCOMP is not set
-# CONFIG_INET_TUNNEL is not set
-CONFIG_IP_TCPDIAG=y
-# CONFIG_IP_TCPDIAG_IPV6 is not set
-# CONFIG_IPV6 is not set
-# CONFIG_NETFILTER is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
-# CONFIG_IP_SCTP is not set
-# CONFIG_ATM is not set
-# CONFIG_BRIDGE is not set
-# CONFIG_VLAN_8021Q is not set
-# CONFIG_DECNET is not set
-# CONFIG_LLC2 is not set
-# CONFIG_IPX is not set
-# CONFIG_ATALK is not set
-# CONFIG_X25 is not set
-# CONFIG_LAPB is not set
-# CONFIG_NET_DIVERT is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-
-#
-# QoS and/or fair queueing
-#
-# CONFIG_NET_SCHED is not set
-# CONFIG_NET_CLS_ROUTE is not set
-
-#
-# Network testing
-#
-# CONFIG_NET_PKTGEN is not set
-# CONFIG_NETPOLL is not set
-# CONFIG_NET_POLL_CONTROLLER is not set
-# CONFIG_HAMRADIO is not set
-# CONFIG_IRDA is not set
-# CONFIG_BT is not set
 CONFIG_NETDEVICES=y
 CONFIG_DUMMY=y
 # CONFIG_BONDING is not set
 # CONFIG_EQUALIZER is not set
 # CONFIG_TUN is not set
+# CONFIG_NET_SB1000 is not set
 
 #
 # ARCnet devices
 #
 # CONFIG_ARCNET is not set
 
+#
+# PHY device support
+#
+# CONFIG_PHYLIB is not set
+
 #
 # Ethernet (10 or 100Mbit)
 #
@@ -443,7 +501,6 @@ CONFIG_NET_PCI=y
 # CONFIG_FORCEDETH is not set
 # CONFIG_DGRS is not set
 CONFIG_EEPRO100=y
-# CONFIG_EEPRO100_PIO is not set
 # CONFIG_E100 is not set
 # CONFIG_FEALNX is not set
 # CONFIG_NATSEMI is not set
@@ -465,13 +522,17 @@ CONFIG_EEPRO100=y
 # CONFIG_HAMACHI is not set
 # CONFIG_YELLOWFIN is not set
 # CONFIG_R8169 is not set
+# CONFIG_SIS190 is not set
+# CONFIG_SKGE is not set
 # CONFIG_SK98LIN is not set
 # CONFIG_VIA_VELOCITY is not set
 # CONFIG_TIGON3 is not set
+# CONFIG_BNX2 is not set
 
 #
 # Ethernet (10000 Mbit)
 #
+# CONFIG_CHELSIO_T1 is not set
 # CONFIG_IXGB is not set
 # CONFIG_S2IO is not set
 
@@ -496,6 +557,8 @@ CONFIG_EEPRO100=y
 # CONFIG_NET_FC is not set
 # CONFIG_SHAPER is not set
 # CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
 
 #
 # ISDN subsystem
@@ -524,18 +587,6 @@ CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
 CONFIG_INPUT_EVDEV=y
 # CONFIG_INPUT_EVBUG is not set
 
-#
-# Input I/O drivers
-#
-# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
-CONFIG_SERIO=y
-CONFIG_SERIO_I8042=y
-CONFIG_SERIO_SERPORT=y
-# CONFIG_SERIO_CT82C710 is not set
-# CONFIG_SERIO_PCIPS2 is not set
-# CONFIG_SERIO_RAW is not set
-
 #
 # Input Device Drivers
 #
@@ -553,6 +604,17 @@ CONFIG_MOUSE_PS2=y
 # CONFIG_INPUT_TOUCHSCREEN is not set
 # CONFIG_INPUT_MISC is not set
 
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+CONFIG_SERIO_I8042=y
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_PCIPS2 is not set
+CONFIG_SERIO_LIBPS2=y
+# CONFIG_SERIO_RAW is not set
+# CONFIG_GAMEPORT is not set
+
 #
 # Character devices
 #
@@ -571,7 +633,6 @@ CONFIG_SERIAL_8250_NR_UARTS=4
 CONFIG_SERIAL_8250_EXTENDED=y
 CONFIG_SERIAL_8250_SHARE_IRQ=y
 # CONFIG_SERIAL_8250_DETECT_IRQ is not set
-# CONFIG_SERIAL_8250_MULTIPORT is not set
 # CONFIG_SERIAL_8250_RSA is not set
 
 #
@@ -579,6 +640,7 @@ CONFIG_SERIAL_8250_SHARE_IRQ=y
 #
 CONFIG_SERIAL_CORE=y
 CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
 CONFIG_UNIX98_PTYS=y
 CONFIG_LEGACY_PTYS=y
 CONFIG_LEGACY_PTY_COUNT=256
@@ -603,14 +665,22 @@ CONFIG_EFI_RTC=y
 #
 CONFIG_AGP=m
 CONFIG_AGP_I460=m
-CONFIG_DRM=y
+CONFIG_DRM=m
 # CONFIG_DRM_TDFX is not set
 CONFIG_DRM_R128=m
 # CONFIG_DRM_RADEON is not set
 # CONFIG_DRM_MGA is not set
 # CONFIG_DRM_SIS is not set
+# CONFIG_DRM_VIA is not set
+# CONFIG_DRM_SAVAGE is not set
 # CONFIG_RAW_DRIVER is not set
 # CONFIG_HPET is not set
+# CONFIG_HANGCHECK_TIMER is not set
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
 
 #
 # I2C support
@@ -635,7 +705,7 @@ CONFIG_I2C_ALGOBIT=y
 # CONFIG_I2C_AMD8111 is not set
 # CONFIG_I2C_I801 is not set
 # CONFIG_I2C_I810 is not set
-# CONFIG_I2C_ISA is not set
+# CONFIG_I2C_PIIX4 is not set
 # CONFIG_I2C_NFORCE2 is not set
 # CONFIG_I2C_PARPORT_LIGHT is not set
 # CONFIG_I2C_PROSAVAGE is not set
@@ -651,16 +721,43 @@ CONFIG_I2C_ALGOBIT=y
 # CONFIG_I2C_PCA_ISA is not set
 
 #
-# Hardware Sensors Chip support
+# Miscellaneous I2C Chip support
 #
-# CONFIG_I2C_SENSOR is not set
+# CONFIG_SENSORS_DS1337 is not set
+# CONFIG_SENSORS_DS1374 is not set
+# CONFIG_SENSORS_EEPROM is not set
+# 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
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Hardware Monitoring support
+#
+CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
 # CONFIG_SENSORS_ADM1021 is not set
 # CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1026 is not set
 # CONFIG_SENSORS_ADM1031 is not set
+# CONFIG_SENSORS_ADM9240 is not set
 # CONFIG_SENSORS_ASB100 is not set
+# CONFIG_SENSORS_ATXP1 is not set
 # CONFIG_SENSORS_DS1621 is not set
 # CONFIG_SENSORS_FSCHER is not set
+# CONFIG_SENSORS_FSCPOS is not set
 # CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_GL520SM is not set
 # CONFIG_SENSORS_IT87 is not set
 # CONFIG_SENSORS_LM63 is not set
 # CONFIG_SENSORS_LM75 is not set
@@ -671,33 +768,26 @@ CONFIG_I2C_ALGOBIT=y
 # CONFIG_SENSORS_LM85 is not set
 # CONFIG_SENSORS_LM87 is not set
 # CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_LM92 is not set
 # CONFIG_SENSORS_MAX1619 is not set
 # CONFIG_SENSORS_PC87360 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_W83792D is not set
 # CONFIG_SENSORS_W83L785TS is not set
 # CONFIG_SENSORS_W83627HF is not set
+# CONFIG_SENSORS_W83627EHF is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
 
 #
-# Other I2C Chip support
-#
-# CONFIG_SENSORS_EEPROM is not set
-# CONFIG_SENSORS_PCF8574 is not set
-# CONFIG_SENSORS_PCF8591 is not set
-# CONFIG_SENSORS_RTC8564 is not set
-# CONFIG_I2C_DEBUG_CORE is not set
-# CONFIG_I2C_DEBUG_ALGO is not set
-# CONFIG_I2C_DEBUG_BUS is not set
-# CONFIG_I2C_DEBUG_CHIP is not set
-
-#
-# Dallas's 1-wire bus
+# Misc devices
 #
-# CONFIG_W1 is not set
 
 #
-# Misc devices
+# Multimedia Capabilities Port drivers
 #
 
 #
@@ -752,11 +842,12 @@ CONFIG_SND_OPL3_LIB=m
 # CONFIG_SND_MTPAV is not set
 # CONFIG_SND_SERIAL_U16550 is not set
 # CONFIG_SND_MPU401 is not set
+CONFIG_SND_AC97_CODEC=m
+CONFIG_SND_AC97_BUS=m
 
 #
 # PCI devices
 #
-CONFIG_SND_AC97_CODEC=m
 # CONFIG_SND_ALI5451 is not set
 # CONFIG_SND_ATIIXP is not set
 # CONFIG_SND_ATIIXP_MODEM is not set
@@ -768,6 +859,8 @@ CONFIG_SND_AC97_CODEC=m
 # CONFIG_SND_CS46XX is not set
 CONFIG_SND_CS4281=m
 # CONFIG_SND_EMU10K1 is not set
+# CONFIG_SND_EMU10K1X is not set
+# CONFIG_SND_CA0106 is not set
 # CONFIG_SND_KORG1212 is not set
 # CONFIG_SND_MIXART is not set
 # CONFIG_SND_NM256 is not set
@@ -775,9 +868,10 @@ CONFIG_SND_CS4281=m
 # CONFIG_SND_RME96 is not set
 # CONFIG_SND_RME9652 is not set
 # CONFIG_SND_HDSP is not set
+# CONFIG_SND_HDSPM is not set
 # CONFIG_SND_TRIDENT is not set
 # CONFIG_SND_YMFPCI is not set
-# CONFIG_SND_ALS4000 is not set
+# CONFIG_SND_AD1889 is not set
 # CONFIG_SND_CMIPCI is not set
 # CONFIG_SND_ENS1370 is not set
 # CONFIG_SND_ENS1371 is not set
@@ -791,13 +885,14 @@ CONFIG_SND_CS4281=m
 # CONFIG_SND_INTEL8X0M is not set
 # CONFIG_SND_SONICVIBES is not set
 # CONFIG_SND_VIA82XX is not set
+# CONFIG_SND_VIA82XX_MODEM is not set
 # CONFIG_SND_VX222 is not set
+# CONFIG_SND_HDA_INTEL is not set
 
 #
 # USB devices
 #
 # CONFIG_SND_USB_AUDIO is not set
-# CONFIG_SND_USB_USX2Y is not set
 
 #
 # Open Sound System
@@ -807,6 +902,8 @@ CONFIG_SND_CS4281=m
 #
 # USB support
 #
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
 CONFIG_USB=m
 # CONFIG_USB_DEBUG is not set
 
@@ -818,35 +915,38 @@ CONFIG_USB_DEVICEFS=y
 # CONFIG_USB_DYNAMIC_MINORS is not set
 # CONFIG_USB_SUSPEND is not set
 # CONFIG_USB_OTG is not set
-CONFIG_USB_ARCH_HAS_HCD=y
-CONFIG_USB_ARCH_HAS_OHCI=y
 
 #
 # USB Host Controller Drivers
 #
 # CONFIG_USB_EHCI_HCD is not set
+# CONFIG_USB_ISP116X_HCD is not set
 # CONFIG_USB_OHCI_HCD is not set
 CONFIG_USB_UHCI_HCD=m
+# CONFIG_USB_SL811_HCD is not set
 
 #
 # USB Device Class drivers
 #
-CONFIG_USB_AUDIO=m
+# CONFIG_OBSOLETE_OSS_USB_DRIVER is not set
 CONFIG_USB_BLUETOOTH_TTY=m
-CONFIG_USB_MIDI=m
 CONFIG_USB_ACM=m
 CONFIG_USB_PRINTER=m
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
+#
 CONFIG_USB_STORAGE=m
 # CONFIG_USB_STORAGE_DEBUG is not set
-# CONFIG_USB_STORAGE_RW_DETECT is not set
 # CONFIG_USB_STORAGE_DATAFAB is not set
 # CONFIG_USB_STORAGE_FREECOM is not set
 # CONFIG_USB_STORAGE_ISD200 is not set
 # CONFIG_USB_STORAGE_DPCM is not set
-# CONFIG_USB_STORAGE_HP8200e is not set
+# CONFIG_USB_STORAGE_USBAT is not set
 # CONFIG_USB_STORAGE_SDDR09 is not set
 # CONFIG_USB_STORAGE_SDDR55 is not set
 # CONFIG_USB_STORAGE_JUMPSHOT is not set
+# CONFIG_USB_STORAGE_ONETOUCH is not set
 
 #
 # USB Input Devices
@@ -863,19 +963,23 @@ CONFIG_USB_HIDDEV=y
 # CONFIG_USB_MOUSE is not set
 # CONFIG_USB_AIPTEK is not set
 # CONFIG_USB_WACOM is not set
+# CONFIG_USB_ACECAD is not set
 # CONFIG_USB_KBTAB is not set
 # CONFIG_USB_POWERMATE is not set
 # CONFIG_USB_MTOUCH is not set
+# CONFIG_USB_ITMTOUCH is not set
 # CONFIG_USB_EGALAX is not set
+# CONFIG_USB_YEALINK is not set
 # CONFIG_USB_XPAD is not set
 # CONFIG_USB_ATI_REMOTE is not set
+# CONFIG_USB_KEYSPAN_REMOTE is not set
+# CONFIG_USB_APPLETOUCH is not set
 
 #
 # USB Imaging devices
 #
 # CONFIG_USB_MDC800 is not set
 # CONFIG_USB_MICROTEK is not set
-# CONFIG_USB_HPUSBSCSI is not set
 
 #
 # USB Multimedia devices
@@ -894,6 +998,7 @@ CONFIG_USB_HIDDEV=y
 # CONFIG_USB_PEGASUS is not set
 # CONFIG_USB_RTL8150 is not set
 # CONFIG_USB_USBNET is not set
+CONFIG_USB_MON=y
 
 #
 # USB port drivers
@@ -909,7 +1014,6 @@ CONFIG_USB_HIDDEV=y
 #
 # CONFIG_USB_EMI62 is not set
 # CONFIG_USB_EMI26 is not set
-# CONFIG_USB_TIGL is not set
 # CONFIG_USB_AUERSWALD is not set
 # CONFIG_USB_RIO500 is not set
 # CONFIG_USB_LEGOTOWER is not set
@@ -918,10 +1022,12 @@ CONFIG_USB_HIDDEV=y
 # CONFIG_USB_CYTHERM is not set
 # CONFIG_USB_PHIDGETKIT is not set
 # CONFIG_USB_PHIDGETSERVO is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_LD is not set
 # CONFIG_USB_TEST is not set
 
 #
-# USB ATM/DSL drivers
+# USB DSL modem support
 #
 
 #
@@ -929,11 +1035,26 @@ CONFIG_USB_HIDDEV=y
 #
 # CONFIG_USB_GADGET is not set
 
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
+# SN Devices
+#
+
 #
 # File systems
 #
 CONFIG_EXT2_FS=y
 # CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
 CONFIG_EXT3_FS=y
 CONFIG_EXT3_FS_XATTR=y
 # CONFIG_EXT3_FS_POSIX_ACL is not set
@@ -945,17 +1066,20 @@ CONFIG_FS_MBCACHE=y
 # CONFIG_JFS_FS is not set
 CONFIG_FS_POSIX_ACL=y
 CONFIG_XFS_FS=y
-# CONFIG_XFS_RT is not set
+CONFIG_XFS_EXPORT=y
 CONFIG_XFS_QUOTA=y
 CONFIG_XFS_SECURITY=y
 CONFIG_XFS_POSIX_ACL=y
+# CONFIG_XFS_RT is not set
 # CONFIG_MINIX_FS is not set
 # CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
 # CONFIG_QUOTA is not set
 CONFIG_QUOTACTL=y
 CONFIG_DNOTIFY=y
 CONFIG_AUTOFS_FS=m
 CONFIG_AUTOFS4_FS=m
+# CONFIG_FUSE_FS is not set
 
 #
 # CD-ROM/DVD Filesystems
@@ -982,14 +1106,11 @@ CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
 CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
 CONFIG_SYSFS=y
-# CONFIG_DEVFS_FS is not set
-CONFIG_DEVPTS_FS_XATTR=y
-CONFIG_DEVPTS_FS_SECURITY=y
 CONFIG_TMPFS=y
-# CONFIG_TMPFS_XATTR is not set
 CONFIG_HUGETLBFS=y
 CONFIG_HUGETLB_PAGE=y
 CONFIG_RAMFS=y
+# CONFIG_RELAYFS_FS is not set
 
 #
 # Miscellaneous filesystems
@@ -1013,15 +1134,18 @@ CONFIG_RAMFS=y
 #
 CONFIG_NFS_FS=m
 CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
 CONFIG_NFS_V4=y
 # CONFIG_NFS_DIRECTIO is not set
 CONFIG_NFSD=m
 CONFIG_NFSD_V3=y
+# CONFIG_NFSD_V3_ACL is not set
 CONFIG_NFSD_V4=y
 CONFIG_NFSD_TCP=y
 CONFIG_LOCKD=m
 CONFIG_LOCKD_V4=y
-CONFIG_EXPORTFS=m
+CONFIG_EXPORTFS=y
+CONFIG_NFS_COMMON=y
 CONFIG_SUNRPC=m
 CONFIG_SUNRPC_GSS=m
 CONFIG_RPCSEC_GSS_KRB5=m
@@ -1031,9 +1155,11 @@ CONFIG_CIFS=m
 CONFIG_CIFS_STATS=y
 CONFIG_CIFS_XATTR=y
 CONFIG_CIFS_POSIX=y
+# CONFIG_CIFS_EXPERIMENTAL is not set
 # CONFIG_NCP_FS is not set
 # CONFIG_CODA_FS is not set
 # CONFIG_AFS_FS is not set
+# CONFIG_9P_FS is not set
 
 #
 # Partition Types
@@ -1103,8 +1229,12 @@ CONFIG_NLS_UTF8=m
 # Library routines
 #
 # CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
 CONFIG_CRC32=y
 # CONFIG_LIBCRC32C is not set
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_GENERIC_PENDING_IRQ=y
 
 #
 # Profiling support
@@ -1115,14 +1245,20 @@ CONFIG_OPROFILE=y
 #
 # Kernel hacking
 #
+# CONFIG_PRINTK_TIME is not set
 CONFIG_DEBUG_KERNEL=y
 CONFIG_MAGIC_SYSRQ=y
+CONFIG_LOG_BUF_SHIFT=16
+CONFIG_DETECT_SOFTLOCKUP=y
 # CONFIG_SCHEDSTATS is not set
 # CONFIG_DEBUG_SLAB is not set
+CONFIG_DEBUG_PREEMPT=y
 # CONFIG_DEBUG_SPINLOCK is not set
 # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
 # CONFIG_DEBUG_KOBJECT is not set
 # CONFIG_DEBUG_INFO is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_KPROBES is not set
 # CONFIG_IA64_GRANULE_16MB is not set
 CONFIG_IA64_GRANULE_64MB=y
 # CONFIG_IA64_PRINT_HAZARDS is not set
@@ -1149,6 +1285,7 @@ CONFIG_CRYPTO_MD5=y
 # CONFIG_CRYPTO_SHA256 is not set
 # CONFIG_CRYPTO_SHA512 is not set
 # CONFIG_CRYPTO_WP512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
 CONFIG_CRYPTO_DES=y
 # CONFIG_CRYPTO_BLOWFISH is not set
 # CONFIG_CRYPTO_TWOFISH is not set
@@ -1164,3 +1301,7 @@ CONFIG_CRYPTO_DES=y
 # CONFIG_CRYPTO_MICHAEL_MIC is not set
 # CONFIG_CRYPTO_CRC32C is not set
 # CONFIG_CRYPTO_TEST is not set
+
+#
+# Hardware crypto devices
+#
diff --git a/arch/ia64/configs/gensparse_defconfig b/arch/ia64/configs/gensparse_defconfig
new file mode 100644 (file)
index 0000000..80f8663
--- /dev/null
@@ -0,0 +1,1319 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.14-rc2
+# Wed Sep 28 08:27:29 2005
+#
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+CONFIG_HOTPLUG=y
+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=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+CONFIG_MODVERSIONS=y
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
+CONFIG_STOP_MACHINE=y
+
+#
+# Processor type and features
+#
+CONFIG_IA64=y
+CONFIG_64BIT=y
+CONFIG_MMU=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_TIME_INTERPOLATION=y
+CONFIG_EFI=y
+CONFIG_GENERIC_IOMAP=y
+CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+CONFIG_IA64_GENERIC=y
+# CONFIG_IA64_DIG is not set
+# CONFIG_IA64_HP_ZX1 is not set
+# CONFIG_IA64_HP_ZX1_SWIOTLB is not set
+# CONFIG_IA64_SGI_SN2 is not set
+# CONFIG_IA64_HP_SIM is not set
+# CONFIG_ITANIUM is not set
+CONFIG_MCKINLEY=y
+# CONFIG_IA64_PAGE_SIZE_4KB is not set
+# CONFIG_IA64_PAGE_SIZE_8KB is not set
+CONFIG_IA64_PAGE_SIZE_16KB=y
+# CONFIG_IA64_PAGE_SIZE_64KB is not set
+# CONFIG_HZ_100 is not set
+CONFIG_HZ_250=y
+# CONFIG_HZ_1000 is not set
+CONFIG_HZ=250
+CONFIG_IA64_L1_CACHE_SHIFT=7
+CONFIG_IA64_CYCLONE=y
+CONFIG_IOSAPIC=y
+# CONFIG_IA64_SGI_SN_XP is not set
+CONFIG_FORCE_MAX_ZONEORDER=17
+CONFIG_SMP=y
+CONFIG_NR_CPUS=512
+CONFIG_HOTPLUG_CPU=y
+# CONFIG_SCHED_SMT is not set
+# CONFIG_PREEMPT is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+# CONFIG_FLATMEM_MANUAL is not set
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+CONFIG_SPARSEMEM_MANUAL=y
+CONFIG_SPARSEMEM=y
+CONFIG_NEED_MULTIPLE_NODES=y
+CONFIG_HAVE_MEMORY_PRESENT=y
+# CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_SPARSEMEM_EXTREME=y
+CONFIG_ARCH_SELECT_MEMORY_MODEL=y
+CONFIG_ARCH_DISCONTIGMEM_ENABLE=y
+CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_ARCH_SPARSEMEM_ENABLE=y
+CONFIG_ARCH_DISCONTIGMEM_DEFAULT=y
+CONFIG_NUMA=y
+CONFIG_HAVE_ARCH_EARLY_PFN_TO_NID=y
+CONFIG_IA32_SUPPORT=y
+CONFIG_COMPAT=y
+CONFIG_IA64_MCA_RECOVERY=y
+CONFIG_PERFMON=y
+CONFIG_IA64_PALINFO=y
+
+#
+# Firmware Drivers
+#
+CONFIG_EFI_VARS=y
+CONFIG_EFI_PCDP=y
+# CONFIG_DELL_RBU is not set
+CONFIG_BINFMT_ELF=y
+CONFIG_BINFMT_MISC=m
+
+#
+# Power management and ACPI
+#
+CONFIG_PM=y
+# CONFIG_PM_DEBUG is not set
+
+#
+# ACPI (Advanced Configuration and Power Interface) Support
+#
+CONFIG_ACPI=y
+CONFIG_ACPI_BUTTON=m
+CONFIG_ACPI_FAN=m
+CONFIG_ACPI_PROCESSOR=m
+CONFIG_ACPI_HOTPLUG_CPU=y
+CONFIG_ACPI_THERMAL=m
+CONFIG_ACPI_NUMA=y
+CONFIG_ACPI_BLACKLIST_YEAR=0
+# CONFIG_ACPI_DEBUG is not set
+CONFIG_ACPI_POWER=y
+CONFIG_ACPI_SYSTEM=y
+CONFIG_ACPI_CONTAINER=m
+
+#
+# CPU Frequency scaling
+#
+# CONFIG_CPU_FREQ is not set
+
+#
+# Bus options (PCI, PCMCIA)
+#
+CONFIG_PCI=y
+CONFIG_PCI_DOMAINS=y
+# CONFIG_PCI_MSI is not set
+CONFIG_PCI_LEGACY_PROC=y
+# CONFIG_PCI_DEBUG is not set
+
+#
+# PCI Hotplug Support
+#
+CONFIG_HOTPLUG_PCI=m
+# CONFIG_HOTPLUG_PCI_FAKE is not set
+CONFIG_HOTPLUG_PCI_ACPI=m
+# CONFIG_HOTPLUG_PCI_ACPI_IBM is not set
+# CONFIG_HOTPLUG_PCI_CPCI is not set
+# CONFIG_HOTPLUG_PCI_SHPC is not set
+# CONFIG_HOTPLUG_PCI_SGI is not set
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+# CONFIG_IP_PNP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE is not set
+CONFIG_ARPD=y
+CONFIG_SYN_COOKIES=y
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_BIC=y
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP 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
+# CONFIG_IEEE80211 is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=m
+# CONFIG_DEBUG_DRIVER is not set
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+# CONFIG_PNP is not set
+
+#
+# Block devices
+#
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=m
+CONFIG_BLK_DEV_CRYPTOLOOP=m
+CONFIG_BLK_DEV_NBD=m
+# CONFIG_BLK_DEV_SX8 is not set
+# CONFIG_BLK_DEV_UB is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_CDROM_PKTCDVD is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+CONFIG_IDE=y
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_IDE_SATA is not set
+CONFIG_BLK_DEV_IDEDISK=y
+# CONFIG_IDEDISK_MULTI_MODE is not set
+CONFIG_BLK_DEV_IDECD=y
+# CONFIG_BLK_DEV_IDETAPE is not set
+CONFIG_BLK_DEV_IDEFLOPPY=y
+CONFIG_BLK_DEV_IDESCSI=m
+# CONFIG_IDE_TASK_IOCTL is not set
+
+#
+# IDE chipset support/bugfixes
+#
+CONFIG_IDE_GENERIC=y
+CONFIG_BLK_DEV_IDEPCI=y
+# CONFIG_IDEPCI_SHARE_IRQ is not set
+# CONFIG_BLK_DEV_OFFBOARD is not set
+CONFIG_BLK_DEV_GENERIC=y
+# CONFIG_BLK_DEV_OPTI621 is not set
+CONFIG_BLK_DEV_IDEDMA_PCI=y
+# CONFIG_BLK_DEV_IDEDMA_FORCED is not set
+CONFIG_IDEDMA_PCI_AUTO=y
+# CONFIG_IDEDMA_ONLYDISK is not set
+# CONFIG_BLK_DEV_AEC62XX is not set
+# CONFIG_BLK_DEV_ALI15X3 is not set
+# CONFIG_BLK_DEV_AMD74XX is not set
+CONFIG_BLK_DEV_CMD64X=y
+# CONFIG_BLK_DEV_TRIFLEX is not set
+# CONFIG_BLK_DEV_CY82C693 is not set
+# CONFIG_BLK_DEV_CS5520 is not set
+# CONFIG_BLK_DEV_CS5530 is not set
+# CONFIG_BLK_DEV_HPT34X is not set
+# CONFIG_BLK_DEV_HPT366 is not set
+# CONFIG_BLK_DEV_SC1200 is not set
+CONFIG_BLK_DEV_PIIX=y
+# CONFIG_BLK_DEV_IT821X is not set
+# CONFIG_BLK_DEV_NS87415 is not set
+# CONFIG_BLK_DEV_PDC202XX_OLD is not set
+# CONFIG_BLK_DEV_PDC202XX_NEW is not set
+# CONFIG_BLK_DEV_SVWKS is not set
+CONFIG_BLK_DEV_SGIIOC4=y
+# CONFIG_BLK_DEV_SIIMAGE is not set
+# CONFIG_BLK_DEV_SLC90E66 is not set
+# CONFIG_BLK_DEV_TRM290 is not set
+# CONFIG_BLK_DEV_VIA82CXXX is not set
+# CONFIG_IDE_ARM is not set
+CONFIG_BLK_DEV_IDEDMA=y
+# CONFIG_IDEDMA_IVB is not set
+CONFIG_IDEDMA_AUTO=y
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=y
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+CONFIG_CHR_DEV_ST=m
+# CONFIG_CHR_DEV_OSST is not set
+CONFIG_BLK_DEV_SR=m
+# CONFIG_BLK_DEV_SR_VENDOR is not set
+CONFIG_CHR_DEV_SG=m
+# CONFIG_CHR_DEV_SCH is not set
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+# CONFIG_SCSI_MULTI_LUN is not set
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+
+#
+# SCSI Transport Attributes
+#
+CONFIG_SCSI_SPI_ATTRS=y
+CONFIG_SCSI_FC_ATTRS=y
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_ATTRS is not set
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+# CONFIG_SCSI_3W_9XXX is not set
+# CONFIG_SCSI_ACARD is not set
+# CONFIG_SCSI_AACRAID is not set
+# CONFIG_SCSI_AIC7XXX is not set
+# CONFIG_SCSI_AIC7XXX_OLD is not set
+# CONFIG_SCSI_AIC79XX is not set
+# CONFIG_MEGARAID_NEWGEN is not set
+# CONFIG_MEGARAID_LEGACY is not set
+CONFIG_SCSI_SATA=y
+# CONFIG_SCSI_SATA_AHCI is not set
+# CONFIG_SCSI_SATA_SVW is not set
+# CONFIG_SCSI_ATA_PIIX is not set
+# CONFIG_SCSI_SATA_MV is not set
+# CONFIG_SCSI_SATA_NV is not set
+# CONFIG_SCSI_SATA_PROMISE is not set
+# CONFIG_SCSI_SATA_QSTOR is not set
+# CONFIG_SCSI_SATA_SX4 is not set
+# CONFIG_SCSI_SATA_SIL is not set
+# CONFIG_SCSI_SATA_SIS is not set
+# CONFIG_SCSI_SATA_ULI is not set
+# CONFIG_SCSI_SATA_VIA is not set
+CONFIG_SCSI_SATA_VITESSE=y
+# CONFIG_SCSI_DMX3191D is not set
+# CONFIG_SCSI_FUTURE_DOMAIN is not set
+# CONFIG_SCSI_IPS is not set
+# CONFIG_SCSI_INITIO is not set
+# CONFIG_SCSI_INIA100 is not set
+CONFIG_SCSI_SYM53C8XX_2=y
+CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=1
+CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16
+CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64
+# CONFIG_SCSI_SYM53C8XX_IOMAPPED is not set
+# CONFIG_SCSI_IPR is not set
+# CONFIG_SCSI_QLOGIC_FC is not set
+CONFIG_SCSI_QLOGIC_1280=y
+# CONFIG_SCSI_QLOGIC_1280_1040 is not set
+CONFIG_SCSI_QLA2XXX=y
+CONFIG_SCSI_QLA21XX=m
+CONFIG_SCSI_QLA22XX=m
+CONFIG_SCSI_QLA2300=m
+CONFIG_SCSI_QLA2322=m
+# CONFIG_SCSI_QLA6312 is not set
+# CONFIG_SCSI_QLA24XX is not set
+# CONFIG_SCSI_LPFC is not set
+# CONFIG_SCSI_DC395x is not set
+# CONFIG_SCSI_DC390T is not set
+# CONFIG_SCSI_DEBUG is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+CONFIG_MD=y
+CONFIG_BLK_DEV_MD=m
+CONFIG_MD_LINEAR=m
+CONFIG_MD_RAID0=m
+CONFIG_MD_RAID1=m
+# CONFIG_MD_RAID10 is not set
+CONFIG_MD_RAID5=m
+CONFIG_MD_RAID6=m
+CONFIG_MD_MULTIPATH=m
+# CONFIG_MD_FAULTY is not set
+CONFIG_BLK_DEV_DM=m
+CONFIG_DM_CRYPT=m
+CONFIG_DM_SNAPSHOT=m
+CONFIG_DM_MIRROR=m
+CONFIG_DM_ZERO=m
+CONFIG_DM_MULTIPATH=m
+# CONFIG_DM_MULTIPATH_EMC is not set
+
+#
+# Fusion MPT device support
+#
+CONFIG_FUSION=y
+CONFIG_FUSION_SPI=y
+CONFIG_FUSION_FC=m
+CONFIG_FUSION_MAX_SGE=128
+# CONFIG_FUSION_CTL is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+CONFIG_DUMMY=m
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# PHY device support
+#
+# CONFIG_PHYLIB is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=m
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_NET_VENDOR_3COM is not set
+
+#
+# Tulip family network device support
+#
+CONFIG_NET_TULIP=y
+# CONFIG_DE2104X is not set
+CONFIG_TULIP=m
+# CONFIG_TULIP_MWI is not set
+# CONFIG_TULIP_MMIO is not set
+# CONFIG_TULIP_NAPI is not set
+# CONFIG_DE4X5 is not set
+# CONFIG_WINBOND_840 is not set
+# CONFIG_DM9102 is not set
+# CONFIG_ULI526X is not set
+# CONFIG_HP100 is not set
+CONFIG_NET_PCI=y
+# CONFIG_PCNET32 is not set
+# CONFIG_AMD8111_ETH is not set
+# CONFIG_ADAPTEC_STARFIRE is not set
+# CONFIG_B44 is not set
+# CONFIG_FORCEDETH is not set
+# CONFIG_DGRS is not set
+CONFIG_EEPRO100=m
+CONFIG_E100=m
+# CONFIG_FEALNX is not set
+# CONFIG_NATSEMI is not set
+# CONFIG_NE2K_PCI is not set
+# CONFIG_8139CP is not set
+# CONFIG_8139TOO is not set
+# CONFIG_SIS900 is not set
+# CONFIG_EPIC100 is not set
+# CONFIG_SUNDANCE is not set
+# CONFIG_VIA_RHINE is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+CONFIG_E1000=y
+# CONFIG_E1000_NAPI is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SIS190 is not set
+# CONFIG_SKGE is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_VIA_VELOCITY is not set
+CONFIG_TIGON3=y
+# CONFIG_BNX2 is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_CHELSIO_T1 is not set
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_NET_FC is not set
+# CONFIG_SHAPER is not set
+CONFIG_NETCONSOLE=y
+CONFIG_NETPOLL=y
+# CONFIG_NETPOLL_RX is not set
+# CONFIG_NETPOLL_TRAP is not set
+CONFIG_NET_POLL_CONTROLLER=y
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+CONFIG_KEYBOARD_ATKBD=y
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+CONFIG_INPUT_MOUSE=y
+CONFIG_MOUSE_PS2=y
+# CONFIG_MOUSE_SERIAL is not set
+# CONFIG_MOUSE_VSXXXAA is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+CONFIG_SERIO_I8042=y
+# CONFIG_SERIO_SERPORT is not set
+# CONFIG_SERIO_PCIPS2 is not set
+CONFIG_SERIO_LIBPS2=y
+# CONFIG_SERIO_RAW is not set
+CONFIG_GAMEPORT=m
+# CONFIG_GAMEPORT_NS558 is not set
+# CONFIG_GAMEPORT_L4 is not set
+# CONFIG_GAMEPORT_EMU10K1 is not set
+# CONFIG_GAMEPORT_FM801 is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+CONFIG_SERIAL_NONSTANDARD=y
+# CONFIG_ROCKETPORT is not set
+# CONFIG_CYCLADES is not set
+# CONFIG_DIGIEPCA is not set
+# CONFIG_MOXA_SMARTIO is not set
+# CONFIG_ISI is not set
+# CONFIG_SYNCLINKMP is not set
+# CONFIG_N_HDLC is not set
+# CONFIG_SPECIALIX is not set
+# CONFIG_SX is not set
+# CONFIG_STALDRV is not set
+CONFIG_SGI_SNSC=y
+CONFIG_SGI_TIOCX=y
+CONFIG_SGI_MBCS=m
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_ACPI=y
+CONFIG_SERIAL_8250_NR_UARTS=6
+CONFIG_SERIAL_8250_EXTENDED=y
+CONFIG_SERIAL_8250_SHARE_IRQ=y
+# CONFIG_SERIAL_8250_DETECT_IRQ is not set
+# CONFIG_SERIAL_8250_RSA is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_SERIAL_SGI_L1_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
+CONFIG_SERIAL_SGI_IOC4=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_HW_RANDOM is not set
+CONFIG_EFI_RTC=y
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+CONFIG_AGP=m
+CONFIG_AGP_I460=m
+CONFIG_AGP_HP_ZX1=m
+CONFIG_AGP_SGI_TIOCA=m
+CONFIG_DRM=m
+CONFIG_DRM_TDFX=m
+CONFIG_DRM_R128=m
+CONFIG_DRM_RADEON=m
+CONFIG_DRM_MGA=m
+CONFIG_DRM_SIS=m
+# CONFIG_DRM_VIA is not set
+# CONFIG_DRM_SAVAGE is not set
+CONFIG_RAW_DRIVER=m
+CONFIG_HPET=y
+# CONFIG_HPET_RTC_IRQ is not set
+CONFIG_HPET_MMAP=y
+CONFIG_MAX_RAW_DEVS=256
+# CONFIG_HANGCHECK_TIMER is not set
+CONFIG_MMTIMER=y
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Hardware Monitoring support
+#
+CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia Capabilities Port drivers
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Console display driver support
+#
+CONFIG_VGA_CONSOLE=y
+CONFIG_DUMMY_CONSOLE=y
+
+#
+# Sound
+#
+CONFIG_SOUND=m
+
+#
+# Advanced Linux Sound Architecture
+#
+CONFIG_SND=m
+CONFIG_SND_TIMER=m
+CONFIG_SND_PCM=m
+CONFIG_SND_HWDEP=m
+CONFIG_SND_RAWMIDI=m
+CONFIG_SND_SEQUENCER=m
+CONFIG_SND_SEQ_DUMMY=m
+CONFIG_SND_OSSEMUL=y
+CONFIG_SND_MIXER_OSS=m
+CONFIG_SND_PCM_OSS=m
+CONFIG_SND_SEQUENCER_OSS=y
+CONFIG_SND_VERBOSE_PRINTK=y
+# CONFIG_SND_DEBUG is not set
+CONFIG_SND_GENERIC_DRIVER=y
+
+#
+# Generic devices
+#
+CONFIG_SND_MPU401_UART=m
+CONFIG_SND_OPL3_LIB=m
+CONFIG_SND_DUMMY=m
+CONFIG_SND_VIRMIDI=m
+CONFIG_SND_MTPAV=m
+CONFIG_SND_SERIAL_U16550=m
+CONFIG_SND_MPU401=m
+CONFIG_SND_AC97_CODEC=m
+CONFIG_SND_AC97_BUS=m
+
+#
+# PCI devices
+#
+# CONFIG_SND_ALI5451 is not set
+# CONFIG_SND_ATIIXP is not set
+# CONFIG_SND_ATIIXP_MODEM is not set
+# CONFIG_SND_AU8810 is not set
+# CONFIG_SND_AU8820 is not set
+# CONFIG_SND_AU8830 is not set
+# CONFIG_SND_AZT3328 is not set
+# CONFIG_SND_BT87X is not set
+CONFIG_SND_CS46XX=m
+CONFIG_SND_CS46XX_NEW_DSP=y
+CONFIG_SND_CS4281=m
+CONFIG_SND_EMU10K1=m
+# CONFIG_SND_EMU10K1X is not set
+# CONFIG_SND_CA0106 is not set
+# CONFIG_SND_KORG1212 is not set
+# CONFIG_SND_MIXART is not set
+# CONFIG_SND_NM256 is not set
+# CONFIG_SND_RME32 is not set
+# CONFIG_SND_RME96 is not set
+# CONFIG_SND_RME9652 is not set
+# CONFIG_SND_HDSP is not set
+# CONFIG_SND_HDSPM is not set
+# CONFIG_SND_TRIDENT is not set
+# CONFIG_SND_YMFPCI is not set
+# CONFIG_SND_AD1889 is not set
+# CONFIG_SND_CMIPCI is not set
+# CONFIG_SND_ENS1370 is not set
+# CONFIG_SND_ENS1371 is not set
+# CONFIG_SND_ES1938 is not set
+# CONFIG_SND_ES1968 is not set
+# CONFIG_SND_MAESTRO3 is not set
+CONFIG_SND_FM801=m
+# CONFIG_SND_FM801_TEA575X is not set
+# CONFIG_SND_ICE1712 is not set
+# CONFIG_SND_ICE1724 is not set
+# CONFIG_SND_INTEL8X0 is not set
+# CONFIG_SND_INTEL8X0M is not set
+# CONFIG_SND_SONICVIBES is not set
+# CONFIG_SND_VIA82XX is not set
+# CONFIG_SND_VIA82XX_MODEM is not set
+# CONFIG_SND_VX222 is not set
+# CONFIG_SND_HDA_INTEL is not set
+
+#
+# USB devices
+#
+# CONFIG_SND_USB_AUDIO is not set
+
+#
+# Open Sound System
+#
+# CONFIG_SOUND_PRIME is not set
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB=m
+# CONFIG_USB_DEBUG is not set
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+# CONFIG_USB_BANDWIDTH is not set
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_SUSPEND is not set
+# CONFIG_USB_OTG is not set
+
+#
+# USB Host Controller Drivers
+#
+CONFIG_USB_EHCI_HCD=m
+# CONFIG_USB_EHCI_SPLIT_ISO is not set
+# CONFIG_USB_EHCI_ROOT_HUB_TT is not set
+# CONFIG_USB_ISP116X_HCD is not set
+CONFIG_USB_OHCI_HCD=m
+# CONFIG_USB_OHCI_BIG_ENDIAN is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+CONFIG_USB_UHCI_HCD=m
+# CONFIG_USB_SL811_HCD is not set
+
+#
+# USB Device Class drivers
+#
+# CONFIG_OBSOLETE_OSS_USB_DRIVER is not set
+# CONFIG_USB_BLUETOOTH_TTY is not set
+# CONFIG_USB_ACM is not set
+# CONFIG_USB_PRINTER is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
+#
+CONFIG_USB_STORAGE=m
+# CONFIG_USB_STORAGE_DEBUG is not set
+# CONFIG_USB_STORAGE_DATAFAB is not set
+# CONFIG_USB_STORAGE_FREECOM is not set
+# CONFIG_USB_STORAGE_ISD200 is not set
+# CONFIG_USB_STORAGE_DPCM is not set
+# CONFIG_USB_STORAGE_USBAT is not set
+# CONFIG_USB_STORAGE_SDDR09 is not set
+# CONFIG_USB_STORAGE_SDDR55 is not set
+# CONFIG_USB_STORAGE_JUMPSHOT is not set
+
+#
+# USB Input Devices
+#
+CONFIG_USB_HID=m
+CONFIG_USB_HIDINPUT=y
+# CONFIG_HID_FF is not set
+# CONFIG_USB_HIDDEV is not set
+
+#
+# USB HID Boot Protocol drivers
+#
+# CONFIG_USB_KBD is not set
+# CONFIG_USB_MOUSE is not set
+# CONFIG_USB_AIPTEK is not set
+# CONFIG_USB_WACOM is not set
+# CONFIG_USB_ACECAD is not set
+# CONFIG_USB_KBTAB is not set
+# CONFIG_USB_POWERMATE is not set
+# CONFIG_USB_MTOUCH is not set
+# CONFIG_USB_ITMTOUCH is not set
+# CONFIG_USB_EGALAX is not set
+# CONFIG_USB_YEALINK is not set
+# CONFIG_USB_XPAD is not set
+# CONFIG_USB_ATI_REMOTE is not set
+# CONFIG_USB_KEYSPAN_REMOTE is not set
+# CONFIG_USB_APPLETOUCH is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+
+#
+# USB Multimedia devices
+#
+# CONFIG_USB_DABUSB is not set
+
+#
+# Video4Linux support is needed for USB Multimedia device support
+#
+
+#
+# USB Network Adapters
+#
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET is not set
+CONFIG_USB_MON=y
+
+#
+# USB port drivers
+#
+
+#
+# USB Serial Converter support
+#
+# CONFIG_USB_SERIAL is not set
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_AUERSWALD is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_LED is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_PHIDGETKIT is not set
+# CONFIG_USB_PHIDGETSERVO is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_SISUSBVGA is not set
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TEST is not set
+
+#
+# USB DSL modem support
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# InfiniBand support
+#
+CONFIG_INFINIBAND=m
+# CONFIG_INFINIBAND_USER_MAD is not set
+# CONFIG_INFINIBAND_USER_ACCESS is not set
+CONFIG_INFINIBAND_MTHCA=m
+# CONFIG_INFINIBAND_MTHCA_DEBUG is not set
+CONFIG_INFINIBAND_IPOIB=m
+# CONFIG_INFINIBAND_IPOIB_DEBUG is not set
+
+#
+# SN Devices
+#
+CONFIG_SGI_IOC4=y
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT2_FS_POSIX_ACL=y
+CONFIG_EXT2_FS_SECURITY=y
+# CONFIG_EXT2_FS_XIP is not set
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_XATTR=y
+CONFIG_EXT3_FS_POSIX_ACL=y
+CONFIG_EXT3_FS_SECURITY=y
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+CONFIG_REISERFS_FS=y
+# CONFIG_REISERFS_CHECK is not set
+# CONFIG_REISERFS_PROC_INFO is not set
+CONFIG_REISERFS_FS_XATTR=y
+CONFIG_REISERFS_FS_POSIX_ACL=y
+CONFIG_REISERFS_FS_SECURITY=y
+# CONFIG_JFS_FS is not set
+CONFIG_FS_POSIX_ACL=y
+CONFIG_XFS_FS=y
+CONFIG_XFS_EXPORT=y
+# CONFIG_XFS_QUOTA is not set
+# CONFIG_XFS_SECURITY is not set
+# CONFIG_XFS_POSIX_ACL is not set
+# CONFIG_XFS_RT 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=y
+CONFIG_AUTOFS4_FS=y
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=m
+CONFIG_JOLIET=y
+# CONFIG_ZISOFS is not set
+CONFIG_UDF_FS=m
+CONFIG_UDF_NLS=y
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+# CONFIG_MSDOS_FS is not set
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+CONFIG_NTFS_FS=m
+# CONFIG_NTFS_DEBUG is not set
+# CONFIG_NTFS_RW is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+CONFIG_HUGETLBFS=y
+CONFIG_HUGETLB_PAGE=y
+CONFIG_RAMFS=y
+# CONFIG_RELAYFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=m
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+CONFIG_NFS_V4=y
+CONFIG_NFS_DIRECTIO=y
+CONFIG_NFSD=m
+CONFIG_NFSD_V3=y
+# CONFIG_NFSD_V3_ACL is not set
+CONFIG_NFSD_V4=y
+CONFIG_NFSD_TCP=y
+CONFIG_LOCKD=m
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=m
+CONFIG_SUNRPC_GSS=m
+CONFIG_RPCSEC_GSS_KRB5=m
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+CONFIG_SMB_FS=m
+CONFIG_SMB_NLS_DEFAULT=y
+CONFIG_SMB_NLS_REMOTE="cp437"
+CONFIG_CIFS=m
+# CONFIG_CIFS_STATS is not set
+# CONFIG_CIFS_XATTR is not set
+# CONFIG_CIFS_EXPERIMENTAL is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+# CONFIG_9P_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_LDM_PARTITION is not set
+CONFIG_SGI_PARTITION=y
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+CONFIG_EFI_PARTITION=y
+
+#
+# Native Language Support
+#
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_CODEPAGE_737=m
+CONFIG_NLS_CODEPAGE_775=m
+CONFIG_NLS_CODEPAGE_850=m
+CONFIG_NLS_CODEPAGE_852=m
+CONFIG_NLS_CODEPAGE_855=m
+CONFIG_NLS_CODEPAGE_857=m
+CONFIG_NLS_CODEPAGE_860=m
+CONFIG_NLS_CODEPAGE_861=m
+CONFIG_NLS_CODEPAGE_862=m
+CONFIG_NLS_CODEPAGE_863=m
+CONFIG_NLS_CODEPAGE_864=m
+CONFIG_NLS_CODEPAGE_865=m
+CONFIG_NLS_CODEPAGE_866=m
+CONFIG_NLS_CODEPAGE_869=m
+CONFIG_NLS_CODEPAGE_936=m
+CONFIG_NLS_CODEPAGE_950=m
+CONFIG_NLS_CODEPAGE_932=m
+CONFIG_NLS_CODEPAGE_949=m
+CONFIG_NLS_CODEPAGE_874=m
+CONFIG_NLS_ISO8859_8=m
+CONFIG_NLS_CODEPAGE_1250=m
+CONFIG_NLS_CODEPAGE_1251=m
+# CONFIG_NLS_ASCII is not set
+CONFIG_NLS_ISO8859_1=y
+CONFIG_NLS_ISO8859_2=m
+CONFIG_NLS_ISO8859_3=m
+CONFIG_NLS_ISO8859_4=m
+CONFIG_NLS_ISO8859_5=m
+CONFIG_NLS_ISO8859_6=m
+CONFIG_NLS_ISO8859_7=m
+CONFIG_NLS_ISO8859_9=m
+CONFIG_NLS_ISO8859_13=m
+CONFIG_NLS_ISO8859_14=m
+CONFIG_NLS_ISO8859_15=m
+CONFIG_NLS_KOI8_R=m
+CONFIG_NLS_KOI8_U=m
+CONFIG_NLS_UTF8=m
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_GENERIC_PENDING_IRQ=y
+
+#
+# HP Simulator drivers
+#
+# CONFIG_HP_SIMETH is not set
+# CONFIG_HP_SIMSERIAL is not set
+# CONFIG_HP_SIMSCSI is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_DEBUG_KERNEL=y
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_LOG_BUF_SHIFT=20
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_KOBJECT is not set
+# CONFIG_DEBUG_INFO is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_KPROBES is not set
+CONFIG_IA64_GRANULE_16MB=y
+# CONFIG_IA64_GRANULE_64MB is not set
+# CONFIG_IA64_PRINT_HAZARDS is not set
+# CONFIG_DISABLE_VHPT is not set
+# CONFIG_IA64_DEBUG_CMPXCHG is not set
+# CONFIG_IA64_DEBUG_IRQ is not set
+CONFIG_SYSVIPC_COMPAT=y
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+CONFIG_CRYPTO=y
+# CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_MD4 is not set
+CONFIG_CRYPTO_MD5=y
+# CONFIG_CRYPTO_SHA1 is not set
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_WP512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+CONFIG_CRYPTO_DES=m
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_AES is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_ARC4 is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Hardware crypto devices
+#
index d452e18..9bc8bca 100644 (file)
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.13-rc6-tiger-smp
-# Wed Aug 17 10:19:51 2005
+# Linux kernel version: 2.6.14-rc1
+# Wed Sep 14 15:17:57 2005
 #
 
 #
@@ -16,6 +16,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
@@ -27,6 +28,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=y
@@ -103,6 +105,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
 CONFIG_HAVE_DEC_LOCK=y
 CONFIG_IA32_SUPPORT=y
 CONFIG_COMPAT=y
@@ -115,6 +118,7 @@ CONFIG_IA64_PALINFO=y
 #
 CONFIG_EFI_VARS=y
 CONFIG_EFI_PCDP=y
+# CONFIG_DELL_RBU is not set
 CONFIG_BINFMT_ELF=y
 CONFIG_BINFMT_MISC=m
 
@@ -122,20 +126,27 @@ CONFIG_BINFMT_MISC=m
 # Power management and ACPI
 #
 CONFIG_PM=y
-CONFIG_ACPI=y
+# CONFIG_PM_DEBUG is not set
 
 #
 # ACPI (Advanced Configuration and Power Interface) Support
 #
+CONFIG_ACPI=y
 CONFIG_ACPI_BUTTON=m
 CONFIG_ACPI_FAN=m
 CONFIG_ACPI_PROCESSOR=m
-# CONFIG_ACPI_HOTPLUG_CPU is not set
+CONFIG_ACPI_HOTPLUG_CPU=y
 CONFIG_ACPI_THERMAL=m
+CONFIG_ACPI_BLACKLIST_YEAR=0
 # CONFIG_ACPI_DEBUG is not set
 CONFIG_ACPI_POWER=y
 CONFIG_ACPI_SYSTEM=y
-# CONFIG_ACPI_CONTAINER is not set
+CONFIG_ACPI_CONTAINER=m
+
+#
+# CPU Frequency scaling
+#
+# CONFIG_CPU_FREQ is not set
 
 #
 # Bus options (PCI, PCMCIA)
@@ -144,7 +155,6 @@ CONFIG_PCI=y
 CONFIG_PCI_DOMAINS=y
 # CONFIG_PCI_MSI is not set
 CONFIG_PCI_LEGACY_PROC=y
-CONFIG_PCI_NAMES=y
 # CONFIG_PCI_DEBUG is not set
 
 #
@@ -188,13 +198,18 @@ CONFIG_SYN_COOKIES=y
 # CONFIG_INET_ESP is not set
 # CONFIG_INET_IPCOMP is not set
 # CONFIG_INET_TUNNEL is not set
-CONFIG_IP_TCPDIAG=y
-# CONFIG_IP_TCPDIAG_IPV6 is not set
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
 # CONFIG_TCP_CONG_ADVANCED is not set
 CONFIG_TCP_CONG_BIC=y
 # CONFIG_IPV6 is not set
 # CONFIG_NETFILTER is not set
 
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
+
 #
 # SCTP Configuration (EXPERIMENTAL)
 #
@@ -218,9 +233,11 @@ CONFIG_TCP_CONG_BIC=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
 
 #
 # Device Drivers
@@ -234,6 +251,11 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y
 CONFIG_FW_LOADER=m
 # CONFIG_DEBUG_DRIVER is not set
 
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
+
 #
 # Memory Technology Devices (MTD)
 #
@@ -247,7 +269,13 @@ CONFIG_FW_LOADER=m
 #
 # Plug and Play support
 #
-# CONFIG_PNP is not set
+CONFIG_PNP=y
+# CONFIG_PNP_DEBUG is not set
+
+#
+# Protocols
+#
+CONFIG_PNPACPI=y
 
 #
 # Block devices
@@ -266,7 +294,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_CDROM_PKTCDVD is not set
 
 #
@@ -299,7 +326,8 @@ CONFIG_BLK_DEV_IDESCSI=m
 #
 # IDE chipset support/bugfixes
 #
-CONFIG_IDE_GENERIC=y
+# CONFIG_IDE_GENERIC is not set
+# CONFIG_BLK_DEV_IDEPNP is not set
 CONFIG_BLK_DEV_IDEPCI=y
 # CONFIG_IDEPCI_SHARE_IRQ is not set
 # CONFIG_BLK_DEV_OFFBOARD is not set
@@ -339,6 +367,7 @@ CONFIG_IDEDMA_AUTO=y
 #
 # SCSI device support
 #
+# CONFIG_RAID_ATTRS is not set
 CONFIG_SCSI=y
 CONFIG_SCSI_PROC_FS=y
 
@@ -366,6 +395,7 @@ CONFIG_CHR_DEV_SG=m
 CONFIG_SCSI_SPI_ATTRS=y
 CONFIG_SCSI_FC_ATTRS=y
 # CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_ATTRS is not set
 
 #
 # SCSI low-level drivers
@@ -454,12 +484,18 @@ CONFIG_DUMMY=m
 # CONFIG_BONDING is not set
 # CONFIG_EQUALIZER is not set
 # CONFIG_TUN is not set
+# CONFIG_NET_SB1000 is not set
 
 #
 # ARCnet devices
 #
 # CONFIG_ARCNET is not set
 
+#
+# PHY device support
+#
+# CONFIG_PHYLIB is not set
+
 #
 # Ethernet (10 or 100Mbit)
 #
@@ -481,6 +517,7 @@ CONFIG_TULIP=m
 # CONFIG_DE4X5 is not set
 # CONFIG_WINBOND_840 is not set
 # CONFIG_DM9102 is not set
+# CONFIG_ULI526X is not set
 # CONFIG_HP100 is not set
 CONFIG_NET_PCI=y
 # CONFIG_PCNET32 is not set
@@ -512,6 +549,7 @@ CONFIG_E1000=y
 # CONFIG_HAMACHI is not set
 # CONFIG_YELLOWFIN is not set
 # CONFIG_R8169 is not set
+# CONFIG_SIS190 is not set
 # CONFIG_SKGE is not set
 # CONFIG_SK98LIN is not set
 # CONFIG_VIA_VELOCITY is not set
@@ -521,6 +559,7 @@ CONFIG_TIGON3=y
 #
 # Ethernet (10000 Mbit)
 #
+# CONFIG_CHELSIO_T1 is not set
 # CONFIG_IXGB is not set
 # CONFIG_S2IO is not set
 
@@ -618,6 +657,7 @@ CONFIG_HW_CONSOLE=y
 CONFIG_SERIAL_NONSTANDARD=y
 # CONFIG_ROCKETPORT is not set
 # CONFIG_CYCLADES is not set
+# CONFIG_DIGIEPCA is not set
 # CONFIG_MOXA_SMARTIO is not set
 # CONFIG_ISI is not set
 # CONFIG_SYNCLINKMP is not set
@@ -675,6 +715,7 @@ CONFIG_DRM_RADEON=m
 CONFIG_DRM_MGA=m
 CONFIG_DRM_SIS=m
 # CONFIG_DRM_VIA is not set
+# CONFIG_DRM_SAVAGE is not set
 CONFIG_RAW_DRIVER=m
 CONFIG_HPET=y
 # CONFIG_HPET_RTC_IRQ is not set
@@ -691,7 +732,6 @@ CONFIG_MAX_RAW_DEVS=256
 # I2C support
 #
 # CONFIG_I2C is not set
-# CONFIG_I2C_SENSOR is not set
 
 #
 # Dallas's 1-wire bus
@@ -702,12 +742,17 @@ CONFIG_MAX_RAW_DEVS=256
 # Hardware Monitoring support
 #
 CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
 # CONFIG_HWMON_DEBUG_CHIP is not set
 
 #
 # Misc devices
 #
 
+#
+# Multimedia Capabilities Port drivers
+#
+
 #
 # Multimedia devices
 #
@@ -800,9 +845,11 @@ CONFIG_USB_HIDINPUT=y
 # CONFIG_USB_MTOUCH is not set
 # CONFIG_USB_ITMTOUCH is not set
 # CONFIG_USB_EGALAX is not set
+# CONFIG_USB_YEALINK is not set
 # CONFIG_USB_XPAD is not set
 # CONFIG_USB_ATI_REMOTE is not set
 # CONFIG_USB_KEYSPAN_REMOTE is not set
+# CONFIG_USB_APPLETOUCH is not set
 
 #
 # USB Imaging devices
@@ -902,16 +949,12 @@ CONFIG_REISERFS_FS_POSIX_ACL=y
 CONFIG_REISERFS_FS_SECURITY=y
 # CONFIG_JFS_FS is not set
 CONFIG_FS_POSIX_ACL=y
-
-#
-# XFS support
-#
 CONFIG_XFS_FS=y
 CONFIG_XFS_EXPORT=y
-# CONFIG_XFS_RT is not set
 # CONFIG_XFS_QUOTA is not set
 # CONFIG_XFS_SECURITY is not set
 # CONFIG_XFS_POSIX_ACL is not set
+# CONFIG_XFS_RT is not set
 # CONFIG_MINIX_FS is not set
 # CONFIG_ROMFS_FS is not set
 CONFIG_INOTIFY=y
@@ -919,6 +962,7 @@ CONFIG_INOTIFY=y
 CONFIG_DNOTIFY=y
 CONFIG_AUTOFS_FS=y
 CONFIG_AUTOFS4_FS=y
+# CONFIG_FUSE_FS is not set
 
 #
 # CD-ROM/DVD Filesystems
@@ -947,13 +991,11 @@ CONFIG_NTFS_FS=m
 CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
 CONFIG_SYSFS=y
-# CONFIG_DEVPTS_FS_XATTR is not set
 CONFIG_TMPFS=y
-CONFIG_TMPFS_XATTR=y
-CONFIG_TMPFS_SECURITY=y
 CONFIG_HUGETLBFS=y
 CONFIG_HUGETLB_PAGE=y
 CONFIG_RAMFS=y
+# CONFIG_RELAYFS_FS is not set
 
 #
 # Miscellaneous filesystems
@@ -1003,6 +1045,7 @@ CONFIG_CIFS=m
 # 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
@@ -1072,10 +1115,12 @@ CONFIG_NLS_UTF8=m
 # Library routines
 #
 # CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
 CONFIG_CRC32=y
 # CONFIG_LIBCRC32C is not set
 CONFIG_GENERIC_HARDIRQS=y
 CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_GENERIC_PENDING_IRQ=y
 
 #
 # Profiling support
@@ -1089,6 +1134,7 @@ CONFIG_GENERIC_IRQ_PROBE=y
 CONFIG_DEBUG_KERNEL=y
 CONFIG_MAGIC_SYSRQ=y
 CONFIG_LOG_BUF_SHIFT=20
+CONFIG_DETECT_SOFTLOCKUP=y
 # CONFIG_SCHEDSTATS is not set
 # CONFIG_DEBUG_SLAB is not set
 # CONFIG_DEBUG_SPINLOCK is not set
index 80b0e9e..0856ca6 100644 (file)
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.13-rc6
-# Wed Aug 17 10:02:43 2005
+# Linux kernel version: 2.6.14-rc1
+# Wed Sep 14 15:15:01 2005
 #
 
 #
@@ -18,6 +18,7 @@ CONFIG_INIT_ENV_ARG_LIMIT=32
 # General setup
 #
 CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
 CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
 # CONFIG_POSIX_MQUEUE is not set
@@ -29,6 +30,7 @@ CONFIG_HOTPLUG=y
 CONFIG_KOBJECT_UEVENT=y
 # CONFIG_IKCONFIG is not set
 # CONFIG_CPUSETS is not set
+CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_EMBEDDED is not set
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_ALL is not set
@@ -103,6 +105,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
 CONFIG_HAVE_DEC_LOCK=y
 CONFIG_IA32_SUPPORT=y
 CONFIG_COMPAT=y
@@ -115,6 +118,7 @@ CONFIG_IA64_PALINFO=y
 #
 CONFIG_EFI_VARS=y
 CONFIG_EFI_PCDP=y
+# CONFIG_DELL_RBU is not set
 CONFIG_BINFMT_ELF=y
 CONFIG_BINFMT_MISC=y
 
@@ -122,20 +126,27 @@ CONFIG_BINFMT_MISC=y
 # Power management and ACPI
 #
 CONFIG_PM=y
-CONFIG_ACPI=y
+# CONFIG_PM_DEBUG is not set
 
 #
 # ACPI (Advanced Configuration and Power Interface) Support
 #
+CONFIG_ACPI=y
 CONFIG_ACPI_BUTTON=y
 CONFIG_ACPI_FAN=y
 CONFIG_ACPI_PROCESSOR=y
 CONFIG_ACPI_THERMAL=y
+CONFIG_ACPI_BLACKLIST_YEAR=0
 # CONFIG_ACPI_DEBUG is not set
 CONFIG_ACPI_POWER=y
 CONFIG_ACPI_SYSTEM=y
 # CONFIG_ACPI_CONTAINER is not set
 
+#
+# CPU Frequency scaling
+#
+# CONFIG_CPU_FREQ is not set
+
 #
 # Bus options (PCI, PCMCIA)
 #
@@ -143,7 +154,6 @@ CONFIG_PCI=y
 CONFIG_PCI_DOMAINS=y
 # CONFIG_PCI_MSI is not set
 CONFIG_PCI_LEGACY_PROC=y
-CONFIG_PCI_NAMES=y
 # CONFIG_PCI_DEBUG is not set
 
 #
@@ -187,8 +197,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 is not set
-# CONFIG_IP_TCPDIAG_IPV6 is not set
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
 # CONFIG_TCP_CONG_ADVANCED is not set
 CONFIG_TCP_CONG_BIC=y
 
@@ -204,13 +214,17 @@ CONFIG_NETFILTER=y
 # IP: Netfilter Configuration
 #
 # CONFIG_IP_NF_CONNTRACK is not set
-# CONFIG_IP_NF_CONNTRACK_MARK is not set
 # CONFIG_IP_NF_QUEUE is not set
 # CONFIG_IP_NF_IPTABLES is not set
 CONFIG_IP_NF_ARPTABLES=y
 # CONFIG_IP_NF_ARPFILTER is not set
 # CONFIG_IP_NF_ARP_MANGLE is not set
 
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
+
 #
 # SCTP Configuration (EXPERIMENTAL)
 #
@@ -234,9 +248,11 @@ CONFIG_IP_NF_ARPTABLES=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
 
 #
 # Device Drivers
@@ -250,6 +266,11 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y
 # CONFIG_FW_LOADER is not set
 # CONFIG_DEBUG_DRIVER is not set
 
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
+
 #
 # Memory Technology Devices (MTD)
 #
@@ -263,7 +284,13 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y
 #
 # Plug and Play support
 #
-# CONFIG_PNP is not set
+CONFIG_PNP=y
+# CONFIG_PNP_DEBUG is not set
+
+#
+# Protocols
+#
+CONFIG_PNPACPI=y
 
 #
 # Block devices
@@ -282,7 +309,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_CDROM_PKTCDVD is not set
 
 #
@@ -315,7 +341,8 @@ CONFIG_BLK_DEV_IDECD=y
 #
 # IDE chipset support/bugfixes
 #
-CONFIG_IDE_GENERIC=y
+# CONFIG_IDE_GENERIC is not set
+# CONFIG_BLK_DEV_IDEPNP is not set
 CONFIG_BLK_DEV_IDEPCI=y
 CONFIG_IDEPCI_SHARE_IRQ=y
 # CONFIG_BLK_DEV_OFFBOARD is not set
@@ -354,6 +381,7 @@ CONFIG_BLK_DEV_IDEDMA=y
 #
 # SCSI device support
 #
+# CONFIG_RAID_ATTRS is not set
 CONFIG_SCSI=y
 CONFIG_SCSI_PROC_FS=y
 
@@ -381,6 +409,7 @@ CONFIG_SCSI_LOGGING=y
 CONFIG_SCSI_SPI_ATTRS=y
 # CONFIG_SCSI_FC_ATTRS is not set
 # CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_ATTRS is not set
 
 #
 # SCSI low-level drivers
@@ -457,12 +486,18 @@ CONFIG_DUMMY=y
 # CONFIG_BONDING is not set
 # CONFIG_EQUALIZER is not set
 # CONFIG_TUN is not set
+# CONFIG_NET_SB1000 is not set
 
 #
 # ARCnet devices
 #
 # CONFIG_ARCNET is not set
 
+#
+# PHY device support
+#
+# CONFIG_PHYLIB is not set
+
 #
 # Ethernet (10 or 100Mbit)
 #
@@ -485,6 +520,7 @@ CONFIG_TULIP_NAPI_HW_MITIGATION=y
 # CONFIG_DE4X5 is not set
 # CONFIG_WINBOND_840 is not set
 # CONFIG_DM9102 is not set
+# CONFIG_ULI526X is not set
 # CONFIG_HP100 is not set
 CONFIG_NET_PCI=y
 # CONFIG_PCNET32 is not set
@@ -516,6 +552,7 @@ CONFIG_E1000=y
 # CONFIG_HAMACHI is not set
 # CONFIG_YELLOWFIN is not set
 # CONFIG_R8169 is not set
+# CONFIG_SIS190 is not set
 # CONFIG_SKGE is not set
 # CONFIG_SK98LIN is not set
 # CONFIG_VIA_VELOCITY is not set
@@ -525,6 +562,7 @@ CONFIG_TIGON3=y
 #
 # Ethernet (10000 Mbit)
 #
+# CONFIG_CHELSIO_T1 is not set
 # CONFIG_IXGB is not set
 # CONFIG_S2IO is not set
 
@@ -650,12 +688,12 @@ CONFIG_AGP=y
 CONFIG_AGP_HP_ZX1=y
 CONFIG_DRM=y
 # CONFIG_DRM_TDFX is not set
-# CONFIG_DRM_GAMMA is not set
 # CONFIG_DRM_R128 is not set
 CONFIG_DRM_RADEON=y
 # CONFIG_DRM_MGA is not set
 # CONFIG_DRM_SIS is not set
 # CONFIG_DRM_VIA is not set
+# CONFIG_DRM_SAVAGE is not set
 # CONFIG_RAW_DRIVER is not set
 # CONFIG_HPET is not set
 # CONFIG_HANGCHECK_TIMER is not set
@@ -689,7 +727,6 @@ CONFIG_I2C_ALGOPCF=y
 # CONFIG_I2C_I801 is not set
 # CONFIG_I2C_I810 is not set
 # CONFIG_I2C_PIIX4 is not set
-# CONFIG_I2C_ISA is not set
 # CONFIG_I2C_NFORCE2 is not set
 # CONFIG_I2C_PARPORT_LIGHT is not set
 # CONFIG_I2C_PROSAVAGE is not set
@@ -703,7 +740,6 @@ CONFIG_I2C_ALGOPCF=y
 # CONFIG_I2C_VIAPRO is not set
 # CONFIG_I2C_VOODOO3 is not set
 # CONFIG_I2C_PCA_ISA is not set
-# CONFIG_I2C_SENSOR is not set
 
 #
 # Miscellaneous I2C Chip support
@@ -730,11 +766,16 @@ CONFIG_I2C_ALGOPCF=y
 # Hardware Monitoring support
 #
 # CONFIG_HWMON is not set
+# CONFIG_HWMON_VID is not set
 
 #
 # Misc devices
 #
 
+#
+# Multimedia Capabilities Port drivers
+#
+
 #
 # Multimedia devices
 #
@@ -806,6 +847,7 @@ CONFIG_FB_RADEON_DEBUG=y
 # CONFIG_FB_KYRO is not set
 # CONFIG_FB_3DFX is not set
 # CONFIG_FB_VOODOO1 is not set
+# CONFIG_FB_CYBLA is not set
 # CONFIG_FB_TRIDENT is not set
 # CONFIG_FB_PM3 is not set
 # CONFIG_FB_S1D13XXX is not set
@@ -862,11 +904,12 @@ CONFIG_SND_OPL3_LIB=y
 # CONFIG_SND_MTPAV is not set
 # CONFIG_SND_SERIAL_U16550 is not set
 # CONFIG_SND_MPU401 is not set
+CONFIG_SND_AC97_CODEC=y
+CONFIG_SND_AC97_BUS=y
 
 #
 # PCI devices
 #
-CONFIG_SND_AC97_CODEC=y
 # CONFIG_SND_ALI5451 is not set
 # CONFIG_SND_ATIIXP is not set
 # CONFIG_SND_ATIIXP_MODEM is not set
@@ -890,7 +933,7 @@ CONFIG_SND_AC97_CODEC=y
 # CONFIG_SND_HDSPM is not set
 # CONFIG_SND_TRIDENT is not set
 # CONFIG_SND_YMFPCI is not set
-# CONFIG_SND_ALS4000 is not set
+# CONFIG_SND_AD1889 is not set
 # CONFIG_SND_CMIPCI is not set
 # CONFIG_SND_ENS1370 is not set
 # CONFIG_SND_ENS1371 is not set
@@ -952,9 +995,8 @@ CONFIG_USB_UHCI_HCD=y
 #
 # USB Device Class drivers
 #
-# CONFIG_USB_AUDIO is not set
+# CONFIG_OBSOLETE_OSS_USB_DRIVER is not set
 # CONFIG_USB_BLUETOOTH_TTY is not set
-# CONFIG_USB_MIDI is not set
 # CONFIG_USB_ACM is not set
 # CONFIG_USB_PRINTER is not set
 
@@ -971,6 +1013,7 @@ CONFIG_USB_STORAGE=y
 # CONFIG_USB_STORAGE_SDDR09 is not set
 # CONFIG_USB_STORAGE_SDDR55 is not set
 # CONFIG_USB_STORAGE_JUMPSHOT is not set
+# CONFIG_USB_STORAGE_ONETOUCH is not set
 
 #
 # USB Input Devices
@@ -987,9 +1030,11 @@ CONFIG_USB_HIDDEV=y
 # CONFIG_USB_MTOUCH is not set
 # CONFIG_USB_ITMTOUCH is not set
 # CONFIG_USB_EGALAX is not set
+# CONFIG_USB_YEALINK is not set
 # CONFIG_USB_XPAD is not set
 # CONFIG_USB_ATI_REMOTE is not set
 # CONFIG_USB_KEYSPAN_REMOTE is not set
+# CONFIG_USB_APPLETOUCH is not set
 
 #
 # USB Imaging devices
@@ -1088,10 +1133,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
@@ -1100,6 +1141,7 @@ CONFIG_FS_MBCACHE=y
 CONFIG_DNOTIFY=y
 CONFIG_AUTOFS_FS=y
 # CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
 
 #
 # CD-ROM/DVD Filesystems
@@ -1126,13 +1168,11 @@ CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
 CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
 CONFIG_SYSFS=y
-# CONFIG_DEVPTS_FS_XATTR is not set
 CONFIG_TMPFS=y
-CONFIG_TMPFS_XATTR=y
-CONFIG_TMPFS_SECURITY=y
 CONFIG_HUGETLBFS=y
 CONFIG_HUGETLB_PAGE=y
 CONFIG_RAMFS=y
+# CONFIG_RELAYFS_FS is not set
 
 #
 # Miscellaneous filesystems
@@ -1177,6 +1217,7 @@ CONFIG_RPCSEC_GSS_KRB5=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
@@ -1246,10 +1287,12 @@ CONFIG_NLS_UTF8=y
 # Library routines
 #
 # CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
 CONFIG_CRC32=y
 # CONFIG_LIBCRC32C is not set
 CONFIG_GENERIC_HARDIRQS=y
 CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_GENERIC_PENDING_IRQ=y
 
 #
 # Profiling support
@@ -1263,6 +1306,7 @@ CONFIG_GENERIC_IRQ_PROBE=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_SPINLOCK is not set
index 5da2081..6e3f147 100644 (file)
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.12
-# Tue Jun 21 11:30:42 2005
+# Linux kernel version: 2.6.14-rc1
+# Wed Sep 14 15:13:03 2005
 #
 
 #
@@ -16,6 +16,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
@@ -27,6 +28,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=y
@@ -80,6 +82,10 @@ CONFIG_MCKINLEY=y
 # CONFIG_IA64_PAGE_SIZE_8KB is not set
 CONFIG_IA64_PAGE_SIZE_16KB=y
 # CONFIG_IA64_PAGE_SIZE_64KB is not set
+# CONFIG_HZ_100 is not set
+CONFIG_HZ_250=y
+# CONFIG_HZ_1000 is not set
+CONFIG_HZ=250
 CONFIG_IA64_L1_CACHE_SHIFT=7
 CONFIG_NUMA=y
 CONFIG_VIRTUAL_MEM_MAP=y
@@ -87,12 +93,21 @@ CONFIG_HOLES_IN_ZONE=y
 CONFIG_ARCH_DISCONTIGMEM_ENABLE=y
 CONFIG_IA64_CYCLONE=y
 CONFIG_IOSAPIC=y
+# CONFIG_IA64_SGI_SN_XP is not set
 CONFIG_FORCE_MAX_ZONEORDER=18
 CONFIG_SMP=y
 CONFIG_NR_CPUS=512
 CONFIG_HOTPLUG_CPU=y
 # CONFIG_SCHED_SMT is not set
 # CONFIG_PREEMPT is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+# CONFIG_FLATMEM_MANUAL is not set
+CONFIG_DISCONTIGMEM_MANUAL=y
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_DISCONTIGMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_NEED_MULTIPLE_NODES=y
+# CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_HAVE_DEC_LOCK=y
 CONFIG_IA32_SUPPORT=y
 CONFIG_COMPAT=y
@@ -105,6 +120,7 @@ CONFIG_IA64_PALINFO=y
 #
 CONFIG_EFI_VARS=y
 CONFIG_EFI_PCDP=y
+# CONFIG_DELL_RBU is not set
 CONFIG_BINFMT_ELF=y
 CONFIG_BINFMT_MISC=m
 
@@ -112,22 +128,29 @@ CONFIG_BINFMT_MISC=m
 # Power management and ACPI
 #
 CONFIG_PM=y
-CONFIG_ACPI=y
+# CONFIG_PM_DEBUG is not set
 
 #
 # ACPI (Advanced Configuration and Power Interface) Support
 #
+CONFIG_ACPI=y
 CONFIG_ACPI_BUTTON=m
 CONFIG_ACPI_FAN=m
 CONFIG_ACPI_PROCESSOR=m
 CONFIG_ACPI_HOTPLUG_CPU=y
 CONFIG_ACPI_THERMAL=m
 CONFIG_ACPI_NUMA=y
+CONFIG_ACPI_BLACKLIST_YEAR=0
 # CONFIG_ACPI_DEBUG is not set
 CONFIG_ACPI_POWER=y
 CONFIG_ACPI_SYSTEM=y
 CONFIG_ACPI_CONTAINER=m
 
+#
+# CPU Frequency scaling
+#
+# CONFIG_CPU_FREQ is not set
+
 #
 # Bus options (PCI, PCMCIA)
 #
@@ -135,7 +158,6 @@ CONFIG_PCI=y
 CONFIG_PCI_DOMAINS=y
 # CONFIG_PCI_MSI is not set
 CONFIG_PCI_LEGACY_PROC=y
-CONFIG_PCI_NAMES=y
 # CONFIG_PCI_DEBUG is not set
 
 #
@@ -147,12 +169,80 @@ CONFIG_HOTPLUG_PCI_ACPI=m
 # CONFIG_HOTPLUG_PCI_ACPI_IBM is not set
 # CONFIG_HOTPLUG_PCI_CPCI is not set
 # CONFIG_HOTPLUG_PCI_SHPC is not set
+# CONFIG_HOTPLUG_PCI_SGI is not set
 
 #
 # PCCARD (PCMCIA/CardBus) support
 #
 # CONFIG_PCCARD is not set
 
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+# CONFIG_IP_PNP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE is not set
+CONFIG_ARPD=y
+CONFIG_SYN_COOKIES=y
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_BIC=y
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP 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_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
+
 #
 # Device Drivers
 #
@@ -162,9 +252,14 @@ CONFIG_HOTPLUG_PCI_ACPI=m
 #
 CONFIG_STANDALONE=y
 CONFIG_PREVENT_FIRMWARE_BUILD=y
-# CONFIG_FW_LOADER is not set
+CONFIG_FW_LOADER=m
 # CONFIG_DEBUG_DRIVER is not set
 
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
+
 #
 # Memory Technology Devices (MTD)
 #
@@ -178,7 +273,13 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y
 #
 # Plug and Play support
 #
-# CONFIG_PNP is not set
+CONFIG_PNP=y
+# CONFIG_PNP_DEBUG is not set
+
+#
+# Protocols
+#
+CONFIG_PNPACPI=y
 
 #
 # Block devices
@@ -197,7 +298,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_CDROM_PKTCDVD is not set
 
 #
@@ -230,7 +330,8 @@ CONFIG_BLK_DEV_IDESCSI=m
 #
 # IDE chipset support/bugfixes
 #
-CONFIG_IDE_GENERIC=y
+# CONFIG_IDE_GENERIC is not set
+# CONFIG_BLK_DEV_IDEPNP is not set
 CONFIG_BLK_DEV_IDEPCI=y
 # CONFIG_IDEPCI_SHARE_IRQ is not set
 # CONFIG_BLK_DEV_OFFBOARD is not set
@@ -252,6 +353,7 @@ CONFIG_BLK_DEV_CMD64X=y
 # CONFIG_BLK_DEV_HPT366 is not set
 # CONFIG_BLK_DEV_SC1200 is not set
 CONFIG_BLK_DEV_PIIX=y
+# CONFIG_BLK_DEV_IT821X is not set
 # CONFIG_BLK_DEV_NS87415 is not set
 # CONFIG_BLK_DEV_PDC202XX_OLD is not set
 # CONFIG_BLK_DEV_PDC202XX_NEW is not set
@@ -270,6 +372,7 @@ CONFIG_IDEDMA_AUTO=y
 #
 # SCSI device support
 #
+# CONFIG_RAID_ATTRS is not set
 CONFIG_SCSI=y
 CONFIG_SCSI_PROC_FS=y
 
@@ -297,6 +400,7 @@ CONFIG_CHR_DEV_SG=m
 CONFIG_SCSI_SPI_ATTRS=y
 CONFIG_SCSI_FC_ATTRS=y
 # CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_ATTRS is not set
 
 #
 # SCSI low-level drivers
@@ -314,6 +418,7 @@ CONFIG_SCSI_SATA=y
 # CONFIG_SCSI_SATA_AHCI is not set
 # CONFIG_SCSI_SATA_SVW is not set
 # CONFIG_SCSI_ATA_PIIX is not set
+# CONFIG_SCSI_SATA_MV is not set
 # CONFIG_SCSI_SATA_NV is not set
 # CONFIG_SCSI_SATA_PROMISE is not set
 # CONFIG_SCSI_SATA_QSTOR is not set
@@ -335,7 +440,6 @@ CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64
 # CONFIG_SCSI_SYM53C8XX_IOMAPPED is not set
 # CONFIG_SCSI_IPR is not set
 # CONFIG_SCSI_QLOGIC_FC is not set
-# CONFIG_SCSI_QLOGIC_FC_FIRMWARE is not set
 CONFIG_SCSI_QLOGIC_1280=y
 # CONFIG_SCSI_QLOGIC_1280_1040 is not set
 CONFIG_SCSI_QLA2XXX=y
@@ -344,6 +448,7 @@ CONFIG_SCSI_QLA22XX=m
 CONFIG_SCSI_QLA2300=m
 CONFIG_SCSI_QLA2322=m
 # CONFIG_SCSI_QLA6312 is not set
+# CONFIG_SCSI_QLA24XX is not set
 # CONFIG_SCSI_LPFC is not set
 # CONFIG_SCSI_DC395x is not set
 # CONFIG_SCSI_DC390T is not set
@@ -390,80 +495,25 @@ CONFIG_FUSION_MAX_SGE=128
 # CONFIG_I2O is not set
 
 #
-# Networking support
-#
-CONFIG_NET=y
-
-#
-# Networking options
-#
-CONFIG_PACKET=y
-# CONFIG_PACKET_MMAP is not set
-CONFIG_UNIX=y
-# CONFIG_NET_KEY is not set
-CONFIG_INET=y
-CONFIG_IP_MULTICAST=y
-# CONFIG_IP_ADVANCED_ROUTER is not set
-# CONFIG_IP_PNP is not set
-# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE is not set
-# CONFIG_IP_MROUTE is not set
-CONFIG_ARPD=y
-CONFIG_SYN_COOKIES=y
-# CONFIG_INET_AH is not set
-# CONFIG_INET_ESP is not set
-# CONFIG_INET_IPCOMP is not set
-# CONFIG_INET_TUNNEL is not set
-CONFIG_IP_TCPDIAG=y
-# CONFIG_IP_TCPDIAG_IPV6 is not set
-# CONFIG_IPV6 is not set
-# CONFIG_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
-
+# Network device support
 #
-# QoS and/or fair queueing
-#
-# CONFIG_NET_SCHED is not set
-# CONFIG_NET_CLS_ROUTE is not set
-
-#
-# Network testing
-#
-# CONFIG_NET_PKTGEN is not set
-CONFIG_NETPOLL=y
-# CONFIG_NETPOLL_RX is not set
-# CONFIG_NETPOLL_TRAP is not set
-CONFIG_NET_POLL_CONTROLLER=y
-# CONFIG_HAMRADIO is not set
-# CONFIG_IRDA is not set
-# CONFIG_BT is not set
 CONFIG_NETDEVICES=y
 CONFIG_DUMMY=m
 # CONFIG_BONDING is not set
 # CONFIG_EQUALIZER is not set
 # CONFIG_TUN is not set
+# CONFIG_NET_SB1000 is not set
 
 #
 # ARCnet devices
 #
 # CONFIG_ARCNET is not set
 
+#
+# PHY device support
+#
+# CONFIG_PHYLIB is not set
+
 #
 # Ethernet (10 or 100Mbit)
 #
@@ -485,6 +535,7 @@ CONFIG_TULIP=m
 # CONFIG_DE4X5 is not set
 # CONFIG_WINBOND_840 is not set
 # CONFIG_DM9102 is not set
+# CONFIG_ULI526X is not set
 # CONFIG_HP100 is not set
 CONFIG_NET_PCI=y
 # CONFIG_PCNET32 is not set
@@ -516,6 +567,7 @@ CONFIG_E1000=y
 # CONFIG_HAMACHI is not set
 # CONFIG_YELLOWFIN is not set
 # CONFIG_R8169 is not set
+# CONFIG_SIS190 is not set
 # CONFIG_SKGE is not set
 # CONFIG_SK98LIN is not set
 # CONFIG_VIA_VELOCITY is not set
@@ -525,6 +577,7 @@ CONFIG_TIGON3=y
 #
 # Ethernet (10000 Mbit)
 #
+# CONFIG_CHELSIO_T1 is not set
 # CONFIG_IXGB is not set
 # CONFIG_S2IO is not set
 
@@ -549,6 +602,10 @@ CONFIG_TIGON3=y
 # CONFIG_NET_FC is not set
 # CONFIG_SHAPER is not set
 CONFIG_NETCONSOLE=y
+CONFIG_NETPOLL=y
+# CONFIG_NETPOLL_RX is not set
+# CONFIG_NETPOLL_TRAP is not set
+CONFIG_NET_POLL_CONTROLLER=y
 
 #
 # ISDN subsystem
@@ -607,9 +664,7 @@ CONFIG_GAMEPORT=m
 # CONFIG_GAMEPORT_NS558 is not set
 # CONFIG_GAMEPORT_L4 is not set
 # CONFIG_GAMEPORT_EMU10K1 is not set
-# CONFIG_GAMEPORT_VORTEX is not set
 # CONFIG_GAMEPORT_FM801 is not set
-# CONFIG_GAMEPORT_CS461X is not set
 
 #
 # Character devices
@@ -620,6 +675,7 @@ CONFIG_HW_CONSOLE=y
 CONFIG_SERIAL_NONSTANDARD=y
 # CONFIG_ROCKETPORT is not set
 # CONFIG_CYCLADES is not set
+# CONFIG_DIGIEPCA is not set
 # CONFIG_MOXA_SMARTIO is not set
 # CONFIG_ISI is not set
 # CONFIG_SYNCLINKMP is not set
@@ -641,7 +697,6 @@ CONFIG_SERIAL_8250_NR_UARTS=6
 CONFIG_SERIAL_8250_EXTENDED=y
 CONFIG_SERIAL_8250_SHARE_IRQ=y
 # CONFIG_SERIAL_8250_DETECT_IRQ is not set
-# CONFIG_SERIAL_8250_MULTIPORT is not set
 # CONFIG_SERIAL_8250_RSA is not set
 
 #
@@ -650,8 +705,8 @@ CONFIG_SERIAL_8250_SHARE_IRQ=y
 CONFIG_SERIAL_CORE=y
 CONFIG_SERIAL_CORE_CONSOLE=y
 CONFIG_SERIAL_SGI_L1_CONSOLE=y
-CONFIG_SERIAL_SGI_IOC4=y
 # CONFIG_SERIAL_JSM is not set
+CONFIG_SERIAL_SGI_IOC4=y
 CONFIG_UNIX98_PTYS=y
 CONFIG_LEGACY_PTYS=y
 CONFIG_LEGACY_PTY_COUNT=256
@@ -684,6 +739,8 @@ CONFIG_DRM_R128=m
 CONFIG_DRM_RADEON=m
 CONFIG_DRM_MGA=m
 CONFIG_DRM_SIS=m
+# CONFIG_DRM_VIA is not set
+# CONFIG_DRM_SAVAGE is not set
 CONFIG_RAW_DRIVER=m
 CONFIG_HPET=y
 # CONFIG_HPET_RTC_IRQ is not set
@@ -707,10 +764,21 @@ CONFIG_MMTIMER=y
 #
 # CONFIG_W1 is not set
 
+#
+# Hardware Monitoring support
+#
+CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
+
 #
 # Misc devices
 #
 
+#
+# Multimedia Capabilities Port drivers
+#
+
 #
 # Multimedia devices
 #
@@ -753,6 +821,7 @@ CONFIG_SND_PCM_OSS=m
 CONFIG_SND_SEQUENCER_OSS=y
 CONFIG_SND_VERBOSE_PRINTK=y
 # CONFIG_SND_DEBUG is not set
+CONFIG_SND_GENERIC_DRIVER=y
 
 #
 # Generic devices
@@ -764,11 +833,12 @@ CONFIG_SND_VIRMIDI=m
 CONFIG_SND_MTPAV=m
 CONFIG_SND_SERIAL_U16550=m
 CONFIG_SND_MPU401=m
+CONFIG_SND_AC97_CODEC=m
+CONFIG_SND_AC97_BUS=m
 
 #
 # PCI devices
 #
-CONFIG_SND_AC97_CODEC=m
 # CONFIG_SND_ALI5451 is not set
 # CONFIG_SND_ATIIXP is not set
 # CONFIG_SND_ATIIXP_MODEM is not set
@@ -790,9 +860,10 @@ CONFIG_SND_EMU10K1=m
 # CONFIG_SND_RME96 is not set
 # CONFIG_SND_RME9652 is not set
 # CONFIG_SND_HDSP is not set
+# CONFIG_SND_HDSPM is not set
 # CONFIG_SND_TRIDENT is not set
 # CONFIG_SND_YMFPCI is not set
-# CONFIG_SND_ALS4000 is not set
+# CONFIG_SND_AD1889 is not set
 # CONFIG_SND_CMIPCI is not set
 # CONFIG_SND_ENS1370 is not set
 # CONFIG_SND_ENS1371 is not set
@@ -844,6 +915,7 @@ CONFIG_USB_DEVICEFS=y
 CONFIG_USB_EHCI_HCD=m
 # CONFIG_USB_EHCI_SPLIT_ISO is not set
 # CONFIG_USB_EHCI_ROOT_HUB_TT is not set
+# CONFIG_USB_ISP116X_HCD is not set
 CONFIG_USB_OHCI_HCD=m
 # CONFIG_USB_OHCI_BIG_ENDIAN is not set
 CONFIG_USB_OHCI_LITTLE_ENDIAN=y
@@ -853,9 +925,8 @@ CONFIG_USB_UHCI_HCD=m
 #
 # USB Device Class drivers
 #
-# CONFIG_USB_AUDIO is not set
+# CONFIG_OBSOLETE_OSS_USB_DRIVER is not set
 # CONFIG_USB_BLUETOOTH_TTY is not set
-# CONFIG_USB_MIDI is not set
 # CONFIG_USB_ACM is not set
 # CONFIG_USB_PRINTER is not set
 
@@ -888,12 +959,17 @@ CONFIG_USB_HIDINPUT=y
 # CONFIG_USB_MOUSE is not set
 # CONFIG_USB_AIPTEK is not set
 # CONFIG_USB_WACOM is not set
+# CONFIG_USB_ACECAD is not set
 # CONFIG_USB_KBTAB is not set
 # CONFIG_USB_POWERMATE is not set
 # CONFIG_USB_MTOUCH is not set
+# CONFIG_USB_ITMTOUCH is not set
 # CONFIG_USB_EGALAX is not set
+# CONFIG_USB_YEALINK is not set
 # CONFIG_USB_XPAD is not set
 # CONFIG_USB_ATI_REMOTE is not set
+# CONFIG_USB_KEYSPAN_REMOTE is not set
+# CONFIG_USB_APPLETOUCH is not set
 
 #
 # USB Imaging devices
@@ -918,7 +994,7 @@ CONFIG_USB_HIDINPUT=y
 # CONFIG_USB_PEGASUS is not set
 # CONFIG_USB_RTL8150 is not set
 # CONFIG_USB_USBNET is not set
-CONFIG_USB_MON=m
+CONFIG_USB_MON=y
 
 #
 # USB port drivers
@@ -944,10 +1020,11 @@ CONFIG_USB_MON=m
 # CONFIG_USB_PHIDGETSERVO is not set
 # CONFIG_USB_IDMOUSE is not set
 # CONFIG_USB_SISUSBVGA is not set
+# CONFIG_USB_LD is not set
 # CONFIG_USB_TEST is not set
 
 #
-# USB ATM/DSL drivers
+# USB DSL modem support
 #
 
 #
@@ -964,6 +1041,8 @@ CONFIG_USB_MON=m
 # InfiniBand support
 #
 CONFIG_INFINIBAND=m
+# CONFIG_INFINIBAND_USER_MAD is not set
+# CONFIG_INFINIBAND_USER_ACCESS is not set
 CONFIG_INFINIBAND_MTHCA=m
 # CONFIG_INFINIBAND_MTHCA_DEBUG is not set
 CONFIG_INFINIBAND_IPOIB=m
@@ -981,6 +1060,7 @@ CONFIG_EXT2_FS=y
 CONFIG_EXT2_FS_XATTR=y
 CONFIG_EXT2_FS_POSIX_ACL=y
 CONFIG_EXT2_FS_SECURITY=y
+# CONFIG_EXT2_FS_XIP is not set
 CONFIG_EXT3_FS=y
 CONFIG_EXT3_FS_XATTR=y
 CONFIG_EXT3_FS_POSIX_ACL=y
@@ -996,22 +1076,20 @@ CONFIG_REISERFS_FS_POSIX_ACL=y
 CONFIG_REISERFS_FS_SECURITY=y
 # CONFIG_JFS_FS is not set
 CONFIG_FS_POSIX_ACL=y
-
-#
-# XFS support
-#
 CONFIG_XFS_FS=y
 CONFIG_XFS_EXPORT=y
-# CONFIG_XFS_RT is not set
 # CONFIG_XFS_QUOTA is not set
 # CONFIG_XFS_SECURITY is not set
 # CONFIG_XFS_POSIX_ACL is not set
+# CONFIG_XFS_RT 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=y
 CONFIG_AUTOFS4_FS=y
+# CONFIG_FUSE_FS is not set
 
 #
 # CD-ROM/DVD Filesystems
@@ -1040,14 +1118,11 @@ CONFIG_NTFS_FS=m
 CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
 CONFIG_SYSFS=y
-# CONFIG_DEVFS_FS is not set
-# CONFIG_DEVPTS_FS_XATTR is not set
 CONFIG_TMPFS=y
-CONFIG_TMPFS_XATTR=y
-CONFIG_TMPFS_SECURITY=y
 CONFIG_HUGETLBFS=y
 CONFIG_HUGETLB_PAGE=y
 CONFIG_RAMFS=y
+# CONFIG_RELAYFS_FS is not set
 
 #
 # Miscellaneous filesystems
@@ -1071,15 +1146,18 @@ CONFIG_RAMFS=y
 #
 CONFIG_NFS_FS=m
 CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
 CONFIG_NFS_V4=y
 CONFIG_NFS_DIRECTIO=y
 CONFIG_NFSD=m
 CONFIG_NFSD_V3=y
+# CONFIG_NFSD_V3_ACL is not set
 CONFIG_NFSD_V4=y
 CONFIG_NFSD_TCP=y
 CONFIG_LOCKD=m
 CONFIG_LOCKD_V4=y
 CONFIG_EXPORTFS=y
+CONFIG_NFS_COMMON=y
 CONFIG_SUNRPC=m
 CONFIG_SUNRPC_GSS=m
 CONFIG_RPCSEC_GSS_KRB5=m
@@ -1094,6 +1172,7 @@ CONFIG_CIFS=m
 # 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
@@ -1163,10 +1242,12 @@ CONFIG_NLS_UTF8=m
 # Library routines
 #
 # CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
 CONFIG_CRC32=y
 # CONFIG_LIBCRC32C is not set
 CONFIG_GENERIC_HARDIRQS=y
 CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_GENERIC_PENDING_IRQ=y
 
 #
 # HP Simulator drivers
@@ -1187,6 +1268,7 @@ CONFIG_GENERIC_IRQ_PROBE=y
 CONFIG_DEBUG_KERNEL=y
 CONFIG_MAGIC_SYSRQ=y
 CONFIG_LOG_BUF_SHIFT=20
+CONFIG_DETECT_SOFTLOCKUP=y
 # CONFIG_SCHEDSTATS is not set
 # CONFIG_DEBUG_SLAB is not set
 # CONFIG_DEBUG_SPINLOCK is not set
@@ -1194,6 +1276,7 @@ CONFIG_LOG_BUF_SHIFT=20
 # CONFIG_DEBUG_KOBJECT is not set
 # CONFIG_DEBUG_INFO is not set
 # CONFIG_DEBUG_FS is not set
+# CONFIG_KPROBES is not set
 CONFIG_IA64_GRANULE_16MB=y
 # CONFIG_IA64_GRANULE_64MB is not set
 # CONFIG_IA64_PRINT_HAZARDS is not set
@@ -1215,7 +1298,7 @@ CONFIG_CRYPTO=y
 # CONFIG_CRYPTO_HMAC is not set
 # CONFIG_CRYPTO_NULL is not set
 # CONFIG_CRYPTO_MD4 is not set
-CONFIG_CRYPTO_MD5=m
+CONFIG_CRYPTO_MD5=y
 # CONFIG_CRYPTO_SHA1 is not set
 # CONFIG_CRYPTO_SHA256 is not set
 # CONFIG_CRYPTO_SHA512 is not set
index 1ba02ba..a5a5637 100644 (file)
@@ -17,7 +17,7 @@
 #include <asm/machvec.h>
 
 /* swiotlb declarations & definitions: */
-extern void swiotlb_init_with_default_size (size_t size);
+extern int swiotlb_late_init_with_default_size (size_t size);
 extern ia64_mv_dma_alloc_coherent      swiotlb_alloc_coherent;
 extern ia64_mv_dma_free_coherent       swiotlb_free_coherent;
 extern ia64_mv_dma_map_single          swiotlb_map_single;
@@ -67,7 +67,16 @@ void
 hwsw_init (void)
 {
        /* default to a smallish 2MB sw I/O TLB */
-       swiotlb_init_with_default_size (2 * (1<<20));
+       if (swiotlb_late_init_with_default_size (2 * (1<<20)) != 0) {
+#ifdef CONFIG_IA64_GENERIC
+               /* Better to have normal DMA than panic */
+               printk(KERN_WARNING "%s: Failed to initialize software I/O TLB,"
+                      " reverting to hpzx1 platform vector\n", __FUNCTION__);
+               machvec_init("hpzx1");
+#else
+               panic("Unable to initialize software I/O TLB services");
+#endif
+       }
 }
 
 void *
index 21bffba..bdccd0b 100644 (file)
@@ -2028,9 +2028,40 @@ static struct acpi_driver acpi_sba_ioc_driver = {
 static int __init
 sba_init(void)
 {
+       if (!ia64_platform_is("hpzx1") && !ia64_platform_is("hpzx1_swiotlb"))
+               return 0;
+
        acpi_bus_register_driver(&acpi_sba_ioc_driver);
-       if (!ioc_list)
+       if (!ioc_list) {
+#ifdef CONFIG_IA64_GENERIC
+               extern int swiotlb_late_init_with_default_size (size_t size);
+
+               /*
+                * If we didn't find something sba_iommu can claim, we
+                * need to setup the swiotlb and switch to the dig machvec.
+                */
+               if (swiotlb_late_init_with_default_size(64 * (1<<20)) != 0)
+                       panic("Unable to find SBA IOMMU or initialize "
+                             "software I/O TLB: Try machvec=dig boot option");
+               machvec_init("dig");
+#else
+               panic("Unable to find SBA IOMMU: Try a generic or DIG kernel");
+#endif
                return 0;
+       }
+
+#if defined(CONFIG_IA64_GENERIC) || defined(CONFIG_IA64_HP_ZX1_SWIOTLB)
+       /*
+        * hpzx1_swiotlb needs to have a fairly small swiotlb bounce
+        * buffer setup to support devices with smaller DMA masks than
+        * sba_iommu can handle.
+        */
+       if (ia64_platform_is("hpzx1_swiotlb")) {
+               extern void hwsw_init(void);
+
+               hwsw_init();
+       }
+#endif
 
 #ifdef CONFIG_PCI
        {
@@ -2048,18 +2079,6 @@ sba_init(void)
 
 subsys_initcall(sba_init); /* must be initialized after ACPI etc., but before any drivers... */
 
-extern void dig_setup(char**);
-/*
- * MAX_DMA_ADDRESS needs to be setup prior to paging_init to do any good,
- * so we use the platform_setup hook to fix it up.
- */
-void __init
-sba_setup(char **cmdline_p)
-{
-       MAX_DMA_ADDRESS = ~0UL;
-       dig_setup(cmdline_p);
-}
-
 static int __init
 nosbagart(char *str)
 {
index a18983a..a3fe975 100644 (file)
@@ -205,10 +205,11 @@ simscsi_get_disk_size (int fd)
        char buf[512];
 
        /*
-        * This is a bit kludgey: the simulator doesn't provide a direct way of determining
-        * the disk size, so we do a binary search, assuming a maximum disk size of 4GB.
+        * This is a bit kludgey: the simulator doesn't provide a
+        * direct way of determining the disk size, so we do a binary
+        * search, assuming a maximum disk size of 128GB.
         */
-       for (bit = (4UL << 30)/512; bit != 0; bit >>= 1) {
+       for (bit = (128UL << 30)/512; bit != 0; bit >>= 1) {
                req.addr = __pa(&buf);
                req.len = sizeof(buf);
                ia64_ssc(fd, 1, __pa(&req), ((sectors | bit) - 1)*512, SSC_READ);
@@ -225,8 +226,10 @@ simscsi_readwrite10 (struct scsi_cmnd *sc, int mode)
 {
        unsigned long offset;
 
-       offset = (  (sc->cmnd[2] << 24) | (sc->cmnd[3] << 16)
-                 | (sc->cmnd[4] <<  8) | (sc->cmnd[5] <<  0))*512;
+       offset = (((unsigned long)sc->cmnd[2] << 24) 
+               | ((unsigned long)sc->cmnd[3] << 16)
+               | ((unsigned long)sc->cmnd[4] <<  8) 
+               | ((unsigned long)sc->cmnd[5] <<  0))*512UL;
        if (sc->use_sg > 0)
                simscsi_sg_readwrite(sc, mode, offset);
        else
index 7e92647..9ad94dd 100644 (file)
@@ -838,7 +838,7 @@ EXPORT_SYMBOL(acpi_unmap_lsapic);
 #endif                         /* CONFIG_ACPI_HOTPLUG_CPU */
 
 #ifdef CONFIG_ACPI_NUMA
-acpi_status __devinit
+static acpi_status __devinit
 acpi_map_iosapic(acpi_handle handle, u32 depth, void *context, void **ret)
 {
        struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
@@ -890,7 +890,16 @@ acpi_map_iosapic(acpi_handle handle, u32 depth, void *context, void **ret)
        map_iosapic_to_node(gsi_base, node);
        return AE_OK;
 }
-#endif                         /* CONFIG_NUMA */
+
+static int __init
+acpi_map_iosapics (void)
+{
+       acpi_get_devices(NULL, acpi_map_iosapic, NULL, NULL);
+       return 0;
+}
+
+fs_initcall(acpi_map_iosapics);
+#endif                         /* CONFIG_ACPI_NUMA */
 
 int acpi_register_ioapic(acpi_handle handle, u64 phys_addr, u32 gsi_base)
 {
index 179f230..f72ea6a 100644 (file)
@@ -239,57 +239,30 @@ is_available_memory (efi_memory_desc_t *md)
        return 0;
 }
 
-/*
- * Trim descriptor MD so its starts at address START_ADDR.  If the descriptor covers
- * memory that is normally available to the kernel, issue a warning that some memory
- * is being ignored.
- */
-static void
-trim_bottom (efi_memory_desc_t *md, u64 start_addr)
-{
-       u64 num_skipped_pages;
+typedef struct kern_memdesc {
+       u64 attribute;
+       u64 start;
+       u64 num_pages;
+} kern_memdesc_t;
 
-       if (md->phys_addr >= start_addr || !md->num_pages)
-               return;
-
-       num_skipped_pages = (start_addr - md->phys_addr) >> EFI_PAGE_SHIFT;
-       if (num_skipped_pages > md->num_pages)
-               num_skipped_pages = md->num_pages;
-
-       if (is_available_memory(md))
-               printk(KERN_NOTICE "efi.%s: ignoring %luKB of memory at 0x%lx due to granule hole "
-                      "at 0x%lx\n", __FUNCTION__,
-                      (num_skipped_pages << EFI_PAGE_SHIFT) >> 10,
-                      md->phys_addr, start_addr - IA64_GRANULE_SIZE);
-       /*
-        * NOTE: Don't set md->phys_addr to START_ADDR because that could cause the memory
-        * descriptor list to become unsorted.  In such a case, md->num_pages will be
-        * zero, so the Right Thing will happen.
-        */
-       md->phys_addr += num_skipped_pages << EFI_PAGE_SHIFT;
-       md->num_pages -= num_skipped_pages;
-}
+static kern_memdesc_t *kern_memmap;
 
 static void
-trim_top (efi_memory_desc_t *md, u64 end_addr)
+walk (efi_freemem_callback_t callback, void *arg, u64 attr)
 {
-       u64 num_dropped_pages, md_end_addr;
-
-       md_end_addr = md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT);
-
-       if (md_end_addr <= end_addr || !md->num_pages)
-               return;
+       kern_memdesc_t *k;
+       u64 start, end, voff;
 
-       num_dropped_pages = (md_end_addr - end_addr) >> EFI_PAGE_SHIFT;
-       if (num_dropped_pages > md->num_pages)
-               num_dropped_pages = md->num_pages;
-
-       if (is_available_memory(md))
-               printk(KERN_NOTICE "efi.%s: ignoring %luKB of memory at 0x%lx due to granule hole "
-                      "at 0x%lx\n", __FUNCTION__,
-                      (num_dropped_pages << EFI_PAGE_SHIFT) >> 10,
-                      md->phys_addr, end_addr);
-       md->num_pages -= num_dropped_pages;
+       voff = (attr == EFI_MEMORY_WB) ? PAGE_OFFSET : __IA64_UNCACHED_OFFSET;
+       for (k = kern_memmap; k->start != ~0UL; k++) {
+               if (k->attribute != attr)
+                       continue;
+               start = PAGE_ALIGN(k->start);
+               end = (k->start + (k->num_pages << EFI_PAGE_SHIFT)) & PAGE_MASK;
+               if (start < end)
+                       if ((*callback)(start + voff, end + voff, arg) < 0)
+                               return;
+       }
 }
 
 /*
@@ -299,148 +272,19 @@ trim_top (efi_memory_desc_t *md, u64 end_addr)
 void
 efi_memmap_walk (efi_freemem_callback_t callback, void *arg)
 {
-       int prev_valid = 0;
-       struct range {
-               u64 start;
-               u64 end;
-       } prev, curr;
-       void *efi_map_start, *efi_map_end, *p, *q;
-       efi_memory_desc_t *md, *check_md;
-       u64 efi_desc_size, start, end, granule_addr, last_granule_addr, first_non_wb_addr = 0;
-       unsigned long total_mem = 0;
-
-       efi_map_start = __va(ia64_boot_param->efi_memmap);
-       efi_map_end   = efi_map_start + ia64_boot_param->efi_memmap_size;
-       efi_desc_size = ia64_boot_param->efi_memdesc_size;
-
-       for (p = efi_map_start; p < efi_map_end; p += efi_desc_size) {
-               md = p;
-
-               /* skip over non-WB memory descriptors; that's all we're interested in... */
-               if (!(md->attribute & EFI_MEMORY_WB))
-                       continue;
-
-               /*
-                * granule_addr is the base of md's first granule.
-                * [granule_addr - first_non_wb_addr) is guaranteed to
-                * be contiguous WB memory.
-                */
-               granule_addr = GRANULEROUNDDOWN(md->phys_addr);
-               first_non_wb_addr = max(first_non_wb_addr, granule_addr);
-
-               if (first_non_wb_addr < md->phys_addr) {
-                       trim_bottom(md, granule_addr + IA64_GRANULE_SIZE);
-                       granule_addr = GRANULEROUNDDOWN(md->phys_addr);
-                       first_non_wb_addr = max(first_non_wb_addr, granule_addr);
-               }
-
-               for (q = p; q < efi_map_end; q += efi_desc_size) {
-                       check_md = q;
-
-                       if ((check_md->attribute & EFI_MEMORY_WB) &&
-                           (check_md->phys_addr == first_non_wb_addr))
-                               first_non_wb_addr += check_md->num_pages << EFI_PAGE_SHIFT;
-                       else
-                               break;          /* non-WB or hole */
-               }
-
-               last_granule_addr = GRANULEROUNDDOWN(first_non_wb_addr);
-               if (last_granule_addr < md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT))
-                       trim_top(md, last_granule_addr);
-
-               if (is_available_memory(md)) {
-                       if (md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT) >= max_addr) {
-                               if (md->phys_addr >= max_addr)
-                                       continue;
-                               md->num_pages = (max_addr - md->phys_addr) >> EFI_PAGE_SHIFT;
-                               first_non_wb_addr = max_addr;
-                       }
-
-                       if (total_mem >= mem_limit)
-                               continue;
-
-                       if (total_mem + (md->num_pages << EFI_PAGE_SHIFT) > mem_limit) {
-                               unsigned long limit_addr = md->phys_addr;
-
-                               limit_addr += mem_limit - total_mem;
-                               limit_addr = GRANULEROUNDDOWN(limit_addr);
-
-                               if (md->phys_addr > limit_addr)
-                                       continue;
-
-                               md->num_pages = (limit_addr - md->phys_addr) >>
-                                               EFI_PAGE_SHIFT;
-                               first_non_wb_addr = max_addr = md->phys_addr +
-                                             (md->num_pages << EFI_PAGE_SHIFT);
-                       }
-                       total_mem += (md->num_pages << EFI_PAGE_SHIFT);
-
-                       if (md->num_pages == 0)
-                               continue;
-
-                       curr.start = PAGE_OFFSET + md->phys_addr;
-                       curr.end   = curr.start + (md->num_pages << EFI_PAGE_SHIFT);
-
-                       if (!prev_valid) {
-                               prev = curr;
-                               prev_valid = 1;
-                       } else {
-                               if (curr.start < prev.start)
-                                       printk(KERN_ERR "Oops: EFI memory table not ordered!\n");
-
-                               if (prev.end == curr.start) {
-                                       /* merge two consecutive memory ranges */
-                                       prev.end = curr.end;
-                               } else {
-                                       start = PAGE_ALIGN(prev.start);
-                                       end = prev.end & PAGE_MASK;
-                                       if ((end > start) && (*callback)(start, end, arg) < 0)
-                                               return;
-                                       prev = curr;
-                               }
-                       }
-               }
-       }
-       if (prev_valid) {
-               start = PAGE_ALIGN(prev.start);
-               end = prev.end & PAGE_MASK;
-               if (end > start)
-                       (*callback)(start, end, arg);
-       }
+       walk(callback, arg, EFI_MEMORY_WB);
 }
 
 /*
- * Walk the EFI memory map to pull out leftover pages in the lower
- * memory regions which do not end up in the regular memory map and
- * stick them into the uncached allocator
- *
- * The regular walk function is significantly more complex than the
- * uncached walk which means it really doesn't make sense to try and
- * marge the two.
+ * Walks the EFI memory map and calls CALLBACK once for each EFI memory descriptor that
+ * has memory that is available for uncached allocator.
  */
-void __init
-efi_memmap_walk_uc (efi_freemem_callback_t callback)
+void
+efi_memmap_walk_uc (efi_freemem_callback_t callback, void *arg)
 {
-       void *efi_map_start, *efi_map_end, *p;
-       efi_memory_desc_t *md;
-       u64 efi_desc_size, start, end;
-
-       efi_map_start = __va(ia64_boot_param->efi_memmap);
-       efi_map_end = efi_map_start + ia64_boot_param->efi_memmap_size;
-       efi_desc_size = ia64_boot_param->efi_memdesc_size;
-
-       for (p = efi_map_start; p < efi_map_end; p += efi_desc_size) {
-               md = p;
-               if (md->attribute == EFI_MEMORY_UC) {
-                       start = PAGE_ALIGN(md->phys_addr);
-                       end = PAGE_ALIGN((md->phys_addr+(md->num_pages << EFI_PAGE_SHIFT)) & PAGE_MASK);
-                       if ((*callback)(start, end, NULL) < 0)
-                               return;
-               }
-       }
+       walk(callback, arg, EFI_MEMORY_UC);
 }
 
-
 /*
  * Look for the PAL_CODE region reported by EFI and maps it using an
  * ITR to enable safe PAL calls in virtual mode.  See IA-64 Processor
@@ -862,3 +706,307 @@ efi_uart_console_only(void)
        printk(KERN_ERR "Malformed %s value\n", name);
        return 0;
 }
+
+#define efi_md_size(md)        (md->num_pages << EFI_PAGE_SHIFT)
+
+static inline u64
+kmd_end(kern_memdesc_t *kmd)
+{
+       return (kmd->start + (kmd->num_pages << EFI_PAGE_SHIFT));
+}
+
+static inline u64
+efi_md_end(efi_memory_desc_t *md)
+{
+       return (md->phys_addr + efi_md_size(md));
+}
+
+static inline int
+efi_wb(efi_memory_desc_t *md)
+{
+       return (md->attribute & EFI_MEMORY_WB);
+}
+
+static inline int
+efi_uc(efi_memory_desc_t *md)
+{
+       return (md->attribute & EFI_MEMORY_UC);
+}
+
+/*
+ * Look for the first granule aligned memory descriptor memory
+ * that is big enough to hold EFI memory map. Make sure this
+ * descriptor is atleast granule sized so it does not get trimmed
+ */
+struct kern_memdesc *
+find_memmap_space (void)
+{
+       u64     contig_low=0, contig_high=0;
+       u64     as = 0, ae;
+       void *efi_map_start, *efi_map_end, *p, *q;
+       efi_memory_desc_t *md, *pmd = NULL, *check_md;
+       u64     space_needed, efi_desc_size;
+       unsigned long total_mem = 0;
+
+       efi_map_start = __va(ia64_boot_param->efi_memmap);
+       efi_map_end   = efi_map_start + ia64_boot_param->efi_memmap_size;
+       efi_desc_size = ia64_boot_param->efi_memdesc_size;
+
+       /*
+        * Worst case: we need 3 kernel descriptors for each efi descriptor
+        * (if every entry has a WB part in the middle, and UC head and tail),
+        * plus one for the end marker.
+        */
+       space_needed = sizeof(kern_memdesc_t) *
+               (3 * (ia64_boot_param->efi_memmap_size/efi_desc_size) + 1);
+
+       for (p = efi_map_start; p < efi_map_end; pmd = md, p += efi_desc_size) {
+               md = p;
+               if (!efi_wb(md)) {
+                       continue;
+               }
+               if (pmd == NULL || !efi_wb(pmd) || efi_md_end(pmd) != md->phys_addr) {
+                       contig_low = GRANULEROUNDUP(md->phys_addr);
+                       contig_high = efi_md_end(md);
+                       for (q = p + efi_desc_size; q < efi_map_end; q += efi_desc_size) {
+                               check_md = q;
+                               if (!efi_wb(check_md))
+                                       break;
+                               if (contig_high != check_md->phys_addr)
+                                       break;
+                               contig_high = efi_md_end(check_md);
+                       }
+                       contig_high = GRANULEROUNDDOWN(contig_high);
+               }
+               if (!is_available_memory(md) || md->type == EFI_LOADER_DATA)
+                       continue;
+
+               /* Round ends inward to granule boundaries */
+               as = max(contig_low, md->phys_addr);
+               ae = min(contig_high, efi_md_end(md));
+
+               /* keep within max_addr= command line arg */
+               ae = min(ae, max_addr);
+               if (ae <= as)
+                       continue;
+
+               /* avoid going over mem= command line arg */
+               if (total_mem + (ae - as) > mem_limit)
+                       ae -= total_mem + (ae - as) - mem_limit;
+
+               if (ae <= as)
+                       continue;
+
+               if (ae - as > space_needed)
+                       break;
+       }
+       if (p >= efi_map_end)
+               panic("Can't allocate space for kernel memory descriptors");
+
+       return __va(as);
+}
+
+/*
+ * Walk the EFI memory map and gather all memory available for kernel
+ * to use.  We can allocate partial granules only if the unavailable
+ * parts exist, and are WB.
+ */
+void
+efi_memmap_init(unsigned long *s, unsigned long *e)
+{
+       struct kern_memdesc *k, *prev = 0;
+       u64     contig_low=0, contig_high=0;
+       u64     as, ae, lim;
+       void *efi_map_start, *efi_map_end, *p, *q;
+       efi_memory_desc_t *md, *pmd = NULL, *check_md;
+       u64     efi_desc_size;
+       unsigned long total_mem = 0;
+
+       k = kern_memmap = find_memmap_space();
+
+       efi_map_start = __va(ia64_boot_param->efi_memmap);
+       efi_map_end   = efi_map_start + ia64_boot_param->efi_memmap_size;
+       efi_desc_size = ia64_boot_param->efi_memdesc_size;
+
+       for (p = efi_map_start; p < efi_map_end; pmd = md, p += efi_desc_size) {
+               md = p;
+               if (!efi_wb(md)) {
+                       if (efi_uc(md) && (md->type == EFI_CONVENTIONAL_MEMORY ||
+                                          md->type == EFI_BOOT_SERVICES_DATA)) {
+                               k->attribute = EFI_MEMORY_UC;
+                               k->start = md->phys_addr;
+                               k->num_pages = md->num_pages;
+                               k++;
+                       }
+                       continue;
+               }
+               if (pmd == NULL || !efi_wb(pmd) || efi_md_end(pmd) != md->phys_addr) {
+                       contig_low = GRANULEROUNDUP(md->phys_addr);
+                       contig_high = efi_md_end(md);
+                       for (q = p + efi_desc_size; q < efi_map_end; q += efi_desc_size) {
+                               check_md = q;
+                               if (!efi_wb(check_md))
+                                       break;
+                               if (contig_high != check_md->phys_addr)
+                                       break;
+                               contig_high = efi_md_end(check_md);
+                       }
+                       contig_high = GRANULEROUNDDOWN(contig_high);
+               }
+               if (!is_available_memory(md))
+                       continue;
+
+               /*
+                * Round ends inward to granule boundaries
+                * Give trimmings to uncached allocator
+                */
+               if (md->phys_addr < contig_low) {
+                       lim = min(efi_md_end(md), contig_low);
+                       if (efi_uc(md)) {
+                               if (k > kern_memmap && (k-1)->attribute == EFI_MEMORY_UC &&
+                                   kmd_end(k-1) == md->phys_addr) {
+                                       (k-1)->num_pages += (lim - md->phys_addr) >> EFI_PAGE_SHIFT;
+                               } else {
+                                       k->attribute = EFI_MEMORY_UC;
+                                       k->start = md->phys_addr;
+                                       k->num_pages = (lim - md->phys_addr) >> EFI_PAGE_SHIFT;
+                                       k++;
+                               }
+                       }
+                       as = contig_low;
+               } else
+                       as = md->phys_addr;
+
+               if (efi_md_end(md) > contig_high) {
+                       lim = max(md->phys_addr, contig_high);
+                       if (efi_uc(md)) {
+                               if (lim == md->phys_addr && k > kern_memmap &&
+                                   (k-1)->attribute == EFI_MEMORY_UC &&
+                                   kmd_end(k-1) == md->phys_addr) {
+                                       (k-1)->num_pages += md->num_pages;
+                               } else {
+                                       k->attribute = EFI_MEMORY_UC;
+                                       k->start = lim;
+                                       k->num_pages = (efi_md_end(md) - lim) >> EFI_PAGE_SHIFT;
+                                       k++;
+                               }
+                       }
+                       ae = contig_high;
+               } else
+                       ae = efi_md_end(md);
+
+               /* keep within max_addr= command line arg */
+               ae = min(ae, max_addr);
+               if (ae <= as)
+                       continue;
+
+               /* avoid going over mem= command line arg */
+               if (total_mem + (ae - as) > mem_limit)
+                       ae -= total_mem + (ae - as) - mem_limit;
+
+               if (ae <= as)
+                       continue;
+               if (prev && kmd_end(prev) == md->phys_addr) {
+                       prev->num_pages += (ae - as) >> EFI_PAGE_SHIFT;
+                       total_mem += ae - as;
+                       continue;
+               }
+               k->attribute = EFI_MEMORY_WB;
+               k->start = as;
+               k->num_pages = (ae - as) >> EFI_PAGE_SHIFT;
+               total_mem += ae - as;
+               prev = k++;
+       }
+       k->start = ~0L; /* end-marker */
+
+       /* reserve the memory we are using for kern_memmap */
+       *s = (u64)kern_memmap;
+       *e = (u64)++k;
+}
+
+void
+efi_initialize_iomem_resources(struct resource *code_resource,
+                              struct resource *data_resource)
+{
+       struct resource *res;
+       void *efi_map_start, *efi_map_end, *p;
+       efi_memory_desc_t *md;
+       u64 efi_desc_size;
+       char *name;
+       unsigned long flags;
+
+       efi_map_start = __va(ia64_boot_param->efi_memmap);
+       efi_map_end   = efi_map_start + ia64_boot_param->efi_memmap_size;
+       efi_desc_size = ia64_boot_param->efi_memdesc_size;
+
+       res = NULL;
+
+       for (p = efi_map_start; p < efi_map_end; p += efi_desc_size) {
+               md = p;
+
+               if (md->num_pages == 0) /* should not happen */
+                       continue;
+
+               flags = IORESOURCE_MEM;
+               switch (md->type) {
+
+                       case EFI_MEMORY_MAPPED_IO:
+                       case EFI_MEMORY_MAPPED_IO_PORT_SPACE:
+                               continue;
+
+                       case EFI_LOADER_CODE:
+                       case EFI_LOADER_DATA:
+                       case EFI_BOOT_SERVICES_DATA:
+                       case EFI_BOOT_SERVICES_CODE:
+                       case EFI_CONVENTIONAL_MEMORY:
+                               if (md->attribute & EFI_MEMORY_WP) {
+                                       name = "System ROM";
+                                       flags |= IORESOURCE_READONLY;
+                               } else {
+                                       name = "System RAM";
+                               }
+                               break;
+
+                       case EFI_ACPI_MEMORY_NVS:
+                               name = "ACPI Non-volatile Storage";
+                               flags |= IORESOURCE_BUSY;
+                               break;
+
+                       case EFI_UNUSABLE_MEMORY:
+                               name = "reserved";
+                               flags |= IORESOURCE_BUSY | IORESOURCE_DISABLED;
+                               break;
+
+                       case EFI_RESERVED_TYPE:
+                       case EFI_RUNTIME_SERVICES_CODE:
+                       case EFI_RUNTIME_SERVICES_DATA:
+                       case EFI_ACPI_RECLAIM_MEMORY:
+                       default:
+                               name = "reserved";
+                               flags |= IORESOURCE_BUSY;
+                               break;
+               }
+
+               if ((res = kcalloc(1, sizeof(struct resource), GFP_KERNEL)) == NULL) {
+                       printk(KERN_ERR "failed to alocate resource for iomem\n");
+                       return;
+               }
+
+               res->name = name;
+               res->start = md->phys_addr;
+               res->end = md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT) - 1;
+               res->flags = flags;
+
+               if (insert_resource(&iomem_resource, res) < 0)
+                       kfree(res);
+               else {
+                       /*
+                        * We don't know which region contains
+                        * kernel data so we try it repeatedly and
+                        * let the resource manager test it.
+                        */
+                       insert_resource(res, code_resource);
+                       insert_resource(res, data_resource);
+               }
+       }
+}
index 205d980..d33244c 100644 (file)
@@ -57,9 +57,9 @@ int show_interrupts(struct seq_file *p, void *v)
 
        if (i == 0) {
                seq_printf(p, "           ");
-               for (j=0; j<NR_CPUS; j++)
-                       if (cpu_online(j))
-                               seq_printf(p, "CPU%d       ",j);
+               for_each_online_cpu(j) {
+                       seq_printf(p, "CPU%d       ",j);
+               }
                seq_putc(p, '\n');
        }
 
@@ -72,9 +72,9 @@ int show_interrupts(struct seq_file *p, void *v)
 #ifndef CONFIG_SMP
                seq_printf(p, "%10u ", kstat_irqs(i));
 #else
-               for (j = 0; j < NR_CPUS; j++)
-                       if (cpu_online(j))
-                               seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]);
+               for_each_online_cpu(j) {
+                       seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]);
+               }
 #endif
                seq_printf(p, " %14s", irq_desc[i].handler->typename);
                seq_printf(p, "  %s", action->name);
index d0a5106..52c47da 100644 (file)
@@ -508,9 +508,7 @@ ia64_mca_wakeup_all(void)
        int cpu;
 
        /* Clear the Rendez checkin flag for all cpus */
-       for(cpu = 0; cpu < NR_CPUS; cpu++) {
-               if (!cpu_online(cpu))
-                       continue;
+       for_each_online_cpu(cpu) {
                if (ia64_mc_info.imi_rendez_checkin[cpu] == IA64_MCA_RENDEZ_CHECKIN_DONE)
                        ia64_mca_wakeup(cpu);
        }
index f1aca7c..7a2f0a7 100644 (file)
@@ -947,8 +947,8 @@ void
 percpu_modcopy (void *pcpudst, const void *src, unsigned long size)
 {
        unsigned int i;
-       for (i = 0; i < NR_CPUS; i++)
-               if (cpu_possible(i))
-                       memcpy(pcpudst + __per_cpu_offset[i], src, size);
+       for_each_cpu(i) {
+               memcpy(pcpudst + __per_cpu_offset[i], src, size);
+       }
 }
 #endif /* CONFIG_SMP */
index 367804a..6a4ac7d 100644 (file)
@@ -64,22 +64,30 @@ ia64_patch (u64 insn_addr, u64 mask, u64 val)
 void
 ia64_patch_imm64 (u64 insn_addr, u64 val)
 {
-       ia64_patch(insn_addr,
+       /* The assembler may generate offset pointing to either slot 1
+          or slot 2 for a long (2-slot) instruction, occupying slots 1
+          and 2.  */
+       insn_addr &= -16UL;
+       ia64_patch(insn_addr + 2,
                   0x01fffefe000UL, (  ((val & 0x8000000000000000UL) >> 27) /* bit 63 -> 36 */
                                     | ((val & 0x0000000000200000UL) <<  0) /* bit 21 -> 21 */
                                     | ((val & 0x00000000001f0000UL) <<  6) /* bit 16 -> 22 */
                                     | ((val & 0x000000000000ff80UL) << 20) /* bit  7 -> 27 */
                                     | ((val & 0x000000000000007fUL) << 13) /* bit  0 -> 13 */));
-       ia64_patch(insn_addr - 1, 0x1ffffffffffUL, val >> 22);
+       ia64_patch(insn_addr + 1, 0x1ffffffffffUL, val >> 22);
 }
 
 void
 ia64_patch_imm60 (u64 insn_addr, u64 val)
 {
-       ia64_patch(insn_addr,
+       /* The assembler may generate offset pointing to either slot 1
+          or slot 2 for a long (2-slot) instruction, occupying slots 1
+          and 2.  */
+       insn_addr &= -16UL;
+       ia64_patch(insn_addr + 2,
                   0x011ffffe000UL, (  ((val & 0x0800000000000000UL) >> 23) /* bit 59 -> 36 */
                                     | ((val & 0x00000000000fffffUL) << 13) /* bit  0 -> 13 */));
-       ia64_patch(insn_addr - 1, 0x1fffffffffcUL, val >> 18);
+       ia64_patch(insn_addr + 1, 0x1fffffffffcUL, val >> 18);
 }
 
 /*
index bbb8bc7..4b19d04 100644 (file)
@@ -587,8 +587,9 @@ thread_matches (struct task_struct *thread, unsigned long addr)
 static struct task_struct *
 find_thread_for_addr (struct task_struct *child, unsigned long addr)
 {
-       struct task_struct *g, *p;
+       struct task_struct *p;
        struct mm_struct *mm;
+       struct list_head *this, *next;
        int mm_users;
 
        if (!(mm = get_task_mm(child)))
@@ -600,28 +601,21 @@ find_thread_for_addr (struct task_struct *child, unsigned long addr)
                goto out;               /* not multi-threaded */
 
        /*
-        * First, traverse the child's thread-list.  Good for scalability with
-        * NPTL-threads.
+        * Traverse the current process' children list.  Every task that
+        * one attaches to becomes a child.  And it is only attached children
+        * of the debugger that are of interest (ptrace_check_attach checks
+        * for this).
         */
-       p = child;
-       do {
-               if (thread_matches(p, addr)) {
-                       child = p;
-                       goto out;
-               }
-               if (mm_users-- <= 1)
-                       goto out;
-       } while ((p = next_thread(p)) != child);
-
-       do_each_thread(g, p) {
-               if (child->mm != mm)
+       list_for_each_safe(this, next, &current->children) {
+               p = list_entry(this, struct task_struct, sibling);
+               if (p->mm != mm)
                        continue;
-
                if (thread_matches(p, addr)) {
                        child = p;
                        goto out;
                }
-       } while_each_thread(g, p);
+       }
+
   out:
        mmput(mm);
        return child;
index 1f5c26d..fc56ca2 100644 (file)
@@ -78,6 +78,19 @@ struct screen_info screen_info;
 unsigned long vga_console_iobase;
 unsigned long vga_console_membase;
 
+static struct resource data_resource = {
+       .name   = "Kernel data",
+       .flags  = IORESOURCE_BUSY | IORESOURCE_MEM
+};
+
+static struct resource code_resource = {
+       .name   = "Kernel code",
+       .flags  = IORESOURCE_BUSY | IORESOURCE_MEM
+};
+extern void efi_initialize_iomem_resources(struct resource *,
+               struct resource *);
+extern char _text[], _end[], _etext[];
+
 unsigned long ia64_max_cacheline_size;
 unsigned long ia64_iobase;     /* virtual address for I/O accesses */
 EXPORT_SYMBOL(ia64_iobase);
@@ -171,6 +184,22 @@ sort_regions (struct rsvd_region *rsvd_region, int max)
        }
 }
 
+/*
+ * Request address space for all standard resources
+ */
+static int __init register_memory(void)
+{
+       code_resource.start = ia64_tpa(_text);
+       code_resource.end   = ia64_tpa(_etext) - 1;
+       data_resource.start = ia64_tpa(_etext);
+       data_resource.end   = ia64_tpa(_end) - 1;
+       efi_initialize_iomem_resources(&code_resource, &data_resource);
+
+       return 0;
+}
+
+__initcall(register_memory);
+
 /**
  * reserve_memory - setup reserved memory areas
  *
@@ -211,6 +240,9 @@ reserve_memory (void)
        }
 #endif
 
+       efi_memmap_init(&rsvd_region[n].start, &rsvd_region[n].end);
+       n++;
+
        /* end of memory marker */
        rsvd_region[n].start = ~0UL;
        rsvd_region[n].end   = ~0UL;
@@ -244,28 +276,31 @@ find_initrd (void)
 static void __init
 io_port_init (void)
 {
-       extern unsigned long ia64_iobase;
        unsigned long phys_iobase;
 
        /*
-        *  Set `iobase' to the appropriate address in region 6 (uncached access range).
+        * Set `iobase' based on the EFI memory map or, failing that, the
+        * value firmware left in ar.k0.
         *
-        *  The EFI memory map is the "preferred" location to get the I/O port space base,
-        *  rather the relying on AR.KR0. This should become more clear in future SAL
-        *  specs. We'll fall back to getting it out of AR.KR0 if no appropriate entry is
-        *  found in the memory map.
+        * Note that in ia32 mode, IN/OUT instructions use ar.k0 to compute
+        * the port's virtual address, so ia32_load_state() loads it with a
+        * user virtual address.  But in ia64 mode, glibc uses the
+        * *physical* address in ar.k0 to mmap the appropriate area from
+        * /dev/mem, and the inX()/outX() interfaces use MMIO.  In both
+        * cases, user-mode can only use the legacy 0-64K I/O port space.
+        *
+        * ar.k0 is not involved in kernel I/O port accesses, which can use
+        * any of the I/O port spaces and are done via MMIO using the
+        * virtual mmio_base from the appropriate io_space[].
         */
        phys_iobase = efi_get_iobase();
-       if (phys_iobase)
-               /* set AR.KR0 since this is all we use it for anyway */
-               ia64_set_kr(IA64_KR_IO_BASE, phys_iobase);
-       else {
+       if (!phys_iobase) {
                phys_iobase = ia64_get_kr(IA64_KR_IO_BASE);
-               printk(KERN_INFO "No I/O port range found in EFI memory map, falling back "
-                      "to AR.KR0\n");
-               printk(KERN_INFO "I/O port base = 0x%lx\n", phys_iobase);
+               printk(KERN_INFO "No I/O port range found in EFI memory map, "
+                       "falling back to AR.KR0 (0x%lx)\n", phys_iobase);
        }
        ia64_iobase = (unsigned long) ioremap(phys_iobase, 0);
+       ia64_set_kr(IA64_KR_IO_BASE, __pa(ia64_iobase));
 
        /* setup legacy IO port space */
        io_space[0].mmio_base = ia64_iobase;
@@ -526,7 +561,7 @@ show_cpuinfo (struct seq_file *m, void *v)
                   c->itc_freq / 1000000, c->itc_freq % 1000000,
                   lpj*HZ/500000, (lpj*HZ/5000) % 100);
 #ifdef CONFIG_SMP
-       seq_printf(m, "siblings   : %u\n", c->num_log);
+       seq_printf(m, "siblings   : %u\n", cpus_weight(cpu_core_map[cpunum]));
        if (c->threads_per_core > 1 || c->cores_per_socket > 1)
                seq_printf(m,
                           "physical id: %u\n"
index 0166a98..657ac99 100644 (file)
@@ -185,8 +185,8 @@ send_IPI_allbutself (int op)
 {
        unsigned int i;
 
-       for (i = 0; i < NR_CPUS; i++) {
-               if (cpu_online(i) && i != smp_processor_id())
+       for_each_online_cpu(i) {
+               if (i != smp_processor_id())
                        send_IPI_single(i, op);
        }
 }
@@ -199,9 +199,9 @@ send_IPI_all (int op)
 {
        int i;
 
-       for (i = 0; i < NR_CPUS; i++)
-               if (cpu_online(i))
-                       send_IPI_single(i, op);
+       for_each_online_cpu(i) {
+               send_IPI_single(i, op);
+       }
 }
 
 /*
index 7d72c0d..400a489 100644 (file)
@@ -694,9 +694,9 @@ smp_cpus_done (unsigned int dummy)
         * Allow the user to impress friends.
         */
 
-       for (cpu = 0; cpu < NR_CPUS; cpu++)
-               if (cpu_online(cpu))
-                       bogosum += cpu_data(cpu)->loops_per_jiffy;
+       for_each_online_cpu(cpu) {
+               bogosum += cpu_data(cpu)->loops_per_jiffy;
+       }
 
        printk(KERN_INFO "Total of %d processors activated (%lu.%02lu BogoMIPS).\n",
               (int)num_online_cpus(), bogosum/(500000/HZ), (bogosum/(5000/HZ))%100);
index 4e9d06c..c6d4044 100644 (file)
@@ -205,23 +205,18 @@ EXPORT_SYMBOL(uncached_free_page);
 static int __init
 uncached_build_memmap(unsigned long start, unsigned long end, void *arg)
 {
-       long length;
-       unsigned long vstart, vend;
+       long length = end - start;
        int node;
 
-       length = end - start;
-       vstart = start + __IA64_UNCACHED_OFFSET;
-       vend = end + __IA64_UNCACHED_OFFSET;
-
        dprintk(KERN_ERR "uncached_build_memmap(%lx %lx)\n", start, end);
 
-       memset((char *)vstart, 0, length);
+       memset((char *)start, 0, length);
 
-       node = paddr_to_nid(start);
+       node = paddr_to_nid(start - __IA64_UNCACHED_OFFSET);
 
-       for (; vstart < vend ; vstart += PAGE_SIZE) {
-               dprintk(KERN_INFO "sticking %lx into the pool!\n", vstart);
-               gen_pool_free(uncached_pool[node], vstart, PAGE_SIZE);
+       for (; start < end ; start += PAGE_SIZE) {
+               dprintk(KERN_INFO "sticking %lx into the pool!\n", start);
+               gen_pool_free(uncached_pool[node], start, PAGE_SIZE);
        }
 
        return 0;
index 3ebbb3c..96edcc0 100644 (file)
  */
 #define IO_TLB_SHIFT 11
 
+#define SLABS_PER_PAGE (1 << (PAGE_SHIFT - IO_TLB_SHIFT))
+
+/*
+ * Minimum IO TLB size to bother booting with.  Systems with mainly
+ * 64bit capable cards will only lightly use the swiotlb.  If we can't
+ * allocate a contiguous 1MB, we're probably in trouble anyway.
+ */
+#define IO_TLB_MIN_SLABS ((1<<20) >> IO_TLB_SHIFT)
+
 int swiotlb_force;
 
 /*
@@ -154,6 +163,99 @@ swiotlb_init (void)
        swiotlb_init_with_default_size(64 * (1<<20));   /* default to 64MB */
 }
 
+/*
+ * Systems with larger DMA zones (those that don't support ISA) can
+ * initialize the swiotlb later using the slab allocator if needed.
+ * This should be just like above, but with some error catching.
+ */
+int
+swiotlb_late_init_with_default_size (size_t default_size)
+{
+       unsigned long i, req_nslabs = io_tlb_nslabs;
+       unsigned int order;
+
+       if (!io_tlb_nslabs) {
+               io_tlb_nslabs = (default_size >> IO_TLB_SHIFT);
+               io_tlb_nslabs = ALIGN(io_tlb_nslabs, IO_TLB_SEGSIZE);
+       }
+
+       /*
+        * Get IO TLB memory from the low pages
+        */
+       order = get_order(io_tlb_nslabs * (1 << IO_TLB_SHIFT));
+       io_tlb_nslabs = SLABS_PER_PAGE << order;
+
+       while ((SLABS_PER_PAGE << order) > IO_TLB_MIN_SLABS) {
+               io_tlb_start = (char *)__get_free_pages(GFP_DMA | __GFP_NOWARN,
+                                                       order);
+               if (io_tlb_start)
+                       break;
+               order--;
+       }
+
+       if (!io_tlb_start)
+               goto cleanup1;
+
+       if (order != get_order(io_tlb_nslabs * (1 << IO_TLB_SHIFT))) {
+               printk(KERN_WARNING "Warning: only able to allocate %ld MB "
+                      "for software IO TLB\n", (PAGE_SIZE << order) >> 20);
+               io_tlb_nslabs = SLABS_PER_PAGE << order;
+       }
+       io_tlb_end = io_tlb_start + io_tlb_nslabs * (1 << IO_TLB_SHIFT);
+       memset(io_tlb_start, 0, io_tlb_nslabs * (1 << IO_TLB_SHIFT));
+
+       /*
+        * Allocate and initialize the free list array.  This array is used
+        * to find contiguous free memory regions of size up to IO_TLB_SEGSIZE
+        * between io_tlb_start and io_tlb_end.
+        */
+       io_tlb_list = (unsigned int *)__get_free_pages(GFP_KERNEL,
+                                     get_order(io_tlb_nslabs * sizeof(int)));
+       if (!io_tlb_list)
+               goto cleanup2;
+
+       for (i = 0; i < io_tlb_nslabs; i++)
+               io_tlb_list[i] = IO_TLB_SEGSIZE - OFFSET(i, IO_TLB_SEGSIZE);
+       io_tlb_index = 0;
+
+       io_tlb_orig_addr = (unsigned char **)__get_free_pages(GFP_KERNEL,
+                                  get_order(io_tlb_nslabs * sizeof(char *)));
+       if (!io_tlb_orig_addr)
+               goto cleanup3;
+
+       memset(io_tlb_orig_addr, 0, io_tlb_nslabs * sizeof(char *));
+
+       /*
+        * Get the overflow emergency buffer
+        */
+       io_tlb_overflow_buffer = (void *)__get_free_pages(GFP_DMA,
+                                                 get_order(io_tlb_overflow));
+       if (!io_tlb_overflow_buffer)
+               goto cleanup4;
+
+       printk(KERN_INFO "Placing %ldMB software IO TLB between 0x%lx - "
+              "0x%lx\n", (io_tlb_nslabs * (1 << IO_TLB_SHIFT)) >> 20,
+              virt_to_phys(io_tlb_start), virt_to_phys(io_tlb_end));
+
+       return 0;
+
+cleanup4:
+       free_pages((unsigned long)io_tlb_orig_addr, get_order(io_tlb_nslabs *
+                                                             sizeof(char *)));
+       io_tlb_orig_addr = NULL;
+cleanup3:
+       free_pages((unsigned long)io_tlb_list, get_order(io_tlb_nslabs *
+                                                        sizeof(int)));
+       io_tlb_list = NULL;
+       io_tlb_end = NULL;
+cleanup2:
+       free_pages((unsigned long)io_tlb_start, order);
+       io_tlb_start = NULL;
+cleanup1:
+       io_tlb_nslabs = req_nslabs;
+       return -ENOMEM;
+}
+
 static inline int
 address_needs_mapping(struct device *hwdev, dma_addr_t addr)
 {
index 7078f67..d78d20f 100644 (file)
@@ -7,6 +7,5 @@ obj-y := init.o fault.o tlb.o extable.o
 obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o
 obj-$(CONFIG_NUMA)        += numa.o
 obj-$(CONFIG_DISCONTIGMEM) += discontig.o
-ifndef CONFIG_DISCONTIGMEM
-obj-y += contig.o
-endif
+obj-$(CONFIG_SPARSEMEM)           += discontig.o
+obj-$(CONFIG_FLATMEM)     += contig.o
index 91a055f..acaaec4 100644 (file)
@@ -269,7 +269,7 @@ paging_init (void)
        efi_memmap_walk(find_largest_hole, (u64 *)&max_gap);
        if (max_gap < LARGE_GAP) {
                vmem_map = (struct page *) 0;
-               free_area_init_node(0, &contig_page_data, zones_size, 0,
+               free_area_init_node(0, NODE_DATA(0), zones_size, 0,
                                    zholes_size);
        } else {
                unsigned long map_size;
@@ -282,7 +282,7 @@ paging_init (void)
                efi_memmap_walk(create_mem_map_page_table, NULL);
 
                NODE_DATA(0)->node_mem_map = vmem_map;
-               free_area_init_node(0, &contig_page_data, zones_size,
+               free_area_init_node(0, NODE_DATA(0), zones_size,
                                    0, zholes_size);
 
                printk("Virtual mem_map starts at 0x%p\n", mem_map);
index b5c90e5..a3788fb 100644 (file)
@@ -421,6 +421,37 @@ static void __init memory_less_nodes(void)
        return;
 }
 
+#ifdef CONFIG_SPARSEMEM
+/**
+ * register_sparse_mem - notify SPARSEMEM that this memory range exists.
+ * @start: physical start of range
+ * @end: physical end of range
+ * @arg: unused
+ *
+ * Simply calls SPARSEMEM to register memory section(s).
+ */
+static int __init register_sparse_mem(unsigned long start, unsigned long end,
+       void *arg)
+{
+       int nid;
+
+       start = __pa(start) >> PAGE_SHIFT;
+       end = __pa(end) >> PAGE_SHIFT;
+       nid = early_pfn_to_nid(start);
+       memory_present(nid, start, end);
+
+       return 0;
+}
+
+static void __init arch_sparse_init(void)
+{
+       efi_memmap_walk(register_sparse_mem, NULL);
+       sparse_init();
+}
+#else
+#define arch_sparse_init() do {} while (0)
+#endif
+
 /**
  * find_memory - walk the EFI memory map and setup the bootmem allocator
  *
@@ -528,8 +559,10 @@ void show_mem(void)
                int shared = 0, cached = 0, reserved = 0;
                printk("Node ID: %d\n", pgdat->node_id);
                for(i = 0; i < pgdat->node_spanned_pages; i++) {
-                       struct page *page = pgdat_page_nr(pgdat, i);
-                       if (!ia64_pfn_valid(pgdat->node_start_pfn+i))
+                       struct page *page;
+                       if (pfn_valid(pgdat->node_start_pfn + i))
+                               page = pfn_to_page(pgdat->node_start_pfn + i);
+                       else
                                continue;
                        if (PageReserved(page))
                                reserved++;
@@ -648,12 +681,16 @@ void __init paging_init(void)
 
        max_dma = virt_to_phys((void *) MAX_DMA_ADDRESS) >> PAGE_SHIFT;
 
+       arch_sparse_init();
+
        efi_memmap_walk(filter_rsvd_memory, count_node_pages);
 
+#ifdef CONFIG_VIRTUAL_MEM_MAP
        vmalloc_end -= PAGE_ALIGN(max_low_pfn * sizeof(struct page));
        vmem_map = (struct page *) vmalloc_end;
        efi_memmap_walk(create_mem_map_page_table, NULL);
        printk("Virtual mem_map starts at 0x%p\n", vmem_map);
+#endif
 
        for_each_online_node(node) {
                memset(zones_size, 0, sizeof(zones_size));
@@ -690,7 +727,9 @@ void __init paging_init(void)
 
                pfn_offset = mem_data[node].min_pfn;
 
+#ifdef CONFIG_VIRTUAL_MEM_MAP
                NODE_DATA(node)->node_mem_map = vmem_map + pfn_offset;
+#endif
                free_area_init_node(node, NODE_DATA(node), zones_size,
                                    pfn_offset, zholes_size);
        }
index 1281c60..98246ac 100644 (file)
@@ -593,7 +593,7 @@ mem_init (void)
        platform_dma_init();
 #endif
 
-#ifndef CONFIG_DISCONTIGMEM
+#ifdef CONFIG_FLATMEM
        if (!mem_map)
                BUG();
        max_mapnr = max_low_pfn;
index 77118bb..4e5c8b3 100644 (file)
@@ -47,3 +47,27 @@ paddr_to_nid(unsigned long paddr)
 
        return (i < num_node_memblks) ? node_memblk[i].nid : (num_node_memblks ? -1 : 0);
 }
+
+#if defined(CONFIG_SPARSEMEM) && defined(CONFIG_NUMA)
+/*
+ * Because of holes evaluate on section limits.
+ * If the section of memory exists, then return the node where the section
+ * resides.  Otherwise return node 0 as the default.  This is used by
+ * SPARSEMEM to allocate the SPARSEMEM sectionmap on the NUMA node where
+ * the section resides.
+ */
+int early_pfn_to_nid(unsigned long pfn)
+{
+       int i, section = pfn >> PFN_SECTION_SHIFT, ssec, esec;
+
+       for (i = 0; i < num_node_memblks; i++) {
+               ssec = node_memblk[i].start_paddr >> PA_SECTION_SHIFT;
+               esec = (node_memblk[i].start_paddr + node_memblk[i].size +
+                       ((1L << PA_SECTION_SHIFT) - 1)) >> PA_SECTION_SHIFT;
+               if (section >= ssec && section < esec)
+                       return node_memblk[i].nid;
+       }
+
+       return 0;
+}
+#endif
index 464557e..c93e0f2 100644 (file)
@@ -77,19 +77,25 @@ wrap_mmu_context (struct mm_struct *mm)
        /* can't call flush_tlb_all() here because of race condition with O(1) scheduler [EF] */
        {
                int cpu = get_cpu(); /* prevent preemption/migration */
-               for (i = 0; i < NR_CPUS; ++i)
-                       if (cpu_online(i) && (i != cpu))
+               for_each_online_cpu(i) {
+                       if (i != cpu)
                                per_cpu(ia64_need_tlb_flush, i) = 1;
+               }
                put_cpu();
        }
        local_flush_tlb_all();
 }
 
 void
-ia64_global_tlb_purge (unsigned long start, unsigned long end, unsigned long nbits)
+ia64_global_tlb_purge (struct mm_struct *mm, unsigned long start, unsigned long end, unsigned long nbits)
 {
        static DEFINE_SPINLOCK(ptcg_lock);
 
+       if (mm != current->active_mm) {
+               flush_tlb_all();
+               return;
+       }
+
        /* HW requires global serialization of ptc.ga.  */
        spin_lock(&ptcg_lock);
        {
@@ -135,15 +141,12 @@ flush_tlb_range (struct vm_area_struct *vma, unsigned long start, unsigned long
        unsigned long size = end - start;
        unsigned long nbits;
 
+#ifndef CONFIG_SMP
        if (mm != current->active_mm) {
-               /* this does happen, but perhaps it's not worth optimizing for? */
-#ifdef CONFIG_SMP
-               flush_tlb_all();
-#else
                mm->context = 0;
-#endif
                return;
        }
+#endif
 
        nbits = ia64_fls(size + 0xfff);
        while (unlikely (((1UL << nbits) & purge.mask) == 0) && (nbits < purge.max_bits))
@@ -153,7 +156,7 @@ flush_tlb_range (struct vm_area_struct *vma, unsigned long start, unsigned long
        start &= ~((1UL << nbits) - 1);
 
 # ifdef CONFIG_SMP
-       platform_global_tlb_purge(start, end, nbits);
+       platform_global_tlb_purge(mm, start, end, nbits);
 # else
        do {
                ia64_ptcl(start, (nbits<<2));
index 9b5de58..017cfc3 100644 (file)
@@ -120,29 +120,6 @@ struct pci_ops pci_root_ops = {
        .write = pci_write,
 };
 
-#ifdef CONFIG_NUMA
-extern acpi_status acpi_map_iosapic(acpi_handle, u32, void *, void **);
-static void acpi_map_iosapics(void)
-{
-       acpi_get_devices(NULL, acpi_map_iosapic, NULL, NULL);
-}
-#else
-static void acpi_map_iosapics(void)
-{
-       return;
-}
-#endif /* CONFIG_NUMA */
-
-static int __init
-pci_acpi_init (void)
-{
-       acpi_map_iosapics();
-
-       return 0;
-}
-
-subsys_initcall(pci_acpi_init);
-
 /* Called by ACPI when it finds a new root bus.  */
 
 static struct pci_controller * __devinit
@@ -191,6 +168,29 @@ add_io_space (struct acpi_resource_address64 *addr)
        return IO_SPACE_BASE(i);
 }
 
+static acpi_status __devinit resource_to_window(struct acpi_resource *resource,
+       struct acpi_resource_address64 *addr)
+{
+       acpi_status status;
+
+       /*
+        * We're only interested in _CRS descriptors that are
+        *      - address space descriptors for memory or I/O space
+        *      - non-zero size
+        *      - producers, i.e., the address space is routed downstream,
+        *        not consumed by the bridge itself
+        */
+       status = acpi_resource_to_address64(resource, addr);
+       if (ACPI_SUCCESS(status) &&
+           (addr->resource_type == ACPI_MEMORY_RANGE ||
+            addr->resource_type == ACPI_IO_RANGE) &&
+           addr->address_length &&
+           addr->producer_consumer == ACPI_PRODUCER)
+               return AE_OK;
+
+       return AE_ERROR;
+}
+
 static acpi_status __devinit
 count_window (struct acpi_resource *resource, void *data)
 {
@@ -198,11 +198,9 @@ count_window (struct acpi_resource *resource, void *data)
        struct acpi_resource_address64 addr;
        acpi_status status;
 
-       status = acpi_resource_to_address64(resource, &addr);
+       status = resource_to_window(resource, &addr);
        if (ACPI_SUCCESS(status))
-               if (addr.resource_type == ACPI_MEMORY_RANGE ||
-                   addr.resource_type == ACPI_IO_RANGE)
-                       (*windows)++;
+               (*windows)++;
 
        return AE_OK;
 }
@@ -221,13 +219,11 @@ static __devinit acpi_status add_window(struct acpi_resource *res, void *data)
        unsigned long flags, offset = 0;
        struct resource *root;
 
-       status = acpi_resource_to_address64(res, &addr);
+       /* Return AE_OK for non-window resources to keep scanning for more */
+       status = resource_to_window(res, &addr);
        if (!ACPI_SUCCESS(status))
                return AE_OK;
 
-       if (!addr.address_length)
-               return AE_OK;
-
        if (addr.resource_type == ACPI_MEMORY_RANGE) {
                flags = IORESOURCE_MEM;
                root = &iomem_resource;
index 45854c6..d71f4de 100644 (file)
@@ -87,7 +87,7 @@ bte_result_t bte_copy(u64 src, u64 dest, u64 len, u64 mode, void *notification)
        unsigned long irq_flags;
        unsigned long itc_end = 0;
        int nasid_to_try[MAX_NODES_TO_TRY];
-       int my_nasid = get_nasid();
+       int my_nasid = cpuid_to_nasid(raw_smp_processor_id());
        int bte_if_index, nasid_index;
        int bte_first, btes_per_node = BTES_PER_NODE;
 
index 906622d..b4f5053 100644 (file)
@@ -22,8 +22,6 @@
 #include "xtalk/hubdev.h"
 #include "xtalk/xwidgetdev.h"
 
-nasid_t master_nasid = INVALID_NASID;  /* Partition Master */
-
 static struct list_head sn_sysdata_list;
 
 /* sysdata list struct */
@@ -165,7 +163,7 @@ static void sn_fixup_ionodes(void)
         * Get SGI Specific HUB chipset information.
         * Inform Prom that this kernel can support domain bus numbering.
         */
-       for (i = 0; i < numionodes; i++) {
+       for (i = 0; i < num_cnodes; i++) {
                hubdev = (struct hubdev_info *)(NODEPDA(i)->pdinfo);
                nasid = cnodeid_to_nasid(i);
                hubdev->max_segment_number = 0xffffffff;
index 6f8c588..0fb579e 100644 (file)
@@ -59,8 +59,6 @@ DEFINE_PER_CPU(struct pda_s, pda_percpu);
 
 #define MAX_PHYS_MEMORY                (1UL << IA64_MAX_PHYS_BITS)     /* Max physical address supported */
 
-lboard_t *root_lboard[MAX_COMPACT_NODES];
-
 extern void bte_init_node(nodepda_t *, cnodeid_t);
 
 extern void sn_timer_init(void);
@@ -97,15 +95,15 @@ u8 sn_region_size;
 EXPORT_SYMBOL(sn_region_size);
 int sn_prom_type;      /* 0=hardware, 1=medusa/realprom, 2=medusa/fakeprom */
 
-short physical_node_map[MAX_PHYSNODE_ID];
+short physical_node_map[MAX_NUMALINK_NODES];
 static unsigned long sn_prom_features[MAX_PROM_FEATURE_SETS];
 
 EXPORT_SYMBOL(physical_node_map);
 
-int numionodes;
+int num_cnodes;
 
 static void sn_init_pdas(char **);
-static void scan_for_ionodes(void);
+static void build_cnode_tables(void);
 
 static nodepda_t *nodepdaindr[MAX_COMPACT_NODES];
 
@@ -139,19 +137,6 @@ extern char drive_info[4 * 16];
 char drive_info[4 * 16];
 #endif
 
-/*
- * Get nasid of current cpu early in boot before nodepda is initialized
- */
-static int
-boot_get_nasid(void)
-{
-       int nasid;
-
-       if (ia64_sn_get_sapic_info(get_sapicid(), &nasid, NULL, NULL))
-               BUG();
-       return nasid;
-}
-
 /*
  * This routine can only be used during init, since
  * smp_boot_data is an init data structure.
@@ -223,7 +208,6 @@ void __init early_sn_setup(void)
 }
 
 extern int platform_intr_list[];
-extern nasid_t master_nasid;
 static int __initdata shub_1_1_found = 0;
 
 /*
@@ -269,7 +253,6 @@ static void __init sn_check_for_wars(void)
 void __init sn_setup(char **cmdline_p)
 {
        long status, ticks_per_sec, drift;
-       int pxm;
        u32 version = sn_sal_rev();
        extern void sn_cpu_init(void);
 
@@ -300,11 +283,10 @@ void __init sn_setup(char **cmdline_p)
 
        MAX_DMA_ADDRESS = PAGE_OFFSET + MAX_PHYS_MEMORY;
 
-       memset(physical_node_map, -1, sizeof(physical_node_map));
-       for (pxm = 0; pxm < MAX_PXM_DOMAINS; pxm++)
-               if (pxm_to_nid_map[pxm] != -1)
-                       physical_node_map[pxm_to_nasid(pxm)] =
-                           pxm_to_nid_map[pxm];
+       /*
+        * Build the tables for managing cnodes.
+        */
+       build_cnode_tables();
 
        /*
         * Old PROMs do not provide an ACPI FADT. Disable legacy keyboard
@@ -319,8 +301,6 @@ void __init sn_setup(char **cmdline_p)
 
        printk("SGI SAL version %x.%02x\n", version >> 8, version & 0x00FF);
 
-       master_nasid = boot_get_nasid();
-
        status =
            ia64_sal_freq_base(SAL_FREQ_BASE_REALTIME_CLOCK, &ticks_per_sec,
                               &drift);
@@ -378,15 +358,6 @@ static void __init sn_init_pdas(char **cmdline_p)
 {
        cnodeid_t cnode;
 
-       memset(sn_cnodeid_to_nasid, -1,
-                       sizeof(__ia64_per_cpu_var(__sn_cnodeid_to_nasid)));
-       for_each_online_node(cnode)
-               sn_cnodeid_to_nasid[cnode] =
-                               pxm_to_nasid(nid_to_pxm_map[cnode]);
-
-       numionodes = num_online_nodes();
-       scan_for_ionodes();
-
        /*
         * Allocate & initalize the nodepda for each node.
         */
@@ -402,7 +373,7 @@ static void __init sn_init_pdas(char **cmdline_p)
        /*
         * Allocate & initialize nodepda for TIOs.  For now, put them on node 0.
         */
-       for (cnode = num_online_nodes(); cnode < numionodes; cnode++) {
+       for (cnode = num_online_nodes(); cnode < num_cnodes; cnode++) {
                nodepdaindr[cnode] =
                    alloc_bootmem_node(NODE_DATA(0), sizeof(nodepda_t));
                memset(nodepdaindr[cnode], 0, sizeof(nodepda_t));
@@ -411,7 +382,7 @@ static void __init sn_init_pdas(char **cmdline_p)
        /*
         * Now copy the array of nodepda pointers to each nodepda.
         */
-       for (cnode = 0; cnode < numionodes; cnode++)
+       for (cnode = 0; cnode < num_cnodes; cnode++)
                memcpy(nodepdaindr[cnode]->pernode_pdaindr, nodepdaindr,
                       sizeof(nodepdaindr));
 
@@ -428,7 +399,7 @@ static void __init sn_init_pdas(char **cmdline_p)
         * Initialize the per node hubdev.  This includes IO Nodes and
         * headless/memless nodes.
         */
-       for (cnode = 0; cnode < numionodes; cnode++) {
+       for (cnode = 0; cnode < num_cnodes; cnode++) {
                hubdev_init_node(nodepdaindr[cnode], cnode);
        }
 }
@@ -553,87 +524,58 @@ void __init sn_cpu_init(void)
 }
 
 /*
- * Scan klconfig for ionodes.  Add the nasids to the
- * physical_node_map and the pda and increment numionodes.
+ * Build tables for converting between NASIDs and cnodes.
  */
+static inline int __init board_needs_cnode(int type)
+{
+       return (type == KLTYPE_SNIA || type == KLTYPE_TIO);
+}
 
-static void __init scan_for_ionodes(void)
+void __init build_cnode_tables(void)
 {
-       int nasid = 0;
+       int nasid;
+       int node;
        lboard_t *brd;
 
-       /* fakeprom does not support klgraph */
-       if (IS_RUNNING_ON_FAKE_PROM())
-               return;
-
-       /* Setup ionodes with memory */
-       for (nasid = 0; nasid < MAX_PHYSNODE_ID; nasid += 2) {
-               char *klgraph_header;
-               cnodeid_t cnodeid;
-
-               if (physical_node_map[nasid] == -1)
-                       continue;
+       memset(physical_node_map, -1, sizeof(physical_node_map));
+       memset(sn_cnodeid_to_nasid, -1,
+                       sizeof(__ia64_per_cpu_var(__sn_cnodeid_to_nasid)));
 
-               cnodeid = -1;
-               klgraph_header = __va(ia64_sn_get_klconfig_addr(nasid));
-               if (!klgraph_header) {
-                       BUG();  /* All nodes must have klconfig tables! */
-               }
-               cnodeid = nasid_to_cnodeid(nasid);
-               root_lboard[cnodeid] = (lboard_t *)
-                   NODE_OFFSET_TO_LBOARD((nasid),
-                                         ((kl_config_hdr_t
-                                           *) (klgraph_header))->
-                                         ch_board_info);
+       /*
+        * First populate the tables with C/M bricks. This ensures that
+        * cnode == node for all C & M bricks.
+        */
+       for_each_online_node(node) {
+               nasid = pxm_to_nasid(nid_to_pxm_map[node]);
+               sn_cnodeid_to_nasid[node] = nasid;
+               physical_node_map[nasid] = node;
        }
 
-       /* Scan headless/memless IO Nodes. */
-       for (nasid = 0; nasid < MAX_PHYSNODE_ID; nasid += 2) {
-               /* if there's no nasid, don't try to read the klconfig on the node */
-               if (physical_node_map[nasid] == -1)
-                       continue;
-               brd = find_lboard_any((lboard_t *)
-                                     root_lboard[nasid_to_cnodeid(nasid)],
-                                     KLTYPE_SNIA);
-               if (brd) {
-                       brd = KLCF_NEXT_ANY(brd);       /* Skip this node's lboard */
-                       if (!brd)
-                               continue;
-               }
-
-               brd = find_lboard_any(brd, KLTYPE_SNIA);
+       /*
+        * num_cnodes is total number of C/M/TIO bricks. Because of the 256 node
+        * limit on the number of nodes, we can't use the generic node numbers 
+        * for this. Note that num_cnodes is incremented below as TIOs or
+        * headless/memoryless nodes are discovered.
+        */
+       num_cnodes = num_online_nodes();
 
-               while (brd) {
-                       sn_cnodeid_to_nasid[numionodes] = brd->brd_nasid;
-                       physical_node_map[brd->brd_nasid] = numionodes;
-                       root_lboard[numionodes] = brd;
-                       numionodes++;
-                       brd = KLCF_NEXT_ANY(brd);
-                       if (!brd)
-                               break;
-
-                       brd = find_lboard_any(brd, KLTYPE_SNIA);
-               }
-       }
+       /* fakeprom does not support klgraph */
+       if (IS_RUNNING_ON_FAKE_PROM())
+               return;
 
-       /* Scan for TIO nodes. */
-       for (nasid = 0; nasid < MAX_PHYSNODE_ID; nasid += 2) {
-               /* if there's no nasid, don't try to read the klconfig on the node */
-               if (physical_node_map[nasid] == -1)
-                       continue;
-               brd = find_lboard_any((lboard_t *)
-                                     root_lboard[nasid_to_cnodeid(nasid)],
-                                     KLTYPE_TIO);
+       /* Find TIOs & headless/memoryless nodes and add them to the tables */
+       for_each_online_node(node) {
+               kl_config_hdr_t *klgraph_header;
+               nasid = cnodeid_to_nasid(node);
+               if ((klgraph_header = ia64_sn_get_klconfig_addr(nasid)) == NULL)
+                       BUG();
+               brd = NODE_OFFSET_TO_LBOARD(nasid, klgraph_header->ch_board_info);
                while (brd) {
-                       sn_cnodeid_to_nasid[numionodes] = brd->brd_nasid;
-                       physical_node_map[brd->brd_nasid] = numionodes;
-                       root_lboard[numionodes] = brd;
-                       numionodes++;
-                       brd = KLCF_NEXT_ANY(brd);
-                       if (!brd)
-                               break;
-
-                       brd = find_lboard_any(brd, KLTYPE_TIO);
+                       if (board_needs_cnode(brd->brd_type) && physical_node_map[brd->brd_nasid] < 0) {
+                               sn_cnodeid_to_nasid[num_cnodes] = brd->brd_nasid;
+                               physical_node_map[brd->brd_nasid] = num_cnodes++;
+                       }
+                       brd = find_lboard_next(brd);
                }
        }
 }
index 0a4ee50..49b530c 100644 (file)
@@ -177,6 +177,7 @@ void sn_tlb_migrate_finish(struct mm_struct *mm)
 
 /**
  * sn2_global_tlb_purge - globally purge translation cache of virtual address range
+ * @mm: mm_struct containing virtual address range
  * @start: start of virtual address range
  * @end: end of virtual address range
  * @nbits: specifies number of bytes to purge per instruction (num = 1<<(nbits & 0xfc))
@@ -188,21 +189,22 @@ void sn_tlb_migrate_finish(struct mm_struct *mm)
  *     - cpu_vm_mask is a bit mask that indicates which cpus have loaded the context.
  *     - cpu_vm_mask is converted into a nodemask of the nodes containing the
  *       cpus in cpu_vm_mask.
- *     - if only one bit is set in cpu_vm_mask & it is the current cpu,
- *       then only the local TLB needs to be flushed. This flushing can be done
- *       using ptc.l. This is the common case & avoids the global spinlock.
+ *     - if only one bit is set in cpu_vm_mask & it is the current cpu & the
+ *       process is purging its own virtual address range, then only the
+ *       local TLB needs to be flushed. This flushing can be done using
+ *       ptc.l. This is the common case & avoids the global spinlock.
  *     - if multiple cpus have loaded the context, then flushing has to be
  *       done with ptc.g/MMRs under protection of the global ptc_lock.
  */
 
 void
-sn2_global_tlb_purge(unsigned long start, unsigned long end,
-                    unsigned long nbits)
+sn2_global_tlb_purge(struct mm_struct *mm, unsigned long start,
+                    unsigned long end, unsigned long nbits)
 {
        int i, opt, shub1, cnode, mynasid, cpu, lcpu = 0, nasid, flushed = 0;
+       int mymm = (mm == current->active_mm);
        volatile unsigned long *ptc0, *ptc1;
-       unsigned long itc, itc2, flags, data0 = 0, data1 = 0;
-       struct mm_struct *mm = current->active_mm;
+       unsigned long itc, itc2, flags, data0 = 0, data1 = 0, rr_value;
        short nasids[MAX_NUMNODES], nix;
        nodemask_t nodes_flushed;
 
@@ -216,9 +218,12 @@ sn2_global_tlb_purge(unsigned long start, unsigned long end,
                i++;
        }
 
+       if (i == 0)
+               return;
+
        preempt_disable();
 
-       if (likely(i == 1 && lcpu == smp_processor_id())) {
+       if (likely(i == 1 && lcpu == smp_processor_id() && mymm)) {
                do {
                        ia64_ptcl(start, nbits << 2);
                        start += (1UL << nbits);
@@ -229,7 +234,7 @@ sn2_global_tlb_purge(unsigned long start, unsigned long end,
                return;
        }
 
-       if (atomic_read(&mm->mm_users) == 1) {
+       if (atomic_read(&mm->mm_users) == 1 && mymm) {
                flush_tlb_mm(mm);
                __get_cpu_var(ptcstats).change_rid++;
                preempt_enable();
@@ -241,11 +246,13 @@ sn2_global_tlb_purge(unsigned long start, unsigned long end,
        for_each_node_mask(cnode, nodes_flushed)
                nasids[nix++] = cnodeid_to_nasid(cnode);
 
+       rr_value = (mm->context << 3) | REGION_NUMBER(start);
+
        shub1 = is_shub1();
        if (shub1) {
                data0 = (1UL << SH1_PTC_0_A_SHFT) |
                        (nbits << SH1_PTC_0_PS_SHFT) |
-                       ((ia64_get_rr(start) >> 8) << SH1_PTC_0_RID_SHFT) |
+                       (rr_value << SH1_PTC_0_RID_SHFT) |
                        (1UL << SH1_PTC_0_START_SHFT);
                ptc0 = (long *)GLOBAL_MMR_PHYS_ADDR(0, SH1_PTC_0);
                ptc1 = (long *)GLOBAL_MMR_PHYS_ADDR(0, SH1_PTC_1);
@@ -254,7 +261,7 @@ sn2_global_tlb_purge(unsigned long start, unsigned long end,
                        (nbits << SH2_PTC_PS_SHFT) |
                        (1UL << SH2_PTC_START_SHFT);
                ptc0 = (long *)GLOBAL_MMR_PHYS_ADDR(0, SH2_PTC + 
-                       ((ia64_get_rr(start) >> 8) << SH2_PTC_RID_SHFT) );
+                       (rr_value << SH2_PTC_RID_SHFT));
                ptc1 = NULL;
        }
        
@@ -275,7 +282,7 @@ sn2_global_tlb_purge(unsigned long start, unsigned long end,
                        data0 = (data0 & ~SH2_PTC_ADDR_MASK) | (start & SH2_PTC_ADDR_MASK);
                for (i = 0; i < nix; i++) {
                        nasid = nasids[i];
-                       if ((!(sn2_ptctest & 3)) && unlikely(nasid == mynasid)) {
+                       if ((!(sn2_ptctest & 3)) && unlikely(nasid == mynasid && mymm)) {
                                ia64_ptcga(start, nbits << 2);
                                ia64_srlz_i();
                        } else {
index 0513aac..6c6fbca 100644 (file)
@@ -476,8 +476,8 @@ static int sn_topology_show(struct seq_file *s, void *d)
                                for_each_online_cpu(j) {
                                        seq_printf(s, j ? ":%d" : ", dist %d",
                                                node_distance(
-                                                   cpuid_to_cnodeid(i),
-                                                   cpuid_to_cnodeid(j)));
+                                                   cpu_to_node(i),
+                                                   cpu_to_node(j)));
                                }
                                seq_putc(s, '\n');
                        }
index b45db51..0d8592a 100644 (file)
@@ -183,11 +183,12 @@ int cx_driver_unregister(struct cx_drv *cx_driver)
  * @part_num: device's part number
  * @mfg_num: device's manufacturer number
  * @hubdev: hub info associated with this device
+ * @bt: board type of the device
  *
  */
 int
 cx_device_register(nasid_t nasid, int part_num, int mfg_num,
-                  struct hubdev_info *hubdev)
+                  struct hubdev_info *hubdev, int bt)
 {
        struct cx_dev *cx_dev;
 
@@ -200,6 +201,7 @@ cx_device_register(nasid_t nasid, int part_num, int mfg_num,
        cx_dev->cx_id.mfg_num = mfg_num;
        cx_dev->cx_id.nasid = nasid;
        cx_dev->hubdev = hubdev;
+       cx_dev->bt = bt;
 
        cx_dev->dev.parent = NULL;
        cx_dev->dev.bus = &tiocx_bus_type;
@@ -238,7 +240,8 @@ static int cx_device_reload(struct cx_dev *cx_dev)
 {
        cx_device_unregister(cx_dev);
        return cx_device_register(cx_dev->cx_id.nasid, cx_dev->cx_id.part_num,
-                                 cx_dev->cx_id.mfg_num, cx_dev->hubdev);
+                                 cx_dev->cx_id.mfg_num, cx_dev->hubdev,
+                                 cx_dev->bt);
 }
 
 static inline uint64_t tiocx_intr_alloc(nasid_t nasid, int widget,
@@ -365,26 +368,20 @@ static void tio_corelet_reset(nasid_t nasid, int corelet)
        udelay(2000);
 }
 
-static int tiocx_btchar_get(int nasid)
+static int is_fpga_tio(int nasid, int *bt)
 {
-       moduleid_t module_id;
-       geoid_t geoid;
-       int cnodeid;
-
-       cnodeid = nasid_to_cnodeid(nasid);
-       geoid = cnodeid_get_geoid(cnodeid);
-       module_id = geo_module(geoid);
-       return MODULE_GET_BTCHAR(module_id);
-}
+       int ioboard_type;
 
-static int is_fpga_brick(int nasid)
-{
-       switch (tiocx_btchar_get(nasid)) {
+       ioboard_type = ia64_sn_sysctl_ioboard_get(nasid);
+
+       switch (ioboard_type) {
        case L1_BRICKTYPE_SA:
        case L1_BRICKTYPE_ATHENA:
-       case L1_BRICKTYPE_DAYTONA:
+       case L1_BOARDTYPE_DAYTONA:
+               *bt = ioboard_type;
                return 1;
        }
+
        return 0;
 }
 
@@ -407,16 +404,22 @@ static int tiocx_reload(struct cx_dev *cx_dev)
 
        if (bitstream_loaded(nasid)) {
                uint64_t cx_id;
-
-               cx_id =
-                   *(volatile uint64_t *)(TIO_SWIN_BASE(nasid, TIOCX_CORELET) +
+               int rv;
+
+               rv = ia64_sn_sysctl_tio_clock_reset(nasid);
+               if (rv) {
+                       printk(KERN_ALERT "CX port JTAG reset failed.\n");
+               } else {
+                       cx_id = *(volatile uint64_t *)
+                               (TIO_SWIN_BASE(nasid, TIOCX_CORELET) +
                                          WIDGET_ID);
-               part_num = XWIDGET_PART_NUM(cx_id);
-               mfg_num = XWIDGET_MFG_NUM(cx_id);
-               DBG("part= 0x%x, mfg= 0x%x\n", part_num, mfg_num);
-               /* just ignore it if it's a CE */
-               if (part_num == TIO_CE_ASIC_PARTNUM)
-                       return 0;
+                       part_num = XWIDGET_PART_NUM(cx_id);
+                       mfg_num = XWIDGET_MFG_NUM(cx_id);
+                       DBG("part= 0x%x, mfg= 0x%x\n", part_num, mfg_num);
+                       /* just ignore it if it's a CE */
+                       if (part_num == TIO_CE_ASIC_PARTNUM)
+                               return 0;
+               }
        }
 
        cx_dev->cx_id.part_num = part_num;
@@ -436,10 +439,10 @@ static ssize_t show_cxdev_control(struct device *dev, struct device_attribute *a
 {
        struct cx_dev *cx_dev = to_cx_dev(dev);
 
-       return sprintf(buf, "0x%x 0x%x 0x%x %d\n",
+       return sprintf(buf, "0x%x 0x%x 0x%x 0x%x\n",
                       cx_dev->cx_id.nasid,
                       cx_dev->cx_id.part_num, cx_dev->cx_id.mfg_num,
-                      tiocx_btchar_get(cx_dev->cx_id.nasid));
+                      cx_dev->bt);
 }
 
 static ssize_t store_cxdev_control(struct device *dev, struct device_attribute *attr, const char *buf,
@@ -486,13 +489,13 @@ static int __init tiocx_init(void)
 
        bus_register(&tiocx_bus_type);
 
-       for (cnodeid = 0; cnodeid < MAX_COMPACT_NODES; cnodeid++) {
+       for (cnodeid = 0; cnodeid < num_cnodes; cnodeid++) {
                nasid_t nasid;
+               int bt;
 
-               if ((nasid = cnodeid_to_nasid(cnodeid)) < 0)
-                       break;  /* No more nasids .. bail out of loop */
+               nasid = cnodeid_to_nasid(cnodeid);
 
-               if ((nasid & 0x1) && is_fpga_brick(nasid)) {
+               if ((nasid & 0x1) && is_fpga_tio(nasid, &bt)) {
                        struct hubdev_info *hubdev;
                        struct xwidget_info *widgetp;
 
@@ -512,7 +515,7 @@ static int __init tiocx_init(void)
 
                        if (cx_device_register
                            (nasid, widgetp->xwi_hwid.part_num,
-                            widgetp->xwi_hwid.mfg_num, hubdev) < 0)
+                            widgetp->xwi_hwid.mfg_num, hubdev, bt) < 0)
                                return -ENXIO;
                        else
                                found_tiocx_device++;
index e5f5a4e..fbcedc7 100644 (file)
@@ -57,7 +57,7 @@
 #define XPC_NASID_FROM_W_B(_w, _b) (((_w) * 64 + (_b)) * 2)
 
 #define XPC_HB_DEFAULT_INTERVAL                5       /* incr HB every x secs */
-#define XPC_HB_CHECK_DEFAULT_TIMEOUT   20      /* check HB every x secs */
+#define XPC_HB_CHECK_DEFAULT_INTERVAL  20      /* check HB every x secs */
 
 /* define the process name of HB checker and the CPU it is pinned to */
 #define XPC_HB_CHECK_THREAD_NAME       "xpc_hb"
 #define XPC_DISCOVERY_THREAD_NAME      "xpc_discovery"
 
 
-#define XPC_HB_ALLOWED(_p, _v) ((_v)->heartbeating_to_mask & (1UL << (_p)))
-#define XPC_ALLOW_HB(_p, _v)   (_v)->heartbeating_to_mask |= (1UL << (_p))
-#define XPC_DISALLOW_HB(_p, _v)        (_v)->heartbeating_to_mask &= (~(1UL << (_p)))
-
-
 /*
- * Reserved Page provided by SAL.
+ * the reserved page
+ *
+ *   SAL reserves one page of memory per partition for XPC. Though a full page
+ *   in length (16384 bytes), its starting address is not page aligned, but it
+ *   is cacheline aligned. The reserved page consists of the following:
+ *
+ *   reserved page header
+ *
+ *     The first cacheline of the reserved page contains the header
+ *     (struct xpc_rsvd_page). Before SAL initialization has completed,
+ *     SAL has set up the following fields of the reserved page header:
+ *     SAL_signature, SAL_version, partid, and nasids_size. The other
+ *     fields are set up by XPC. (xpc_rsvd_page points to the local
+ *     partition's reserved page.)
  *
- * SAL provides one page per partition of reserved memory.  When SAL
- * initialization is complete, SAL_signature, SAL_version, partid,
- * part_nasids, and mach_nasids are set.
+ *   part_nasids mask
+ *   mach_nasids mask
+ *
+ *     SAL also sets up two bitmaps (or masks), one that reflects the actual
+ *     nasids in this partition (part_nasids), and the other that reflects
+ *     the actual nasids in the entire machine (mach_nasids). We're only
+ *     interested in the even numbered nasids (which contain the processors
+ *     and/or memory), so we only need half as many bits to represent the
+ *     nasids. The part_nasids mask is located starting at the first cacheline
+ *     following the reserved page header. The mach_nasids mask follows right
+ *     after the part_nasids mask. The size in bytes of each mask is reflected
+ *     by the reserved page header field 'nasids_size'. (Local partition's
+ *     mask pointers are xpc_part_nasids and xpc_mach_nasids.)
+ *
+ *   vars
+ *   vars part
+ *
+ *     Immediately following the mach_nasids mask are the XPC variables
+ *     required by other partitions. First are those that are generic to all
+ *     partitions (vars), followed on the next available cacheline by those
+ *     which are partition specific (vars part). These are setup by XPC.
+ *     (Local partition's vars pointers are xpc_vars and xpc_vars_part.)
  *
  * Note: Until vars_pa is set, the partition XPC code has not been initialized.
  */
 struct xpc_rsvd_page {
-       u64 SAL_signature;      /* SAL unique signature */
-       u64 SAL_version;        /* SAL specified version */
-       u8 partid;              /* partition ID from SAL */
+       u64 SAL_signature;      /* SAL: unique signature */
+       u64 SAL_version;        /* SAL: version */
+       u8 partid;              /* SAL: partition ID */
        u8 version;
-       u8 pad[6];              /* pad to u64 align */
+       u8 pad1[6];             /* align to next u64 in cacheline */
        volatile u64 vars_pa;
-       u64 part_nasids[XP_NASID_MASK_WORDS] ____cacheline_aligned;
-       u64 mach_nasids[XP_NASID_MASK_WORDS] ____cacheline_aligned;
+       struct timespec stamp;  /* time when reserved page was setup by XPC */
+       u64 pad2[9];            /* align to last u64 in cacheline */
+       u64 nasids_size;        /* SAL: size of each nasid mask in bytes */
 };
-#define XPC_RP_VERSION _XPC_VERSION(1,0) /* version 1.0 of the reserved page */
 
-#define XPC_RSVD_PAGE_ALIGNED_SIZE \
-                       (L1_CACHE_ALIGN(sizeof(struct xpc_rsvd_page)))
+#define XPC_RP_VERSION _XPC_VERSION(1,1) /* version 1.1 of the reserved page */
+
+#define XPC_SUPPORTS_RP_STAMP(_version) \
+                       (_version >= _XPC_VERSION(1,1))
+
+/*
+ * compare stamps - the return value is:
+ *
+ *     < 0,    if stamp1 < stamp2
+ *     = 0,    if stamp1 == stamp2
+ *     > 0,    if stamp1 > stamp2
+ */
+static inline int
+xpc_compare_stamps(struct timespec *stamp1, struct timespec *stamp2)
+{
+       int ret;
+
+
+       if ((ret = stamp1->tv_sec - stamp2->tv_sec) == 0) {
+               ret = stamp1->tv_nsec - stamp2->tv_nsec;
+       }
+       return ret;
+}
 
 
 /*
@@ -121,11 +169,58 @@ struct xpc_vars {
        u64 vars_part_pa;
        u64 amos_page_pa;       /* paddr of page of AMOs from MSPEC driver */
        AMO_t *amos_page;       /* vaddr of page of AMOs from MSPEC driver */
-       AMO_t *act_amos;        /* pointer to the first activation AMO */
 };
-#define XPC_V_VERSION _XPC_VERSION(3,0) /* version 3.0 of the cross vars */
 
-#define XPC_VARS_ALIGNED_SIZE  (L1_CACHE_ALIGN(sizeof(struct xpc_vars)))
+#define XPC_V_VERSION _XPC_VERSION(3,1) /* version 3.1 of the cross vars */
+
+#define XPC_SUPPORTS_DISENGAGE_REQUEST(_version) \
+                       (_version >= _XPC_VERSION(3,1))
+
+
+static inline int
+xpc_hb_allowed(partid_t partid, struct xpc_vars *vars)
+{
+       return ((vars->heartbeating_to_mask & (1UL << partid)) != 0);
+}
+
+static inline void
+xpc_allow_hb(partid_t partid, struct xpc_vars *vars)
+{
+       u64 old_mask, new_mask;
+
+       do {
+               old_mask = vars->heartbeating_to_mask;
+               new_mask = (old_mask | (1UL << partid));
+       } while (cmpxchg(&vars->heartbeating_to_mask, old_mask, new_mask) !=
+                                                       old_mask);
+}
+
+static inline void
+xpc_disallow_hb(partid_t partid, struct xpc_vars *vars)
+{
+       u64 old_mask, new_mask;
+
+       do {
+               old_mask = vars->heartbeating_to_mask;
+               new_mask = (old_mask & ~(1UL << partid));
+       } while (cmpxchg(&vars->heartbeating_to_mask, old_mask, new_mask) !=
+                                                       old_mask);
+}
+
+
+/*
+ * The AMOs page consists of a number of AMO variables which are divided into
+ * four groups, The first two groups are used to identify an IRQ's sender.
+ * These two groups consist of 64 and 128 AMO variables respectively. The last
+ * two groups, consisting of just one AMO variable each, are used to identify
+ * the remote partitions that are currently engaged (from the viewpoint of
+ * the XPC running on the remote partition).
+ */
+#define XPC_NOTIFY_IRQ_AMOS       0
+#define XPC_ACTIVATE_IRQ_AMOS     (XPC_NOTIFY_IRQ_AMOS + XP_MAX_PARTITIONS)
+#define XPC_ENGAGED_PARTITIONS_AMO (XPC_ACTIVATE_IRQ_AMOS + XP_NASID_MASK_WORDS)
+#define XPC_DISENGAGE_REQUEST_AMO  (XPC_ENGAGED_PARTITIONS_AMO + 1)
+
 
 /*
  * The following structure describes the per partition specific variables.
@@ -165,6 +260,16 @@ struct xpc_vars_part {
 #define XPC_VP_MAGIC2  0x0073726176435058L  /* 'XPCvars\0'L (little endian) */
 
 
+/* the reserved page sizes and offsets */
+
+#define XPC_RP_HEADER_SIZE     L1_CACHE_ALIGN(sizeof(struct xpc_rsvd_page))
+#define XPC_RP_VARS_SIZE       L1_CACHE_ALIGN(sizeof(struct xpc_vars))
+
+#define XPC_RP_PART_NASIDS(_rp) (u64 *) ((u8 *) _rp + XPC_RP_HEADER_SIZE)
+#define XPC_RP_MACH_NASIDS(_rp) (XPC_RP_PART_NASIDS(_rp) + xp_nasid_mask_words)
+#define XPC_RP_VARS(_rp)       ((struct xpc_vars *) XPC_RP_MACH_NASIDS(_rp) + xp_nasid_mask_words)
+#define XPC_RP_VARS_PART(_rp)  (struct xpc_vars_part *) ((u8 *) XPC_RP_VARS(rp) + XPC_RP_VARS_SIZE)
+
 
 /*
  * Functions registered by add_timer() or called by kernel_thread() only
@@ -349,6 +454,9 @@ struct xpc_channel {
        atomic_t n_on_msg_allocate_wq;   /* #on msg allocation wait queue */
        wait_queue_head_t msg_allocate_wq; /* msg allocation wait queue */
 
+       u8 delayed_IPI_flags;           /* IPI flags received, but delayed */
+                                       /* action until channel disconnected */
+
        /* queue of msg senders who want to be notified when msg received */
 
        atomic_t n_to_notify;           /* #of msg senders to notify */
@@ -358,7 +466,7 @@ struct xpc_channel {
        void *key;                      /* pointer to user's key */
 
        struct semaphore msg_to_pull_sema; /* next msg to pull serialization */
-       struct semaphore teardown_sema;    /* wait for teardown completion */
+       struct semaphore wdisconnect_sema; /* wait for channel disconnect */
 
        struct xpc_openclose_args *local_openclose_args; /* args passed on */
                                        /* opening or closing of channel */
@@ -410,6 +518,8 @@ struct xpc_channel {
 
 #define        XPC_C_DISCONNECTED      0x00002000 /* channel is disconnected */
 #define        XPC_C_DISCONNECTING     0x00004000 /* channel is being disconnected */
+#define        XPC_C_DISCONNECTCALLOUT 0x00008000 /* chan disconnected callout made */
+#define        XPC_C_WDISCONNECT       0x00010000 /* waiting for channel disconnect */
 
 
 
@@ -422,6 +532,8 @@ struct xpc_partition {
 
        /* XPC HB infrastructure */
 
+       u8 remote_rp_version;           /* version# of partition's rsvd pg */
+       struct timespec remote_rp_stamp;/* time when rsvd pg was initialized */
        u64 remote_rp_pa;               /* phys addr of partition's rsvd pg */
        u64 remote_vars_pa;             /* phys addr of partition's vars */
        u64 remote_vars_part_pa;        /* phys addr of partition's vars part */
@@ -432,14 +544,18 @@ struct xpc_partition {
        u32 act_IRQ_rcvd;               /* IRQs since activation */
        spinlock_t act_lock;            /* protect updating of act_state */
        u8 act_state;                   /* from XPC HB viewpoint */
+       u8 remote_vars_version;         /* version# of partition's vars */
        enum xpc_retval reason;         /* reason partition is deactivating */
        int reason_line;                /* line# deactivation initiated from */
        int reactivate_nasid;           /* nasid in partition to reactivate */
 
+       unsigned long disengage_request_timeout; /* timeout in jiffies */
+       struct timer_list disengage_request_timer;
+
 
        /* XPC infrastructure referencing and teardown control */
 
-       volatile u8 setup_state;                        /* infrastructure setup state */
+       volatile u8 setup_state;        /* infrastructure setup state */
        wait_queue_head_t teardown_wq;  /* kthread waiting to teardown infra */
        atomic_t references;            /* #of references to infrastructure */
 
@@ -454,6 +570,7 @@ struct xpc_partition {
 
        u8 nchannels;              /* #of defined channels supported */
        atomic_t nchannels_active; /* #of channels that are not DISCONNECTED */
+       atomic_t nchannels_engaged;/* #of channels engaged with remote part */
        struct xpc_channel *channels;/* array of channel structures */
 
        void *local_GPs_base;     /* base address of kmalloc'd space */
@@ -518,6 +635,7 @@ struct xpc_partition {
 #define XPC_P_TORNDOWN         0x03    /* infrastructure is torndown */
 
 
+
 /*
  * struct xpc_partition IPI_timer #of seconds to wait before checking for
  * dropped IPIs. These occur whenever an IPI amo write doesn't complete until
@@ -526,6 +644,13 @@ struct xpc_partition {
 #define XPC_P_DROPPED_IPI_WAIT (0.25 * HZ)
 
 
+/* number of seconds to wait for other partitions to disengage */
+#define XPC_DISENGAGE_REQUEST_DEFAULT_TIMELIMIT        90
+
+/* interval in seconds to print 'waiting disengagement' messages */
+#define XPC_DISENGAGE_PRINTMSG_INTERVAL                10
+
+
 #define XPC_PARTID(_p) ((partid_t) ((_p) - &xpc_partitions[0]))
 
 
@@ -534,24 +659,20 @@ struct xpc_partition {
 extern struct xpc_registration xpc_registrations[];
 
 
-/* >>> found in xpc_main.c only */
+/* found in xpc_main.c */
 extern struct device *xpc_part;
 extern struct device *xpc_chan;
+extern int xpc_disengage_request_timelimit;
 extern irqreturn_t xpc_notify_IRQ_handler(int, void *, struct pt_regs *);
 extern void xpc_dropped_IPI_check(struct xpc_partition *);
+extern void xpc_activate_partition(struct xpc_partition *);
 extern void xpc_activate_kthreads(struct xpc_channel *, int);
 extern void xpc_create_kthreads(struct xpc_channel *, int);
 extern void xpc_disconnect_wait(int);
 
 
-/* found in xpc_main.c and efi-xpc.c */
-extern void xpc_activate_partition(struct xpc_partition *);
-
-
 /* found in xpc_partition.c */
 extern int xpc_exiting;
-extern int xpc_hb_interval;
-extern int xpc_hb_check_interval;
 extern struct xpc_vars *xpc_vars;
 extern struct xpc_rsvd_page *xpc_rsvd_page;
 extern struct xpc_vars_part *xpc_vars_part;
@@ -561,6 +682,7 @@ extern struct xpc_rsvd_page *xpc_rsvd_page_init(void);
 extern void xpc_allow_IPI_ops(void);
 extern void xpc_restrict_IPI_ops(void);
 extern int xpc_identify_act_IRQ_sender(void);
+extern int xpc_partition_disengaged(struct xpc_partition *);
 extern enum xpc_retval xpc_mark_partition_active(struct xpc_partition *);
 extern void xpc_mark_partition_inactive(struct xpc_partition *);
 extern void xpc_discovery(void);
@@ -585,8 +707,8 @@ extern void xpc_connected_callout(struct xpc_channel *);
 extern void xpc_deliver_msg(struct xpc_channel *);
 extern void xpc_disconnect_channel(const int, struct xpc_channel *,
                                        enum xpc_retval, unsigned long *);
-extern void xpc_disconnected_callout(struct xpc_channel *);
-extern void xpc_partition_down(struct xpc_partition *, enum xpc_retval);
+extern void xpc_disconnecting_callout(struct xpc_channel *);
+extern void xpc_partition_going_down(struct xpc_partition *, enum xpc_retval);
 extern void xpc_teardown_infrastructure(struct xpc_partition *);
 
 
@@ -673,6 +795,157 @@ xpc_part_ref(struct xpc_partition *part)
 
 
 
+/*
+ * This next set of inlines are used to keep track of when a partition is
+ * potentially engaged in accessing memory belonging to another partition.
+ */
+
+static inline void
+xpc_mark_partition_engaged(struct xpc_partition *part)
+{
+       unsigned long irq_flags;
+       AMO_t *amo = (AMO_t *) __va(part->remote_amos_page_pa +
+                               (XPC_ENGAGED_PARTITIONS_AMO * sizeof(AMO_t)));
+
+
+       local_irq_save(irq_flags);
+
+       /* set bit corresponding to our partid in remote partition's AMO */
+       FETCHOP_STORE_OP(TO_AMO((u64) &amo->variable), FETCHOP_OR,
+                                               (1UL << sn_partition_id));
+       /*
+        * We must always use the nofault function regardless of whether we
+        * are on a Shub 1.1 system or a Shub 1.2 slice 0xc processor. If we
+        * didn't, we'd never know that the other partition is down and would
+        * keep sending IPIs and AMOs to it until the heartbeat times out.
+        */
+       (void) xp_nofault_PIOR((u64 *) GLOBAL_MMR_ADDR(NASID_GET(&amo->
+                               variable), xp_nofault_PIOR_target));
+
+       local_irq_restore(irq_flags);
+}
+
+static inline void
+xpc_mark_partition_disengaged(struct xpc_partition *part)
+{
+       unsigned long irq_flags;
+       AMO_t *amo = (AMO_t *) __va(part->remote_amos_page_pa +
+                               (XPC_ENGAGED_PARTITIONS_AMO * sizeof(AMO_t)));
+
+
+       local_irq_save(irq_flags);
+
+       /* clear bit corresponding to our partid in remote partition's AMO */
+       FETCHOP_STORE_OP(TO_AMO((u64) &amo->variable), FETCHOP_AND,
+                                               ~(1UL << sn_partition_id));
+       /*
+        * We must always use the nofault function regardless of whether we
+        * are on a Shub 1.1 system or a Shub 1.2 slice 0xc processor. If we
+        * didn't, we'd never know that the other partition is down and would
+        * keep sending IPIs and AMOs to it until the heartbeat times out.
+        */
+       (void) xp_nofault_PIOR((u64 *) GLOBAL_MMR_ADDR(NASID_GET(&amo->
+                               variable), xp_nofault_PIOR_target));
+
+       local_irq_restore(irq_flags);
+}
+
+static inline void
+xpc_request_partition_disengage(struct xpc_partition *part)
+{
+       unsigned long irq_flags;
+       AMO_t *amo = (AMO_t *) __va(part->remote_amos_page_pa +
+                               (XPC_DISENGAGE_REQUEST_AMO * sizeof(AMO_t)));
+
+
+       local_irq_save(irq_flags);
+
+       /* set bit corresponding to our partid in remote partition's AMO */
+       FETCHOP_STORE_OP(TO_AMO((u64) &amo->variable), FETCHOP_OR,
+                                               (1UL << sn_partition_id));
+       /*
+        * We must always use the nofault function regardless of whether we
+        * are on a Shub 1.1 system or a Shub 1.2 slice 0xc processor. If we
+        * didn't, we'd never know that the other partition is down and would
+        * keep sending IPIs and AMOs to it until the heartbeat times out.
+        */
+       (void) xp_nofault_PIOR((u64 *) GLOBAL_MMR_ADDR(NASID_GET(&amo->
+                               variable), xp_nofault_PIOR_target));
+
+       local_irq_restore(irq_flags);
+}
+
+static inline void
+xpc_cancel_partition_disengage_request(struct xpc_partition *part)
+{
+       unsigned long irq_flags;
+       AMO_t *amo = (AMO_t *) __va(part->remote_amos_page_pa +
+                               (XPC_DISENGAGE_REQUEST_AMO * sizeof(AMO_t)));
+
+
+       local_irq_save(irq_flags);
+
+       /* clear bit corresponding to our partid in remote partition's AMO */
+       FETCHOP_STORE_OP(TO_AMO((u64) &amo->variable), FETCHOP_AND,
+                                               ~(1UL << sn_partition_id));
+       /*
+        * We must always use the nofault function regardless of whether we
+        * are on a Shub 1.1 system or a Shub 1.2 slice 0xc processor. If we
+        * didn't, we'd never know that the other partition is down and would
+        * keep sending IPIs and AMOs to it until the heartbeat times out.
+        */
+       (void) xp_nofault_PIOR((u64 *) GLOBAL_MMR_ADDR(NASID_GET(&amo->
+                               variable), xp_nofault_PIOR_target));
+
+       local_irq_restore(irq_flags);
+}
+
+static inline u64
+xpc_partition_engaged(u64 partid_mask)
+{
+       AMO_t *amo = xpc_vars->amos_page + XPC_ENGAGED_PARTITIONS_AMO;
+
+
+       /* return our partition's AMO variable ANDed with partid_mask */
+       return (FETCHOP_LOAD_OP(TO_AMO((u64) &amo->variable), FETCHOP_LOAD) &
+                                                               partid_mask);
+}
+
+static inline u64
+xpc_partition_disengage_requested(u64 partid_mask)
+{
+       AMO_t *amo = xpc_vars->amos_page + XPC_DISENGAGE_REQUEST_AMO;
+
+
+       /* return our partition's AMO variable ANDed with partid_mask */
+       return (FETCHOP_LOAD_OP(TO_AMO((u64) &amo->variable), FETCHOP_LOAD) &
+                                                               partid_mask);
+}
+
+static inline void
+xpc_clear_partition_engaged(u64 partid_mask)
+{
+       AMO_t *amo = xpc_vars->amos_page + XPC_ENGAGED_PARTITIONS_AMO;
+
+
+       /* clear bit(s) based on partid_mask in our partition's AMO */
+       FETCHOP_STORE_OP(TO_AMO((u64) &amo->variable), FETCHOP_AND,
+                                                               ~partid_mask);
+}
+
+static inline void
+xpc_clear_partition_disengage_request(u64 partid_mask)
+{
+       AMO_t *amo = xpc_vars->amos_page + XPC_DISENGAGE_REQUEST_AMO;
+
+
+       /* clear bit(s) based on partid_mask in our partition's AMO */
+       FETCHOP_STORE_OP(TO_AMO((u64) &amo->variable), FETCHOP_AND,
+                                                               ~partid_mask);
+}
+
+
+
 /*
  * The following set of macros and inlines are used for the sending and
  * receiving of IPIs (also known as IRQs). There are two flavors of IPIs,
@@ -722,13 +995,13 @@ xpc_IPI_send(AMO_t *amo, u64 flag, int nasid, int phys_cpuid, int vector)
  * Flag the appropriate AMO variable and send an IPI to the specified node.
  */
 static inline void
-xpc_activate_IRQ_send(u64 amos_page, int from_nasid, int to_nasid,
+xpc_activate_IRQ_send(u64 amos_page_pa, int from_nasid, int to_nasid,
                        int to_phys_cpuid)
 {
        int w_index = XPC_NASID_W_INDEX(from_nasid);
        int b_index = XPC_NASID_B_INDEX(from_nasid);
-       AMO_t *amos = (AMO_t *) __va(amos_page +
-                                       (XP_MAX_PARTITIONS * sizeof(AMO_t)));
+       AMO_t *amos = (AMO_t *) __va(amos_page_pa +
+                               (XPC_ACTIVATE_IRQ_AMOS * sizeof(AMO_t)));
 
 
        (void) xpc_IPI_send(&amos[w_index], (1UL << b_index), to_nasid,
@@ -756,6 +1029,13 @@ xpc_IPI_send_reactivate(struct xpc_partition *part)
                                xpc_vars->act_nasid, xpc_vars->act_phys_cpuid);
 }
 
+static inline void
+xpc_IPI_send_disengage(struct xpc_partition *part)
+{
+       xpc_activate_IRQ_send(part->remote_amos_page_pa, cnodeid_to_nasid(0),
+                       part->remote_act_nasid, part->remote_act_phys_cpuid);
+}
+
 
 /*
  * IPIs associated with SGI_XPC_NOTIFY IRQ.
@@ -836,6 +1116,7 @@ xpc_notify_IRQ_send_local(struct xpc_channel *ch, u8 ipi_flag,
 
 /* given an AMO variable and a channel#, get its associated IPI flags */
 #define XPC_GET_IPI_FLAGS(_amo, _c)    ((u8) (((_amo) >> ((_c) * 8)) & 0xff))
+#define XPC_SET_IPI_FLAGS(_amo, _c, _f)        (_amo) |= ((u64) (_f) << ((_c) * 8))
 
 #define        XPC_ANY_OPENCLOSE_IPI_FLAGS_SET(_amo) ((_amo) & 0x0f0f0f0f0f0f0f0f)
 #define XPC_ANY_MSG_IPI_FLAGS_SET(_amo)       ((_amo) & 0x1010101010101010)
@@ -903,17 +1184,18 @@ xpc_IPI_send_local_msgrequest(struct xpc_channel *ch)
  * cacheable mapping for the entire region. This will prevent speculative
  * reading of cached copies of our lines from being issued which will cause
  * a PI FSB Protocol error to be generated by the SHUB. For XPC, we need 64
- * (XP_MAX_PARTITIONS) AMO variables for message notification (xpc_main.c)
- * and an additional 16 AMO variables for partition activation (xpc_hb.c).
+ * AMO variables (based on XP_MAX_PARTITIONS) for message notification and an
+ * additional 128 AMO variables (based on XP_NASID_MASK_WORDS) for partition
+ * activation and 2 AMO variables for partition deactivation.
  */
 static inline AMO_t *
-xpc_IPI_init(partid_t partid)
+xpc_IPI_init(int index)
 {
-       AMO_t *part_amo = xpc_vars->amos_page + partid;
+       AMO_t *amo = xpc_vars->amos_page + index;
 
 
-       xpc_IPI_receive(part_amo);
-       return part_amo;
+       (void) xpc_IPI_receive(amo);    /* clear AMO variable */
+       return amo;
 }
 
 
index 94698be..abf4fc2 100644 (file)
@@ -57,6 +57,7 @@ xpc_initialize_channels(struct xpc_partition *part, partid_t partid)
 
                spin_lock_init(&ch->lock);
                sema_init(&ch->msg_to_pull_sema, 1);    /* mutex */
+               sema_init(&ch->wdisconnect_sema, 0);    /* event wait */
 
                atomic_set(&ch->n_on_msg_allocate_wq, 0);
                init_waitqueue_head(&ch->msg_allocate_wq);
@@ -166,6 +167,7 @@ xpc_setup_infrastructure(struct xpc_partition *part)
        xpc_initialize_channels(part, partid);
 
        atomic_set(&part->nchannels_active, 0);
+       atomic_set(&part->nchannels_engaged, 0);
 
 
        /* local_IPI_amo were set to 0 by an earlier memset() */
@@ -555,8 +557,6 @@ xpc_allocate_msgqueues(struct xpc_channel *ch)
                sema_init(&ch->notify_queue[i].sema, 0);
        }
 
-       sema_init(&ch->teardown_sema, 0);       /* event wait */
-
        spin_lock_irqsave(&ch->lock, irq_flags);
        ch->flags |= XPC_C_SETUP;
        spin_unlock_irqrestore(&ch->lock, irq_flags);
@@ -625,6 +625,55 @@ xpc_process_connect(struct xpc_channel *ch, unsigned long *irq_flags)
 }
 
 
+/*
+ * Notify those who wanted to be notified upon delivery of their message.
+ */
+static void
+xpc_notify_senders(struct xpc_channel *ch, enum xpc_retval reason, s64 put)
+{
+       struct xpc_notify *notify;
+       u8 notify_type;
+       s64 get = ch->w_remote_GP.get - 1;
+
+
+       while (++get < put && atomic_read(&ch->n_to_notify) > 0) {
+
+               notify = &ch->notify_queue[get % ch->local_nentries];
+
+               /*
+                * See if the notify entry indicates it was associated with
+                * a message who's sender wants to be notified. It is possible
+                * that it is, but someone else is doing or has done the
+                * notification.
+                */
+               notify_type = notify->type;
+               if (notify_type == 0 ||
+                               cmpxchg(&notify->type, notify_type, 0) !=
+                                                               notify_type) {
+                       continue;
+               }
+
+               DBUG_ON(notify_type != XPC_N_CALL);
+
+               atomic_dec(&ch->n_to_notify);
+
+               if (notify->func != NULL) {
+                       dev_dbg(xpc_chan, "notify->func() called, notify=0x%p, "
+                               "msg_number=%ld, partid=%d, channel=%d\n",
+                               (void *) notify, get, ch->partid, ch->number);
+
+                       notify->func(reason, ch->partid, ch->number,
+                                                               notify->key);
+
+                       dev_dbg(xpc_chan, "notify->func() returned, "
+                               "notify=0x%p, msg_number=%ld, partid=%d, "
+                               "channel=%d\n", (void *) notify, get,
+                               ch->partid, ch->number);
+               }
+       }
+}
+
+
 /*
  * Free up message queues and other stuff that were allocated for the specified
  * channel.
@@ -669,9 +718,6 @@ xpc_free_msgqueues(struct xpc_channel *ch)
                ch->remote_msgqueue = NULL;
                kfree(ch->notify_queue);
                ch->notify_queue = NULL;
-
-               /* in case someone is waiting for the teardown to complete */
-               up(&ch->teardown_sema);
        }
 }
 
@@ -683,7 +729,7 @@ static void
 xpc_process_disconnect(struct xpc_channel *ch, unsigned long *irq_flags)
 {
        struct xpc_partition *part = &xpc_partitions[ch->partid];
-       u32 ch_flags = ch->flags;
+       u32 channel_was_connected = (ch->flags & XPC_C_WASCONNECTED);
 
 
        DBUG_ON(!spin_is_locked(&ch->lock));
@@ -701,12 +747,13 @@ xpc_process_disconnect(struct xpc_channel *ch, unsigned long *irq_flags)
        }
        DBUG_ON(atomic_read(&ch->kthreads_assigned) != 0);
 
-       /* it's now safe to free the channel's message queues */
-
-       xpc_free_msgqueues(ch);
-       DBUG_ON(ch->flags & XPC_C_SETUP);
+       if (part->act_state == XPC_P_DEACTIVATING) {
+               /* can't proceed until the other side disengages from us */
+               if (xpc_partition_engaged(1UL << ch->partid)) {
+                       return;
+               }
 
-       if (part->act_state != XPC_P_DEACTIVATING) {
+       } else {
 
                /* as long as the other side is up do the full protocol */
 
@@ -724,16 +771,42 @@ xpc_process_disconnect(struct xpc_channel *ch, unsigned long *irq_flags)
                }
        }
 
+       /* wake those waiting for notify completion */
+       if (atomic_read(&ch->n_to_notify) > 0) {
+               /* >>> we do callout while holding ch->lock */
+               xpc_notify_senders(ch, ch->reason, ch->w_local_GP.put);
+       }
+
        /* both sides are disconnected now */
 
-       ch->flags = XPC_C_DISCONNECTED; /* clear all flags, but this one */
+       /* it's now safe to free the channel's message queues */
+       xpc_free_msgqueues(ch);
+
+       /* mark disconnected, clear all other flags except XPC_C_WDISCONNECT */
+       ch->flags = (XPC_C_DISCONNECTED | (ch->flags & XPC_C_WDISCONNECT));
 
        atomic_dec(&part->nchannels_active);
 
-       if (ch_flags & XPC_C_WASCONNECTED) {
+       if (channel_was_connected) {
                dev_info(xpc_chan, "channel %d to partition %d disconnected, "
                        "reason=%d\n", ch->number, ch->partid, ch->reason);
        }
+
+       if (ch->flags & XPC_C_WDISCONNECT) {
+               spin_unlock_irqrestore(&ch->lock, *irq_flags);
+               up(&ch->wdisconnect_sema);
+               spin_lock_irqsave(&ch->lock, *irq_flags);
+
+       } else if (ch->delayed_IPI_flags) {
+               if (part->act_state != XPC_P_DEACTIVATING) {
+                       /* time to take action on any delayed IPI flags */
+                       spin_lock(&part->IPI_lock);
+                       XPC_SET_IPI_FLAGS(part->local_IPI_amo, ch->number,
+                                                       ch->delayed_IPI_flags);
+                       spin_unlock(&part->IPI_lock);
+               }
+               ch->delayed_IPI_flags = 0;
+       }
 }
 
 
@@ -754,6 +827,19 @@ xpc_process_openclose_IPI(struct xpc_partition *part, int ch_number,
 
        spin_lock_irqsave(&ch->lock, irq_flags);
 
+again:
+
+       if ((ch->flags & XPC_C_DISCONNECTED) &&
+                                       (ch->flags & XPC_C_WDISCONNECT)) {
+               /*
+                * Delay processing IPI flags until thread waiting disconnect
+                * has had a chance to see that the channel is disconnected.
+                */
+               ch->delayed_IPI_flags |= IPI_flags;
+               spin_unlock_irqrestore(&ch->lock, irq_flags);
+               return;
+       }
+
 
        if (IPI_flags & XPC_IPI_CLOSEREQUEST) {
 
@@ -764,7 +850,7 @@ xpc_process_openclose_IPI(struct xpc_partition *part, int ch_number,
                /*
                 * If RCLOSEREQUEST is set, we're probably waiting for
                 * RCLOSEREPLY. We should find it and a ROPENREQUEST packed
-                * with this RCLOSEQREUQEST in the IPI_flags.
+                * with this RCLOSEREQUEST in the IPI_flags.
                 */
 
                if (ch->flags & XPC_C_RCLOSEREQUEST) {
@@ -779,14 +865,22 @@ xpc_process_openclose_IPI(struct xpc_partition *part, int ch_number,
 
                        /* both sides have finished disconnecting */
                        xpc_process_disconnect(ch, &irq_flags);
+                       DBUG_ON(!(ch->flags & XPC_C_DISCONNECTED));
+                       goto again;
                }
 
                if (ch->flags & XPC_C_DISCONNECTED) {
-                       // >>> explain this section
-
                        if (!(IPI_flags & XPC_IPI_OPENREQUEST)) {
-                               DBUG_ON(part->act_state !=
-                                                       XPC_P_DEACTIVATING);
+                               if ((XPC_GET_IPI_FLAGS(part->local_IPI_amo,
+                                        ch_number) & XPC_IPI_OPENREQUEST)) {
+
+                                       DBUG_ON(ch->delayed_IPI_flags != 0);
+                                       spin_lock(&part->IPI_lock);
+                                       XPC_SET_IPI_FLAGS(part->local_IPI_amo,
+                                                       ch_number,
+                                                       XPC_IPI_CLOSEREQUEST);
+                                       spin_unlock(&part->IPI_lock);
+                               }
                                spin_unlock_irqrestore(&ch->lock, irq_flags);
                                return;
                        }
@@ -816,9 +910,13 @@ xpc_process_openclose_IPI(struct xpc_partition *part, int ch_number,
                        }
 
                        XPC_DISCONNECT_CHANNEL(ch, reason, &irq_flags);
-               } else {
-                       xpc_process_disconnect(ch, &irq_flags);
+
+                       DBUG_ON(IPI_flags & XPC_IPI_CLOSEREPLY);
+                       spin_unlock_irqrestore(&ch->lock, irq_flags);
+                       return;
                }
+
+               xpc_process_disconnect(ch, &irq_flags);
        }
 
 
@@ -834,7 +932,20 @@ xpc_process_openclose_IPI(struct xpc_partition *part, int ch_number,
                }
 
                DBUG_ON(!(ch->flags & XPC_C_CLOSEREQUEST));
-               DBUG_ON(!(ch->flags & XPC_C_RCLOSEREQUEST));
+
+               if (!(ch->flags & XPC_C_RCLOSEREQUEST)) {
+                       if ((XPC_GET_IPI_FLAGS(part->local_IPI_amo, ch_number)
+                                               & XPC_IPI_CLOSEREQUEST)) {
+
+                               DBUG_ON(ch->delayed_IPI_flags != 0);
+                               spin_lock(&part->IPI_lock);
+                               XPC_SET_IPI_FLAGS(part->local_IPI_amo,
+                                               ch_number, XPC_IPI_CLOSEREPLY);
+                               spin_unlock(&part->IPI_lock);
+                       }
+                       spin_unlock_irqrestore(&ch->lock, irq_flags);
+                       return;
+               }
 
                ch->flags |= XPC_C_RCLOSEREPLY;
 
@@ -852,8 +963,14 @@ xpc_process_openclose_IPI(struct xpc_partition *part, int ch_number,
                        "channel=%d\n", args->msg_size, args->local_nentries,
                        ch->partid, ch->number);
 
-               if ((ch->flags & XPC_C_DISCONNECTING) ||
-                                       part->act_state == XPC_P_DEACTIVATING) {
+               if (part->act_state == XPC_P_DEACTIVATING ||
+                                       (ch->flags & XPC_C_ROPENREQUEST)) {
+                       spin_unlock_irqrestore(&ch->lock, irq_flags);
+                       return;
+               }
+
+               if (ch->flags & (XPC_C_DISCONNECTING | XPC_C_WDISCONNECT)) {
+                       ch->delayed_IPI_flags |= XPC_IPI_OPENREQUEST;
                        spin_unlock_irqrestore(&ch->lock, irq_flags);
                        return;
                }
@@ -867,8 +984,11 @@ xpc_process_openclose_IPI(struct xpc_partition *part, int ch_number,
                 *      msg_size = size of channel's messages in bytes
                 *      local_nentries = remote partition's local_nentries
                 */
-               DBUG_ON(args->msg_size == 0);
-               DBUG_ON(args->local_nentries == 0);
+               if (args->msg_size == 0 || args->local_nentries == 0) {
+                       /* assume OPENREQUEST was delayed by mistake */
+                       spin_unlock_irqrestore(&ch->lock, irq_flags);
+                       return;
+               }
 
                ch->flags |= (XPC_C_ROPENREQUEST | XPC_C_CONNECTING);
                ch->remote_nentries = args->local_nentries;
@@ -906,7 +1026,13 @@ xpc_process_openclose_IPI(struct xpc_partition *part, int ch_number,
                        spin_unlock_irqrestore(&ch->lock, irq_flags);
                        return;
                }
-               DBUG_ON(!(ch->flags & XPC_C_OPENREQUEST));
+               if (!(ch->flags & XPC_C_OPENREQUEST)) {
+                       XPC_DISCONNECT_CHANNEL(ch, xpcOpenCloseError,
+                                                               &irq_flags);
+                       spin_unlock_irqrestore(&ch->lock, irq_flags);
+                       return;
+               }
+
                DBUG_ON(!(ch->flags & XPC_C_ROPENREQUEST));
                DBUG_ON(ch->flags & XPC_C_CONNECTED);
 
@@ -960,8 +1086,8 @@ xpc_connect_channel(struct xpc_channel *ch)
        struct xpc_registration *registration = &xpc_registrations[ch->number];
 
 
-       if (down_interruptible(&registration->sema) != 0) {
-               return xpcInterrupted;
+       if (down_trylock(&registration->sema) != 0) {
+               return xpcRetry;
        }
 
        if (!XPC_CHANNEL_REGISTERED(ch->number)) {
@@ -1039,55 +1165,6 @@ xpc_connect_channel(struct xpc_channel *ch)
 }
 
 
-/*
- * Notify those who wanted to be notified upon delivery of their message.
- */
-static void
-xpc_notify_senders(struct xpc_channel *ch, enum xpc_retval reason, s64 put)
-{
-       struct xpc_notify *notify;
-       u8 notify_type;
-       s64 get = ch->w_remote_GP.get - 1;
-
-
-       while (++get < put && atomic_read(&ch->n_to_notify) > 0) {
-
-               notify = &ch->notify_queue[get % ch->local_nentries];
-
-               /*
-                * See if the notify entry indicates it was associated with
-                * a message who's sender wants to be notified. It is possible
-                * that it is, but someone else is doing or has done the
-                * notification.
-                */
-               notify_type = notify->type;
-               if (notify_type == 0 ||
-                               cmpxchg(&notify->type, notify_type, 0) !=
-                                                               notify_type) {
-                       continue;
-               }
-
-               DBUG_ON(notify_type != XPC_N_CALL);
-
-               atomic_dec(&ch->n_to_notify);
-
-               if (notify->func != NULL) {
-                       dev_dbg(xpc_chan, "notify->func() called, notify=0x%p, "
-                               "msg_number=%ld, partid=%d, channel=%d\n",
-                               (void *) notify, get, ch->partid, ch->number);
-
-                       notify->func(reason, ch->partid, ch->number,
-                                                               notify->key);
-
-                       dev_dbg(xpc_chan, "notify->func() returned, "
-                               "notify=0x%p, msg_number=%ld, partid=%d, "
-                               "channel=%d\n", (void *) notify, get,
-                               ch->partid, ch->number);
-               }
-       }
-}
-
-
 /*
  * Clear some of the msg flags in the local message queue.
  */
@@ -1240,6 +1317,7 @@ xpc_process_channel_activity(struct xpc_partition *part)
        u64 IPI_amo, IPI_flags;
        struct xpc_channel *ch;
        int ch_number;
+       u32 ch_flags;
 
 
        IPI_amo = xpc_get_IPI_flags(part);
@@ -1266,8 +1344,9 @@ xpc_process_channel_activity(struct xpc_partition *part)
                        xpc_process_openclose_IPI(part, ch_number, IPI_flags);
                }
 
+               ch_flags = ch->flags;   /* need an atomic snapshot of flags */
 
-               if (ch->flags & XPC_C_DISCONNECTING) {
+               if (ch_flags & XPC_C_DISCONNECTING) {
                        spin_lock_irqsave(&ch->lock, irq_flags);
                        xpc_process_disconnect(ch, &irq_flags);
                        spin_unlock_irqrestore(&ch->lock, irq_flags);
@@ -1278,9 +1357,9 @@ xpc_process_channel_activity(struct xpc_partition *part)
                        continue;
                }
 
-               if (!(ch->flags & XPC_C_CONNECTED)) {
-                       if (!(ch->flags & XPC_C_OPENREQUEST)) {
-                               DBUG_ON(ch->flags & XPC_C_SETUP);
+               if (!(ch_flags & XPC_C_CONNECTED)) {
+                       if (!(ch_flags & XPC_C_OPENREQUEST)) {
+                               DBUG_ON(ch_flags & XPC_C_SETUP);
                                (void) xpc_connect_channel(ch);
                        } else {
                                spin_lock_irqsave(&ch->lock, irq_flags);
@@ -1305,8 +1384,8 @@ xpc_process_channel_activity(struct xpc_partition *part)
 
 
 /*
- * XPC's heartbeat code calls this function to inform XPC that a partition has
- * gone down.  XPC responds by tearing down the XPartition Communication
+ * XPC's heartbeat code calls this function to inform XPC that a partition is
+ * going down.  XPC responds by tearing down the XPartition Communication
  * infrastructure used for the just downed partition.
  *
  * XPC's heartbeat code will never call this function and xpc_partition_up()
@@ -1314,7 +1393,7 @@ xpc_process_channel_activity(struct xpc_partition *part)
  * at the same time.
  */
 void
-xpc_partition_down(struct xpc_partition *part, enum xpc_retval reason)
+xpc_partition_going_down(struct xpc_partition *part, enum xpc_retval reason)
 {
        unsigned long irq_flags;
        int ch_number;
@@ -1330,12 +1409,11 @@ xpc_partition_down(struct xpc_partition *part, enum xpc_retval reason)
        }
 
 
-       /* disconnect all channels associated with the downed partition */
+       /* disconnect channels associated with the partition going down */
 
        for (ch_number = 0; ch_number < part->nchannels; ch_number++) {
                ch = &part->channels[ch_number];
 
-
                xpc_msgqueue_ref(ch);
                spin_lock_irqsave(&ch->lock, irq_flags);
 
@@ -1370,6 +1448,7 @@ xpc_teardown_infrastructure(struct xpc_partition *part)
         * this partition.
         */
 
+       DBUG_ON(atomic_read(&part->nchannels_engaged) != 0);
        DBUG_ON(atomic_read(&part->nchannels_active) != 0);
        DBUG_ON(part->setup_state != XPC_P_SETUP);
        part->setup_state = XPC_P_WTEARDOWN;
@@ -1428,19 +1507,11 @@ xpc_initiate_connect(int ch_number)
                if (xpc_part_ref(part)) {
                        ch = &part->channels[ch_number];
 
-                       if (!(ch->flags & XPC_C_DISCONNECTING)) {
-                               DBUG_ON(ch->flags & XPC_C_OPENREQUEST);
-                               DBUG_ON(ch->flags & XPC_C_CONNECTED);
-                               DBUG_ON(ch->flags & XPC_C_SETUP);
-
-                               /*
-                                * Initiate the establishment of a connection
-                                * on the newly registered channel to the
-                                * remote partition.
-                                */
-                               xpc_wakeup_channel_mgr(part);
-                       }
-
+                       /*
+                        * Initiate the establishment of a connection on the
+                        * newly registered channel to the remote partition.
+                        */
+                       xpc_wakeup_channel_mgr(part);
                        xpc_part_deref(part);
                }
        }
@@ -1450,9 +1521,6 @@ xpc_initiate_connect(int ch_number)
 void
 xpc_connected_callout(struct xpc_channel *ch)
 {
-       unsigned long irq_flags;
-
-
        /* let the registerer know that a connection has been established */
 
        if (ch->func != NULL) {
@@ -1465,10 +1533,6 @@ xpc_connected_callout(struct xpc_channel *ch)
                dev_dbg(xpc_chan, "ch->func() returned, reason=xpcConnected, "
                        "partid=%d, channel=%d\n", ch->partid, ch->number);
        }
-
-       spin_lock_irqsave(&ch->lock, irq_flags);
-       ch->flags |= XPC_C_CONNECTCALLOUT;
-       spin_unlock_irqrestore(&ch->lock, irq_flags);
 }
 
 
@@ -1506,8 +1570,12 @@ xpc_initiate_disconnect(int ch_number)
 
                        spin_lock_irqsave(&ch->lock, irq_flags);
 
-                       XPC_DISCONNECT_CHANNEL(ch, xpcUnregistering,
+                       if (!(ch->flags & XPC_C_DISCONNECTED)) {
+                               ch->flags |= XPC_C_WDISCONNECT;
+
+                               XPC_DISCONNECT_CHANNEL(ch, xpcUnregistering,
                                                                &irq_flags);
+                       }
 
                        spin_unlock_irqrestore(&ch->lock, irq_flags);
 
@@ -1523,8 +1591,9 @@ xpc_initiate_disconnect(int ch_number)
 /*
  * To disconnect a channel, and reflect it back to all who may be waiting.
  *
- * >>> An OPEN is not allowed until XPC_C_DISCONNECTING is cleared by
- * >>> xpc_free_msgqueues().
+ * An OPEN is not allowed until XPC_C_DISCONNECTING is cleared by
+ * xpc_process_disconnect(), and if set, XPC_C_WDISCONNECT is cleared by
+ * xpc_disconnect_wait().
  *
  * THE CHANNEL IS TO BE LOCKED BY THE CALLER AND WILL REMAIN LOCKED UPON RETURN.
  */
@@ -1532,7 +1601,7 @@ void
 xpc_disconnect_channel(const int line, struct xpc_channel *ch,
                        enum xpc_retval reason, unsigned long *irq_flags)
 {
-       u32 flags;
+       u32 channel_was_connected = (ch->flags & XPC_C_CONNECTED);
 
 
        DBUG_ON(!spin_is_locked(&ch->lock));
@@ -1547,61 +1616,53 @@ xpc_disconnect_channel(const int line, struct xpc_channel *ch,
 
        XPC_SET_REASON(ch, reason, line);
 
-       flags = ch->flags;
+       ch->flags |= (XPC_C_CLOSEREQUEST | XPC_C_DISCONNECTING);
        /* some of these may not have been set */
        ch->flags &= ~(XPC_C_OPENREQUEST | XPC_C_OPENREPLY |
                        XPC_C_ROPENREQUEST | XPC_C_ROPENREPLY |
                        XPC_C_CONNECTING | XPC_C_CONNECTED);
 
-       ch->flags |= (XPC_C_CLOSEREQUEST | XPC_C_DISCONNECTING);
        xpc_IPI_send_closerequest(ch, irq_flags);
 
-       if (flags & XPC_C_CONNECTED) {
+       if (channel_was_connected) {
                ch->flags |= XPC_C_WASCONNECTED;
        }
 
+       spin_unlock_irqrestore(&ch->lock, *irq_flags);
+
+       /* wake all idle kthreads so they can exit */
        if (atomic_read(&ch->kthreads_idle) > 0) {
-               /* wake all idle kthreads so they can exit */
                wake_up_all(&ch->idle_wq);
        }
 
-       spin_unlock_irqrestore(&ch->lock, *irq_flags);
-
-
        /* wake those waiting to allocate an entry from the local msg queue */
-
        if (atomic_read(&ch->n_on_msg_allocate_wq) > 0) {
                wake_up(&ch->msg_allocate_wq);
        }
 
-       /* wake those waiting for notify completion */
-
-       if (atomic_read(&ch->n_to_notify) > 0) {
-               xpc_notify_senders(ch, reason, ch->w_local_GP.put);
-       }
-
        spin_lock_irqsave(&ch->lock, *irq_flags);
 }
 
 
 void
-xpc_disconnected_callout(struct xpc_channel *ch)
+xpc_disconnecting_callout(struct xpc_channel *ch)
 {
        /*
-        * Let the channel's registerer know that the channel is now
+        * Let the channel's registerer know that the channel is being
         * disconnected. We don't want to do this if the registerer was never
-        * informed of a connection being made, unless the disconnect was for
-        * abnormal reasons.
+        * informed of a connection being made.
         */
 
        if (ch->func != NULL) {
-               dev_dbg(xpc_chan, "ch->func() called, reason=%d, partid=%d, "
-                       "channel=%d\n", ch->reason, ch->partid, ch->number);
+               dev_dbg(xpc_chan, "ch->func() called, reason=xpcDisconnecting,"
+                       " partid=%d, channel=%d\n", ch->partid, ch->number);
 
-               ch->func(ch->reason, ch->partid, ch->number, NULL, ch->key);
+               ch->func(xpcDisconnecting, ch->partid, ch->number, NULL,
+                                                               ch->key);
 
-               dev_dbg(xpc_chan, "ch->func() returned, reason=%d, partid=%d, "
-                       "channel=%d\n", ch->reason, ch->partid, ch->number);
+               dev_dbg(xpc_chan, "ch->func() returned, reason="
+                       "xpcDisconnecting, partid=%d, channel=%d\n",
+                       ch->partid, ch->number);
        }
 }
 
@@ -1848,7 +1909,7 @@ xpc_send_msg(struct xpc_channel *ch, struct xpc_msg *msg, u8 notify_type,
                        xpc_notify_func func, void *key)
 {
        enum xpc_retval ret = xpcSuccess;
-       struct xpc_notify *notify = NULL;   // >>> to keep the compiler happy!!
+       struct xpc_notify *notify = notify;
        s64 put, msg_number = msg->number;
 
 
index ed7c215..cece3c7 100644 (file)
@@ -54,6 +54,7 @@
 #include <linux/interrupt.h>
 #include <linux/slab.h>
 #include <linux/delay.h>
+#include <linux/reboot.h>
 #include <asm/sn/intr.h>
 #include <asm/sn/sn_sal.h>
 #include <asm/uaccess.h>
@@ -82,11 +83,17 @@ struct device *xpc_chan = &xpc_chan_dbg_subname;
 
 /* systune related variables for /proc/sys directories */
 
-static int xpc_hb_min = 1;
-static int xpc_hb_max = 10;
+static int xpc_hb_interval = XPC_HB_DEFAULT_INTERVAL;
+static int xpc_hb_min_interval = 1;
+static int xpc_hb_max_interval = 10;
 
-static int xpc_hb_check_min = 10;
-static int xpc_hb_check_max = 120;
+static int xpc_hb_check_interval = XPC_HB_CHECK_DEFAULT_INTERVAL;
+static int xpc_hb_check_min_interval = 10;
+static int xpc_hb_check_max_interval = 120;
+
+int xpc_disengage_request_timelimit = XPC_DISENGAGE_REQUEST_DEFAULT_TIMELIMIT;
+static int xpc_disengage_request_min_timelimit = 0;
+static int xpc_disengage_request_max_timelimit = 120;
 
 static ctl_table xpc_sys_xpc_hb_dir[] = {
        {
@@ -99,7 +106,8 @@ static ctl_table xpc_sys_xpc_hb_dir[] = {
                &proc_dointvec_minmax,
                &sysctl_intvec,
                NULL,
-               &xpc_hb_min, &xpc_hb_max
+               &xpc_hb_min_interval,
+               &xpc_hb_max_interval
        },
        {
                2,
@@ -111,7 +119,8 @@ static ctl_table xpc_sys_xpc_hb_dir[] = {
                &proc_dointvec_minmax,
                &sysctl_intvec,
                NULL,
-               &xpc_hb_check_min, &xpc_hb_check_max
+               &xpc_hb_check_min_interval,
+               &xpc_hb_check_max_interval
        },
        {0}
 };
@@ -124,6 +133,19 @@ static ctl_table xpc_sys_xpc_dir[] = {
                0555,
                xpc_sys_xpc_hb_dir
        },
+       {
+               2,
+               "disengage_request_timelimit",
+               &xpc_disengage_request_timelimit,
+               sizeof(int),
+               0644,
+               NULL,
+               &proc_dointvec_minmax,
+               &sysctl_intvec,
+               NULL,
+               &xpc_disengage_request_min_timelimit,
+               &xpc_disengage_request_max_timelimit
+       },
        {0}
 };
 static ctl_table xpc_sys_dir[] = {
@@ -148,10 +170,10 @@ static DECLARE_WAIT_QUEUE_HEAD(xpc_act_IRQ_wq);
 
 static unsigned long xpc_hb_check_timeout;
 
-/* xpc_hb_checker thread exited notification */
+/* notification that the xpc_hb_checker thread has exited */
 static DECLARE_MUTEX_LOCKED(xpc_hb_checker_exited);
 
-/* xpc_discovery thread exited notification */
+/* notification that the xpc_discovery thread has exited */
 static DECLARE_MUTEX_LOCKED(xpc_discovery_exited);
 
 
@@ -161,6 +183,30 @@ static struct timer_list xpc_hb_timer;
 static void xpc_kthread_waitmsgs(struct xpc_partition *, struct xpc_channel *);
 
 
+static int xpc_system_reboot(struct notifier_block *, unsigned long, void *);
+static struct notifier_block xpc_reboot_notifier = {
+       .notifier_call = xpc_system_reboot,
+};
+
+
+/*
+ * Timer function to enforce the timelimit on the partition disengage request.
+ */
+static void
+xpc_timeout_partition_disengage_request(unsigned long data)
+{
+       struct xpc_partition *part = (struct xpc_partition *) data;
+
+
+       DBUG_ON(jiffies < part->disengage_request_timeout);
+
+       (void) xpc_partition_disengaged(part);
+
+       DBUG_ON(part->disengage_request_timeout != 0);
+       DBUG_ON(xpc_partition_engaged(1UL << XPC_PARTID(part)) != 0);
+}
+
+
 /*
  * Notify the heartbeat check thread that an IRQ has been received.
  */
@@ -214,12 +260,6 @@ xpc_hb_checker(void *ignore)
 
        while (!(volatile int) xpc_exiting) {
 
-               /* wait for IRQ or timeout */
-               (void) wait_event_interruptible(xpc_act_IRQ_wq,
-                           (last_IRQ_count < atomic_read(&xpc_act_IRQ_rcvd) ||
-                                       jiffies >= xpc_hb_check_timeout ||
-                                               (volatile int) xpc_exiting));
-
                dev_dbg(xpc_part, "woke up with %d ticks rem; %d IRQs have "
                        "been received\n",
                        (int) (xpc_hb_check_timeout - jiffies),
@@ -240,6 +280,7 @@ xpc_hb_checker(void *ignore)
                }
 
 
+               /* check for outstanding IRQs */
                new_IRQ_count = atomic_read(&xpc_act_IRQ_rcvd);
                if (last_IRQ_count < new_IRQ_count || force_IRQ != 0) {
                        force_IRQ = 0;
@@ -257,12 +298,18 @@ xpc_hb_checker(void *ignore)
                        xpc_hb_check_timeout = jiffies +
                                           (xpc_hb_check_interval * HZ);
                }
+
+               /* wait for IRQ or timeout */
+               (void) wait_event_interruptible(xpc_act_IRQ_wq,
+                           (last_IRQ_count < atomic_read(&xpc_act_IRQ_rcvd) ||
+                                       jiffies >= xpc_hb_check_timeout ||
+                                               (volatile int) xpc_exiting));
        }
 
        dev_dbg(xpc_part, "heartbeat checker is exiting\n");
 
 
-       /* mark this thread as inactive */
+       /* mark this thread as having exited */
        up(&xpc_hb_checker_exited);
        return 0;
 }
@@ -282,7 +329,7 @@ xpc_initiate_discovery(void *ignore)
 
        dev_dbg(xpc_part, "discovery thread is exiting\n");
 
-       /* mark this thread as inactive */
+       /* mark this thread as having exited */
        up(&xpc_discovery_exited);
        return 0;
 }
@@ -309,7 +356,7 @@ xpc_make_first_contact(struct xpc_partition *part)
                        "partition %d\n", XPC_PARTID(part));
 
                /* wait a 1/4 of a second or so */
-               msleep_interruptible(250);
+               (void) msleep_interruptible(250);
 
                if (part->act_state == XPC_P_DEACTIVATING) {
                        return part->reason;
@@ -336,7 +383,8 @@ static void
 xpc_channel_mgr(struct xpc_partition *part)
 {
        while (part->act_state != XPC_P_DEACTIVATING ||
-                               atomic_read(&part->nchannels_active) > 0) {
+                       atomic_read(&part->nchannels_active) > 0 ||
+                                       !xpc_partition_disengaged(part)) {
 
                xpc_process_channel_activity(part);
 
@@ -360,7 +408,8 @@ xpc_channel_mgr(struct xpc_partition *part)
                                (volatile u64) part->local_IPI_amo != 0 ||
                                ((volatile u8) part->act_state ==
                                                        XPC_P_DEACTIVATING &&
-                               atomic_read(&part->nchannels_active) == 0)));
+                               atomic_read(&part->nchannels_active) == 0 &&
+                               xpc_partition_disengaged(part))));
                atomic_set(&part->channel_mgr_requests, 1);
 
                // >>> Does it need to wakeup periodically as well? In case we
@@ -482,7 +531,7 @@ xpc_activating(void *__partid)
                return 0;
        }
 
-       XPC_ALLOW_HB(partid, xpc_vars);
+       xpc_allow_hb(partid, xpc_vars);
        xpc_IPI_send_activated(part);
 
 
@@ -492,6 +541,7 @@ xpc_activating(void *__partid)
         */
        (void) xpc_partition_up(part);
 
+       xpc_disallow_hb(partid, xpc_vars);
        xpc_mark_partition_inactive(part);
 
        if (part->reason == xpcReactivating) {
@@ -670,6 +720,7 @@ xpc_daemonize_kthread(void *args)
        struct xpc_partition *part = &xpc_partitions[partid];
        struct xpc_channel *ch;
        int n_needed;
+       unsigned long irq_flags;
 
 
        daemonize("xpc%02dc%d", partid, ch_number);
@@ -680,11 +731,14 @@ xpc_daemonize_kthread(void *args)
        ch = &part->channels[ch_number];
 
        if (!(ch->flags & XPC_C_DISCONNECTING)) {
-               DBUG_ON(!(ch->flags & XPC_C_CONNECTED));
 
                /* let registerer know that connection has been established */
 
-               if (atomic_read(&ch->kthreads_assigned) == 1) {
+               spin_lock_irqsave(&ch->lock, irq_flags);
+               if (!(ch->flags & XPC_C_CONNECTCALLOUT)) {
+                       ch->flags |= XPC_C_CONNECTCALLOUT;
+                       spin_unlock_irqrestore(&ch->lock, irq_flags);
+
                        xpc_connected_callout(ch);
 
                        /*
@@ -699,16 +753,28 @@ xpc_daemonize_kthread(void *args)
                                        !(ch->flags & XPC_C_DISCONNECTING)) {
                                xpc_activate_kthreads(ch, n_needed);
                        }
+               } else {
+                       spin_unlock_irqrestore(&ch->lock, irq_flags);
                }
 
                xpc_kthread_waitmsgs(part, ch);
        }
 
-       if (atomic_dec_return(&ch->kthreads_assigned) == 0 &&
-                       ((ch->flags & XPC_C_CONNECTCALLOUT) ||
-                               (ch->reason != xpcUnregistering &&
-                                       ch->reason != xpcOtherUnregistering))) {
-               xpc_disconnected_callout(ch);
+       if (atomic_dec_return(&ch->kthreads_assigned) == 0) {
+               spin_lock_irqsave(&ch->lock, irq_flags);
+               if ((ch->flags & XPC_C_CONNECTCALLOUT) &&
+                               !(ch->flags & XPC_C_DISCONNECTCALLOUT)) {
+                       ch->flags |= XPC_C_DISCONNECTCALLOUT;
+                       spin_unlock_irqrestore(&ch->lock, irq_flags);
+
+                       xpc_disconnecting_callout(ch);
+               } else {
+                       spin_unlock_irqrestore(&ch->lock, irq_flags);
+               }
+               if (atomic_dec_return(&part->nchannels_engaged) == 0) {
+                       xpc_mark_partition_disengaged(part);
+                       xpc_IPI_send_disengage(part);
+               }
        }
 
 
@@ -740,12 +806,33 @@ xpc_create_kthreads(struct xpc_channel *ch, int needed)
        unsigned long irq_flags;
        pid_t pid;
        u64 args = XPC_PACK_ARGS(ch->partid, ch->number);
+       struct xpc_partition *part = &xpc_partitions[ch->partid];
 
 
        while (needed-- > 0) {
+
+               /*
+                * The following is done on behalf of the newly created
+                * kthread. That kthread is responsible for doing the
+                * counterpart to the following before it exits.
+                */
+               (void) xpc_part_ref(part);
+               xpc_msgqueue_ref(ch);
+               if (atomic_inc_return(&ch->kthreads_assigned) == 1 &&
+                   atomic_inc_return(&part->nchannels_engaged) == 1) {
+                       xpc_mark_partition_engaged(part);
+               }
+
                pid = kernel_thread(xpc_daemonize_kthread, (void *) args, 0);
                if (pid < 0) {
                        /* the fork failed */
+                       if (atomic_dec_return(&ch->kthreads_assigned) == 0 &&
+                           atomic_dec_return(&part->nchannels_engaged) == 0) {
+                               xpc_mark_partition_disengaged(part);
+                               xpc_IPI_send_disengage(part);
+                       }
+                       xpc_msgqueue_deref(ch);
+                       xpc_part_deref(part);
 
                        if (atomic_read(&ch->kthreads_assigned) <
                                                ch->kthreads_idle_limit) {
@@ -765,14 +852,6 @@ xpc_create_kthreads(struct xpc_channel *ch, int needed)
                        break;
                }
 
-               /*
-                * The following is done on behalf of the newly created
-                * kthread. That kthread is responsible for doing the
-                * counterpart to the following before it exits.
-                */
-               (void) xpc_part_ref(&xpc_partitions[ch->partid]);
-               xpc_msgqueue_ref(ch);
-               atomic_inc(&ch->kthreads_assigned);
                ch->kthreads_created++; // >>> temporary debug only!!!
        }
 }
@@ -781,87 +860,142 @@ xpc_create_kthreads(struct xpc_channel *ch, int needed)
 void
 xpc_disconnect_wait(int ch_number)
 {
+       unsigned long irq_flags;
        partid_t partid;
        struct xpc_partition *part;
        struct xpc_channel *ch;
+       int wakeup_channel_mgr;
 
 
        /* now wait for all callouts to the caller's function to cease */
        for (partid = 1; partid < XP_MAX_PARTITIONS; partid++) {
                part = &xpc_partitions[partid];
 
-               if (xpc_part_ref(part)) {
-                       ch = &part->channels[ch_number];
+               if (!xpc_part_ref(part)) {
+                       continue;
+               }
 
-// >>> how do we keep from falling into the window between our check and going
-// >>> down and coming back up where sema is re-inited?
-                       if (ch->flags & XPC_C_SETUP) {
-                               (void) down(&ch->teardown_sema);
-                       }
+               ch = &part->channels[ch_number];
 
+               if (!(ch->flags & XPC_C_WDISCONNECT)) {
                        xpc_part_deref(part);
+                       continue;
+               }
+
+               (void) down(&ch->wdisconnect_sema);
+
+               spin_lock_irqsave(&ch->lock, irq_flags);
+               DBUG_ON(!(ch->flags & XPC_C_DISCONNECTED));
+               wakeup_channel_mgr = 0;
+
+               if (ch->delayed_IPI_flags) {
+                       if (part->act_state != XPC_P_DEACTIVATING) {
+                               spin_lock(&part->IPI_lock);
+                               XPC_SET_IPI_FLAGS(part->local_IPI_amo,
+                                       ch->number, ch->delayed_IPI_flags);
+                               spin_unlock(&part->IPI_lock);
+                               wakeup_channel_mgr = 1;
+                       }
+                       ch->delayed_IPI_flags = 0;
                }
+
+               ch->flags &= ~XPC_C_WDISCONNECT;
+               spin_unlock_irqrestore(&ch->lock, irq_flags);
+
+               if (wakeup_channel_mgr) {
+                       xpc_wakeup_channel_mgr(part);
+               }
+
+               xpc_part_deref(part);
        }
 }
 
 
 static void
-xpc_do_exit(void)
+xpc_do_exit(enum xpc_retval reason)
 {
        partid_t partid;
        int active_part_count;
        struct xpc_partition *part;
+       unsigned long printmsg_time;
 
 
-       /* now it's time to eliminate our heartbeat */
-       del_timer_sync(&xpc_hb_timer);
-       xpc_vars->heartbeating_to_mask = 0;
-
-       /* indicate to others that our reserved page is uninitialized */
-       xpc_rsvd_page->vars_pa = 0;
-
-       /*
-        * Ignore all incoming interrupts. Without interupts the heartbeat
-        * checker won't activate any new partitions that may come up.
-        */
-       free_irq(SGI_XPC_ACTIVATE, NULL);
+       /* a 'rmmod XPC' and a 'reboot' cannot both end up here together */
+       DBUG_ON(xpc_exiting == 1);
 
        /*
-        * Cause the heartbeat checker and the discovery threads to exit.
-        * We don't want them attempting to activate new partitions as we
-        * try to deactivate the existing ones.
+        * Let the heartbeat checker thread and the discovery thread
+        * (if one is running) know that they should exit. Also wake up
+        * the heartbeat checker thread in case it's sleeping.
         */
        xpc_exiting = 1;
        wake_up_interruptible(&xpc_act_IRQ_wq);
 
-       /* wait for the heartbeat checker thread to mark itself inactive */
-       down(&xpc_hb_checker_exited);
+       /* ignore all incoming interrupts */
+       free_irq(SGI_XPC_ACTIVATE, NULL);
 
-       /* wait for the discovery thread to mark itself inactive */
+       /* wait for the discovery thread to exit */
        down(&xpc_discovery_exited);
 
+       /* wait for the heartbeat checker thread to exit */
+       down(&xpc_hb_checker_exited);
 
-       msleep_interruptible(300);
+
+       /* sleep for a 1/3 of a second or so */
+       (void) msleep_interruptible(300);
 
 
        /* wait for all partitions to become inactive */
 
+       printmsg_time = jiffies;
+
        do {
                active_part_count = 0;
 
                for (partid = 1; partid < XP_MAX_PARTITIONS; partid++) {
                        part = &xpc_partitions[partid];
-                       if (part->act_state != XPC_P_INACTIVE) {
-                               active_part_count++;
 
-                               XPC_DEACTIVATE_PARTITION(part, xpcUnloading);
+                       if (xpc_partition_disengaged(part) &&
+                                       part->act_state == XPC_P_INACTIVE) {
+                               continue;
                        }
+
+                       active_part_count++;
+
+                       XPC_DEACTIVATE_PARTITION(part, reason);
                }
 
-               if (active_part_count)
-                       msleep_interruptible(300);
-       } while (active_part_count > 0);
+               if (active_part_count == 0) {
+                       break;
+               }
 
+               if (jiffies >= printmsg_time) {
+                       dev_info(xpc_part, "waiting for partitions to "
+                               "deactivate/disengage, active count=%d, remote "
+                               "engaged=0x%lx\n", active_part_count,
+                               xpc_partition_engaged(1UL << partid));
+
+                       printmsg_time = jiffies +
+                                       (XPC_DISENGAGE_PRINTMSG_INTERVAL * HZ);
+               }
+
+               /* sleep for a 1/3 of a second or so */
+               (void) msleep_interruptible(300);
+
+       } while (1);
+
+       DBUG_ON(xpc_partition_engaged(-1UL));
+
+
+       /* indicate to others that our reserved page is uninitialized */
+       xpc_rsvd_page->vars_pa = 0;
+
+       /* now it's time to eliminate our heartbeat */
+       del_timer_sync(&xpc_hb_timer);
+       DBUG_ON(xpc_vars->heartbeating_to_mask != 0);
+
+       /* take ourselves off of the reboot_notifier_list */
+       (void) unregister_reboot_notifier(&xpc_reboot_notifier);
 
        /* close down protections for IPI operations */
        xpc_restrict_IPI_ops();
@@ -876,6 +1010,34 @@ xpc_do_exit(void)
 }
 
 
+/*
+ * This function is called when the system is being rebooted.
+ */
+static int
+xpc_system_reboot(struct notifier_block *nb, unsigned long event, void *unused)
+{
+       enum xpc_retval reason;
+
+
+       switch (event) {
+       case SYS_RESTART:
+               reason = xpcSystemReboot;
+               break;
+       case SYS_HALT:
+               reason = xpcSystemHalt;
+               break;
+       case SYS_POWER_OFF:
+               reason = xpcSystemPoweroff;
+               break;
+       default:
+               reason = xpcSystemGoingDown;
+       }
+
+       xpc_do_exit(reason);
+       return NOTIFY_DONE;
+}
+
+
 int __init
 xpc_init(void)
 {
@@ -891,11 +1053,11 @@ xpc_init(void)
 
        /*
         * xpc_remote_copy_buffer is used as a temporary buffer for bte_copy'ng
-        * both a partition's reserved page and its XPC variables. Its size was
-        * based on the size of a reserved page. So we need to ensure that the
-        * XPC variables will fit as well.
+        * various portions of a partition's reserved page. Its size is based
+        * on the size of the reserved page header and part_nasids mask. So we
+        * need to ensure that the other items will fit as well.
         */
-       if (XPC_VARS_ALIGNED_SIZE > XPC_RSVD_PAGE_ALIGNED_SIZE) {
+       if (XPC_RP_VARS_SIZE > XPC_RP_HEADER_SIZE + XP_NASID_MASK_BYTES) {
                dev_err(xpc_part, "xpc_remote_copy_buffer is not big enough\n");
                return -EPERM;
        }
@@ -924,6 +1086,12 @@ xpc_init(void)
                spin_lock_init(&part->act_lock);
                part->act_state = XPC_P_INACTIVE;
                XPC_SET_REASON(part, 0, 0);
+
+               init_timer(&part->disengage_request_timer);
+               part->disengage_request_timer.function =
+                               xpc_timeout_partition_disengage_request;
+               part->disengage_request_timer.data = (unsigned long) part;
+
                part->setup_state = XPC_P_UNSET;
                init_waitqueue_head(&part->teardown_wq);
                atomic_set(&part->references, 0);
@@ -980,6 +1148,13 @@ xpc_init(void)
        }
 
 
+       /* add ourselves to the reboot_notifier_list */
+       ret = register_reboot_notifier(&xpc_reboot_notifier);
+       if (ret != 0) {
+               dev_warn(xpc_part, "can't register reboot notifier\n");
+       }
+
+
        /*
         * Set the beating to other partitions into motion.  This is
         * the last requirement for other partitions' discovery to
@@ -1001,6 +1176,9 @@ xpc_init(void)
                /* indicate to others that our reserved page is uninitialized */
                xpc_rsvd_page->vars_pa = 0;
 
+               /* take ourselves off of the reboot_notifier_list */
+               (void) unregister_reboot_notifier(&xpc_reboot_notifier);
+
                del_timer_sync(&xpc_hb_timer);
                free_irq(SGI_XPC_ACTIVATE, NULL);
                xpc_restrict_IPI_ops();
@@ -1024,7 +1202,7 @@ xpc_init(void)
                /* mark this new thread as a non-starter */
                up(&xpc_discovery_exited);
 
-               xpc_do_exit();
+               xpc_do_exit(xpcUnloading);
                return -EBUSY;
        }
 
@@ -1043,7 +1221,7 @@ module_init(xpc_init);
 void __exit
 xpc_exit(void)
 {
-       xpc_do_exit();
+       xpc_do_exit(xpcUnloading);
 }
 module_exit(xpc_exit);
 
@@ -1060,3 +1238,7 @@ module_param(xpc_hb_check_interval, int, 0);
 MODULE_PARM_DESC(xpc_hb_check_interval, "Number of seconds between "
                "heartbeat checks.");
 
+module_param(xpc_disengage_request_timelimit, int, 0);
+MODULE_PARM_DESC(xpc_disengage_request_timelimit, "Number of seconds to wait "
+               "for disengage request to complete.");
+
index 578265e..581e113 100644 (file)
@@ -44,16 +44,19 @@ static u64 xpc_sh2_IPI_access3;
 
 
 /* original protection values for each node */
-u64 xpc_prot_vec[MAX_COMPACT_NODES];
+u64 xpc_prot_vec[MAX_NUMNODES];
 
 
-/* this partition's reserved page */
+/* this partition's reserved page pointers */
 struct xpc_rsvd_page *xpc_rsvd_page;
-
-/* this partition's XPC variables (within the reserved page) */
+static u64 *xpc_part_nasids;
+static u64 *xpc_mach_nasids;
 struct xpc_vars *xpc_vars;
 struct xpc_vars_part *xpc_vars_part;
 
+static int xp_nasid_mask_bytes;        /* actual size in bytes of nasid mask */
+static int xp_nasid_mask_words;        /* actual size in words of nasid mask */
+
 
 /*
  * For performance reasons, each entry of xpc_partitions[] is cacheline
@@ -65,20 +68,16 @@ struct xpc_partition xpc_partitions[XP_MAX_PARTITIONS + 1];
 
 
 /*
- * Generic buffer used to store a local copy of the remote partitions
- * reserved page or XPC variables.
+ * Generic buffer used to store a local copy of portions of a remote
+ * partition's reserved page (either its header and part_nasids mask,
+ * or its vars).
  *
  * xpc_discovery runs only once and is a seperate thread that is
  * very likely going to be processing in parallel with receiving
  * interrupts.
  */
-char ____cacheline_aligned
-               xpc_remote_copy_buffer[XPC_RSVD_PAGE_ALIGNED_SIZE];
-
-
-/* systune related variables */
-int xpc_hb_interval = XPC_HB_DEFAULT_INTERVAL;
-int xpc_hb_check_interval = XPC_HB_CHECK_DEFAULT_TIMEOUT;
+char ____cacheline_aligned xpc_remote_copy_buffer[XPC_RP_HEADER_SIZE +
+                                                       XP_NASID_MASK_BYTES];
 
 
 /*
@@ -86,13 +85,16 @@ int xpc_hb_check_interval = XPC_HB_CHECK_DEFAULT_TIMEOUT;
  * for that nasid. This function returns 0 on any error.
  */
 static u64
-xpc_get_rsvd_page_pa(int nasid, u64 buf, u64 buf_size)
+xpc_get_rsvd_page_pa(int nasid)
 {
        bte_result_t bte_res;
        s64 status;
        u64 cookie = 0;
        u64 rp_pa = nasid;      /* seed with nasid */
        u64 len = 0;
+       u64 buf = buf;
+       u64 buf_len = 0;
+       void *buf_base = NULL;
 
 
        while (1) {
@@ -108,13 +110,22 @@ xpc_get_rsvd_page_pa(int nasid, u64 buf, u64 buf_size)
                        break;
                }
 
-               if (len > buf_size) {
-                       dev_err(xpc_part, "len (=0x%016lx) > buf_size\n", len);
-                       status = SALRET_ERROR;
-                       break;
+               if (L1_CACHE_ALIGN(len) > buf_len) {
+                       if (buf_base != NULL) {
+                               kfree(buf_base);
+                       }
+                       buf_len = L1_CACHE_ALIGN(len);
+                       buf = (u64) xpc_kmalloc_cacheline_aligned(buf_len,
+                                                       GFP_KERNEL, &buf_base);
+                       if (buf_base == NULL) {
+                               dev_err(xpc_part, "unable to kmalloc "
+                                       "len=0x%016lx\n", buf_len);
+                               status = SALRET_ERROR;
+                               break;
+                       }
                }
 
-               bte_res = xp_bte_copy(rp_pa, ia64_tpa(buf), buf_size,
+               bte_res = xp_bte_copy(rp_pa, ia64_tpa(buf), buf_len,
                                        (BTE_NOTIFY | BTE_WACQUIRE), NULL);
                if (bte_res != BTE_SUCCESS) {
                        dev_dbg(xpc_part, "xp_bte_copy failed %i\n", bte_res);
@@ -123,6 +134,10 @@ xpc_get_rsvd_page_pa(int nasid, u64 buf, u64 buf_size)
                }
        }
 
+       if (buf_base != NULL) {
+               kfree(buf_base);
+       }
+
        if (status != SALRET_OK) {
                rp_pa = 0;
        }
@@ -141,15 +156,15 @@ xpc_rsvd_page_init(void)
 {
        struct xpc_rsvd_page *rp;
        AMO_t *amos_page;
-       u64 rp_pa, next_cl, nasid_array = 0;
+       u64 rp_pa, nasid_array = 0;
        int i, ret;
 
 
        /* get the local reserved page's address */
 
-       rp_pa = xpc_get_rsvd_page_pa(cnodeid_to_nasid(0),
-                                       (u64) xpc_remote_copy_buffer,
-                                               XPC_RSVD_PAGE_ALIGNED_SIZE);
+       preempt_disable();
+       rp_pa = xpc_get_rsvd_page_pa(cpuid_to_nasid(smp_processor_id()));
+       preempt_enable();
        if (rp_pa == 0) {
                dev_err(xpc_part, "SAL failed to locate the reserved page\n");
                return NULL;
@@ -164,12 +179,19 @@ xpc_rsvd_page_init(void)
 
        rp->version = XPC_RP_VERSION;
 
-       /*
-        * Place the XPC variables on the cache line following the
-        * reserved page structure.
-        */
-       next_cl = (u64) rp + XPC_RSVD_PAGE_ALIGNED_SIZE;
-       xpc_vars = (struct xpc_vars *) next_cl;
+       /* establish the actual sizes of the nasid masks */
+       if (rp->SAL_version == 1) {
+               /* SAL_version 1 didn't set the nasids_size field */
+               rp->nasids_size = 128;
+       }
+       xp_nasid_mask_bytes = rp->nasids_size;
+       xp_nasid_mask_words = xp_nasid_mask_bytes / 8;
+
+       /* setup the pointers to the various items in the reserved page */
+       xpc_part_nasids = XPC_RP_PART_NASIDS(rp);
+       xpc_mach_nasids = XPC_RP_MACH_NASIDS(rp);
+       xpc_vars = XPC_RP_VARS(rp);
+       xpc_vars_part = XPC_RP_VARS_PART(rp);
 
        /*
         * Before clearing xpc_vars, see if a page of AMOs had been previously
@@ -221,33 +243,32 @@ xpc_rsvd_page_init(void)
                amos_page = (AMO_t *) TO_AMO((u64) amos_page);
        }
 
+       /* clear xpc_vars */
        memset(xpc_vars, 0, sizeof(struct xpc_vars));
 
-       /*
-        * Place the XPC per partition specific variables on the cache line
-        * following the XPC variables structure.
-        */
-       next_cl += XPC_VARS_ALIGNED_SIZE;
-       memset((u64 *) next_cl, 0, sizeof(struct xpc_vars_part) *
-                                                       XP_MAX_PARTITIONS);
-       xpc_vars_part = (struct xpc_vars_part *) next_cl;
-       xpc_vars->vars_part_pa = __pa(next_cl);
-
        xpc_vars->version = XPC_V_VERSION;
        xpc_vars->act_nasid = cpuid_to_nasid(0);
        xpc_vars->act_phys_cpuid = cpu_physical_id(0);
+       xpc_vars->vars_part_pa = __pa(xpc_vars_part);
+       xpc_vars->amos_page_pa = ia64_tpa((u64) amos_page);
        xpc_vars->amos_page = amos_page;  /* save for next load of XPC */
 
 
-       /*
-        * Initialize the activation related AMO variables.
-        */
-       xpc_vars->act_amos = xpc_IPI_init(XP_MAX_PARTITIONS);
-       for (i = 1; i < XP_NASID_MASK_WORDS; i++) {
-               xpc_IPI_init(i + XP_MAX_PARTITIONS);
+       /* clear xpc_vars_part */
+       memset((u64 *) xpc_vars_part, 0, sizeof(struct xpc_vars_part) *
+                                                       XP_MAX_PARTITIONS);
+
+       /* initialize the activate IRQ related AMO variables */
+       for (i = 0; i < xp_nasid_mask_words; i++) {
+               (void) xpc_IPI_init(XPC_ACTIVATE_IRQ_AMOS + i);
        }
-       /* export AMO page's physical address to other partitions */
-       xpc_vars->amos_page_pa = ia64_tpa((u64) xpc_vars->amos_page);
+
+       /* initialize the engaged remote partitions related AMO variables */
+       (void) xpc_IPI_init(XPC_ENGAGED_PARTITIONS_AMO);
+       (void) xpc_IPI_init(XPC_DISENGAGE_REQUEST_AMO);
+
+       /* timestamp of when reserved page was setup by XPC */
+       rp->stamp = CURRENT_TIME;
 
        /*
         * This signifies to the remote partition that our reserved
@@ -387,6 +408,11 @@ xpc_check_remote_hb(void)
        remote_vars = (struct xpc_vars *) xpc_remote_copy_buffer;
 
        for (partid = 1; partid < XP_MAX_PARTITIONS; partid++) {
+
+               if (xpc_exiting) {
+                       break;
+               }
+
                if (partid == sn_partition_id) {
                        continue;
                }
@@ -401,7 +427,7 @@ xpc_check_remote_hb(void)
                /* pull the remote_hb cache line */
                bres = xp_bte_copy(part->remote_vars_pa,
                                        ia64_tpa((u64) remote_vars),
-                                       XPC_VARS_ALIGNED_SIZE,
+                                       XPC_RP_VARS_SIZE,
                                        (BTE_NOTIFY | BTE_WACQUIRE), NULL);
                if (bres != BTE_SUCCESS) {
                        XPC_DEACTIVATE_PARTITION(part,
@@ -417,7 +443,7 @@ xpc_check_remote_hb(void)
 
                if (((remote_vars->heartbeat == part->last_heartbeat) &&
                        (remote_vars->kdb_status == 0)) ||
-                            !XPC_HB_ALLOWED(sn_partition_id, remote_vars)) {
+                            !xpc_hb_allowed(sn_partition_id, remote_vars)) {
 
                        XPC_DEACTIVATE_PARTITION(part, xpcNoHeartbeat);
                        continue;
@@ -429,31 +455,31 @@ xpc_check_remote_hb(void)
 
 
 /*
- * Get a copy of the remote partition's rsvd page.
+ * Get a copy of a portion of the remote partition's rsvd page.
  *
  * remote_rp points to a buffer that is cacheline aligned for BTE copies and
- * assumed to be of size XPC_RSVD_PAGE_ALIGNED_SIZE.
+ * is large enough to contain a copy of their reserved page header and
+ * part_nasids mask.
  */
 static enum xpc_retval
 xpc_get_remote_rp(int nasid, u64 *discovered_nasids,
-               struct xpc_rsvd_page *remote_rp, u64 *remote_rsvd_page_pa)
+               struct xpc_rsvd_page *remote_rp, u64 *remote_rp_pa)
 {
        int bres, i;
 
 
        /* get the reserved page's physical address */
 
-       *remote_rsvd_page_pa = xpc_get_rsvd_page_pa(nasid, (u64) remote_rp,
-                                               XPC_RSVD_PAGE_ALIGNED_SIZE);
-       if (*remote_rsvd_page_pa == 0) {
+       *remote_rp_pa = xpc_get_rsvd_page_pa(nasid);
+       if (*remote_rp_pa == 0) {
                return xpcNoRsvdPageAddr;
        }
 
 
-       /* pull over the reserved page structure */
+       /* pull over the reserved page header and part_nasids mask */
 
-       bres = xp_bte_copy(*remote_rsvd_page_pa, ia64_tpa((u64) remote_rp),
-                               XPC_RSVD_PAGE_ALIGNED_SIZE,
+       bres = xp_bte_copy(*remote_rp_pa, ia64_tpa((u64) remote_rp),
+                               XPC_RP_HEADER_SIZE + xp_nasid_mask_bytes,
                                (BTE_NOTIFY | BTE_WACQUIRE), NULL);
        if (bres != BTE_SUCCESS) {
                return xpc_map_bte_errors(bres);
@@ -461,8 +487,11 @@ xpc_get_remote_rp(int nasid, u64 *discovered_nasids,
 
 
        if (discovered_nasids != NULL) {
-               for (i = 0; i < XP_NASID_MASK_WORDS; i++) {
-                       discovered_nasids[i] |= remote_rp->part_nasids[i];
+               u64 *remote_part_nasids = XPC_RP_PART_NASIDS(remote_rp);
+
+
+               for (i = 0; i < xp_nasid_mask_words; i++) {
+                       discovered_nasids[i] |= remote_part_nasids[i];
                }
        }
 
@@ -489,10 +518,10 @@ xpc_get_remote_rp(int nasid, u64 *discovered_nasids,
 
 
 /*
- * Get a copy of the remote partition's XPC variables.
+ * Get a copy of the remote partition's XPC variables from the reserved page.
  *
  * remote_vars points to a buffer that is cacheline aligned for BTE copies and
- * assumed to be of size XPC_VARS_ALIGNED_SIZE.
+ * assumed to be of size XPC_RP_VARS_SIZE.
  */
 static enum xpc_retval
 xpc_get_remote_vars(u64 remote_vars_pa, struct xpc_vars *remote_vars)
@@ -508,7 +537,7 @@ xpc_get_remote_vars(u64 remote_vars_pa, struct xpc_vars *remote_vars)
        /* pull over the cross partition variables */
 
        bres = xp_bte_copy(remote_vars_pa, ia64_tpa((u64) remote_vars),
-                               XPC_VARS_ALIGNED_SIZE,
+                               XPC_RP_VARS_SIZE,
                                (BTE_NOTIFY | BTE_WACQUIRE), NULL);
        if (bres != BTE_SUCCESS) {
                return xpc_map_bte_errors(bres);
@@ -524,7 +553,56 @@ xpc_get_remote_vars(u64 remote_vars_pa, struct xpc_vars *remote_vars)
 
 
 /*
- * Prior code has determine the nasid which generated an IPI.  Inspect
+ * Update the remote partition's info.
+ */
+static void
+xpc_update_partition_info(struct xpc_partition *part, u8 remote_rp_version,
+               struct timespec *remote_rp_stamp, u64 remote_rp_pa,
+               u64 remote_vars_pa, struct xpc_vars *remote_vars)
+{
+       part->remote_rp_version = remote_rp_version;
+       dev_dbg(xpc_part, "  remote_rp_version = 0x%016lx\n",
+               part->remote_rp_version);
+
+       part->remote_rp_stamp = *remote_rp_stamp;
+       dev_dbg(xpc_part, "  remote_rp_stamp (tv_sec = 0x%lx tv_nsec = 0x%lx\n",
+               part->remote_rp_stamp.tv_sec, part->remote_rp_stamp.tv_nsec);
+
+       part->remote_rp_pa = remote_rp_pa;
+       dev_dbg(xpc_part, "  remote_rp_pa = 0x%016lx\n", part->remote_rp_pa);
+
+       part->remote_vars_pa = remote_vars_pa;
+       dev_dbg(xpc_part, "  remote_vars_pa = 0x%016lx\n",
+               part->remote_vars_pa);
+
+       part->last_heartbeat = remote_vars->heartbeat;
+       dev_dbg(xpc_part, "  last_heartbeat = 0x%016lx\n",
+               part->last_heartbeat);
+
+       part->remote_vars_part_pa = remote_vars->vars_part_pa;
+       dev_dbg(xpc_part, "  remote_vars_part_pa = 0x%016lx\n",
+               part->remote_vars_part_pa);
+
+       part->remote_act_nasid = remote_vars->act_nasid;
+       dev_dbg(xpc_part, "  remote_act_nasid = 0x%x\n",
+               part->remote_act_nasid);
+
+       part->remote_act_phys_cpuid = remote_vars->act_phys_cpuid;
+       dev_dbg(xpc_part, "  remote_act_phys_cpuid = 0x%x\n",
+               part->remote_act_phys_cpuid);
+
+       part->remote_amos_page_pa = remote_vars->amos_page_pa;
+       dev_dbg(xpc_part, "  remote_amos_page_pa = 0x%lx\n",
+               part->remote_amos_page_pa);
+
+       part->remote_vars_version = remote_vars->version;
+       dev_dbg(xpc_part, "  remote_vars_version = 0x%x\n",
+               part->remote_vars_version);
+}
+
+
+/*
+ * Prior code has determined the nasid which generated an IPI.  Inspect
  * that nasid to determine if its partition needs to be activated or
  * deactivated.
  *
@@ -542,8 +620,12 @@ xpc_identify_act_IRQ_req(int nasid)
 {
        struct xpc_rsvd_page *remote_rp;
        struct xpc_vars *remote_vars;
-       u64 remote_rsvd_page_pa;
+       u64 remote_rp_pa;
        u64 remote_vars_pa;
+       int remote_rp_version;
+       int reactivate = 0;
+       int stamp_diff;
+       struct timespec remote_rp_stamp = { 0, 0 };
        partid_t partid;
        struct xpc_partition *part;
        enum xpc_retval ret;
@@ -553,7 +635,7 @@ xpc_identify_act_IRQ_req(int nasid)
 
        remote_rp = (struct xpc_rsvd_page *) xpc_remote_copy_buffer;
 
-       ret = xpc_get_remote_rp(nasid, NULL, remote_rp, &remote_rsvd_page_pa);
+       ret = xpc_get_remote_rp(nasid, NULL, remote_rp, &remote_rp_pa);
        if (ret != xpcSuccess) {
                dev_warn(xpc_part, "unable to get reserved page from nasid %d, "
                        "which sent interrupt, reason=%d\n", nasid, ret);
@@ -561,6 +643,10 @@ xpc_identify_act_IRQ_req(int nasid)
        }
 
        remote_vars_pa = remote_rp->vars_pa;
+       remote_rp_version = remote_rp->version;
+       if (XPC_SUPPORTS_RP_STAMP(remote_rp_version)) {
+               remote_rp_stamp = remote_rp->stamp;
+       }
        partid = remote_rp->partid;
        part = &xpc_partitions[partid];
 
@@ -586,44 +672,117 @@ xpc_identify_act_IRQ_req(int nasid)
                "%ld:0x%lx\n", (int) nasid, (int) partid, part->act_IRQ_rcvd,
                remote_vars->heartbeat, remote_vars->heartbeating_to_mask);
 
+       if (xpc_partition_disengaged(part) &&
+                                       part->act_state == XPC_P_INACTIVE) {
 
-       if (part->act_state == XPC_P_INACTIVE) {
+               xpc_update_partition_info(part, remote_rp_version,
+                                       &remote_rp_stamp, remote_rp_pa,
+                                       remote_vars_pa, remote_vars);
 
-               part->remote_rp_pa = remote_rsvd_page_pa;
-               dev_dbg(xpc_part, "  remote_rp_pa = 0x%016lx\n",
-                       part->remote_rp_pa);
+               if (XPC_SUPPORTS_DISENGAGE_REQUEST(part->remote_vars_version)) {
+                       if (xpc_partition_disengage_requested(1UL << partid)) {
+                               /*
+                                * Other side is waiting on us to disengage,
+                                * even though we already have.
+                                */
+                               return;
+                       }
+               } else {
+                       /* other side doesn't support disengage requests */
+                       xpc_clear_partition_disengage_request(1UL << partid);
+               }
 
-               part->remote_vars_pa = remote_vars_pa;
-               dev_dbg(xpc_part, "  remote_vars_pa = 0x%016lx\n",
-                       part->remote_vars_pa);
+               xpc_activate_partition(part);
+               return;
+       }
 
-               part->last_heartbeat = remote_vars->heartbeat;
-               dev_dbg(xpc_part, "  last_heartbeat = 0x%016lx\n",
-                       part->last_heartbeat);
+       DBUG_ON(part->remote_rp_version == 0);
+       DBUG_ON(part->remote_vars_version == 0);
+
+       if (!XPC_SUPPORTS_RP_STAMP(part->remote_rp_version)) {
+               DBUG_ON(XPC_SUPPORTS_DISENGAGE_REQUEST(part->
+                                                       remote_vars_version));
+
+               if (!XPC_SUPPORTS_RP_STAMP(remote_rp_version)) {
+                       DBUG_ON(XPC_SUPPORTS_DISENGAGE_REQUEST(remote_vars->
+                                                               version));
+                       /* see if the other side rebooted */
+                       if (part->remote_amos_page_pa ==
+                               remote_vars->amos_page_pa &&
+                                       xpc_hb_allowed(sn_partition_id,
+                                                               remote_vars)) {
+                               /* doesn't look that way, so ignore the IPI */
+                               return;
+                       }
+               }
 
-               part->remote_vars_part_pa = remote_vars->vars_part_pa;
-               dev_dbg(xpc_part, "  remote_vars_part_pa = 0x%016lx\n",
-                       part->remote_vars_part_pa);
+               /*
+                * Other side rebooted and previous XPC didn't support the
+                * disengage request, so we don't need to do anything special.
+                */
 
-               part->remote_act_nasid = remote_vars->act_nasid;
-               dev_dbg(xpc_part, "  remote_act_nasid = 0x%x\n",
-                       part->remote_act_nasid);
+               xpc_update_partition_info(part, remote_rp_version,
+                                               &remote_rp_stamp, remote_rp_pa,
+                                               remote_vars_pa, remote_vars);
+               part->reactivate_nasid = nasid;
+               XPC_DEACTIVATE_PARTITION(part, xpcReactivating);
+               return;
+       }
 
-               part->remote_act_phys_cpuid = remote_vars->act_phys_cpuid;
-               dev_dbg(xpc_part, "  remote_act_phys_cpuid = 0x%x\n",
-                       part->remote_act_phys_cpuid);
+       DBUG_ON(!XPC_SUPPORTS_DISENGAGE_REQUEST(part->remote_vars_version));
 
-               part->remote_amos_page_pa = remote_vars->amos_page_pa;
-               dev_dbg(xpc_part, "  remote_amos_page_pa = 0x%lx\n",
-                       part->remote_amos_page_pa);
+       if (!XPC_SUPPORTS_RP_STAMP(remote_rp_version)) {
+               DBUG_ON(!XPC_SUPPORTS_DISENGAGE_REQUEST(remote_vars->version));
 
-               xpc_activate_partition(part);
+               /*
+                * Other side rebooted and previous XPC did support the
+                * disengage request, but the new one doesn't.
+                */
+
+               xpc_clear_partition_engaged(1UL << partid);
+               xpc_clear_partition_disengage_request(1UL << partid);
 
-       } else if (part->remote_amos_page_pa != remote_vars->amos_page_pa ||
-                       !XPC_HB_ALLOWED(sn_partition_id, remote_vars)) {
+               xpc_update_partition_info(part, remote_rp_version,
+                                               &remote_rp_stamp, remote_rp_pa,
+                                               remote_vars_pa, remote_vars);
+               reactivate = 1;
+
+       } else {
+               DBUG_ON(!XPC_SUPPORTS_DISENGAGE_REQUEST(remote_vars->version));
 
+               stamp_diff = xpc_compare_stamps(&part->remote_rp_stamp,
+                                                       &remote_rp_stamp);
+               if (stamp_diff != 0) {
+                       DBUG_ON(stamp_diff >= 0);
+
+                       /*
+                        * Other side rebooted and the previous XPC did support
+                        * the disengage request, as does the new one.
+                        */
+
+                       DBUG_ON(xpc_partition_engaged(1UL << partid));
+                       DBUG_ON(xpc_partition_disengage_requested(1UL <<
+                                                               partid));
+
+                       xpc_update_partition_info(part, remote_rp_version,
+                                               &remote_rp_stamp, remote_rp_pa,
+                                               remote_vars_pa, remote_vars);
+                       reactivate = 1;
+               }
+       }
+
+       if (!xpc_partition_disengaged(part)) {
+               /* still waiting on other side to disengage from us */
+               return;
+       }
+
+       if (reactivate) {
                part->reactivate_nasid = nasid;
                XPC_DEACTIVATE_PARTITION(part, xpcReactivating);
+
+       } else if (XPC_SUPPORTS_DISENGAGE_REQUEST(part->remote_vars_version) &&
+                       xpc_partition_disengage_requested(1UL << partid)) {
+               XPC_DEACTIVATE_PARTITION(part, xpcOtherGoingDown);
        }
 }
 
@@ -643,14 +802,17 @@ xpc_identify_act_IRQ_sender(void)
        u64 nasid;                      /* remote nasid */
        int n_IRQs_detected = 0;
        AMO_t *act_amos;
-       struct xpc_rsvd_page *rp = (struct xpc_rsvd_page *) xpc_rsvd_page;
 
 
-       act_amos = xpc_vars->act_amos;
+       act_amos = xpc_vars->amos_page + XPC_ACTIVATE_IRQ_AMOS;
 
 
        /* scan through act AMO variable looking for non-zero entries */
-       for (word = 0; word < XP_NASID_MASK_WORDS; word++) {
+       for (word = 0; word < xp_nasid_mask_words; word++) {
+
+               if (xpc_exiting) {
+                       break;
+               }
 
                nasid_mask = xpc_IPI_receive(&act_amos[word]);
                if (nasid_mask == 0) {
@@ -668,7 +830,7 @@ xpc_identify_act_IRQ_sender(void)
                 * remote nasid in our reserved pages machine mask.
                 * This is used in the event of module reload.
                 */
-               rp->mach_nasids[word] |= nasid_mask;
+               xpc_mach_nasids[word] |= nasid_mask;
 
 
                /* locate the nasid(s) which sent interrupts */
@@ -687,6 +849,55 @@ xpc_identify_act_IRQ_sender(void)
 }
 
 
+/*
+ * See if the other side has responded to a partition disengage request
+ * from us.
+ */
+int
+xpc_partition_disengaged(struct xpc_partition *part)
+{
+       partid_t partid = XPC_PARTID(part);
+       int disengaged;
+
+
+       disengaged = (xpc_partition_engaged(1UL << partid) == 0);
+       if (part->disengage_request_timeout) {
+               if (!disengaged) {
+                       if (jiffies < part->disengage_request_timeout) {
+                               /* timelimit hasn't been reached yet */
+                               return 0;
+                       }
+
+                       /*
+                        * Other side hasn't responded to our disengage
+                        * request in a timely fashion, so assume it's dead.
+                        */
+
+                       xpc_clear_partition_engaged(1UL << partid);
+                       disengaged = 1;
+               }
+               part->disengage_request_timeout = 0;
+
+               /* cancel the timer function, provided it's not us */
+               if (!in_interrupt()) {
+                       del_singleshot_timer_sync(&part->
+                                                     disengage_request_timer);
+               }
+
+               DBUG_ON(part->act_state != XPC_P_DEACTIVATING &&
+                                       part->act_state != XPC_P_INACTIVE);
+               if (part->act_state != XPC_P_INACTIVE) {
+                       xpc_wakeup_channel_mgr(part);
+               }
+
+               if (XPC_SUPPORTS_DISENGAGE_REQUEST(part->remote_vars_version)) {
+                       xpc_cancel_partition_disengage_request(part);
+               }
+       }
+       return disengaged;
+}
+
+
 /*
  * Mark specified partition as active.
  */
@@ -721,7 +932,6 @@ xpc_deactivate_partition(const int line, struct xpc_partition *part,
                                enum xpc_retval reason)
 {
        unsigned long irq_flags;
-       partid_t partid = XPC_PARTID(part);
 
 
        spin_lock_irqsave(&part->act_lock, irq_flags);
@@ -749,17 +959,27 @@ xpc_deactivate_partition(const int line, struct xpc_partition *part,
 
        spin_unlock_irqrestore(&part->act_lock, irq_flags);
 
-       XPC_DISALLOW_HB(partid, xpc_vars);
+       if (XPC_SUPPORTS_DISENGAGE_REQUEST(part->remote_vars_version)) {
+               xpc_request_partition_disengage(part);
+               xpc_IPI_send_disengage(part);
 
-       dev_dbg(xpc_part, "bringing partition %d down, reason = %d\n", partid,
-               reason);
+               /* set a timelimit on the disengage request */
+               part->disengage_request_timeout = jiffies +
+                                       (xpc_disengage_request_timelimit * HZ);
+               part->disengage_request_timer.expires =
+                                       part->disengage_request_timeout;
+               add_timer(&part->disengage_request_timer);
+       }
+
+       dev_dbg(xpc_part, "bringing partition %d down, reason = %d\n",
+               XPC_PARTID(part), reason);
 
-       xpc_partition_down(part, reason);
+       xpc_partition_going_down(part, reason);
 }
 
 
 /*
- * Mark specified partition as active.
+ * Mark specified partition as inactive.
  */
 void
 xpc_mark_partition_inactive(struct xpc_partition *part)
@@ -792,9 +1012,10 @@ xpc_discovery(void)
        void *remote_rp_base;
        struct xpc_rsvd_page *remote_rp;
        struct xpc_vars *remote_vars;
-       u64 remote_rsvd_page_pa;
+       u64 remote_rp_pa;
        u64 remote_vars_pa;
        int region;
+       int region_size;
        int max_regions;
        int nasid;
        struct xpc_rsvd_page *rp;
@@ -804,7 +1025,8 @@ xpc_discovery(void)
        enum xpc_retval ret;
 
 
-       remote_rp = xpc_kmalloc_cacheline_aligned(XPC_RSVD_PAGE_ALIGNED_SIZE,
+       remote_rp = xpc_kmalloc_cacheline_aligned(XPC_RP_HEADER_SIZE +
+                                               xp_nasid_mask_bytes,
                                                GFP_KERNEL, &remote_rp_base);
        if (remote_rp == NULL) {
                return;
@@ -812,13 +1034,13 @@ xpc_discovery(void)
        remote_vars = (struct xpc_vars *) remote_rp;
 
 
-       discovered_nasids = kmalloc(sizeof(u64) * XP_NASID_MASK_WORDS,
+       discovered_nasids = kmalloc(sizeof(u64) * xp_nasid_mask_words,
                                                        GFP_KERNEL);
        if (discovered_nasids == NULL) {
                kfree(remote_rp_base);
                return;
        }
-       memset(discovered_nasids, 0, sizeof(u64) * XP_NASID_MASK_WORDS);
+       memset(discovered_nasids, 0, sizeof(u64) * xp_nasid_mask_words);
 
        rp = (struct xpc_rsvd_page *) xpc_rsvd_page;
 
@@ -827,11 +1049,19 @@ xpc_discovery(void)
         * nodes that can comprise an access protection grouping. The access
         * protection is in regards to memory, IOI and IPI.
         */
-//>>> move the next two #defines into either include/asm-ia64/sn/arch.h or
-//>>> include/asm-ia64/sn/addrs.h
-#define SH1_MAX_REGIONS                64
-#define SH2_MAX_REGIONS                256
-       max_regions = is_shub2() ? SH2_MAX_REGIONS : SH1_MAX_REGIONS;
+       max_regions = 64;
+       region_size = sn_region_size;
+
+       switch (region_size) {
+       case 128:
+               max_regions *= 2;
+       case 64:
+               max_regions *= 2;
+       case 32:
+               max_regions *= 2;
+               region_size = 16;
+               DBUG_ON(!is_shub2());
+       }
 
        for (region = 0; region < max_regions; region++) {
 
@@ -841,8 +1071,8 @@ xpc_discovery(void)
 
                dev_dbg(xpc_part, "searching region %d\n", region);
 
-               for (nasid = (region * sn_region_size * 2);
-                    nasid < ((region + 1) * sn_region_size * 2);
+               for (nasid = (region * region_size * 2);
+                    nasid < ((region + 1) * region_size * 2);
                     nasid += 2) {
 
                        if ((volatile int) xpc_exiting) {
@@ -852,14 +1082,14 @@ xpc_discovery(void)
                        dev_dbg(xpc_part, "checking nasid %d\n", nasid);
 
 
-                       if (XPC_NASID_IN_ARRAY(nasid, rp->part_nasids)) {
+                       if (XPC_NASID_IN_ARRAY(nasid, xpc_part_nasids)) {
                                dev_dbg(xpc_part, "PROM indicates Nasid %d is "
                                        "part of the local partition; skipping "
                                        "region\n", nasid);
                                break;
                        }
 
-                       if (!(XPC_NASID_IN_ARRAY(nasid, rp->mach_nasids))) {
+                       if (!(XPC_NASID_IN_ARRAY(nasid, xpc_mach_nasids))) {
                                dev_dbg(xpc_part, "PROM indicates Nasid %d was "
                                        "not on Numa-Link network at reset\n",
                                        nasid);
@@ -877,7 +1107,7 @@ xpc_discovery(void)
                        /* pull over the reserved page structure */
 
                        ret = xpc_get_remote_rp(nasid, discovered_nasids,
-                                             remote_rp, &remote_rsvd_page_pa);
+                                             remote_rp, &remote_rp_pa);
                        if (ret != xpcSuccess) {
                                dev_dbg(xpc_part, "unable to get reserved page "
                                        "from nasid %d, reason=%d\n", nasid,
@@ -948,6 +1178,13 @@ xpc_discovery(void)
                                remote_vars->act_nasid,
                                remote_vars->act_phys_cpuid);
 
+                       if (XPC_SUPPORTS_DISENGAGE_REQUEST(remote_vars->
+                                                               version)) {
+                               part->remote_amos_page_pa =
+                                               remote_vars->amos_page_pa;
+                               xpc_mark_partition_disengaged(part);
+                               xpc_cancel_partition_disengage_request(part);
+                       }
                        xpc_IPI_send_activate(remote_vars);
                }
        }
@@ -974,12 +1211,12 @@ xpc_initiate_partid_to_nasids(partid_t partid, void *nasid_mask)
                return xpcPartitionDown;
        }
 
-       part_nasid_pa = part->remote_rp_pa +
-               (u64) &((struct xpc_rsvd_page *) 0)->part_nasids;
+       memset(nasid_mask, 0, XP_NASID_MASK_BYTES);
+
+       part_nasid_pa = (u64) XPC_RP_PART_NASIDS(part->remote_rp_pa);
 
        bte_res = xp_bte_copy(part_nasid_pa, ia64_tpa((u64) nasid_mask),
-                               L1_CACHE_ALIGN(XP_NASID_MASK_BYTES),
-                               (BTE_NOTIFY | BTE_WACQUIRE), NULL);
+                       xp_nasid_mask_bytes, (BTE_NOTIFY | BTE_WACQUIRE), NULL);
 
        return xpc_map_bte_errors(bte_res);
 }
index 75e6e87..9bf9f23 100644 (file)
@@ -326,6 +326,29 @@ int sn_pci_legacy_read(struct pci_bus *bus, u16 port, u32 *val, u8 size)
 {
        unsigned long addr;
        int ret;
+       struct ia64_sal_retval isrv;
+
+       /*
+        * First, try the SN_SAL_IOIF_PCI_SAFE SAL call which can work
+        * around hw issues at the pci bus level.  SGI proms older than
+        * 4.10 don't implment this.
+        */
+
+       SAL_CALL(isrv, SN_SAL_IOIF_PCI_SAFE,
+               pci_domain_nr(bus), bus->number,
+               0, /* io */
+               0, /* read */
+               port, size, __pa(val));
+
+       if (isrv.status == 0)
+               return size;
+
+       /*
+        * If the above failed, retry using the SAL_PROBE call which should
+        * be present in all proms (but which cannot work round PCI chipset
+        * bugs).  This code is retained for compatability with old
+        * pre-4.10 proms, and should be removed at some point in the future.
+        */
 
        if (!SN_PCIBUS_BUSSOFT(bus))
                return -ENODEV;
@@ -349,6 +372,29 @@ int sn_pci_legacy_write(struct pci_bus *bus, u16 port, u32 val, u8 size)
        int ret = size;
        unsigned long paddr;
        unsigned long *addr;
+       struct ia64_sal_retval isrv;
+
+       /*
+        * First, try the SN_SAL_IOIF_PCI_SAFE SAL call which can work
+        * around hw issues at the pci bus level.  SGI proms older than
+        * 4.10 don't implment this.
+        */
+
+       SAL_CALL(isrv, SN_SAL_IOIF_PCI_SAFE,
+               pci_domain_nr(bus), bus->number,
+               0, /* io */
+               1, /* write */
+               port, size, __pa(&val));
+
+       if (isrv.status == 0)
+               return size;
+
+       /*
+        * If the above failed, retry using the SAL_PROBE call which should
+        * be present in all proms (but which cannot work round PCI chipset
+        * bugs).  This code is retained for compatability with old
+        * pre-4.10 proms, and should be removed at some point in the future.
+        */
 
        if (!SN_PCIBUS_BUSSOFT(bus)) {
                ret = -ENODEV;
index 21426d0..4f718c3 100644 (file)
@@ -8,6 +8,7 @@
 
 #include <linux/interrupt.h>
 #include <linux/types.h>
+#include <asm/sn/io.h>
 #include <asm/sn/pcibr_provider.h>
 #include <asm/sn/pcibus_provider_defs.h>
 #include <asm/sn/pcidev.h>
@@ -29,10 +30,10 @@ void pcireg_control_bit_clr(struct pcibus_info *pcibus_info, uint64_t bits)
        if (pcibus_info) {
                switch (pcibus_info->pbi_bridge_type) {
                case PCIBR_BRIDGETYPE_TIOCP:
-                       ptr->tio.cp_control &= ~bits;
+                       __sn_clrq_relaxed(&ptr->tio.cp_control, bits);
                        break;
                case PCIBR_BRIDGETYPE_PIC:
-                       ptr->pic.p_wid_control &= ~bits;
+                       __sn_clrq_relaxed(&ptr->pic.p_wid_control, bits);
                        break;
                default:
                        panic
@@ -49,10 +50,10 @@ void pcireg_control_bit_set(struct pcibus_info *pcibus_info, uint64_t bits)
        if (pcibus_info) {
                switch (pcibus_info->pbi_bridge_type) {
                case PCIBR_BRIDGETYPE_TIOCP:
-                       ptr->tio.cp_control |= bits;
+                       __sn_setq_relaxed(&ptr->tio.cp_control, bits);
                        break;
                case PCIBR_BRIDGETYPE_PIC:
-                       ptr->pic.p_wid_control |= bits;
+                       __sn_setq_relaxed(&ptr->pic.p_wid_control, bits);
                        break;
                default:
                        panic
@@ -73,10 +74,10 @@ uint64_t pcireg_tflush_get(struct pcibus_info *pcibus_info)
        if (pcibus_info) {
                switch (pcibus_info->pbi_bridge_type) {
                case PCIBR_BRIDGETYPE_TIOCP:
-                       ret = ptr->tio.cp_tflush;
+                       ret = __sn_readq_relaxed(&ptr->tio.cp_tflush);
                        break;
                case PCIBR_BRIDGETYPE_PIC:
-                       ret = ptr->pic.p_wid_tflush;
+                       ret = __sn_readq_relaxed(&ptr->pic.p_wid_tflush);
                        break;
                default:
                        panic
@@ -103,10 +104,10 @@ uint64_t pcireg_intr_status_get(struct pcibus_info * pcibus_info)
        if (pcibus_info) {
                switch (pcibus_info->pbi_bridge_type) {
                case PCIBR_BRIDGETYPE_TIOCP:
-                       ret = ptr->tio.cp_int_status;
+                       ret = __sn_readq_relaxed(&ptr->tio.cp_int_status);
                        break;
                case PCIBR_BRIDGETYPE_PIC:
-                       ret = ptr->pic.p_int_status;
+                       ret = __sn_readq_relaxed(&ptr->pic.p_int_status);
                        break;
                default:
                        panic
@@ -127,10 +128,10 @@ void pcireg_intr_enable_bit_clr(struct pcibus_info *pcibus_info, uint64_t bits)
        if (pcibus_info) {
                switch (pcibus_info->pbi_bridge_type) {
                case PCIBR_BRIDGETYPE_TIOCP:
-                       ptr->tio.cp_int_enable &= ~bits;
+                       __sn_clrq_relaxed(&ptr->tio.cp_int_enable, bits);
                        break;
                case PCIBR_BRIDGETYPE_PIC:
-                       ptr->pic.p_int_enable &= ~bits;
+                       __sn_clrq_relaxed(&ptr->pic.p_int_enable, ~bits);
                        break;
                default:
                        panic
@@ -147,10 +148,10 @@ void pcireg_intr_enable_bit_set(struct pcibus_info *pcibus_info, uint64_t bits)
        if (pcibus_info) {
                switch (pcibus_info->pbi_bridge_type) {
                case PCIBR_BRIDGETYPE_TIOCP:
-                       ptr->tio.cp_int_enable |= bits;
+                       __sn_setq_relaxed(&ptr->tio.cp_int_enable, bits);
                        break;
                case PCIBR_BRIDGETYPE_PIC:
-                       ptr->pic.p_int_enable |= bits;
+                       __sn_setq_relaxed(&ptr->pic.p_int_enable, bits);
                        break;
                default:
                        panic
@@ -171,14 +172,16 @@ void pcireg_intr_addr_addr_set(struct pcibus_info *pcibus_info, int int_n,
        if (pcibus_info) {
                switch (pcibus_info->pbi_bridge_type) {
                case PCIBR_BRIDGETYPE_TIOCP:
-                       ptr->tio.cp_int_addr[int_n] &= ~TIOCP_HOST_INTR_ADDR;
-                       ptr->tio.cp_int_addr[int_n] |=
-                           (addr & TIOCP_HOST_INTR_ADDR);
+                       __sn_clrq_relaxed(&ptr->tio.cp_int_addr[int_n],
+                           TIOCP_HOST_INTR_ADDR);
+                       __sn_setq_relaxed(&ptr->tio.cp_int_addr[int_n],
+                           (addr & TIOCP_HOST_INTR_ADDR));
                        break;
                case PCIBR_BRIDGETYPE_PIC:
-                       ptr->pic.p_int_addr[int_n] &= ~PIC_HOST_INTR_ADDR;
-                       ptr->pic.p_int_addr[int_n] |=
-                           (addr & PIC_HOST_INTR_ADDR);
+                       __sn_clrq_relaxed(&ptr->pic.p_int_addr[int_n],
+                           PIC_HOST_INTR_ADDR);
+                       __sn_setq_relaxed(&ptr->pic.p_int_addr[int_n],
+                           (addr & PIC_HOST_INTR_ADDR));
                        break;
                default:
                        panic
@@ -198,10 +201,10 @@ void pcireg_force_intr_set(struct pcibus_info *pcibus_info, int int_n)
        if (pcibus_info) {
                switch (pcibus_info->pbi_bridge_type) {
                case PCIBR_BRIDGETYPE_TIOCP:
-                       ptr->tio.cp_force_pin[int_n] = 1;
+                       writeq(1, &ptr->tio.cp_force_pin[int_n]);
                        break;
                case PCIBR_BRIDGETYPE_PIC:
-                       ptr->pic.p_force_pin[int_n] = 1;
+                       writeq(1, &ptr->pic.p_force_pin[int_n]);
                        break;
                default:
                        panic
@@ -222,10 +225,12 @@ uint64_t pcireg_wrb_flush_get(struct pcibus_info *pcibus_info, int device)
        if (pcibus_info) {
                switch (pcibus_info->pbi_bridge_type) {
                case PCIBR_BRIDGETYPE_TIOCP:
-                       ret = ptr->tio.cp_wr_req_buf[device];
+                       ret =
+                           __sn_readq_relaxed(&ptr->tio.cp_wr_req_buf[device]);
                        break;
                case PCIBR_BRIDGETYPE_PIC:
-                       ret = ptr->pic.p_wr_req_buf[device];
+                       ret =
+                           __sn_readq_relaxed(&ptr->pic.p_wr_req_buf[device]);
                        break;
                default:
                      panic("pcireg_wrb_flush_get: unknown bridgetype bridge 0x%p", (void *)ptr);
@@ -244,10 +249,10 @@ void pcireg_int_ate_set(struct pcibus_info *pcibus_info, int ate_index,
        if (pcibus_info) {
                switch (pcibus_info->pbi_bridge_type) {
                case PCIBR_BRIDGETYPE_TIOCP:
-                       ptr->tio.cp_int_ate_ram[ate_index] = (uint64_t) val;
+                       writeq(val, &ptr->tio.cp_int_ate_ram[ate_index]);
                        break;
                case PCIBR_BRIDGETYPE_PIC:
-                       ptr->pic.p_int_ate_ram[ate_index] = (uint64_t) val;
+                       writeq(val, &ptr->pic.p_int_ate_ram[ate_index]);
                        break;
                default:
                        panic
@@ -265,12 +270,10 @@ uint64_t *pcireg_int_ate_addr(struct pcibus_info *pcibus_info, int ate_index)
        if (pcibus_info) {
                switch (pcibus_info->pbi_bridge_type) {
                case PCIBR_BRIDGETYPE_TIOCP:
-                       ret =
-                           (uint64_t *) & (ptr->tio.cp_int_ate_ram[ate_index]);
+                       ret = &ptr->tio.cp_int_ate_ram[ate_index];
                        break;
                case PCIBR_BRIDGETYPE_PIC:
-                       ret =
-                           (uint64_t *) & (ptr->pic.p_int_ate_ram[ate_index]);
+                       ret = &ptr->pic.p_int_ate_ram[ate_index];
                        break;
                default:
                        panic
index 19bced3..46b646a 100644 (file)
@@ -11,6 +11,7 @@
 #include <linux/pci.h>
 #include <asm/sn/sn_sal.h>
 #include <asm/sn/addrs.h>
+#include <asm/sn/io.h>
 #include <asm/sn/pcidev.h>
 #include <asm/sn/pcibus_provider_defs.h>
 #include <asm/sn/tioca_provider.h>
@@ -37,7 +38,7 @@ tioca_gart_init(struct tioca_kernel *tioca_kern)
        uint64_t offset;
        struct page *tmp;
        struct tioca_common *tioca_common;
-       volatile struct tioca *ca_base;
+       struct tioca *ca_base;
 
        tioca_common = tioca_kern->ca_common;
        ca_base = (struct tioca *)tioca_common->ca_common.bs_base;
@@ -174,27 +175,29 @@ tioca_gart_init(struct tioca_kernel *tioca_kern)
         *      DISABLE GART PREFETCHING due to hw bug tracked in SGI PV930029
         */
 
-       ca_base->ca_control1 |= CA_AGPDMA_OP_ENB_COMBDELAY;     /* PV895469 ? */
-       ca_base->ca_control2 &= ~(CA_GART_MEM_PARAM);
-       ca_base->ca_control2 |= (0x2ull << CA_GART_MEM_PARAM_SHFT);
+       __sn_setq_relaxed(&ca_base->ca_control1,
+                       CA_AGPDMA_OP_ENB_COMBDELAY);    /* PV895469 ? */
+       __sn_clrq_relaxed(&ca_base->ca_control2, CA_GART_MEM_PARAM);
+       __sn_setq_relaxed(&ca_base->ca_control2,
+                       (0x2ull << CA_GART_MEM_PARAM_SHFT));
        tioca_kern->ca_gart_iscoherent = 1;
-       ca_base->ca_control2 &=
-           ~(CA_GART_WR_PREFETCH_ENB | CA_GART_RD_PREFETCH_ENB);
+       __sn_clrq_relaxed(&ca_base->ca_control2,
+                       (CA_GART_WR_PREFETCH_ENB | CA_GART_RD_PREFETCH_ENB));
 
        /*
         * Unmask GART fetch error interrupts.  Clear residual errors first.
         */
 
-       ca_base->ca_int_status_alias = CA_GART_FETCH_ERR;
-       ca_base->ca_mult_error_alias = CA_GART_FETCH_ERR;
-       ca_base->ca_int_mask &= ~CA_GART_FETCH_ERR;
+       writeq(CA_GART_FETCH_ERR, &ca_base->ca_int_status_alias);
+       writeq(CA_GART_FETCH_ERR, &ca_base->ca_mult_error_alias);
+       __sn_clrq_relaxed(&ca_base->ca_int_mask, CA_GART_FETCH_ERR);
 
        /*
         * Program the aperature and gart registers in TIOCA
         */
 
-       ca_base->ca_gart_aperature = ap_reg;
-       ca_base->ca_gart_ptr_table = tioca_kern->ca_gart_coretalk_addr | 1;
+       writeq(ap_reg, &ca_base->ca_gart_aperature);
+       writeq(tioca_kern->ca_gart_coretalk_addr|1, &ca_base->ca_gart_ptr_table);
 
        return 0;
 }
@@ -211,7 +214,6 @@ void
 tioca_fastwrite_enable(struct tioca_kernel *tioca_kern)
 {
        int cap_ptr;
-       uint64_t ca_control1;
        uint32_t reg;
        struct tioca *tioca_base;
        struct pci_dev *pdev;
@@ -256,9 +258,7 @@ tioca_fastwrite_enable(struct tioca_kernel *tioca_kern)
         */
 
        tioca_base = (struct tioca *)common->ca_common.bs_base;
-       ca_control1 = tioca_base->ca_control1;
-       ca_control1 |= CA_AGP_FW_ENABLE;
-       tioca_base->ca_control1 = ca_control1;
+       __sn_setq_relaxed(&tioca_base->ca_control1, CA_AGP_FW_ENABLE);
 }
 
 EXPORT_SYMBOL(tioca_fastwrite_enable); /* used by agp-sgi */
@@ -345,7 +345,7 @@ tioca_dma_d48(struct pci_dev *pdev, uint64_t paddr)
                return 0;
        }
 
-       agp_dma_extn = ca_base->ca_agp_dma_addr_extn;
+       agp_dma_extn = __sn_readq_relaxed(&ca_base->ca_agp_dma_addr_extn);
        if (node_upper != (agp_dma_extn >> CA_AGP_DMA_NODE_ID_SHFT)) {
                printk(KERN_ERR "%s:  coretalk upper node (%u) "
                       "mismatch with ca_agp_dma_addr_extn (%lu)\n",
index 8e75db2..9f03d4e 100644 (file)
@@ -11,6 +11,7 @@
 #include <linux/pci.h>
 #include <asm/sn/sn_sal.h>
 #include <asm/sn/addrs.h>
+#include <asm/sn/io.h>
 #include <asm/sn/pcidev.h>
 #include <asm/sn/pcibus_provider_defs.h>
 #include <asm/sn/tioce_provider.h>
@@ -227,7 +228,7 @@ tioce_alloc_map(struct tioce_kernel *ce_kern, int type, int port,
 
                ate = ATE_MAKE(addr, pagesize);
                ate_shadow[i + j] = ate;
-               ate_reg[i + j] = ate;
+               writeq(ate, &ate_reg[i + j]);
                addr += pagesize;
        }
 
@@ -268,10 +269,10 @@ tioce_dma_d32(struct pci_dev *pdev, uint64_t ct_addr)
        pcidev_to_tioce(pdev, &ce_mmr, &ce_kern, &port);
 
        if (ce_kern->ce_port[port].dirmap_refcnt == 0) {
-               volatile uint64_t tmp;
+               uint64_t tmp;
 
                ce_kern->ce_port[port].dirmap_shadow = ct_upper;
-               ce_mmr->ce_ure_dir_map[port] = ct_upper;
+               writeq(ct_upper, &ce_mmr->ce_ure_dir_map[port]);
                tmp = ce_mmr->ce_ure_dir_map[port];
                dma_ok = 1;
        } else
@@ -343,7 +344,7 @@ tioce_dma_unmap(struct pci_dev *pdev, dma_addr_t bus_addr, int dir)
        if (TIOCE_D32_ADDR(bus_addr)) {
                if (--ce_kern->ce_port[port].dirmap_refcnt == 0) {
                        ce_kern->ce_port[port].dirmap_shadow = 0;
-                       ce_mmr->ce_ure_dir_map[port] = 0;
+                       writeq(0, &ce_mmr->ce_ure_dir_map[port]);
                }
        } else {
                struct tioce_dmamap *map;
@@ -582,18 +583,18 @@ tioce_kern_init(struct tioce_common *tioce_common)
         */
 
        tioce_mmr = (struct tioce *)tioce_common->ce_pcibus.bs_base;
-       tioce_mmr->ce_ure_page_map &= ~CE_URE_PAGESIZE_MASK;
-       tioce_mmr->ce_ure_page_map |= CE_URE_256K_PAGESIZE;
+       __sn_clrq_relaxed(&tioce_mmr->ce_ure_page_map, CE_URE_PAGESIZE_MASK);
+       __sn_setq_relaxed(&tioce_mmr->ce_ure_page_map, CE_URE_256K_PAGESIZE);
        tioce_kern->ce_ate3240_pagesize = KB(256);
 
        for (i = 0; i < TIOCE_NUM_M40_ATES; i++) {
                tioce_kern->ce_ate40_shadow[i] = 0;
-               tioce_mmr->ce_ure_ate40[i] = 0;
+               writeq(0, &tioce_mmr->ce_ure_ate40[i]);
        }
 
        for (i = 0; i < TIOCE_NUM_M3240_ATES; i++) {
                tioce_kern->ce_ate3240_shadow[i] = 0;
-               tioce_mmr->ce_ure_ate3240[i] = 0;
+               writeq(0, &tioce_mmr->ce_ure_ate3240[i]);
        }
 
        return tioce_kern;
@@ -665,7 +666,7 @@ tioce_force_interrupt(struct sn_irq_info *sn_irq_info)
        default:
                return;
        }
-       ce_mmr->ce_adm_force_int = force_int_val;
+       writeq(force_int_val, &ce_mmr->ce_adm_force_int);
 }
 
 /**
@@ -686,6 +687,7 @@ tioce_target_interrupt(struct sn_irq_info *sn_irq_info)
        struct tioce_common *ce_common;
        struct tioce *ce_mmr;
        int bit;
+       uint64_t vector;
 
        pcidev_info = (struct pcidev_info *)sn_irq_info->irq_pciioinfo;
        if (!pcidev_info)
@@ -696,11 +698,11 @@ tioce_target_interrupt(struct sn_irq_info *sn_irq_info)
 
        bit = sn_irq_info->irq_int_bit;
 
-       ce_mmr->ce_adm_int_mask |= (1UL << bit);
-       ce_mmr->ce_adm_int_dest[bit] =
-               ((uint64_t)sn_irq_info->irq_irq << INTR_VECTOR_SHFT) |
-                          sn_irq_info->irq_xtalkaddr;
-       ce_mmr->ce_adm_int_mask &= ~(1UL << bit);
+       __sn_setq_relaxed(&ce_mmr->ce_adm_int_mask, (1UL << bit));
+       vector = (uint64_t)sn_irq_info->irq_irq << INTR_VECTOR_SHFT;
+       vector |= sn_irq_info->irq_xtalkaddr;
+       writeq(vector, &ce_mmr->ce_adm_int_dest[bit]);
+       __sn_clrq_relaxed(&ce_mmr->ce_adm_int_mask, (1UL << bit));
 
        tioce_force_interrupt(sn_irq_info);
 }
index f4a62a1..43e395a 100644 (file)
@@ -253,6 +253,7 @@ int do_settimeofday(struct timespec *tv)
 
        return 0;
 }
+EXPORT_SYMBOL(do_settimeofday);
 
 static int set_rtc_time(unsigned long nowtime)
 {
index 1a109a6..65670be 100644 (file)
@@ -5,7 +5,7 @@
 # Rewritten to use lists instead of if-statements.
 #
 
-obj-$(CONFIG_PCI)              += pci/
+obj-$(CONFIG_PCI)              += pci/ usb/
 obj-$(CONFIG_PARISC)           += parisc/
 obj-y                          += video/
 obj-$(CONFIG_ACPI)             += acpi/
index 15e6a8f..0d2e101 100644 (file)
@@ -30,23 +30,6 @@ LIST_HEAD(dpm_off_irq);
 DECLARE_MUTEX(dpm_sem);
 DECLARE_MUTEX(dpm_list_sem);
 
-/*
- * PM Reference Counting.
- */
-
-static inline void device_pm_hold(struct device * dev)
-{
-       if (dev)
-               atomic_inc(&dev->power.pm_users);
-}
-
-static inline void device_pm_release(struct device * dev)
-{
-       if (dev)
-               atomic_dec(&dev->power.pm_users);
-}
-
-
 /**
  *     device_pm_set_parent - Specify power dependency.
  *     @dev:           Device who needs power.
@@ -62,10 +45,8 @@ static inline void device_pm_release(struct device * dev)
 
 void device_pm_set_parent(struct device * dev, struct device * parent)
 {
-       struct device * old_parent = dev->power.pm_parent;
-       device_pm_release(old_parent);
-       dev->power.pm_parent = parent;
-       device_pm_hold(parent);
+       put_device(dev->power.pm_parent);
+       dev->power.pm_parent = get_device(parent);
 }
 EXPORT_SYMBOL_GPL(device_pm_set_parent);
 
@@ -75,7 +56,6 @@ int device_pm_add(struct device * dev)
 
        pr_debug("PM: Adding info for %s:%s\n",
                 dev->bus ? dev->bus->name : "No Bus", dev->kobj.name);
-       atomic_set(&dev->power.pm_users, 0);
        down(&dpm_list_sem);
        list_add_tail(&dev->power.entry, &dpm_active);
        device_pm_set_parent(dev, dev->parent);
@@ -91,7 +71,7 @@ void device_pm_remove(struct device * dev)
                 dev->bus ? dev->bus->name : "No Bus", dev->kobj.name);
        down(&dpm_list_sem);
        dpm_sysfs_remove(dev);
-       device_pm_release(dev->power.pm_parent);
+       put_device(dev->power.pm_parent);
        list_del_init(&dev->power.entry);
        up(&dpm_list_sem);
 }
index 2e700d7..fb3d35a 100644 (file)
@@ -67,9 +67,6 @@ extern int suspend_device(struct device *, pm_message_t);
  * runtime.c
  */
 
-extern int dpm_runtime_suspend(struct device *, pm_message_t);
-extern void dpm_runtime_resume(struct device *);
-
 #else /* CONFIG_PM */
 
 
@@ -82,14 +79,4 @@ static inline void device_pm_remove(struct device * dev)
 
 }
 
-static inline int dpm_runtime_suspend(struct device * dev, pm_message_t state)
-{
-       return 0;
-}
-
-static inline void dpm_runtime_resume(struct device * dev)
-{
-
-}
-
 #endif
index e8f0519..adbc314 100644 (file)
@@ -36,6 +36,7 @@ void dpm_runtime_resume(struct device * dev)
        runtime_resume(dev);
        up(&dpm_sem);
 }
+EXPORT_SYMBOL(dpm_runtime_resume);
 
 
 /**
index 4081c36..5641722 100644 (file)
@@ -1344,6 +1344,7 @@ as_add_aliased_request(struct as_data *ad, struct as_rq *arq, struct as_rq *alia
         * Don't want to have to handle merges.
         */
        as_del_arq_hash(arq);
+       arq->request->flags |= REQ_NOMERGE;
 }
 
 /*
index ed4d500..bfb23d5 100644 (file)
@@ -1512,7 +1512,7 @@ static void ub_state_sense(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
        scmd->nsg = 1;
        sg = &scmd->sgv[0];
        sg->page = virt_to_page(sc->top_sense);
-       sg->offset = (unsigned int)sc->top_sense & (PAGE_SIZE-1);
+       sg->offset = (unsigned long)sc->top_sense & (PAGE_SIZE-1);
        sg->length = UB_SENSE_SIZE;
        scmd->len = UB_SENSE_SIZE;
        scmd->lun = cmd->lun;
@@ -1891,7 +1891,7 @@ static int ub_sync_read_cap(struct ub_dev *sc, struct ub_lun *lun,
        cmd->nsg = 1;
        sg = &cmd->sgv[0];
        sg->page = virt_to_page(p);
-       sg->offset = (unsigned int)p & (PAGE_SIZE-1);
+       sg->offset = (unsigned long)p & (PAGE_SIZE-1);
        sg->length = 8;
        cmd->len = 8;
        cmd->lun = lun;
index d3aa159..7957fc9 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/init.h>
 #include <linux/agp_backend.h>
 #include <asm/sn/addrs.h>
+#include <asm/sn/io.h>
 #include <asm/sn/pcidev.h>
 #include <asm/sn/pcibus_provider_defs.h>
 #include <asm/sn/tioca_provider.h>
index 1200618..78c89a3 100644 (file)
@@ -441,7 +441,7 @@ static irqreturn_t
 mmtimer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
        int i;
-       mmtimer_t *base = timers + cpuid_to_cnodeid(smp_processor_id()) *
+       mmtimer_t *base = timers + cpu_to_node(smp_processor_id()) *
                                                NUM_COMPARATORS;
        unsigned long expires = 0;
        int result = IRQ_NONE;
@@ -608,7 +608,7 @@ static int sgi_timer_set(struct k_itimer *timr, int flags,
         */
        preempt_disable();
 
-       nodeid =  cpuid_to_cnodeid(smp_processor_id());
+       nodeid =  cpu_to_node(smp_processor_id());
        base = timers + nodeid * NUM_COMPARATORS;
 retry:
        /* Don't use an allocated timer, or a deleted one that's pending */
index 1758a83..0e7d216 100644 (file)
@@ -377,7 +377,7 @@ scdrv_init(void)
        dev_t first_dev, dev;
        nasid_t event_nasid = ia64_sn_get_console_nasid();
 
-       if (alloc_chrdev_region(&first_dev, 0, numionodes,
+       if (alloc_chrdev_region(&first_dev, 0, num_cnodes,
                                SYSCTL_BASENAME) < 0) {
                printk("%s: failed to register SN system controller device\n",
                       __FUNCTION__);
@@ -385,7 +385,7 @@ scdrv_init(void)
        }
        snsc_class = class_create(THIS_MODULE, SYSCTL_BASENAME);
 
-       for (cnode = 0; cnode < numionodes; cnode++) {
+       for (cnode = 0; cnode < num_cnodes; cnode++) {
                        geoid = cnodeid_get_geoid(cnode);
                        devnamep = devname;
                        format_module_id(devnamep, geo_module(geoid),
index 5ac86f5..0c3c695 100644 (file)
  * $Id: agent.c 1389 2004-12-27 22:56:47Z roland $
  */
 
-#include <linux/dma-mapping.h>
-
-#include <asm/bug.h>
+#include "agent.h"
+#include "smi.h"
 
-#include <rdma/ib_smi.h>
+#define SPFX "ib_agent: "
 
-#include "smi.h"
-#include "agent_priv.h"
-#include "mad_priv.h"
-#include "agent.h"
+struct ib_agent_port_private {
+       struct list_head port_list;
+       struct ib_mad_agent *agent[2];
+};
 
-spinlock_t ib_agent_port_list_lock;
+static DEFINE_SPINLOCK(ib_agent_port_list_lock);
 static LIST_HEAD(ib_agent_port_list);
 
-/*
- * Caller must hold ib_agent_port_list_lock
- */
-static inline struct ib_agent_port_private *
-__ib_get_agent_port(struct ib_device *device, int port_num,
-                   struct ib_mad_agent *mad_agent)
+static struct ib_agent_port_private *
+__ib_get_agent_port(struct ib_device *device, int port_num)
 {
        struct ib_agent_port_private *entry;
 
-       BUG_ON(!(!!device ^ !!mad_agent));  /* Exactly one MUST be (!NULL) */
-
-       if (device) {
-               list_for_each_entry(entry, &ib_agent_port_list, port_list) {
-                       if (entry->smp_agent->device == device &&
-                           entry->port_num == port_num)
-                               return entry;
-               }
-       } else {
-               list_for_each_entry(entry, &ib_agent_port_list, port_list) {
-                       if ((entry->smp_agent == mad_agent) ||
-                           (entry->perf_mgmt_agent == mad_agent))
-                               return entry;
-               }
+       list_for_each_entry(entry, &ib_agent_port_list, port_list) {
+               if (entry->agent[0]->device == device &&
+                   entry->agent[0]->port_num == port_num)
+                       return entry;
        }
        return NULL;
 }
 
-static inline struct ib_agent_port_private *
-ib_get_agent_port(struct ib_device *device, int port_num,
-                 struct ib_mad_agent *mad_agent)
+static struct ib_agent_port_private *
+ib_get_agent_port(struct ib_device *device, int port_num)
 {
        struct ib_agent_port_private *entry;
        unsigned long flags;
 
        spin_lock_irqsave(&ib_agent_port_list_lock, flags);
-       entry = __ib_get_agent_port(device, port_num, mad_agent);
+       entry = __ib_get_agent_port(device, port_num);
        spin_unlock_irqrestore(&ib_agent_port_list_lock, flags);
-
        return entry;
 }
 
@@ -100,192 +83,76 @@ int smi_check_local_dr_smp(struct ib_smp *smp,
 
        if (smp->mgmt_class != IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE)
                return 1;
-       port_priv = ib_get_agent_port(device, port_num, NULL);
+
+       port_priv = ib_get_agent_port(device, port_num);
        if (!port_priv) {
                printk(KERN_DEBUG SPFX "smi_check_local_dr_smp %s port %d "
-                      "not open\n",
-                      device->name, port_num);
+                      "not open\n", device->name, port_num);
                return 1;
        }
 
-       return smi_check_local_smp(port_priv->smp_agent, smp);
+       return smi_check_local_smp(port_priv->agent[0], smp);
 }
 
-static int agent_mad_send(struct ib_mad_agent *mad_agent,
-                         struct ib_agent_port_private *port_priv,
-                         struct ib_mad_private *mad_priv,
-                         struct ib_grh *grh,
-                         struct ib_wc *wc)
+int agent_send_response(struct ib_mad *mad, struct ib_grh *grh,
+                       struct ib_wc *wc, struct ib_device *device,
+                       int port_num, int qpn)
 {
-       struct ib_agent_send_wr *agent_send_wr;
-       struct ib_sge gather_list;
-       struct ib_send_wr send_wr;
-       struct ib_send_wr *bad_send_wr;
-       struct ib_ah_attr ah_attr;
-       unsigned long flags;
-       int ret = 1;
-
-       agent_send_wr = kmalloc(sizeof(*agent_send_wr), GFP_KERNEL);
-       if (!agent_send_wr)
-               goto out;
-       agent_send_wr->mad = mad_priv;
-
-       gather_list.addr = dma_map_single(mad_agent->device->dma_device,
-                                         &mad_priv->mad,
-                                         sizeof(mad_priv->mad),
-                                         DMA_TO_DEVICE);
-       gather_list.length = sizeof(mad_priv->mad);
-       gather_list.lkey = mad_agent->mr->lkey;
-
-       send_wr.next = NULL;
-       send_wr.opcode = IB_WR_SEND;
-       send_wr.sg_list = &gather_list;
-       send_wr.num_sge = 1;
-       send_wr.wr.ud.remote_qpn = wc->src_qp; /* DQPN */
-       send_wr.wr.ud.timeout_ms = 0;
-       send_wr.send_flags = IB_SEND_SIGNALED | IB_SEND_SOLICITED;
+       struct ib_agent_port_private *port_priv;
+       struct ib_mad_agent *agent;
+       struct ib_mad_send_buf *send_buf;
+       struct ib_ah *ah;
+       int ret;
 
-       ah_attr.dlid = wc->slid;
-       ah_attr.port_num = mad_agent->port_num;
-       ah_attr.src_path_bits = wc->dlid_path_bits;
-       ah_attr.sl = wc->sl;
-       ah_attr.static_rate = 0;
-       ah_attr.ah_flags = 0; /* No GRH */
-       if (mad_priv->mad.mad.mad_hdr.mgmt_class == IB_MGMT_CLASS_PERF_MGMT) {
-               if (wc->wc_flags & IB_WC_GRH) {
-                       ah_attr.ah_flags = IB_AH_GRH;
-                       /* Should sgid be looked up ? */
-                       ah_attr.grh.sgid_index = 0;
-                       ah_attr.grh.hop_limit = grh->hop_limit;
-                       ah_attr.grh.flow_label = be32_to_cpu(
-                               grh->version_tclass_flow)  & 0xfffff;
-                       ah_attr.grh.traffic_class = (be32_to_cpu(
-                               grh->version_tclass_flow) >> 20) & 0xff;
-                       memcpy(ah_attr.grh.dgid.raw,
-                              grh->sgid.raw,
-                              sizeof(ah_attr.grh.dgid));
-               }
+       port_priv = ib_get_agent_port(device, port_num);
+       if (!port_priv) {
+               printk(KERN_ERR SPFX "Unable to find port agent\n");
+               return -ENODEV;
        }
 
-       agent_send_wr->ah = ib_create_ah(mad_agent->qp->pd, &ah_attr);
-       if (IS_ERR(agent_send_wr->ah)) {
-               printk(KERN_ERR SPFX "No memory for address handle\n");
-               kfree(agent_send_wr);
-               goto out;
+       agent = port_priv->agent[qpn];
+       ah = ib_create_ah_from_wc(agent->qp->pd, wc, grh, port_num);
+       if (IS_ERR(ah)) {
+               ret = PTR_ERR(ah);
+               printk(KERN_ERR SPFX "ib_create_ah_from_wc error:%d\n", ret);
+               return ret;
        }
 
-       send_wr.wr.ud.ah = agent_send_wr->ah;
-       if (mad_priv->mad.mad.mad_hdr.mgmt_class == IB_MGMT_CLASS_PERF_MGMT) {
-               send_wr.wr.ud.pkey_index = wc->pkey_index;
-               send_wr.wr.ud.remote_qkey = IB_QP1_QKEY;
-       } else {        /* for SMPs */
-               send_wr.wr.ud.pkey_index = 0;
-               send_wr.wr.ud.remote_qkey = 0;
+       send_buf = ib_create_send_mad(agent, wc->src_qp, wc->pkey_index, 0,
+                                     IB_MGMT_MAD_HDR, IB_MGMT_MAD_DATA,
+                                     GFP_KERNEL);
+       if (IS_ERR(send_buf)) {
+               ret = PTR_ERR(send_buf);
+               printk(KERN_ERR SPFX "ib_create_send_mad error:%d\n", ret);
+               goto err1;
        }
-       send_wr.wr.ud.mad_hdr = &mad_priv->mad.mad.mad_hdr;
-       send_wr.wr_id = (unsigned long)agent_send_wr;
 
-       pci_unmap_addr_set(agent_send_wr, mapping, gather_list.addr);
-
-       /* Send */
-       spin_lock_irqsave(&port_priv->send_list_lock, flags);
-       if (ib_post_send_mad(mad_agent, &send_wr, &bad_send_wr)) {
-               spin_unlock_irqrestore(&port_priv->send_list_lock, flags);
-               dma_unmap_single(mad_agent->device->dma_device,
-                                pci_unmap_addr(agent_send_wr, mapping),
-                                sizeof(mad_priv->mad),
-                                DMA_TO_DEVICE);
-               ib_destroy_ah(agent_send_wr->ah);
-               kfree(agent_send_wr);
-       } else {
-               list_add_tail(&agent_send_wr->send_list,
-                             &port_priv->send_posted_list);
-               spin_unlock_irqrestore(&port_priv->send_list_lock, flags);
-               ret = 0;
+       memcpy(send_buf->mad, mad, sizeof *mad);
+       send_buf->ah = ah;
+       if ((ret = ib_post_send_mad(send_buf, NULL))) {
+               printk(KERN_ERR SPFX "ib_post_send_mad error:%d\n", ret);
+               goto err2;
        }
-
-out:
+       return 0;
+err2:
+       ib_free_send_mad(send_buf);
+err1:
+       ib_destroy_ah(ah);
        return ret;
 }
 
-int agent_send(struct ib_mad_private *mad,
-              struct ib_grh *grh,
-              struct ib_wc *wc,
-              struct ib_device *device,
-              int port_num)
-{
-       struct ib_agent_port_private *port_priv;
-       struct ib_mad_agent *mad_agent;
-
-       port_priv = ib_get_agent_port(device, port_num, NULL);
-       if (!port_priv) {
-               printk(KERN_DEBUG SPFX "agent_send %s port %d not open\n",
-                      device->name, port_num);
-               return 1;
-       }
-
-       /* Get mad agent based on mgmt_class in MAD */
-       switch (mad->mad.mad.mad_hdr.mgmt_class) {
-               case IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE:
-               case IB_MGMT_CLASS_SUBN_LID_ROUTED:
-                       mad_agent = port_priv->smp_agent;
-                       break;
-               case IB_MGMT_CLASS_PERF_MGMT:
-                       mad_agent = port_priv->perf_mgmt_agent;
-                       break;
-               default:
-                       return 1;
-       }
-
-       return agent_mad_send(mad_agent, port_priv, mad, grh, wc);
-}
-
 static void agent_send_handler(struct ib_mad_agent *mad_agent,
                               struct ib_mad_send_wc *mad_send_wc)
 {
-       struct ib_agent_port_private    *port_priv;
-       struct ib_agent_send_wr         *agent_send_wr;
-       unsigned long                   flags;
-
-       /* Find matching MAD agent */
-       port_priv = ib_get_agent_port(NULL, 0, mad_agent);
-       if (!port_priv) {
-               printk(KERN_ERR SPFX "agent_send_handler: no matching MAD "
-                      "agent %p\n", mad_agent);
-               return;
-       }
-
-       agent_send_wr = (struct ib_agent_send_wr *)(unsigned long)mad_send_wc->wr_id;
-       spin_lock_irqsave(&port_priv->send_list_lock, flags);
-       /* Remove completed send from posted send MAD list */
-       list_del(&agent_send_wr->send_list);
-       spin_unlock_irqrestore(&port_priv->send_list_lock, flags);
-
-       dma_unmap_single(mad_agent->device->dma_device,
-                        pci_unmap_addr(agent_send_wr, mapping),
-                        sizeof(agent_send_wr->mad->mad),
-                        DMA_TO_DEVICE);
-
-       ib_destroy_ah(agent_send_wr->ah);
-
-       /* Release allocated memory */
-       kmem_cache_free(ib_mad_cache, agent_send_wr->mad);
-       kfree(agent_send_wr);
+       ib_destroy_ah(mad_send_wc->send_buf->ah);
+       ib_free_send_mad(mad_send_wc->send_buf);
 }
 
 int ib_agent_port_open(struct ib_device *device, int port_num)
 {
-       int ret;
        struct ib_agent_port_private *port_priv;
        unsigned long flags;
-
-       /* First, check if port already open for SMI */
-       port_priv = ib_get_agent_port(device, port_num, NULL);
-       if (port_priv) {
-               printk(KERN_DEBUG SPFX "%s port %d already open\n",
-                      device->name, port_num);
-               return 0;
-       }
+       int ret;
 
        /* Create new device info */
        port_priv = kmalloc(sizeof *port_priv, GFP_KERNEL);
@@ -294,32 +161,25 @@ int ib_agent_port_open(struct ib_device *device, int port_num)
                ret = -ENOMEM;
                goto error1;
        }
-
        memset(port_priv, 0, sizeof *port_priv);
-       port_priv->port_num = port_num;
-       spin_lock_init(&port_priv->send_list_lock);
-       INIT_LIST_HEAD(&port_priv->send_posted_list);
 
-       /* Obtain send only MAD agent for SM class (SMI QP) */
-       port_priv->smp_agent = ib_register_mad_agent(device, port_num,
-                                                    IB_QPT_SMI,
-                                                    NULL, 0,
+       /* Obtain send only MAD agent for SMI QP */
+       port_priv->agent[0] = ib_register_mad_agent(device, port_num,
+                                                   IB_QPT_SMI, NULL, 0,
                                                    &agent_send_handler,
-                                                    NULL, NULL);
-
-       if (IS_ERR(port_priv->smp_agent)) {
-               ret = PTR_ERR(port_priv->smp_agent);
+                                                   NULL, NULL);
+       if (IS_ERR(port_priv->agent[0])) {
+               ret = PTR_ERR(port_priv->agent[0]);
                goto error2;
        }
 
-       /* Obtain send only MAD agent for PerfMgmt class (GSI QP) */
-       port_priv->perf_mgmt_agent = ib_register_mad_agent(device, port_num,
-                                                          IB_QPT_GSI,
-                                                          NULL, 0,
-                                                         &agent_send_handler,
-                                                          NULL, NULL);
-       if (IS_ERR(port_priv->perf_mgmt_agent)) {
-               ret = PTR_ERR(port_priv->perf_mgmt_agent);
+       /* Obtain send only MAD agent for GSI QP */
+       port_priv->agent[1] = ib_register_mad_agent(device, port_num,
+                                                   IB_QPT_GSI, NULL, 0,
+                                                   &agent_send_handler,
+                                                   NULL, NULL);
+       if (IS_ERR(port_priv->agent[1])) {
+               ret = PTR_ERR(port_priv->agent[1]);
                goto error3;
        }
 
@@ -330,7 +190,7 @@ int ib_agent_port_open(struct ib_device *device, int port_num)
        return 0;
 
 error3:
-       ib_unregister_mad_agent(port_priv->smp_agent);
+       ib_unregister_mad_agent(port_priv->agent[0]);
 error2:
        kfree(port_priv);
 error1:
@@ -343,7 +203,7 @@ int ib_agent_port_close(struct ib_device *device, int port_num)
        unsigned long flags;
 
        spin_lock_irqsave(&ib_agent_port_list_lock, flags);
-       port_priv = __ib_get_agent_port(device, port_num, NULL);
+       port_priv = __ib_get_agent_port(device, port_num);
        if (port_priv == NULL) {
                spin_unlock_irqrestore(&ib_agent_port_list_lock, flags);
                printk(KERN_ERR SPFX "Port %d not found\n", port_num);
@@ -352,9 +212,8 @@ int ib_agent_port_close(struct ib_device *device, int port_num)
        list_del(&port_priv->port_list);
        spin_unlock_irqrestore(&ib_agent_port_list_lock, flags);
 
-       ib_unregister_mad_agent(port_priv->perf_mgmt_agent);
-       ib_unregister_mad_agent(port_priv->smp_agent);
+       ib_unregister_mad_agent(port_priv->agent[1]);
+       ib_unregister_mad_agent(port_priv->agent[0]);
        kfree(port_priv);
-
        return 0;
 }
index d942684..86d72fa 100644 (file)
 #ifndef __AGENT_H_
 #define __AGENT_H_
 
-extern spinlock_t ib_agent_port_list_lock;
+#include <linux/err.h>
+#include <rdma/ib_mad.h>
 
-extern int ib_agent_port_open(struct ib_device *device,
-                             int port_num);
+extern int ib_agent_port_open(struct ib_device *device, int port_num);
 
 extern int ib_agent_port_close(struct ib_device *device, int port_num);
 
-extern int agent_send(struct ib_mad_private *mad,
-                     struct ib_grh *grh,
-                     struct ib_wc *wc,
-                     struct ib_device *device,
-                     int port_num);
+extern int agent_send_response(struct ib_mad *mad, struct ib_grh *grh,
+                              struct ib_wc *wc, struct ib_device *device,
+                              int port_num, int qpn);
 
 #endif /* __AGENT_H_ */
diff --git a/drivers/infiniband/core/agent_priv.h b/drivers/infiniband/core/agent_priv.h
deleted file mode 100644 (file)
index 2ec6d7f..0000000
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright (c) 2004, 2005 Mellanox Technologies Ltd.  All rights reserved.
- * Copyright (c) 2004, 2005 Infinicon Corporation.  All rights reserved.
- * Copyright (c) 2004, 2005 Intel Corporation.  All rights reserved.
- * Copyright (c) 2004, 2005 Topspin Corporation.  All rights reserved.
- * Copyright (c) 2004, 2005 Voltaire Corporation.  All rights reserved.
- *
- * This software is available to you under a choice of one of two
- * licenses.  You may choose to be licensed under the terms of the GNU
- * General Public License (GPL) Version 2, available from the file
- * COPYING in the main directory of this source tree, or the
- * OpenIB.org BSD license below:
- *
- *     Redistribution and use in source and binary forms, with or
- *     without modification, are permitted provided that the following
- *     conditions are met:
- *
- *      - Redistributions of source code must retain the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer.
- *
- *      - Redistributions in binary form must reproduce the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer in the documentation and/or other materials
- *        provided with the distribution.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- *
- * $Id: agent_priv.h 1640 2005-01-24 22:39:02Z halr $
- */
-
-#ifndef __IB_AGENT_PRIV_H__
-#define __IB_AGENT_PRIV_H__
-
-#include <linux/pci.h>
-
-#define SPFX "ib_agent: "
-
-struct ib_agent_send_wr {
-       struct list_head send_list;
-       struct ib_ah *ah;
-       struct ib_mad_private *mad;
-       DECLARE_PCI_UNMAP_ADDR(mapping)
-};
-
-struct ib_agent_port_private {
-       struct list_head port_list;
-       struct list_head send_posted_list;
-       spinlock_t send_list_lock;
-       int port_num;
-       struct ib_mad_agent *smp_agent;       /* SM class */
-       struct ib_mad_agent *perf_mgmt_agent; /* PerfMgmt class */
-};
-
-#endif /* __IB_AGENT_PRIV_H__ */
index 54db6d4..580c3a2 100644 (file)
@@ -135,6 +135,7 @@ struct cm_id_private {
        __be64 tid;
        __be32 local_qpn;
        __be32 remote_qpn;
+       enum ib_qp_type qp_type;
        __be32 sq_psn;
        __be32 rq_psn;
        int timeout_ms;
@@ -175,8 +176,7 @@ static int cm_alloc_msg(struct cm_id_private *cm_id_priv,
 
        m = ib_create_send_mad(mad_agent, cm_id_priv->id.remote_cm_qpn, 
                               cm_id_priv->av.pkey_index,
-                              ah, 0, sizeof(struct ib_mad_hdr),
-                              sizeof(struct ib_mad)-sizeof(struct ib_mad_hdr),
+                              0, IB_MGMT_MAD_HDR, IB_MGMT_MAD_DATA,
                               GFP_ATOMIC);
        if (IS_ERR(m)) {
                ib_destroy_ah(ah);
@@ -184,7 +184,8 @@ static int cm_alloc_msg(struct cm_id_private *cm_id_priv,
        }
 
        /* Timeout set by caller if response is expected. */
-       m->send_wr.wr.ud.retries = cm_id_priv->max_cm_retries;
+       m->ah = ah;
+       m->retries = cm_id_priv->max_cm_retries;
 
        atomic_inc(&cm_id_priv->refcount);
        m->context[0] = cm_id_priv;
@@ -205,20 +206,20 @@ static int cm_alloc_response_msg(struct cm_port *port,
                return PTR_ERR(ah);
 
        m = ib_create_send_mad(port->mad_agent, 1, mad_recv_wc->wc->pkey_index,
-                              ah, 0, sizeof(struct ib_mad_hdr),
-                              sizeof(struct ib_mad)-sizeof(struct ib_mad_hdr),
+                              0, IB_MGMT_MAD_HDR, IB_MGMT_MAD_DATA,
                               GFP_ATOMIC);
        if (IS_ERR(m)) {
                ib_destroy_ah(ah);
                return PTR_ERR(m);
        }
+       m->ah = ah;
        *msg = m;
        return 0;
 }
 
 static void cm_free_msg(struct ib_mad_send_buf *msg)
 {
-       ib_destroy_ah(msg->send_wr.wr.ud.ah);
+       ib_destroy_ah(msg->ah);
        if (msg->context[0])
                cm_deref_id(msg->context[0]);
        ib_free_send_mad(msg);
@@ -366,9 +367,15 @@ static struct cm_id_private * cm_insert_listen(struct cm_id_private *cm_id_priv)
                cur_cm_id_priv = rb_entry(parent, struct cm_id_private,
                                          service_node);
                if ((cur_cm_id_priv->id.service_mask & service_id) ==
-                   (service_mask & cur_cm_id_priv->id.service_id))
-                       return cm_id_priv;
-               if (service_id < cur_cm_id_priv->id.service_id)
+                   (service_mask & cur_cm_id_priv->id.service_id) &&
+                   (cm_id_priv->id.device == cur_cm_id_priv->id.device))
+                       return cur_cm_id_priv;
+
+               if (cm_id_priv->id.device < cur_cm_id_priv->id.device)
+                       link = &(*link)->rb_left;
+               else if (cm_id_priv->id.device > cur_cm_id_priv->id.device)
+                       link = &(*link)->rb_right;
+               else if (service_id < cur_cm_id_priv->id.service_id)
                        link = &(*link)->rb_left;
                else
                        link = &(*link)->rb_right;
@@ -378,7 +385,8 @@ static struct cm_id_private * cm_insert_listen(struct cm_id_private *cm_id_priv)
        return NULL;
 }
 
-static struct cm_id_private * cm_find_listen(__be64 service_id)
+static struct cm_id_private * cm_find_listen(struct ib_device *device,
+                                            __be64 service_id)
 {
        struct rb_node *node = cm.listen_service_table.rb_node;
        struct cm_id_private *cm_id_priv;
@@ -386,9 +394,15 @@ static struct cm_id_private * cm_find_listen(__be64 service_id)
        while (node) {
                cm_id_priv = rb_entry(node, struct cm_id_private, service_node);
                if ((cm_id_priv->id.service_mask & service_id) ==
-                   (cm_id_priv->id.service_mask & cm_id_priv->id.service_id))
+                    cm_id_priv->id.service_id &&
+                   (cm_id_priv->id.device == device))
                        return cm_id_priv;
-               if (service_id < cm_id_priv->id.service_id)
+
+               if (device < cm_id_priv->id.device)
+                       node = node->rb_left;
+               else if (device > cm_id_priv->id.device)
+                       node = node->rb_right;
+               else if (service_id < cm_id_priv->id.service_id)
                        node = node->rb_left;
                else
                        node = node->rb_right;
@@ -523,7 +537,8 @@ static void cm_reject_sidr_req(struct cm_id_private *cm_id_priv,
        ib_send_cm_sidr_rep(&cm_id_priv->id, &param);
 }
 
-struct ib_cm_id *ib_create_cm_id(ib_cm_handler cm_handler,
+struct ib_cm_id *ib_create_cm_id(struct ib_device *device,
+                                ib_cm_handler cm_handler,
                                 void *context)
 {
        struct cm_id_private *cm_id_priv;
@@ -535,6 +550,7 @@ struct ib_cm_id *ib_create_cm_id(ib_cm_handler cm_handler,
 
        memset(cm_id_priv, 0, sizeof *cm_id_priv);
        cm_id_priv->id.state = IB_CM_IDLE;
+       cm_id_priv->id.device = device;
        cm_id_priv->id.cm_handler = cm_handler;
        cm_id_priv->id.context = context;
        cm_id_priv->id.remote_cm_qpn = 1;
@@ -662,8 +678,7 @@ retest:
                break;
        case IB_CM_SIDR_REQ_SENT:
                cm_id->state = IB_CM_IDLE;
-               ib_cancel_mad(cm_id_priv->av.port->mad_agent,
-                             (unsigned long) cm_id_priv->msg);
+               ib_cancel_mad(cm_id_priv->av.port->mad_agent, cm_id_priv->msg);
                spin_unlock_irqrestore(&cm_id_priv->lock, flags);
                break;
        case IB_CM_SIDR_REQ_RCVD:
@@ -674,8 +689,7 @@ retest:
        case IB_CM_MRA_REQ_RCVD:
        case IB_CM_REP_SENT:
        case IB_CM_MRA_REP_RCVD:
-               ib_cancel_mad(cm_id_priv->av.port->mad_agent,
-                             (unsigned long) cm_id_priv->msg);
+               ib_cancel_mad(cm_id_priv->av.port->mad_agent, cm_id_priv->msg);
                /* Fall through */
        case IB_CM_REQ_RCVD:
        case IB_CM_MRA_REQ_SENT:
@@ -692,8 +706,7 @@ retest:
                ib_send_cm_dreq(cm_id, NULL, 0);
                goto retest;
        case IB_CM_DREQ_SENT:
-               ib_cancel_mad(cm_id_priv->av.port->mad_agent,
-                             (unsigned long) cm_id_priv->msg);
+               ib_cancel_mad(cm_id_priv->av.port->mad_agent, cm_id_priv->msg);
                cm_enter_timewait(cm_id_priv);
                spin_unlock_irqrestore(&cm_id_priv->lock, flags);
                break;
@@ -867,7 +880,6 @@ int ib_send_cm_req(struct ib_cm_id *cm_id,
                   struct ib_cm_req_param *param)
 {
        struct cm_id_private *cm_id_priv;
-       struct ib_send_wr *bad_send_wr;
        struct cm_req_msg *req_msg;
        unsigned long flags;
        int ret;
@@ -911,6 +923,7 @@ int ib_send_cm_req(struct ib_cm_id *cm_id,
        cm_id_priv->responder_resources = param->responder_resources;
        cm_id_priv->retry_count = param->retry_count;
        cm_id_priv->path_mtu = param->primary_path->mtu;
+       cm_id_priv->qp_type = param->qp_type;
 
        ret = cm_alloc_msg(cm_id_priv, &cm_id_priv->msg);
        if (ret)
@@ -919,7 +932,7 @@ int ib_send_cm_req(struct ib_cm_id *cm_id,
        req_msg = (struct cm_req_msg *) cm_id_priv->msg->mad;
        cm_format_req(req_msg, cm_id_priv, param);
        cm_id_priv->tid = req_msg->hdr.tid;
-       cm_id_priv->msg->send_wr.wr.ud.timeout_ms = cm_id_priv->timeout_ms;
+       cm_id_priv->msg->timeout_ms = cm_id_priv->timeout_ms;
        cm_id_priv->msg->context[1] = (void *) (unsigned long) IB_CM_REQ_SENT;
 
        cm_id_priv->local_qpn = cm_req_get_local_qpn(req_msg);
@@ -928,8 +941,7 @@ int ib_send_cm_req(struct ib_cm_id *cm_id,
                                cm_req_get_primary_local_ack_timeout(req_msg);
 
        spin_lock_irqsave(&cm_id_priv->lock, flags);
-       ret = ib_post_send_mad(cm_id_priv->av.port->mad_agent,
-                               &cm_id_priv->msg->send_wr, &bad_send_wr);
+       ret = ib_post_send_mad(cm_id_priv->msg, NULL);
        if (ret) {
                spin_unlock_irqrestore(&cm_id_priv->lock, flags);
                goto error2;
@@ -952,7 +964,6 @@ static int cm_issue_rej(struct cm_port *port,
                        void *ari, u8 ari_length)
 {
        struct ib_mad_send_buf *msg = NULL;
-       struct ib_send_wr *bad_send_wr;
        struct cm_rej_msg *rej_msg, *rcv_msg;
        int ret;
 
@@ -975,7 +986,7 @@ static int cm_issue_rej(struct cm_port *port,
                memcpy(rej_msg->ari, ari, ari_length);
        }
 
-       ret = ib_post_send_mad(port->mad_agent, &msg->send_wr, &bad_send_wr);
+       ret = ib_post_send_mad(msg, NULL);
        if (ret)
                cm_free_msg(msg);
 
@@ -1047,7 +1058,6 @@ static void cm_format_req_event(struct cm_work *work,
        req_msg = (struct cm_req_msg *)work->mad_recv_wc->recv_buf.mad;
        param = &work->cm_event.param.req_rcvd;
        param->listen_id = listen_id;
-       param->device = cm_id_priv->av.port->mad_agent->device;
        param->port = cm_id_priv->av.port->port_num;
        param->primary_path = &work->path[0];
        if (req_msg->alt_local_lid)
@@ -1156,7 +1166,6 @@ static void cm_dup_req_handler(struct cm_work *work,
                               struct cm_id_private *cm_id_priv)
 {
        struct ib_mad_send_buf *msg = NULL;
-       struct ib_send_wr *bad_send_wr;
        unsigned long flags;
        int ret;
 
@@ -1185,8 +1194,7 @@ static void cm_dup_req_handler(struct cm_work *work,
        }
        spin_unlock_irqrestore(&cm_id_priv->lock, flags);
 
-       ret = ib_post_send_mad(cm_id_priv->av.port->mad_agent, &msg->send_wr,
-                              &bad_send_wr);
+       ret = ib_post_send_mad(msg, NULL);
        if (ret)
                goto free;
        return;
@@ -1226,7 +1234,8 @@ static struct cm_id_private * cm_match_req(struct cm_work *work,
        }
 
        /* Find matching listen request. */
-       listen_cm_id_priv = cm_find_listen(req_msg->service_id);
+       listen_cm_id_priv = cm_find_listen(cm_id_priv->id.device,
+                                          req_msg->service_id);
        if (!listen_cm_id_priv) {
                spin_unlock_irqrestore(&cm.lock, flags);
                cm_issue_rej(work->port, work->mad_recv_wc,
@@ -1254,7 +1263,7 @@ static int cm_req_handler(struct cm_work *work)
 
        req_msg = (struct cm_req_msg *)work->mad_recv_wc->recv_buf.mad;
 
-       cm_id = ib_create_cm_id(NULL, NULL);
+       cm_id = ib_create_cm_id(work->port->cm_dev->device, NULL, NULL);
        if (IS_ERR(cm_id))
                return PTR_ERR(cm_id);
 
@@ -1305,6 +1314,7 @@ static int cm_req_handler(struct cm_work *work)
                                cm_req_get_primary_local_ack_timeout(req_msg);
        cm_id_priv->retry_count = cm_req_get_retry_count(req_msg);
        cm_id_priv->rnr_retry_count = cm_req_get_rnr_retry_count(req_msg);
+       cm_id_priv->qp_type = cm_req_get_qp_type(req_msg);
 
        cm_format_req_event(work, cm_id_priv, &listen_cm_id_priv->id);
        cm_process_work(cm_id_priv, work);
@@ -1349,7 +1359,6 @@ int ib_send_cm_rep(struct ib_cm_id *cm_id,
        struct cm_id_private *cm_id_priv;
        struct ib_mad_send_buf *msg;
        struct cm_rep_msg *rep_msg;
-       struct ib_send_wr *bad_send_wr;
        unsigned long flags;
        int ret;
 
@@ -1371,11 +1380,10 @@ int ib_send_cm_rep(struct ib_cm_id *cm_id,
 
        rep_msg = (struct cm_rep_msg *) msg->mad;
        cm_format_rep(rep_msg, cm_id_priv, param);
-       msg->send_wr.wr.ud.timeout_ms = cm_id_priv->timeout_ms;
+       msg->timeout_ms = cm_id_priv->timeout_ms;
        msg->context[1] = (void *) (unsigned long) IB_CM_REP_SENT;
 
-       ret = ib_post_send_mad(cm_id_priv->av.port->mad_agent,
-                              &msg->send_wr, &bad_send_wr);
+       ret = ib_post_send_mad(msg, NULL);
        if (ret) {
                spin_unlock_irqrestore(&cm_id_priv->lock, flags);
                cm_free_msg(msg);
@@ -1413,7 +1421,6 @@ int ib_send_cm_rtu(struct ib_cm_id *cm_id,
 {
        struct cm_id_private *cm_id_priv;
        struct ib_mad_send_buf *msg;
-       struct ib_send_wr *bad_send_wr;
        unsigned long flags;
        void *data;
        int ret;
@@ -1440,8 +1447,7 @@ int ib_send_cm_rtu(struct ib_cm_id *cm_id,
        cm_format_rtu((struct cm_rtu_msg *) msg->mad, cm_id_priv,
                      private_data, private_data_len);
 
-       ret = ib_post_send_mad(cm_id_priv->av.port->mad_agent,
-                              &msg->send_wr, &bad_send_wr);
+       ret = ib_post_send_mad(msg, NULL);
        if (ret) {
                spin_unlock_irqrestore(&cm_id_priv->lock, flags);
                cm_free_msg(msg);
@@ -1486,7 +1492,6 @@ static void cm_dup_rep_handler(struct cm_work *work)
        struct cm_id_private *cm_id_priv;
        struct cm_rep_msg *rep_msg;
        struct ib_mad_send_buf *msg = NULL;
-       struct ib_send_wr *bad_send_wr;
        unsigned long flags;
        int ret;
 
@@ -1514,8 +1519,7 @@ static void cm_dup_rep_handler(struct cm_work *work)
                goto unlock;
        spin_unlock_irqrestore(&cm_id_priv->lock, flags);
 
-       ret = ib_post_send_mad(cm_id_priv->av.port->mad_agent, &msg->send_wr,
-                              &bad_send_wr);
+       ret = ib_post_send_mad(msg, NULL);
        if (ret)
                goto free;
        goto deref;
@@ -1583,8 +1587,7 @@ static int cm_rep_handler(struct cm_work *work)
 
        /* todo: handle peer_to_peer */
 
-       ib_cancel_mad(cm_id_priv->av.port->mad_agent,
-                     (unsigned long) cm_id_priv->msg);
+       ib_cancel_mad(cm_id_priv->av.port->mad_agent, cm_id_priv->msg);
        ret = atomic_inc_and_test(&cm_id_priv->work_count);
        if (!ret)
                list_add_tail(&work->list, &cm_id_priv->work_list);
@@ -1618,8 +1621,7 @@ static int cm_establish_handler(struct cm_work *work)
                goto out;
        }
 
-       ib_cancel_mad(cm_id_priv->av.port->mad_agent,
-                     (unsigned long) cm_id_priv->msg);
+       ib_cancel_mad(cm_id_priv->av.port->mad_agent, cm_id_priv->msg);
        ret = atomic_inc_and_test(&cm_id_priv->work_count);
        if (!ret)
                list_add_tail(&work->list, &cm_id_priv->work_list);
@@ -1658,8 +1660,7 @@ static int cm_rtu_handler(struct cm_work *work)
        }
        cm_id_priv->id.state = IB_CM_ESTABLISHED;
 
-       ib_cancel_mad(cm_id_priv->av.port->mad_agent,
-                     (unsigned long) cm_id_priv->msg);
+       ib_cancel_mad(cm_id_priv->av.port->mad_agent, cm_id_priv->msg);
        ret = atomic_inc_and_test(&cm_id_priv->work_count);
        if (!ret)
                list_add_tail(&work->list, &cm_id_priv->work_list);
@@ -1696,7 +1697,6 @@ int ib_send_cm_dreq(struct ib_cm_id *cm_id,
 {
        struct cm_id_private *cm_id_priv;
        struct ib_mad_send_buf *msg;
-       struct ib_send_wr *bad_send_wr;
        unsigned long flags;
        int ret;
 
@@ -1718,11 +1718,10 @@ int ib_send_cm_dreq(struct ib_cm_id *cm_id,
 
        cm_format_dreq((struct cm_dreq_msg *) msg->mad, cm_id_priv,
                       private_data, private_data_len);
-       msg->send_wr.wr.ud.timeout_ms = cm_id_priv->timeout_ms;
+       msg->timeout_ms = cm_id_priv->timeout_ms;
        msg->context[1] = (void *) (unsigned long) IB_CM_DREQ_SENT;
 
-       ret = ib_post_send_mad(cm_id_priv->av.port->mad_agent,
-                              &msg->send_wr, &bad_send_wr);
+       ret = ib_post_send_mad(msg, NULL);
        if (ret) {
                cm_enter_timewait(cm_id_priv);
                spin_unlock_irqrestore(&cm_id_priv->lock, flags);
@@ -1756,7 +1755,6 @@ int ib_send_cm_drep(struct ib_cm_id *cm_id,
 {
        struct cm_id_private *cm_id_priv;
        struct ib_mad_send_buf *msg;
-       struct ib_send_wr *bad_send_wr;
        unsigned long flags;
        void *data;
        int ret;
@@ -1786,8 +1784,7 @@ int ib_send_cm_drep(struct ib_cm_id *cm_id,
        cm_format_drep((struct cm_drep_msg *) msg->mad, cm_id_priv,
                       private_data, private_data_len);
 
-       ret = ib_post_send_mad(cm_id_priv->av.port->mad_agent, &msg->send_wr,
-                              &bad_send_wr);
+       ret = ib_post_send_mad(msg, NULL);
        if (ret) {
                spin_unlock_irqrestore(&cm_id_priv->lock, flags);
                cm_free_msg(msg);
@@ -1804,7 +1801,6 @@ static int cm_dreq_handler(struct cm_work *work)
        struct cm_id_private *cm_id_priv;
        struct cm_dreq_msg *dreq_msg;
        struct ib_mad_send_buf *msg = NULL;
-       struct ib_send_wr *bad_send_wr;
        unsigned long flags;
        int ret;
 
@@ -1823,8 +1819,7 @@ static int cm_dreq_handler(struct cm_work *work)
        switch (cm_id_priv->id.state) {
        case IB_CM_REP_SENT:
        case IB_CM_DREQ_SENT:
-               ib_cancel_mad(cm_id_priv->av.port->mad_agent,
-                             (unsigned long) cm_id_priv->msg);
+               ib_cancel_mad(cm_id_priv->av.port->mad_agent, cm_id_priv->msg);
                break;
        case IB_CM_ESTABLISHED:
        case IB_CM_MRA_REP_RCVD:
@@ -1838,8 +1833,7 @@ static int cm_dreq_handler(struct cm_work *work)
                               cm_id_priv->private_data_len);
                spin_unlock_irqrestore(&cm_id_priv->lock, flags);
 
-               if (ib_post_send_mad(cm_id_priv->av.port->mad_agent,
-                                    &msg->send_wr, &bad_send_wr))
+               if (ib_post_send_mad(msg, NULL))
                        cm_free_msg(msg);
                goto deref;
        default:
@@ -1886,8 +1880,7 @@ static int cm_drep_handler(struct cm_work *work)
        }
        cm_enter_timewait(cm_id_priv);
 
-       ib_cancel_mad(cm_id_priv->av.port->mad_agent,
-                     (unsigned long) cm_id_priv->msg);
+       ib_cancel_mad(cm_id_priv->av.port->mad_agent, cm_id_priv->msg);
        ret = atomic_inc_and_test(&cm_id_priv->work_count);
        if (!ret)
                list_add_tail(&work->list, &cm_id_priv->work_list);
@@ -1912,7 +1905,6 @@ int ib_send_cm_rej(struct ib_cm_id *cm_id,
 {
        struct cm_id_private *cm_id_priv;
        struct ib_mad_send_buf *msg;
-       struct ib_send_wr *bad_send_wr;
        unsigned long flags;
        int ret;
 
@@ -1956,8 +1948,7 @@ int ib_send_cm_rej(struct ib_cm_id *cm_id,
        if (ret)
                goto out;
 
-       ret = ib_post_send_mad(cm_id_priv->av.port->mad_agent,
-                              &msg->send_wr, &bad_send_wr);
+       ret = ib_post_send_mad(msg, NULL);
        if (ret)
                cm_free_msg(msg);
 
@@ -2033,8 +2024,7 @@ static int cm_rej_handler(struct cm_work *work)
        case IB_CM_MRA_REQ_RCVD:
        case IB_CM_REP_SENT:
        case IB_CM_MRA_REP_RCVD:
-               ib_cancel_mad(cm_id_priv->av.port->mad_agent,
-                             (unsigned long) cm_id_priv->msg);
+               ib_cancel_mad(cm_id_priv->av.port->mad_agent, cm_id_priv->msg);
                /* fall through */
        case IB_CM_REQ_RCVD:
        case IB_CM_MRA_REQ_SENT:
@@ -2044,8 +2034,7 @@ static int cm_rej_handler(struct cm_work *work)
                        cm_reset_to_idle(cm_id_priv);
                break;
        case IB_CM_DREQ_SENT:
-               ib_cancel_mad(cm_id_priv->av.port->mad_agent,
-                             (unsigned long) cm_id_priv->msg);
+               ib_cancel_mad(cm_id_priv->av.port->mad_agent, cm_id_priv->msg);
                /* fall through */
        case IB_CM_REP_RCVD:
        case IB_CM_MRA_REP_SENT:
@@ -2080,7 +2069,6 @@ int ib_send_cm_mra(struct ib_cm_id *cm_id,
 {
        struct cm_id_private *cm_id_priv;
        struct ib_mad_send_buf *msg;
-       struct ib_send_wr *bad_send_wr;
        void *data;
        unsigned long flags;
        int ret;
@@ -2104,8 +2092,7 @@ int ib_send_cm_mra(struct ib_cm_id *cm_id,
                cm_format_mra((struct cm_mra_msg *) msg->mad, cm_id_priv,
                              CM_MSG_RESPONSE_REQ, service_timeout,
                              private_data, private_data_len);
-               ret = ib_post_send_mad(cm_id_priv->av.port->mad_agent,
-                                      &msg->send_wr, &bad_send_wr);
+               ret = ib_post_send_mad(msg, NULL);
                if (ret)
                        goto error2;
                cm_id->state = IB_CM_MRA_REQ_SENT;
@@ -2118,8 +2105,7 @@ int ib_send_cm_mra(struct ib_cm_id *cm_id,
                cm_format_mra((struct cm_mra_msg *) msg->mad, cm_id_priv,
                              CM_MSG_RESPONSE_REP, service_timeout,
                              private_data, private_data_len);
-               ret = ib_post_send_mad(cm_id_priv->av.port->mad_agent,
-                                      &msg->send_wr, &bad_send_wr);
+               ret = ib_post_send_mad(msg, NULL);
                if (ret)
                        goto error2;
                cm_id->state = IB_CM_MRA_REP_SENT;
@@ -2132,8 +2118,7 @@ int ib_send_cm_mra(struct ib_cm_id *cm_id,
                cm_format_mra((struct cm_mra_msg *) msg->mad, cm_id_priv,
                              CM_MSG_RESPONSE_OTHER, service_timeout,
                              private_data, private_data_len);
-               ret = ib_post_send_mad(cm_id_priv->av.port->mad_agent,
-                                      &msg->send_wr, &bad_send_wr);
+               ret = ib_post_send_mad(msg, NULL);
                if (ret)
                        goto error2;
                cm_id->lap_state = IB_CM_MRA_LAP_SENT;
@@ -2195,14 +2180,14 @@ static int cm_mra_handler(struct cm_work *work)
        case IB_CM_REQ_SENT:
                if (cm_mra_get_msg_mraed(mra_msg) != CM_MSG_RESPONSE_REQ ||
                    ib_modify_mad(cm_id_priv->av.port->mad_agent,
-                                 (unsigned long) cm_id_priv->msg, timeout))
+                                 cm_id_priv->msg, timeout))
                        goto out;
                cm_id_priv->id.state = IB_CM_MRA_REQ_RCVD;
                break;
        case IB_CM_REP_SENT:
                if (cm_mra_get_msg_mraed(mra_msg) != CM_MSG_RESPONSE_REP ||
                    ib_modify_mad(cm_id_priv->av.port->mad_agent,
-                                 (unsigned long) cm_id_priv->msg, timeout))
+                                 cm_id_priv->msg, timeout))
                        goto out;
                cm_id_priv->id.state = IB_CM_MRA_REP_RCVD;
                break;
@@ -2210,7 +2195,7 @@ static int cm_mra_handler(struct cm_work *work)
                if (cm_mra_get_msg_mraed(mra_msg) != CM_MSG_RESPONSE_OTHER ||
                    cm_id_priv->id.lap_state != IB_CM_LAP_SENT ||
                    ib_modify_mad(cm_id_priv->av.port->mad_agent,
-                                 (unsigned long) cm_id_priv->msg, timeout))
+                                 cm_id_priv->msg, timeout))
                        goto out;
                cm_id_priv->id.lap_state = IB_CM_MRA_LAP_RCVD;
                break;
@@ -2273,7 +2258,6 @@ int ib_send_cm_lap(struct ib_cm_id *cm_id,
 {
        struct cm_id_private *cm_id_priv;
        struct ib_mad_send_buf *msg;
-       struct ib_send_wr *bad_send_wr;
        unsigned long flags;
        int ret;
 
@@ -2294,11 +2278,10 @@ int ib_send_cm_lap(struct ib_cm_id *cm_id,
 
        cm_format_lap((struct cm_lap_msg *) msg->mad, cm_id_priv,
                      alternate_path, private_data, private_data_len);
-       msg->send_wr.wr.ud.timeout_ms = cm_id_priv->timeout_ms;
+       msg->timeout_ms = cm_id_priv->timeout_ms;
        msg->context[1] = (void *) (unsigned long) IB_CM_ESTABLISHED;
 
-       ret = ib_post_send_mad(cm_id_priv->av.port->mad_agent,
-                              &msg->send_wr, &bad_send_wr);
+       ret = ib_post_send_mad(msg, NULL);
        if (ret) {
                spin_unlock_irqrestore(&cm_id_priv->lock, flags);
                cm_free_msg(msg);
@@ -2342,7 +2325,6 @@ static int cm_lap_handler(struct cm_work *work)
        struct cm_lap_msg *lap_msg;
        struct ib_cm_lap_event_param *param;
        struct ib_mad_send_buf *msg = NULL;
-       struct ib_send_wr *bad_send_wr;
        unsigned long flags;
        int ret;
 
@@ -2376,8 +2358,7 @@ static int cm_lap_handler(struct cm_work *work)
                              cm_id_priv->private_data_len);
                spin_unlock_irqrestore(&cm_id_priv->lock, flags);
 
-               if (ib_post_send_mad(cm_id_priv->av.port->mad_agent,
-                                    &msg->send_wr, &bad_send_wr))
+               if (ib_post_send_mad(msg, NULL))
                        cm_free_msg(msg);
                goto deref;
        default:
@@ -2433,7 +2414,6 @@ int ib_send_cm_apr(struct ib_cm_id *cm_id,
 {
        struct cm_id_private *cm_id_priv;
        struct ib_mad_send_buf *msg;
-       struct ib_send_wr *bad_send_wr;
        unsigned long flags;
        int ret;
 
@@ -2456,8 +2436,7 @@ int ib_send_cm_apr(struct ib_cm_id *cm_id,
 
        cm_format_apr((struct cm_apr_msg *) msg->mad, cm_id_priv, status,
                      info, info_length, private_data, private_data_len);
-       ret = ib_post_send_mad(cm_id_priv->av.port->mad_agent,
-                              &msg->send_wr, &bad_send_wr);
+       ret = ib_post_send_mad(msg, NULL);
        if (ret) {
                spin_unlock_irqrestore(&cm_id_priv->lock, flags);
                cm_free_msg(msg);
@@ -2496,8 +2475,7 @@ static int cm_apr_handler(struct cm_work *work)
                goto out;
        }
        cm_id_priv->id.lap_state = IB_CM_LAP_IDLE;
-       ib_cancel_mad(cm_id_priv->av.port->mad_agent,
-                     (unsigned long) cm_id_priv->msg);
+       ib_cancel_mad(cm_id_priv->av.port->mad_agent, cm_id_priv->msg);
        cm_id_priv->msg = NULL;
 
        ret = atomic_inc_and_test(&cm_id_priv->work_count);
@@ -2572,7 +2550,6 @@ int ib_send_cm_sidr_req(struct ib_cm_id *cm_id,
 {
        struct cm_id_private *cm_id_priv;
        struct ib_mad_send_buf *msg;
-       struct ib_send_wr *bad_send_wr;
        unsigned long flags;
        int ret;
 
@@ -2595,13 +2572,12 @@ int ib_send_cm_sidr_req(struct ib_cm_id *cm_id,
 
        cm_format_sidr_req((struct cm_sidr_req_msg *) msg->mad, cm_id_priv,
                           param);
-       msg->send_wr.wr.ud.timeout_ms = cm_id_priv->timeout_ms;
+       msg->timeout_ms = cm_id_priv->timeout_ms;
        msg->context[1] = (void *) (unsigned long) IB_CM_SIDR_REQ_SENT;
 
        spin_lock_irqsave(&cm_id_priv->lock, flags);
        if (cm_id->state == IB_CM_IDLE)
-               ret = ib_post_send_mad(cm_id_priv->av.port->mad_agent,
-                                      &msg->send_wr, &bad_send_wr);
+               ret = ib_post_send_mad(msg, NULL);
        else
                ret = -EINVAL;
 
@@ -2629,7 +2605,6 @@ static void cm_format_sidr_req_event(struct cm_work *work,
        param = &work->cm_event.param.sidr_req_rcvd;
        param->pkey = __be16_to_cpu(sidr_req_msg->pkey);
        param->listen_id = listen_id;
-       param->device = work->port->mad_agent->device;
        param->port = work->port->port_num;
        work->cm_event.private_data = &sidr_req_msg->private_data;
 }
@@ -2642,7 +2617,7 @@ static int cm_sidr_req_handler(struct cm_work *work)
        struct ib_wc *wc;
        unsigned long flags;
 
-       cm_id = ib_create_cm_id(NULL, NULL);
+       cm_id = ib_create_cm_id(work->port->cm_dev->device, NULL, NULL);
        if (IS_ERR(cm_id))
                return PTR_ERR(cm_id);
        cm_id_priv = container_of(cm_id, struct cm_id_private, id);
@@ -2666,7 +2641,8 @@ static int cm_sidr_req_handler(struct cm_work *work)
                spin_unlock_irqrestore(&cm.lock, flags);
                goto out; /* Duplicate message. */
        }
-       cur_cm_id_priv = cm_find_listen(sidr_req_msg->service_id);
+       cur_cm_id_priv = cm_find_listen(cm_id->device,
+                                       sidr_req_msg->service_id);
        if (!cur_cm_id_priv) {
                rb_erase(&cm_id_priv->sidr_id_node, &cm.remote_sidr_table);
                spin_unlock_irqrestore(&cm.lock, flags);
@@ -2715,7 +2691,6 @@ int ib_send_cm_sidr_rep(struct ib_cm_id *cm_id,
 {
        struct cm_id_private *cm_id_priv;
        struct ib_mad_send_buf *msg;
-       struct ib_send_wr *bad_send_wr;
        unsigned long flags;
        int ret;
 
@@ -2737,8 +2712,7 @@ int ib_send_cm_sidr_rep(struct ib_cm_id *cm_id,
 
        cm_format_sidr_rep((struct cm_sidr_rep_msg *) msg->mad, cm_id_priv,
                           param);
-       ret = ib_post_send_mad(cm_id_priv->av.port->mad_agent,
-                              &msg->send_wr, &bad_send_wr);
+       ret = ib_post_send_mad(msg, NULL);
        if (ret) {
                spin_unlock_irqrestore(&cm_id_priv->lock, flags);
                cm_free_msg(msg);
@@ -2791,8 +2765,7 @@ static int cm_sidr_rep_handler(struct cm_work *work)
                goto out;
        }
        cm_id_priv->id.state = IB_CM_IDLE;
-       ib_cancel_mad(cm_id_priv->av.port->mad_agent,
-                     (unsigned long) cm_id_priv->msg);
+       ib_cancel_mad(cm_id_priv->av.port->mad_agent, cm_id_priv->msg);
        spin_unlock_irqrestore(&cm_id_priv->lock, flags);
 
        cm_format_sidr_rep_event(work);
@@ -2860,9 +2833,7 @@ discard:
 static void cm_send_handler(struct ib_mad_agent *mad_agent,
                            struct ib_mad_send_wc *mad_send_wc)
 {
-       struct ib_mad_send_buf *msg;
-
-       msg = (struct ib_mad_send_buf *)(unsigned long)mad_send_wc->wr_id;
+       struct ib_mad_send_buf *msg = mad_send_wc->send_buf;
 
        switch (mad_send_wc->status) {
        case IB_WC_SUCCESS:
@@ -3064,10 +3035,10 @@ static int cm_init_qp_init_attr(struct cm_id_private *cm_id_priv,
        case IB_CM_ESTABLISHED:
                *qp_attr_mask = IB_QP_STATE | IB_QP_ACCESS_FLAGS |
                                IB_QP_PKEY_INDEX | IB_QP_PORT;
-               qp_attr->qp_access_flags = IB_ACCESS_LOCAL_WRITE;
+               qp_attr->qp_access_flags = IB_ACCESS_LOCAL_WRITE |
+                                          IB_ACCESS_REMOTE_WRITE;
                if (cm_id_priv->responder_resources)
-                       qp_attr->qp_access_flags |= IB_ACCESS_REMOTE_WRITE |
-                                                   IB_ACCESS_REMOTE_READ;
+                       qp_attr->qp_access_flags |= IB_ACCESS_REMOTE_READ;
                qp_attr->pkey_index = cm_id_priv->av.pkey_index;
                qp_attr->port_num = cm_id_priv->av.port->port_num;
                ret = 0;
@@ -3097,14 +3068,18 @@ static int cm_init_qp_rtr_attr(struct cm_id_private *cm_id_priv,
        case IB_CM_MRA_REP_RCVD:
        case IB_CM_ESTABLISHED:
                *qp_attr_mask = IB_QP_STATE | IB_QP_AV | IB_QP_PATH_MTU |
-                               IB_QP_DEST_QPN | IB_QP_RQ_PSN |
-                               IB_QP_MAX_DEST_RD_ATOMIC | IB_QP_MIN_RNR_TIMER;
+                               IB_QP_DEST_QPN | IB_QP_RQ_PSN;
                qp_attr->ah_attr = cm_id_priv->av.ah_attr;
                qp_attr->path_mtu = cm_id_priv->path_mtu;
                qp_attr->dest_qp_num = be32_to_cpu(cm_id_priv->remote_qpn);
                qp_attr->rq_psn = be32_to_cpu(cm_id_priv->rq_psn);
-               qp_attr->max_dest_rd_atomic = cm_id_priv->responder_resources;
-               qp_attr->min_rnr_timer = 0;
+               if (cm_id_priv->qp_type == IB_QPT_RC) {
+                       *qp_attr_mask |= IB_QP_MAX_DEST_RD_ATOMIC |
+                                        IB_QP_MIN_RNR_TIMER;
+                       qp_attr->max_dest_rd_atomic =
+                                       cm_id_priv->responder_resources;
+                       qp_attr->min_rnr_timer = 0;
+               }
                if (cm_id_priv->alt_av.ah_attr.dlid) {
                        *qp_attr_mask |= IB_QP_ALT_PATH;
                        qp_attr->alt_ah_attr = cm_id_priv->alt_av.ah_attr;
@@ -3133,14 +3108,17 @@ static int cm_init_qp_rts_attr(struct cm_id_private *cm_id_priv,
        case IB_CM_REP_SENT:
        case IB_CM_MRA_REP_RCVD:
        case IB_CM_ESTABLISHED:
-               *qp_attr_mask = IB_QP_STATE | IB_QP_TIMEOUT | IB_QP_RETRY_CNT |
-                               IB_QP_RNR_RETRY | IB_QP_SQ_PSN |
-                               IB_QP_MAX_QP_RD_ATOMIC;
-               qp_attr->timeout = cm_id_priv->local_ack_timeout;
-               qp_attr->retry_cnt = cm_id_priv->retry_count;
-               qp_attr->rnr_retry = cm_id_priv->rnr_retry_count;
+               *qp_attr_mask = IB_QP_STATE | IB_QP_SQ_PSN;
                qp_attr->sq_psn = be32_to_cpu(cm_id_priv->sq_psn);
-               qp_attr->max_rd_atomic = cm_id_priv->initiator_depth;
+               if (cm_id_priv->qp_type == IB_QPT_RC) {
+                       *qp_attr_mask |= IB_QP_TIMEOUT | IB_QP_RETRY_CNT |
+                                        IB_QP_RNR_RETRY |
+                                        IB_QP_MAX_QP_RD_ATOMIC;
+                       qp_attr->timeout = cm_id_priv->local_ack_timeout;
+                       qp_attr->retry_cnt = cm_id_priv->retry_count;
+                       qp_attr->rnr_retry = cm_id_priv->rnr_retry_count;
+                       qp_attr->max_rd_atomic = cm_id_priv->initiator_depth;
+               }
                if (cm_id_priv->alt_av.ah_attr.dlid) {
                        *qp_attr_mask |= IB_QP_PATH_MIG_STATE;
                        qp_attr->path_mig_state = IB_MIG_REARM;
@@ -3323,6 +3301,7 @@ static void __exit ib_cm_cleanup(void)
        flush_workqueue(cm.wq);
        destroy_workqueue(cm.wq);
        ib_unregister_client(&cm_client);
+       idr_destroy(&cm.local_id_table);
 }
 
 module_init(ib_cm_init);
index 813ab70..4d3aee9 100644 (file)
@@ -186,6 +186,7 @@ static inline void cm_req_set_qp_type(struct cm_req_msg *req_msg,
                req_msg->offset40 = cpu_to_be32((be32_to_cpu(
                                                  req_msg->offset40) &
                                                   0xFFFFFFF9) | 0x2);
+               break;
        default:
                req_msg->offset40 = cpu_to_be32(be32_to_cpu(
                                                 req_msg->offset40) &
index d3cf84e..5a6e449 100644 (file)
@@ -514,6 +514,12 @@ int ib_query_port(struct ib_device *device,
                  u8 port_num,
                  struct ib_port_attr *port_attr)
 {
+       if (device->node_type == IB_NODE_SWITCH) {
+               if (port_num)
+                       return -EINVAL;
+       } else if (port_num < 1 || port_num > device->phys_port_cnt)
+               return -EINVAL;
+
        return device->query_port(device, port_num, port_attr);
 }
 EXPORT_SYMBOL(ib_query_port);
@@ -583,6 +589,12 @@ int ib_modify_port(struct ib_device *device,
                   u8 port_num, int port_modify_mask,
                   struct ib_port_modify *port_modify)
 {
+       if (device->node_type == IB_NODE_SWITCH) {
+               if (port_num)
+                       return -EINVAL;
+       } else if (port_num < 1 || port_num > device->phys_port_cnt)
+               return -EINVAL;
+
        return device->modify_port(device, port_num, port_modify_mask,
                                   port_modify);
 }
index a14ca87..88f9f8c 100644 (file)
@@ -579,7 +579,7 @@ static void dequeue_mad(struct ib_mad_list_head *mad_list)
 }
 
 static void snoop_send(struct ib_mad_qp_info *qp_info,
-                      struct ib_send_wr *send_wr,
+                      struct ib_mad_send_buf *send_buf,
                       struct ib_mad_send_wc *mad_send_wc,
                       int mad_snoop_flags)
 {
@@ -597,7 +597,7 @@ static void snoop_send(struct ib_mad_qp_info *qp_info,
                atomic_inc(&mad_snoop_priv->refcount);
                spin_unlock_irqrestore(&qp_info->snoop_lock, flags);
                mad_snoop_priv->agent.snoop_handler(&mad_snoop_priv->agent,
-                                                   send_wr, mad_send_wc);
+                                                   send_buf, mad_send_wc);
                if (atomic_dec_and_test(&mad_snoop_priv->refcount))
                        wake_up(&mad_snoop_priv->wait);
                spin_lock_irqsave(&qp_info->snoop_lock, flags);
@@ -654,10 +654,10 @@ static void build_smp_wc(u64 wr_id, u16 slid, u16 pkey_index, u8 port_num,
  * Return < 0 if error
  */
 static int handle_outgoing_dr_smp(struct ib_mad_agent_private *mad_agent_priv,
-                                 struct ib_smp *smp,
-                                 struct ib_send_wr *send_wr)
+                                 struct ib_mad_send_wr_private *mad_send_wr)
 {
        int ret;
+       struct ib_smp *smp = mad_send_wr->send_buf.mad;
        unsigned long flags;
        struct ib_mad_local_private *local;
        struct ib_mad_private *mad_priv;
@@ -666,6 +666,7 @@ static int handle_outgoing_dr_smp(struct ib_mad_agent_private *mad_agent_priv,
        struct ib_device *device = mad_agent_priv->agent.device;
        u8 port_num = mad_agent_priv->agent.port_num;
        struct ib_wc mad_wc;
+       struct ib_send_wr *send_wr = &mad_send_wr->send_wr;
 
        if (!smi_handle_dr_smp_send(smp, device->node_type, port_num)) {
                ret = -EINVAL;
@@ -745,13 +746,7 @@ static int handle_outgoing_dr_smp(struct ib_mad_agent_private *mad_agent_priv,
                goto out;
        }
 
-       local->send_wr = *send_wr;
-       local->send_wr.sg_list = local->sg_list;
-       memcpy(local->sg_list, send_wr->sg_list,
-              sizeof *send_wr->sg_list * send_wr->num_sge);
-       local->send_wr.next = NULL;
-       local->tid = send_wr->wr.ud.mad_hdr->tid;
-       local->wr_id = send_wr->wr_id;
+       local->mad_send_wr = mad_send_wr;
        /* Reference MAD agent until send side of local completion handled */
        atomic_inc(&mad_agent_priv->refcount);
        /* Queue local completion to local list */
@@ -781,17 +776,17 @@ static int get_buf_length(int hdr_len, int data_len)
 
 struct ib_mad_send_buf * ib_create_send_mad(struct ib_mad_agent *mad_agent,
                                            u32 remote_qpn, u16 pkey_index,
-                                           struct ib_ah *ah, int rmpp_active,
+                                           int rmpp_active,
                                            int hdr_len, int data_len,
                                            gfp_t gfp_mask)
 {
        struct ib_mad_agent_private *mad_agent_priv;
-       struct ib_mad_send_buf *send_buf;
+       struct ib_mad_send_wr_private *mad_send_wr;
        int buf_size;
        void *buf;
 
-       mad_agent_priv = container_of(mad_agent,
-                                     struct ib_mad_agent_private, agent);
+       mad_agent_priv = container_of(mad_agent, struct ib_mad_agent_private,
+                                     agent);
        buf_size = get_buf_length(hdr_len, data_len);
 
        if ((!mad_agent->rmpp_version &&
@@ -799,45 +794,40 @@ struct ib_mad_send_buf * ib_create_send_mad(struct ib_mad_agent *mad_agent,
            (!rmpp_active && buf_size > sizeof(struct ib_mad)))
                return ERR_PTR(-EINVAL);
 
-       buf = kmalloc(sizeof *send_buf + buf_size, gfp_mask);
+       buf = kmalloc(sizeof *mad_send_wr + buf_size, gfp_mask);
        if (!buf)
                return ERR_PTR(-ENOMEM);
-       memset(buf, 0, sizeof *send_buf + buf_size);
-
-       send_buf = buf + buf_size;
-       send_buf->mad = buf;
-
-       send_buf->sge.addr = dma_map_single(mad_agent->device->dma_device,
-                                           buf, buf_size, DMA_TO_DEVICE);
-       pci_unmap_addr_set(send_buf, mapping, send_buf->sge.addr);
-       send_buf->sge.length = buf_size;
-       send_buf->sge.lkey = mad_agent->mr->lkey;
-
-       send_buf->send_wr.wr_id = (unsigned long) send_buf;
-       send_buf->send_wr.sg_list = &send_buf->sge;
-       send_buf->send_wr.num_sge = 1;
-       send_buf->send_wr.opcode = IB_WR_SEND;
-       send_buf->send_wr.send_flags = IB_SEND_SIGNALED;
-       send_buf->send_wr.wr.ud.ah = ah;
-       send_buf->send_wr.wr.ud.mad_hdr = &send_buf->mad->mad_hdr;
-       send_buf->send_wr.wr.ud.remote_qpn = remote_qpn;
-       send_buf->send_wr.wr.ud.remote_qkey = IB_QP_SET_QKEY;
-       send_buf->send_wr.wr.ud.pkey_index = pkey_index;
+       memset(buf, 0, sizeof *mad_send_wr + buf_size);
+
+       mad_send_wr = buf + buf_size;
+       mad_send_wr->send_buf.mad = buf;
+
+       mad_send_wr->mad_agent_priv = mad_agent_priv;
+       mad_send_wr->sg_list[0].length = buf_size;
+       mad_send_wr->sg_list[0].lkey = mad_agent->mr->lkey;
+
+       mad_send_wr->send_wr.wr_id = (unsigned long) mad_send_wr;
+       mad_send_wr->send_wr.sg_list = mad_send_wr->sg_list;
+       mad_send_wr->send_wr.num_sge = 1;
+       mad_send_wr->send_wr.opcode = IB_WR_SEND;
+       mad_send_wr->send_wr.send_flags = IB_SEND_SIGNALED;
+       mad_send_wr->send_wr.wr.ud.remote_qpn = remote_qpn;
+       mad_send_wr->send_wr.wr.ud.remote_qkey = IB_QP_SET_QKEY;
+       mad_send_wr->send_wr.wr.ud.pkey_index = pkey_index;
 
        if (rmpp_active) {
-               struct ib_rmpp_mad *rmpp_mad;
-               rmpp_mad = (struct ib_rmpp_mad *)send_buf->mad;
+               struct ib_rmpp_mad *rmpp_mad = mad_send_wr->send_buf.mad;
                rmpp_mad->rmpp_hdr.paylen_newwin = cpu_to_be32(hdr_len -
-                       offsetof(struct ib_rmpp_mad, data) + data_len);
+                                                  IB_MGMT_RMPP_HDR + data_len);
                rmpp_mad->rmpp_hdr.rmpp_version = mad_agent->rmpp_version;
                rmpp_mad->rmpp_hdr.rmpp_type = IB_MGMT_RMPP_TYPE_DATA;
                ib_set_rmpp_flags(&rmpp_mad->rmpp_hdr,
                                  IB_MGMT_RMPP_FLAG_ACTIVE);
        }
 
-       send_buf->mad_agent = mad_agent;
+       mad_send_wr->send_buf.mad_agent = mad_agent;
        atomic_inc(&mad_agent_priv->refcount);
-       return send_buf;
+       return &mad_send_wr->send_buf;
 }
 EXPORT_SYMBOL(ib_create_send_mad);
 
@@ -847,10 +837,6 @@ void ib_free_send_mad(struct ib_mad_send_buf *send_buf)
 
        mad_agent_priv = container_of(send_buf->mad_agent,
                                      struct ib_mad_agent_private, agent);
-
-       dma_unmap_single(send_buf->mad_agent->device->dma_device,
-                        pci_unmap_addr(send_buf, mapping),
-                        send_buf->sge.length, DMA_TO_DEVICE);
        kfree(send_buf->mad);
 
        if (atomic_dec_and_test(&mad_agent_priv->refcount))
@@ -861,8 +847,10 @@ EXPORT_SYMBOL(ib_free_send_mad);
 int ib_send_mad(struct ib_mad_send_wr_private *mad_send_wr)
 {
        struct ib_mad_qp_info *qp_info;
-       struct ib_send_wr *bad_send_wr;
        struct list_head *list;
+       struct ib_send_wr *bad_send_wr;
+       struct ib_mad_agent *mad_agent;
+       struct ib_sge *sge;
        unsigned long flags;
        int ret;
 
@@ -871,10 +859,17 @@ int ib_send_mad(struct ib_mad_send_wr_private *mad_send_wr)
        mad_send_wr->send_wr.wr_id = (unsigned long)&mad_send_wr->mad_list;
        mad_send_wr->mad_list.mad_queue = &qp_info->send_queue;
 
+       mad_agent = mad_send_wr->send_buf.mad_agent;
+       sge = mad_send_wr->sg_list;
+       sge->addr = dma_map_single(mad_agent->device->dma_device,
+                                  mad_send_wr->send_buf.mad, sge->length,
+                                  DMA_TO_DEVICE);
+       pci_unmap_addr_set(mad_send_wr, mapping, sge->addr);
+
        spin_lock_irqsave(&qp_info->send_queue.lock, flags);
        if (qp_info->send_queue.count < qp_info->send_queue.max_active) {
-               ret = ib_post_send(mad_send_wr->mad_agent_priv->agent.qp,
-                                  &mad_send_wr->send_wr, &bad_send_wr);
+               ret = ib_post_send(mad_agent->qp, &mad_send_wr->send_wr,
+                                  &bad_send_wr);
                list = &qp_info->send_queue.list;
        } else {
                ret = 0;
@@ -886,6 +881,11 @@ int ib_send_mad(struct ib_mad_send_wr_private *mad_send_wr)
                list_add_tail(&mad_send_wr->mad_list.list, list);
        }
        spin_unlock_irqrestore(&qp_info->send_queue.lock, flags);
+       if (ret)
+               dma_unmap_single(mad_agent->device->dma_device,
+                                pci_unmap_addr(mad_send_wr, mapping),
+                                sge->length, DMA_TO_DEVICE);
+
        return ret;
 }
 
@@ -893,45 +893,28 @@ int ib_send_mad(struct ib_mad_send_wr_private *mad_send_wr)
  * ib_post_send_mad - Posts MAD(s) to the send queue of the QP associated
  *  with the registered client
  */
-int ib_post_send_mad(struct ib_mad_agent *mad_agent,
-                    struct ib_send_wr *send_wr,
-                    struct ib_send_wr **bad_send_wr)
+int ib_post_send_mad(struct ib_mad_send_buf *send_buf,
+                    struct ib_mad_send_buf **bad_send_buf)
 {
-       int ret = -EINVAL;
        struct ib_mad_agent_private *mad_agent_priv;
-
-       /* Validate supplied parameters */
-       if (!bad_send_wr)
-               goto error1;
-
-       if (!mad_agent || !send_wr)
-               goto error2;
-
-       if (!mad_agent->send_handler)
-               goto error2;
-
-       mad_agent_priv = container_of(mad_agent,
-                                     struct ib_mad_agent_private,
-                                     agent);
+       struct ib_mad_send_buf *next_send_buf;
+       struct ib_mad_send_wr_private *mad_send_wr;
+       unsigned long flags;
+       int ret = -EINVAL;
 
        /* Walk list of send WRs and post each on send list */
-       while (send_wr) {
-               unsigned long                   flags;
-               struct ib_send_wr               *next_send_wr;
-               struct ib_mad_send_wr_private   *mad_send_wr;
-               struct ib_smp                   *smp;
-
-               /* Validate more parameters */
-               if (send_wr->num_sge > IB_MAD_SEND_REQ_MAX_SG)
-                       goto error2;
+       for (; send_buf; send_buf = next_send_buf) {
 
-               if (send_wr->wr.ud.timeout_ms && !mad_agent->recv_handler)
-                       goto error2;
-
-               if (!send_wr->wr.ud.mad_hdr) {
-                       printk(KERN_ERR PFX "MAD header must be supplied "
-                              "in WR %p\n", send_wr);
-                       goto error2;
+               mad_send_wr = container_of(send_buf,
+                                          struct ib_mad_send_wr_private,
+                                          send_buf);
+               mad_agent_priv = mad_send_wr->mad_agent_priv;
+
+               if (!send_buf->mad_agent->send_handler ||
+                   (send_buf->timeout_ms &&
+                    !send_buf->mad_agent->recv_handler)) {
+                       ret = -EINVAL;
+                       goto error;
                }
 
                /*
@@ -939,40 +922,24 @@ int ib_post_send_mad(struct ib_mad_agent *mad_agent,
                 * current one completes, and the user modifies the work
                 * request associated with the completion
                 */
-               next_send_wr = (struct ib_send_wr *)send_wr->next;
+               next_send_buf = send_buf->next;
+               mad_send_wr->send_wr.wr.ud.ah = send_buf->ah;
 
-               smp = (struct ib_smp *)send_wr->wr.ud.mad_hdr;
-               if (smp->mgmt_class == IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE) {
-                       ret = handle_outgoing_dr_smp(mad_agent_priv, smp,
-                                                    send_wr);
+               if (((struct ib_mad_hdr *) send_buf->mad)->mgmt_class ==
+                   IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE) {
+                       ret = handle_outgoing_dr_smp(mad_agent_priv,
+                                                    mad_send_wr);
                        if (ret < 0)            /* error */
-                               goto error2;
+                               goto error;
                        else if (ret == 1)      /* locally consumed */
-                               goto next;
+                               continue;
                }
 
-               /* Allocate MAD send WR tracking structure */
-               mad_send_wr = kmalloc(sizeof *mad_send_wr, GFP_ATOMIC);
-               if (!mad_send_wr) {
-                       printk(KERN_ERR PFX "No memory for "
-                              "ib_mad_send_wr_private\n");
-                       ret = -ENOMEM;
-                       goto error2;
-               }
-               memset(mad_send_wr, 0, sizeof *mad_send_wr);
-
-               mad_send_wr->send_wr = *send_wr;
-               mad_send_wr->send_wr.sg_list = mad_send_wr->sg_list;
-               memcpy(mad_send_wr->sg_list, send_wr->sg_list,
-                      sizeof *send_wr->sg_list * send_wr->num_sge);
-               mad_send_wr->wr_id = send_wr->wr_id;
-               mad_send_wr->tid = send_wr->wr.ud.mad_hdr->tid;
-               mad_send_wr->mad_agent_priv = mad_agent_priv;
+               mad_send_wr->tid = ((struct ib_mad_hdr *) send_buf->mad)->tid;
                /* Timeout will be updated after send completes */
-               mad_send_wr->timeout = msecs_to_jiffies(send_wr->wr.
-                                                       ud.timeout_ms);
-               mad_send_wr->retries = mad_send_wr->send_wr.wr.ud.retries;
-               /* One reference for each work request to QP + response */
+               mad_send_wr->timeout = msecs_to_jiffies(send_buf->timeout_ms);
+               mad_send_wr->retries = send_buf->retries;
+               /* Reference for work request to QP + response */
                mad_send_wr->refcount = 1 + (mad_send_wr->timeout > 0);
                mad_send_wr->status = IB_WC_SUCCESS;
 
@@ -995,16 +962,13 @@ int ib_post_send_mad(struct ib_mad_agent *mad_agent,
                        list_del(&mad_send_wr->agent_list);
                        spin_unlock_irqrestore(&mad_agent_priv->lock, flags);
                        atomic_dec(&mad_agent_priv->refcount);
-                       goto error2;
+                       goto error;
                }
-next:
-               send_wr = next_send_wr;
        }
        return 0;
-
-error2:
-       *bad_send_wr = send_wr;
-error1:
+error:
+       if (bad_send_buf)
+               *bad_send_buf = send_buf;
        return ret;
 }
 EXPORT_SYMBOL(ib_post_send_mad);
@@ -1447,8 +1411,7 @@ find_mad_agent(struct ib_mad_port_private *port_priv,
                 * of MAD.
                 */
                hi_tid = be64_to_cpu(mad->mad_hdr.tid) >> 32;
-               list_for_each_entry(entry, &port_priv->agent_list,
-                                   agent_list) {
+               list_for_each_entry(entry, &port_priv->agent_list, agent_list) {
                        if (entry->agent.hi_tid == hi_tid) {
                                mad_agent = entry;
                                break;
@@ -1571,8 +1534,7 @@ ib_find_send_mad(struct ib_mad_agent_private *mad_agent_priv, __be64 tid)
         */
        list_for_each_entry(mad_send_wr, &mad_agent_priv->send_list,
                            agent_list) {
-               if (is_data_mad(mad_agent_priv,
-                               mad_send_wr->send_wr.wr.ud.mad_hdr) &&
+               if (is_data_mad(mad_agent_priv, mad_send_wr->send_buf.mad) &&
                    mad_send_wr->tid == tid && mad_send_wr->timeout) {
                        /* Verify request has not been canceled */
                        return (mad_send_wr->status == IB_WC_SUCCESS) ?
@@ -1628,14 +1590,14 @@ static void ib_mad_complete_recv(struct ib_mad_agent_private *mad_agent_priv,
                spin_unlock_irqrestore(&mad_agent_priv->lock, flags);
 
                /* Defined behavior is to complete response before request */
-               mad_recv_wc->wc->wr_id = mad_send_wr->wr_id;
+               mad_recv_wc->wc->wr_id = (unsigned long) &mad_send_wr->send_buf;
                mad_agent_priv->agent.recv_handler(&mad_agent_priv->agent,
                                                   mad_recv_wc);
                atomic_dec(&mad_agent_priv->refcount);
 
                mad_send_wc.status = IB_WC_SUCCESS;
                mad_send_wc.vendor_err = 0;
-               mad_send_wc.wr_id = mad_send_wr->wr_id;
+               mad_send_wc.send_buf = &mad_send_wr->send_buf;
                ib_mad_complete_send_wr(mad_send_wr, &mad_send_wc);
        } else {
                mad_agent_priv->agent.recv_handler(&mad_agent_priv->agent,
@@ -1728,11 +1690,11 @@ local:
                        if (ret & IB_MAD_RESULT_CONSUMED)
                                goto out;
                        if (ret & IB_MAD_RESULT_REPLY) {
-                               /* Send response */
-                               if (!agent_send(response, &recv->grh, wc,
-                                               port_priv->device,
-                                               port_priv->port_num))
-                                       response = NULL;
+                               agent_send_response(&response->mad.mad,
+                                                   &recv->grh, wc,
+                                                   port_priv->device,
+                                                   port_priv->port_num,
+                                                   qp_info->qp->qp_num);
                                goto out;
                        }
                }
@@ -1866,15 +1828,15 @@ void ib_mad_complete_send_wr(struct ib_mad_send_wr_private *mad_send_wr,
 
        if (mad_send_wr->status != IB_WC_SUCCESS )
                mad_send_wc->status = mad_send_wr->status;
-       if (ret != IB_RMPP_RESULT_INTERNAL)
+       if (ret == IB_RMPP_RESULT_INTERNAL)
+               ib_rmpp_send_handler(mad_send_wc);
+       else
                mad_agent_priv->agent.send_handler(&mad_agent_priv->agent,
                                                   mad_send_wc);
 
        /* Release reference on agent taken when sending */
        if (atomic_dec_and_test(&mad_agent_priv->refcount))
                wake_up(&mad_agent_priv->wait);
-
-       kfree(mad_send_wr);
        return;
 done:
        spin_unlock_irqrestore(&mad_agent_priv->lock, flags);
@@ -1888,6 +1850,7 @@ static void ib_mad_send_done_handler(struct ib_mad_port_private *port_priv,
        struct ib_mad_qp_info           *qp_info;
        struct ib_mad_queue             *send_queue;
        struct ib_send_wr               *bad_send_wr;
+       struct ib_mad_send_wc           mad_send_wc;
        unsigned long flags;
        int ret;
 
@@ -1898,6 +1861,9 @@ static void ib_mad_send_done_handler(struct ib_mad_port_private *port_priv,
        qp_info = send_queue->qp_info;
 
 retry:
+       dma_unmap_single(mad_send_wr->send_buf.mad_agent->device->dma_device,
+                        pci_unmap_addr(mad_send_wr, mapping),
+                        mad_send_wr->sg_list[0].length, DMA_TO_DEVICE);
        queued_send_wr = NULL;
        spin_lock_irqsave(&send_queue->lock, flags);
        list_del(&mad_list->list);
@@ -1914,17 +1880,17 @@ retry:
        }
        spin_unlock_irqrestore(&send_queue->lock, flags);
 
-       /* Restore client wr_id in WC and complete send */
-       wc->wr_id = mad_send_wr->wr_id;
+       mad_send_wc.send_buf = &mad_send_wr->send_buf;
+       mad_send_wc.status = wc->status;
+       mad_send_wc.vendor_err = wc->vendor_err;
        if (atomic_read(&qp_info->snoop_count))
-               snoop_send(qp_info, &mad_send_wr->send_wr,
-                          (struct ib_mad_send_wc *)wc,
+               snoop_send(qp_info, &mad_send_wr->send_buf, &mad_send_wc,
                           IB_MAD_SNOOP_SEND_COMPLETIONS);
-       ib_mad_complete_send_wr(mad_send_wr, (struct ib_mad_send_wc *)wc);
+       ib_mad_complete_send_wr(mad_send_wr, &mad_send_wc);
 
        if (queued_send_wr) {
                ret = ib_post_send(qp_info->qp, &queued_send_wr->send_wr,
-                               &bad_send_wr);
+                                  &bad_send_wr);
                if (ret) {
                        printk(KERN_ERR PFX "ib_post_send failed: %d\n", ret);
                        mad_send_wr = queued_send_wr;
@@ -2066,38 +2032,37 @@ static void cancel_mads(struct ib_mad_agent_private *mad_agent_priv)
 
        list_for_each_entry_safe(mad_send_wr, temp_mad_send_wr,
                                 &cancel_list, agent_list) {
-               mad_send_wc.wr_id = mad_send_wr->wr_id;
+               mad_send_wc.send_buf = &mad_send_wr->send_buf;
+               list_del(&mad_send_wr->agent_list);
                mad_agent_priv->agent.send_handler(&mad_agent_priv->agent,
                                                   &mad_send_wc);
-
-               list_del(&mad_send_wr->agent_list);
-               kfree(mad_send_wr);
                atomic_dec(&mad_agent_priv->refcount);
        }
 }
 
 static struct ib_mad_send_wr_private*
-find_send_by_wr_id(struct ib_mad_agent_private *mad_agent_priv, u64 wr_id)
+find_send_wr(struct ib_mad_agent_private *mad_agent_priv,
+            struct ib_mad_send_buf *send_buf)
 {
        struct ib_mad_send_wr_private *mad_send_wr;
 
        list_for_each_entry(mad_send_wr, &mad_agent_priv->wait_list,
                            agent_list) {
-               if (mad_send_wr->wr_id == wr_id)
+               if (&mad_send_wr->send_buf == send_buf)
                        return mad_send_wr;
        }
 
        list_for_each_entry(mad_send_wr, &mad_agent_priv->send_list,
                            agent_list) {
-               if (is_data_mad(mad_agent_priv,
-                               mad_send_wr->send_wr.wr.ud.mad_hdr) &&
-                   mad_send_wr->wr_id == wr_id)
+               if (is_data_mad(mad_agent_priv, mad_send_wr->send_buf.mad) &&
+                   &mad_send_wr->send_buf == send_buf)
                        return mad_send_wr;
        }
        return NULL;
 }
 
-int ib_modify_mad(struct ib_mad_agent *mad_agent, u64 wr_id, u32 timeout_ms)
+int ib_modify_mad(struct ib_mad_agent *mad_agent,
+                 struct ib_mad_send_buf *send_buf, u32 timeout_ms)
 {
        struct ib_mad_agent_private *mad_agent_priv;
        struct ib_mad_send_wr_private *mad_send_wr;
@@ -2107,7 +2072,7 @@ int ib_modify_mad(struct ib_mad_agent *mad_agent, u64 wr_id, u32 timeout_ms)
        mad_agent_priv = container_of(mad_agent, struct ib_mad_agent_private,
                                      agent);
        spin_lock_irqsave(&mad_agent_priv->lock, flags);
-       mad_send_wr = find_send_by_wr_id(mad_agent_priv, wr_id);
+       mad_send_wr = find_send_wr(mad_agent_priv, send_buf);
        if (!mad_send_wr || mad_send_wr->status != IB_WC_SUCCESS) {
                spin_unlock_irqrestore(&mad_agent_priv->lock, flags);
                return -EINVAL;
@@ -2119,7 +2084,7 @@ int ib_modify_mad(struct ib_mad_agent *mad_agent, u64 wr_id, u32 timeout_ms)
                mad_send_wr->refcount -= (mad_send_wr->timeout > 0);
        }
 
-       mad_send_wr->send_wr.wr.ud.timeout_ms = timeout_ms;
+       mad_send_wr->send_buf.timeout_ms = timeout_ms;
        if (active)
                mad_send_wr->timeout = msecs_to_jiffies(timeout_ms);
        else
@@ -2130,9 +2095,10 @@ int ib_modify_mad(struct ib_mad_agent *mad_agent, u64 wr_id, u32 timeout_ms)
 }
 EXPORT_SYMBOL(ib_modify_mad);
 
-void ib_cancel_mad(struct ib_mad_agent *mad_agent, u64 wr_id)
+void ib_cancel_mad(struct ib_mad_agent *mad_agent,
+                  struct ib_mad_send_buf *send_buf)
 {
-       ib_modify_mad(mad_agent, wr_id, 0);
+       ib_modify_mad(mad_agent, send_buf, 0);
 }
 EXPORT_SYMBOL(ib_cancel_mad);
 
@@ -2166,10 +2132,9 @@ static void local_completions(void *data)
                         * Defined behavior is to complete response
                         * before request
                         */
-                       build_smp_wc(local->wr_id,
+                       build_smp_wc((unsigned long) local->mad_send_wr,
                                     be16_to_cpu(IB_LID_PERMISSIVE),
-                                    0 /* pkey index */,
-                                    recv_mad_agent->agent.port_num, &wc);
+                                    0, recv_mad_agent->agent.port_num, &wc);
 
                        local->mad_priv->header.recv_wc.wc = &wc;
                        local->mad_priv->header.recv_wc.mad_len =
@@ -2196,11 +2161,11 @@ local_send_completion:
                /* Complete send */
                mad_send_wc.status = IB_WC_SUCCESS;
                mad_send_wc.vendor_err = 0;
-               mad_send_wc.wr_id = local->wr_id;
+               mad_send_wc.send_buf = &local->mad_send_wr->send_buf;
                if (atomic_read(&mad_agent_priv->qp_info->snoop_count))
-                       snoop_send(mad_agent_priv->qp_info, &local->send_wr,
-                                 &mad_send_wc,
-                                  IB_MAD_SNOOP_SEND_COMPLETIONS);
+                       snoop_send(mad_agent_priv->qp_info,
+                                  &local->mad_send_wr->send_buf,
+                                  &mad_send_wc, IB_MAD_SNOOP_SEND_COMPLETIONS);
                mad_agent_priv->agent.send_handler(&mad_agent_priv->agent,
                                                   &mad_send_wc);
 
@@ -2221,8 +2186,7 @@ static int retry_send(struct ib_mad_send_wr_private *mad_send_wr)
        if (!mad_send_wr->retries--)
                return -ETIMEDOUT;
 
-       mad_send_wr->timeout = msecs_to_jiffies(mad_send_wr->send_wr.
-                                               wr.ud.timeout_ms);
+       mad_send_wr->timeout = msecs_to_jiffies(mad_send_wr->send_buf.timeout_ms);
 
        if (mad_send_wr->mad_agent_priv->agent.rmpp_version) {
                ret = ib_retry_rmpp(mad_send_wr);
@@ -2285,11 +2249,10 @@ static void timeout_sends(void *data)
                        mad_send_wc.status = IB_WC_RESP_TIMEOUT_ERR;
                else
                        mad_send_wc.status = mad_send_wr->status;
-               mad_send_wc.wr_id = mad_send_wr->wr_id;
+               mad_send_wc.send_buf = &mad_send_wr->send_buf;
                mad_agent_priv->agent.send_handler(&mad_agent_priv->agent,
                                                   &mad_send_wc);
 
-               kfree(mad_send_wr);
                atomic_dec(&mad_agent_priv->refcount);
                spin_lock_irqsave(&mad_agent_priv->lock, flags);
        }
@@ -2683,40 +2646,47 @@ static int ib_mad_port_close(struct ib_device *device, int port_num)
 
 static void ib_mad_init_device(struct ib_device *device)
 {
-       int num_ports, cur_port, i;
+       int start, end, i;
 
        if (device->node_type == IB_NODE_SWITCH) {
-               num_ports = 1;
-               cur_port = 0;
+               start = 0;
+               end   = 0;
        } else {
-               num_ports = device->phys_port_cnt;
-               cur_port = 1;
+               start = 1;
+               end   = device->phys_port_cnt;
        }
-       for (i = 0; i < num_ports; i++, cur_port++) {
-               if (ib_mad_port_open(device, cur_port)) {
+
+       for (i = start; i <= end; i++) {
+               if (ib_mad_port_open(device, i)) {
                        printk(KERN_ERR PFX "Couldn't open %s port %d\n",
-                              device->name, cur_port);
-                       goto error_device_open;
+                              device->name, i);
+                       goto error;
                }
-               if (ib_agent_port_open(device, cur_port)) {
+               if (ib_agent_port_open(device, i)) {
                        printk(KERN_ERR PFX "Couldn't open %s port %d "
                               "for agents\n",
-                              device->name, cur_port);
-                       goto error_device_open;
+                              device->name, i);
+                       goto error_agent;
                }
        }
        return;
 
-error_device_open:
-       while (i > 0) {
-               cur_port--;
-               if (ib_agent_port_close(device, cur_port))
+error_agent:
+       if (ib_mad_port_close(device, i))
+               printk(KERN_ERR PFX "Couldn't close %s port %d\n",
+                      device->name, i);
+
+error:
+       i--;
+
+       while (i >= start) {
+               if (ib_agent_port_close(device, i))
                        printk(KERN_ERR PFX "Couldn't close %s port %d "
                               "for agents\n",
-                              device->name, cur_port);
-               if (ib_mad_port_close(device, cur_port))
+                              device->name, i);
+               if (ib_mad_port_close(device, i))
                        printk(KERN_ERR PFX "Couldn't close %s port %d\n",
-                              device->name, cur_port);
+                              device->name, i);
                i--;
        }
 }
@@ -2754,7 +2724,6 @@ static int __init ib_mad_init_module(void)
        int ret;
 
        spin_lock_init(&ib_mad_port_list_lock);
-       spin_lock_init(&ib_agent_port_list_lock);
 
        ib_mad_cache = kmem_cache_create("ib_mad",
                                         sizeof(struct ib_mad_private),
index f1ba794..570f786 100644 (file)
@@ -118,9 +118,10 @@ struct ib_mad_send_wr_private {
        struct ib_mad_list_head mad_list;
        struct list_head agent_list;
        struct ib_mad_agent_private *mad_agent_priv;
+       struct ib_mad_send_buf send_buf;
+       DECLARE_PCI_UNMAP_ADDR(mapping)
        struct ib_send_wr send_wr;
        struct ib_sge sg_list[IB_MAD_SEND_REQ_MAX_SG];
-       u64 wr_id;                      /* client WR ID */
        __be64 tid;
        unsigned long timeout;
        int retries;
@@ -141,10 +142,7 @@ struct ib_mad_local_private {
        struct list_head completion_list;
        struct ib_mad_private *mad_priv;
        struct ib_mad_agent_private *recv_mad_agent;
-       struct ib_send_wr send_wr;
-       struct ib_sge sg_list[IB_MAD_SEND_REQ_MAX_SG];
-       u64 wr_id;                      /* client WR ID */
-       __be64 tid;
+       struct ib_mad_send_wr_private *mad_send_wr;
 };
 
 struct ib_mad_mgmt_method_table {
index e23836d..3249e1d 100644 (file)
@@ -103,12 +103,12 @@ void ib_cancel_rmpp_recvs(struct ib_mad_agent_private *agent)
 static int data_offset(u8 mgmt_class)
 {
        if (mgmt_class == IB_MGMT_CLASS_SUBN_ADM)
-               return offsetof(struct ib_sa_mad, data);
+               return IB_MGMT_SA_HDR;
        else if ((mgmt_class >= IB_MGMT_CLASS_VENDOR_RANGE2_START) &&
                 (mgmt_class <= IB_MGMT_CLASS_VENDOR_RANGE2_END))
-               return offsetof(struct ib_vendor_mad, data);
+               return IB_MGMT_VENDOR_HDR;
        else
-               return offsetof(struct ib_rmpp_mad, data);
+               return IB_MGMT_RMPP_HDR;
 }
 
 static void format_ack(struct ib_rmpp_mad *ack,
@@ -135,55 +135,52 @@ static void ack_recv(struct mad_rmpp_recv *rmpp_recv,
                     struct ib_mad_recv_wc *recv_wc)
 {
        struct ib_mad_send_buf *msg;
-       struct ib_send_wr *bad_send_wr;
-       int hdr_len, ret;
+       int ret;
 
-       hdr_len = sizeof(struct ib_mad_hdr) + sizeof(struct ib_rmpp_hdr);
        msg = ib_create_send_mad(&rmpp_recv->agent->agent, recv_wc->wc->src_qp,
-                                recv_wc->wc->pkey_index, rmpp_recv->ah, 1,
-                                hdr_len, sizeof(struct ib_rmpp_mad) - hdr_len,
-                                GFP_KERNEL);
+                                recv_wc->wc->pkey_index, 1, IB_MGMT_RMPP_HDR,
+                                IB_MGMT_RMPP_DATA, GFP_KERNEL);
        if (!msg)
                return;
 
-       format_ack((struct ib_rmpp_mad *) msg->mad,
-                  (struct ib_rmpp_mad *) recv_wc->recv_buf.mad, rmpp_recv);
-       ret = ib_post_send_mad(&rmpp_recv->agent->agent, &msg->send_wr,
-                              &bad_send_wr);
+       format_ack(msg->mad, (struct ib_rmpp_mad *) recv_wc->recv_buf.mad,
+                  rmpp_recv);
+       msg->ah = rmpp_recv->ah;
+       ret = ib_post_send_mad(msg, NULL);
        if (ret)
                ib_free_send_mad(msg);
 }
 
-static int alloc_response_msg(struct ib_mad_agent *agent,
-                             struct ib_mad_recv_wc *recv_wc,
-                             struct ib_mad_send_buf **msg)
+static struct ib_mad_send_buf *alloc_response_msg(struct ib_mad_agent *agent,
+                                                 struct ib_mad_recv_wc *recv_wc)
 {
-       struct ib_mad_send_buf *m;
+       struct ib_mad_send_buf *msg;
        struct ib_ah *ah;
-       int hdr_len;
 
        ah = ib_create_ah_from_wc(agent->qp->pd, recv_wc->wc,
                                  recv_wc->recv_buf.grh, agent->port_num);
        if (IS_ERR(ah))
-               return PTR_ERR(ah);
-
-       hdr_len = sizeof(struct ib_mad_hdr) + sizeof(struct ib_rmpp_hdr);
-       m = ib_create_send_mad(agent, recv_wc->wc->src_qp,
-                              recv_wc->wc->pkey_index, ah, 1, hdr_len,
-                              sizeof(struct ib_rmpp_mad) - hdr_len,
-                              GFP_KERNEL);
-       if (IS_ERR(m)) {
+               return (void *) ah;
+
+       msg = ib_create_send_mad(agent, recv_wc->wc->src_qp,
+                                recv_wc->wc->pkey_index, 1,
+                                IB_MGMT_RMPP_HDR, IB_MGMT_RMPP_DATA,
+                                GFP_KERNEL);
+       if (IS_ERR(msg))
                ib_destroy_ah(ah);
-               return PTR_ERR(m);
-       }
-       *msg = m;
-       return 0;
+       else
+               msg->ah = ah;
+
+       return msg;
 }
 
-static void free_msg(struct ib_mad_send_buf *msg)
+void ib_rmpp_send_handler(struct ib_mad_send_wc *mad_send_wc)
 {
-       ib_destroy_ah(msg->send_wr.wr.ud.ah);
-       ib_free_send_mad(msg);
+       struct ib_rmpp_mad *rmpp_mad = mad_send_wc->send_buf->mad;
+
+       if (rmpp_mad->rmpp_hdr.rmpp_type != IB_MGMT_RMPP_TYPE_ACK)
+               ib_destroy_ah(mad_send_wc->send_buf->ah);
+       ib_free_send_mad(mad_send_wc->send_buf);
 }
 
 static void nack_recv(struct ib_mad_agent_private *agent,
@@ -191,14 +188,13 @@ static void nack_recv(struct ib_mad_agent_private *agent,
 {
        struct ib_mad_send_buf *msg;
        struct ib_rmpp_mad *rmpp_mad;
-       struct ib_send_wr *bad_send_wr;
        int ret;
 
-       ret = alloc_response_msg(&agent->agent, recv_wc, &msg);
-       if (ret)
+       msg = alloc_response_msg(&agent->agent, recv_wc);
+       if (IS_ERR(msg))
                return;
 
-       rmpp_mad = (struct ib_rmpp_mad *) msg->mad;
+       rmpp_mad = msg->mad;
        memcpy(rmpp_mad, recv_wc->recv_buf.mad,
               data_offset(recv_wc->recv_buf.mad->mad_hdr.mgmt_class));
 
@@ -210,9 +206,11 @@ static void nack_recv(struct ib_mad_agent_private *agent,
        rmpp_mad->rmpp_hdr.seg_num = 0;
        rmpp_mad->rmpp_hdr.paylen_newwin = 0;
 
-       ret = ib_post_send_mad(&agent->agent, &msg->send_wr, &bad_send_wr);
-       if (ret)
-               free_msg(msg);
+       ret = ib_post_send_mad(msg, NULL);
+       if (ret) {
+               ib_destroy_ah(msg->ah);
+               ib_free_send_mad(msg);
+       }
 }
 
 static void recv_timeout_handler(void *data)
@@ -585,7 +583,7 @@ static int send_next_seg(struct ib_mad_send_wr_private *mad_send_wr)
        int timeout;
        u32 paylen;
 
-       rmpp_mad = (struct ib_rmpp_mad *)mad_send_wr->send_wr.wr.ud.mad_hdr;
+       rmpp_mad = mad_send_wr->send_buf.mad;
        ib_set_rmpp_flags(&rmpp_mad->rmpp_hdr, IB_MGMT_RMPP_FLAG_ACTIVE);
        rmpp_mad->rmpp_hdr.seg_num = cpu_to_be32(mad_send_wr->seg_num);
 
@@ -612,7 +610,7 @@ static int send_next_seg(struct ib_mad_send_wr_private *mad_send_wr)
        }
 
        /* 2 seconds for an ACK until we can find the packet lifetime */
-       timeout = mad_send_wr->send_wr.wr.ud.timeout_ms;
+       timeout = mad_send_wr->send_buf.timeout_ms;
        if (!timeout || timeout > 2000)
                mad_send_wr->timeout = msecs_to_jiffies(2000);
        mad_send_wr->seg_num++;
@@ -640,7 +638,7 @@ static void abort_send(struct ib_mad_agent_private *agent, __be64 tid,
 
        wc.status = IB_WC_REM_ABORT_ERR;
        wc.vendor_err = rmpp_status;
-       wc.wr_id = mad_send_wr->wr_id;
+       wc.send_buf = &mad_send_wr->send_buf;
        ib_mad_complete_send_wr(mad_send_wr, &wc);
        return;
 out:
@@ -694,12 +692,12 @@ static void process_rmpp_ack(struct ib_mad_agent_private *agent,
 
        if (seg_num > mad_send_wr->last_ack) {
                mad_send_wr->last_ack = seg_num;
-               mad_send_wr->retries = mad_send_wr->send_wr.wr.ud.retries;
+               mad_send_wr->retries = mad_send_wr->send_buf.retries;
        }
        mad_send_wr->newwin = newwin;
        if (mad_send_wr->last_ack == mad_send_wr->total_seg) {
                /* If no response is expected, the ACK completes the send */
-               if (!mad_send_wr->send_wr.wr.ud.timeout_ms) {
+               if (!mad_send_wr->send_buf.timeout_ms) {
                        struct ib_mad_send_wc wc;
 
                        ib_mark_mad_done(mad_send_wr);
@@ -707,13 +705,13 @@ static void process_rmpp_ack(struct ib_mad_agent_private *agent,
 
                        wc.status = IB_WC_SUCCESS;
                        wc.vendor_err = 0;
-                       wc.wr_id = mad_send_wr->wr_id;
+                       wc.send_buf = &mad_send_wr->send_buf;
                        ib_mad_complete_send_wr(mad_send_wr, &wc);
                        return;
                }
                if (mad_send_wr->refcount == 1)
-                       ib_reset_mad_timeout(mad_send_wr, mad_send_wr->
-                                            send_wr.wr.ud.timeout_ms);
+                       ib_reset_mad_timeout(mad_send_wr,
+                                            mad_send_wr->send_buf.timeout_ms);
        } else if (mad_send_wr->refcount == 1 &&
                   mad_send_wr->seg_num < mad_send_wr->newwin &&
                   mad_send_wr->seg_num <= mad_send_wr->total_seg) {
@@ -842,7 +840,7 @@ int ib_send_rmpp_mad(struct ib_mad_send_wr_private *mad_send_wr)
        struct ib_rmpp_mad *rmpp_mad;
        int i, total_len, ret;
 
-       rmpp_mad = (struct ib_rmpp_mad *)mad_send_wr->send_wr.wr.ud.mad_hdr;
+       rmpp_mad = mad_send_wr->send_buf.mad;
        if (!(ib_get_rmpp_flags(&rmpp_mad->rmpp_hdr) &
              IB_MGMT_RMPP_FLAG_ACTIVE))
                return IB_RMPP_RESULT_UNHANDLED;
@@ -863,7 +861,7 @@ int ib_send_rmpp_mad(struct ib_mad_send_wr_private *mad_send_wr)
 
         mad_send_wr->total_seg = (total_len - mad_send_wr->data_offset) /
                        (sizeof(struct ib_rmpp_mad) - mad_send_wr->data_offset);
-       mad_send_wr->pad = total_len - offsetof(struct ib_rmpp_mad, data) -
+       mad_send_wr->pad = total_len - IB_MGMT_RMPP_HDR -
                           be32_to_cpu(rmpp_mad->rmpp_hdr.paylen_newwin);
 
        /* We need to wait for the final ACK even if there isn't a response */
@@ -878,23 +876,15 @@ int ib_process_rmpp_send_wc(struct ib_mad_send_wr_private *mad_send_wr,
                            struct ib_mad_send_wc *mad_send_wc)
 {
        struct ib_rmpp_mad *rmpp_mad;
-       struct ib_mad_send_buf *msg;
        int ret;
 
-       rmpp_mad = (struct ib_rmpp_mad *)mad_send_wr->send_wr.wr.ud.mad_hdr;
+       rmpp_mad = mad_send_wr->send_buf.mad;
        if (!(ib_get_rmpp_flags(&rmpp_mad->rmpp_hdr) &
              IB_MGMT_RMPP_FLAG_ACTIVE))
                return IB_RMPP_RESULT_UNHANDLED; /* RMPP not active */
 
-       if (rmpp_mad->rmpp_hdr.rmpp_type != IB_MGMT_RMPP_TYPE_DATA) {
-               msg = (struct ib_mad_send_buf *) (unsigned long)
-                     mad_send_wc->wr_id;
-               if (rmpp_mad->rmpp_hdr.rmpp_type == IB_MGMT_RMPP_TYPE_ACK)
-                       ib_free_send_mad(msg);
-               else
-                       free_msg(msg);
+       if (rmpp_mad->rmpp_hdr.rmpp_type != IB_MGMT_RMPP_TYPE_DATA)
                return IB_RMPP_RESULT_INTERNAL;  /* ACK, STOP, or ABORT */
-       }
 
        if (mad_send_wc->status != IB_WC_SUCCESS ||
            mad_send_wr->status != IB_WC_SUCCESS)
@@ -905,7 +895,7 @@ int ib_process_rmpp_send_wc(struct ib_mad_send_wr_private *mad_send_wr,
 
        if (mad_send_wr->last_ack == mad_send_wr->total_seg) {
                mad_send_wr->timeout =
-                       msecs_to_jiffies(mad_send_wr->send_wr.wr.ud.timeout_ms);
+                       msecs_to_jiffies(mad_send_wr->send_buf.timeout_ms);
                return IB_RMPP_RESULT_PROCESSED; /* Send done */
        }
 
@@ -926,7 +916,7 @@ int ib_retry_rmpp(struct ib_mad_send_wr_private *mad_send_wr)
        struct ib_rmpp_mad *rmpp_mad;
        int ret;
 
-       rmpp_mad = (struct ib_rmpp_mad *)mad_send_wr->send_wr.wr.ud.mad_hdr;
+       rmpp_mad = mad_send_wr->send_buf.mad;
        if (!(ib_get_rmpp_flags(&rmpp_mad->rmpp_hdr) &
              IB_MGMT_RMPP_FLAG_ACTIVE))
                return IB_RMPP_RESULT_UNHANDLED; /* RMPP not active */
index c4924df..f0616fd 100644 (file)
@@ -51,6 +51,8 @@ ib_process_rmpp_recv_wc(struct ib_mad_agent_private *agent,
 int ib_process_rmpp_send_wc(struct ib_mad_send_wr_private *mad_send_wr,
                            struct ib_mad_send_wc *mad_send_wc);
 
+void ib_rmpp_send_handler(struct ib_mad_send_wc *mad_send_wc);
+
 void ib_cancel_rmpp_recvs(struct ib_mad_agent_private *agent);
 
 int ib_retry_rmpp(struct ib_mad_send_wr_private *mad_send_wr);
index 2626182..89ce9dc 100644 (file)
@@ -73,11 +73,10 @@ struct ib_sa_device {
 struct ib_sa_query {
        void (*callback)(struct ib_sa_query *, int, struct ib_sa_mad *);
        void (*release)(struct ib_sa_query *);
-       struct ib_sa_port  *port;
-       struct ib_sa_mad   *mad;
-       struct ib_sa_sm_ah *sm_ah;
-       DECLARE_PCI_UNMAP_ADDR(mapping)
-       int                 id;
+       struct ib_sa_port      *port;
+       struct ib_mad_send_buf *mad_buf;
+       struct ib_sa_sm_ah     *sm_ah;
+       int                     id;
 };
 
 struct ib_sa_service_query {
@@ -426,6 +425,7 @@ void ib_sa_cancel_query(int id, struct ib_sa_query *query)
 {
        unsigned long flags;
        struct ib_mad_agent *agent;
+       struct ib_mad_send_buf *mad_buf;
 
        spin_lock_irqsave(&idr_lock, flags);
        if (idr_find(&query_idr, id) != query) {
@@ -433,9 +433,10 @@ void ib_sa_cancel_query(int id, struct ib_sa_query *query)
                return;
        }
        agent = query->port->agent;
+       mad_buf = query->mad_buf;
        spin_unlock_irqrestore(&idr_lock, flags);
 
-       ib_cancel_mad(agent, id);
+       ib_cancel_mad(agent, mad_buf);
 }
 EXPORT_SYMBOL(ib_sa_cancel_query);
 
@@ -457,71 +458,46 @@ static void init_mad(struct ib_sa_mad *mad, struct ib_mad_agent *agent)
 
 static int send_mad(struct ib_sa_query *query, int timeout_ms)
 {
-       struct ib_sa_port *port = query->port;
        unsigned long flags;
-       int ret;
-       struct ib_sge      gather_list;
-       struct ib_send_wr *bad_wr, wr = {
-               .opcode      = IB_WR_SEND,
-               .sg_list     = &gather_list,
-               .num_sge     = 1,
-               .send_flags  = IB_SEND_SIGNALED,
-               .wr          = {
-                        .ud = {
-                                .mad_hdr     = &query->mad->mad_hdr,
-                                .remote_qpn  = 1,
-                                .remote_qkey = IB_QP1_QKEY,
-                                .timeout_ms  = timeout_ms,
-                        }
-                }
-       };
+       int ret, id;
 
 retry:
        if (!idr_pre_get(&query_idr, GFP_ATOMIC))
                return -ENOMEM;
        spin_lock_irqsave(&idr_lock, flags);
-       ret = idr_get_new(&query_idr, query, &query->id);
+       ret = idr_get_new(&query_idr, query, &id);
        spin_unlock_irqrestore(&idr_lock, flags);
        if (ret == -EAGAIN)
                goto retry;
        if (ret)
                return ret;
 
-       wr.wr_id = query->id;
+       query->mad_buf->timeout_ms  = timeout_ms;
+       query->mad_buf->context[0] = query;
+       query->id = id;
 
-       spin_lock_irqsave(&port->ah_lock, flags);
-       kref_get(&port->sm_ah->ref);
-       query->sm_ah = port->sm_ah;
-       wr.wr.ud.ah  = port->sm_ah->ah;
-       spin_unlock_irqrestore(&port->ah_lock, flags);
+       spin_lock_irqsave(&query->port->ah_lock, flags);
+       kref_get(&query->port->sm_ah->ref);
+       query->sm_ah = query->port->sm_ah;
+       spin_unlock_irqrestore(&query->port->ah_lock, flags);
 
-       gather_list.addr   = dma_map_single(port->agent->device->dma_device,
-                                           query->mad,
-                                           sizeof (struct ib_sa_mad),
-                                           DMA_TO_DEVICE);
-       gather_list.length = sizeof (struct ib_sa_mad);
-       gather_list.lkey   = port->agent->mr->lkey;
-       pci_unmap_addr_set(query, mapping, gather_list.addr);
+       query->mad_buf->ah = query->sm_ah->ah;
 
-       ret = ib_post_send_mad(port->agent, &wr, &bad_wr);
+       ret = ib_post_send_mad(query->mad_buf, NULL);
        if (ret) {
-               dma_unmap_single(port->agent->device->dma_device,
-                                pci_unmap_addr(query, mapping),
-                                sizeof (struct ib_sa_mad),
-                                DMA_TO_DEVICE);
-               kref_put(&query->sm_ah->ref, free_sm_ah);
                spin_lock_irqsave(&idr_lock, flags);
-               idr_remove(&query_idr, query->id);
+               idr_remove(&query_idr, id);
                spin_unlock_irqrestore(&idr_lock, flags);
+
+               kref_put(&query->sm_ah->ref, free_sm_ah);
        }
 
        /*
         * It's not safe to dereference query any more, because the
         * send may already have completed and freed the query in
-        * another context.  So use wr.wr_id, which has a copy of the
-        * query's id.
+        * another context.
         */
-       return ret ? ret : wr.wr_id;
+       return ret ? ret : id;
 }
 
 static void ib_sa_path_rec_callback(struct ib_sa_query *sa_query,
@@ -543,7 +519,6 @@ static void ib_sa_path_rec_callback(struct ib_sa_query *sa_query,
 
 static void ib_sa_path_rec_release(struct ib_sa_query *sa_query)
 {
-       kfree(sa_query->mad);
        kfree(container_of(sa_query, struct ib_sa_path_query, sa_query));
 }
 
@@ -583,43 +558,58 @@ int ib_sa_path_rec_get(struct ib_device *device, u8 port_num,
 {
        struct ib_sa_path_query *query;
        struct ib_sa_device *sa_dev = ib_get_client_data(device, &sa_client);
-       struct ib_sa_port   *port   = &sa_dev->port[port_num - sa_dev->start_port];
-       struct ib_mad_agent *agent  = port->agent;
+       struct ib_sa_port   *port;
+       struct ib_mad_agent *agent;
+       struct ib_sa_mad *mad;
        int ret;
 
+       if (!sa_dev)
+               return -ENODEV;
+
+       port  = &sa_dev->port[port_num - sa_dev->start_port];
+       agent = port->agent;
+
        query = kmalloc(sizeof *query, gfp_mask);
        if (!query)
                return -ENOMEM;
-       query->sa_query.mad = kmalloc(sizeof *query->sa_query.mad, gfp_mask);
-       if (!query->sa_query.mad) {
-               kfree(query);
-               return -ENOMEM;
+
+       query->sa_query.mad_buf = ib_create_send_mad(agent, 1, 0,
+                                                    0, IB_MGMT_SA_HDR,
+                                                    IB_MGMT_SA_DATA, gfp_mask);
+       if (!query->sa_query.mad_buf) {
+               ret = -ENOMEM;
+               goto err1;
        }
 
        query->callback = callback;
        query->context  = context;
 
-       init_mad(query->sa_query.mad, agent);
+       mad = query->sa_query.mad_buf->mad;
+       init_mad(mad, agent);
 
-       query->sa_query.callback              = callback ? ib_sa_path_rec_callback : NULL;
-       query->sa_query.release               = ib_sa_path_rec_release;
-       query->sa_query.port                  = port;
-       query->sa_query.mad->mad_hdr.method   = IB_MGMT_METHOD_GET;
-       query->sa_query.mad->mad_hdr.attr_id  = cpu_to_be16(IB_SA_ATTR_PATH_REC);
-       query->sa_query.mad->sa_hdr.comp_mask = comp_mask;
+       query->sa_query.callback = callback ? ib_sa_path_rec_callback : NULL;
+       query->sa_query.release  = ib_sa_path_rec_release;
+       query->sa_query.port     = port;
+       mad->mad_hdr.method      = IB_MGMT_METHOD_GET;
+       mad->mad_hdr.attr_id     = cpu_to_be16(IB_SA_ATTR_PATH_REC);
+       mad->sa_hdr.comp_mask    = comp_mask;
 
-       ib_pack(path_rec_table, ARRAY_SIZE(path_rec_table),
-               rec, query->sa_query.mad->data);
+       ib_pack(path_rec_table, ARRAY_SIZE(path_rec_table), rec, mad->data);
 
        *sa_query = &query->sa_query;
 
        ret = send_mad(&query->sa_query, timeout_ms);
-       if (ret < 0) {
-               *sa_query = NULL;
-               kfree(query->sa_query.mad);
-               kfree(query);
-       }
+       if (ret < 0)
+               goto err2;
+
+       return ret;
 
+err2:
+       *sa_query = NULL;
+       ib_free_send_mad(query->sa_query.mad_buf);
+
+err1:
+       kfree(query);
        return ret;
 }
 EXPORT_SYMBOL(ib_sa_path_rec_get);
@@ -643,7 +633,6 @@ static void ib_sa_service_rec_callback(struct ib_sa_query *sa_query,
 
 static void ib_sa_service_rec_release(struct ib_sa_query *sa_query)
 {
-       kfree(sa_query->mad);
        kfree(container_of(sa_query, struct ib_sa_service_query, sa_query));
 }
 
@@ -685,10 +674,17 @@ int ib_sa_service_rec_query(struct ib_device *device, u8 port_num, u8 method,
 {
        struct ib_sa_service_query *query;
        struct ib_sa_device *sa_dev = ib_get_client_data(device, &sa_client);
-       struct ib_sa_port   *port   = &sa_dev->port[port_num - sa_dev->start_port];
-       struct ib_mad_agent *agent  = port->agent;
+       struct ib_sa_port   *port;
+       struct ib_mad_agent *agent;
+       struct ib_sa_mad *mad;
        int ret;
 
+       if (!sa_dev)
+               return -ENODEV;
+
+       port  = &sa_dev->port[port_num - sa_dev->start_port];
+       agent = port->agent;
+
        if (method != IB_MGMT_METHOD_GET &&
            method != IB_MGMT_METHOD_SET &&
            method != IB_SA_METHOD_DELETE)
@@ -697,37 +693,45 @@ int ib_sa_service_rec_query(struct ib_device *device, u8 port_num, u8 method,
        query = kmalloc(sizeof *query, gfp_mask);
        if (!query)
                return -ENOMEM;
-       query->sa_query.mad = kmalloc(sizeof *query->sa_query.mad, gfp_mask);
-       if (!query->sa_query.mad) {
-               kfree(query);
-               return -ENOMEM;
+
+       query->sa_query.mad_buf = ib_create_send_mad(agent, 1, 0,
+                                                    0, IB_MGMT_SA_HDR,
+                                                    IB_MGMT_SA_DATA, gfp_mask);
+       if (!query->sa_query.mad_buf) {
+               ret = -ENOMEM;
+               goto err1;
        }
 
        query->callback = callback;
        query->context  = context;
 
-       init_mad(query->sa_query.mad, agent);
+       mad = query->sa_query.mad_buf->mad;
+       init_mad(mad, agent);
 
-       query->sa_query.callback              = callback ? ib_sa_service_rec_callback : NULL;
-       query->sa_query.release               = ib_sa_service_rec_release;
-       query->sa_query.port                  = port;
-       query->sa_query.mad->mad_hdr.method   = method;
-       query->sa_query.mad->mad_hdr.attr_id  =
-                               cpu_to_be16(IB_SA_ATTR_SERVICE_REC);
-       query->sa_query.mad->sa_hdr.comp_mask = comp_mask;
+       query->sa_query.callback = callback ? ib_sa_service_rec_callback : NULL;
+       query->sa_query.release  = ib_sa_service_rec_release;
+       query->sa_query.port     = port;
+       mad->mad_hdr.method      = method;
+       mad->mad_hdr.attr_id     = cpu_to_be16(IB_SA_ATTR_SERVICE_REC);
+       mad->sa_hdr.comp_mask    = comp_mask;
 
        ib_pack(service_rec_table, ARRAY_SIZE(service_rec_table),
-               rec, query->sa_query.mad->data);
+               rec, mad->data);
 
        *sa_query = &query->sa_query;
 
        ret = send_mad(&query->sa_query, timeout_ms);
-       if (ret < 0) {
-               *sa_query = NULL;
-               kfree(query->sa_query.mad);
-               kfree(query);
-       }
+       if (ret < 0)
+               goto err2;
+
+       return ret;
 
+err2:
+       *sa_query = NULL;
+       ib_free_send_mad(query->sa_query.mad_buf);
+
+err1:
+       kfree(query);
        return ret;
 }
 EXPORT_SYMBOL(ib_sa_service_rec_query);
@@ -751,7 +755,6 @@ static void ib_sa_mcmember_rec_callback(struct ib_sa_query *sa_query,
 
 static void ib_sa_mcmember_rec_release(struct ib_sa_query *sa_query)
 {
-       kfree(sa_query->mad);
        kfree(container_of(sa_query, struct ib_sa_mcmember_query, sa_query));
 }
 
@@ -768,60 +771,69 @@ int ib_sa_mcmember_rec_query(struct ib_device *device, u8 port_num,
 {
        struct ib_sa_mcmember_query *query;
        struct ib_sa_device *sa_dev = ib_get_client_data(device, &sa_client);
-       struct ib_sa_port   *port   = &sa_dev->port[port_num - sa_dev->start_port];
-       struct ib_mad_agent *agent  = port->agent;
+       struct ib_sa_port   *port;
+       struct ib_mad_agent *agent;
+       struct ib_sa_mad *mad;
        int ret;
 
+       if (!sa_dev)
+               return -ENODEV;
+
+       port  = &sa_dev->port[port_num - sa_dev->start_port];
+       agent = port->agent;
+
        query = kmalloc(sizeof *query, gfp_mask);
        if (!query)
                return -ENOMEM;
-       query->sa_query.mad = kmalloc(sizeof *query->sa_query.mad, gfp_mask);
-       if (!query->sa_query.mad) {
-               kfree(query);
-               return -ENOMEM;
+
+       query->sa_query.mad_buf = ib_create_send_mad(agent, 1, 0,
+                                                    0, IB_MGMT_SA_HDR,
+                                                    IB_MGMT_SA_DATA, gfp_mask);
+       if (!query->sa_query.mad_buf) {
+               ret = -ENOMEM;
+               goto err1;
        }
 
        query->callback = callback;
        query->context  = context;
 
-       init_mad(query->sa_query.mad, agent);
+       mad = query->sa_query.mad_buf->mad;
+       init_mad(mad, agent);
 
-       query->sa_query.callback              = callback ? ib_sa_mcmember_rec_callback : NULL;
-       query->sa_query.release               = ib_sa_mcmember_rec_release;
-       query->sa_query.port                  = port;
-       query->sa_query.mad->mad_hdr.method   = method;
-       query->sa_query.mad->mad_hdr.attr_id  = cpu_to_be16(IB_SA_ATTR_MC_MEMBER_REC);
-       query->sa_query.mad->sa_hdr.comp_mask = comp_mask;
+       query->sa_query.callback = callback ? ib_sa_mcmember_rec_callback : NULL;
+       query->sa_query.release  = ib_sa_mcmember_rec_release;
+       query->sa_query.port     = port;
+       mad->mad_hdr.method      = method;
+       mad->mad_hdr.attr_id     = cpu_to_be16(IB_SA_ATTR_MC_MEMBER_REC);
+       mad->sa_hdr.comp_mask    = comp_mask;
 
        ib_pack(mcmember_rec_table, ARRAY_SIZE(mcmember_rec_table),
-               rec, query->sa_query.mad->data);
+               rec, mad->data);
 
        *sa_query = &query->sa_query;
 
        ret = send_mad(&query->sa_query, timeout_ms);
-       if (ret < 0) {
-               *sa_query = NULL;
-               kfree(query->sa_query.mad);
-               kfree(query);
-       }
+       if (ret < 0)
+               goto err2;
 
        return ret;
+
+err2:
+       *sa_query = NULL;
+       ib_free_send_mad(query->sa_query.mad_buf);
+
+err1:
+       kfree(query);
+       return ret;
 }
 EXPORT_SYMBOL(ib_sa_mcmember_rec_query);
 
 static void send_handler(struct ib_mad_agent *agent,
                         struct ib_mad_send_wc *mad_send_wc)
 {
-       struct ib_sa_query *query;
+       struct ib_sa_query *query = mad_send_wc->send_buf->context[0];
        unsigned long flags;
 
-       spin_lock_irqsave(&idr_lock, flags);
-       query = idr_find(&query_idr, mad_send_wc->wr_id);
-       spin_unlock_irqrestore(&idr_lock, flags);
-
-       if (!query)
-               return;
-
        if (query->callback)
                switch (mad_send_wc->status) {
                case IB_WC_SUCCESS:
@@ -838,30 +850,25 @@ static void send_handler(struct ib_mad_agent *agent,
                        break;
                }
 
-       dma_unmap_single(agent->device->dma_device,
-                        pci_unmap_addr(query, mapping),
-                        sizeof (struct ib_sa_mad),
-                        DMA_TO_DEVICE);
-       kref_put(&query->sm_ah->ref, free_sm_ah);
-
-       query->release(query);
-
        spin_lock_irqsave(&idr_lock, flags);
-       idr_remove(&query_idr, mad_send_wc->wr_id);
+       idr_remove(&query_idr, query->id);
        spin_unlock_irqrestore(&idr_lock, flags);
+
+        ib_free_send_mad(mad_send_wc->send_buf);
+       kref_put(&query->sm_ah->ref, free_sm_ah);
+       query->release(query);
 }
 
 static void recv_handler(struct ib_mad_agent *mad_agent,
                         struct ib_mad_recv_wc *mad_recv_wc)
 {
        struct ib_sa_query *query;
-       unsigned long flags;
+       struct ib_mad_send_buf *mad_buf;
 
-       spin_lock_irqsave(&idr_lock, flags);
-       query = idr_find(&query_idr, mad_recv_wc->wc->wr_id);
-       spin_unlock_irqrestore(&idr_lock, flags);
+       mad_buf = (void *) (unsigned long) mad_recv_wc->wc->wr_id;
+       query = mad_buf->context[0];
 
-       if (query && query->callback) {
+       if (query->callback) {
                if (mad_recv_wc->wc->status == IB_WC_SUCCESS)
                        query->callback(query,
                                        mad_recv_wc->recv_buf.mad->mad_hdr.status ?
@@ -975,6 +982,7 @@ static int __init ib_sa_init(void)
 static void __exit ib_sa_cleanup(void)
 {
        ib_unregister_client(&sa_client);
+       idr_destroy(&query_idr);
 }
 
 module_init(ib_sa_init);
index db25503..2b3c401 100644 (file)
@@ -39,6 +39,8 @@
 #ifndef __SMI_H_
 #define __SMI_H_
 
+#include <rdma/ib_smi.h>
+
 int smi_handle_dr_smp_recv(struct ib_smp *smp,
                           u8 node_type,
                           int port_num,
index 211ba32..7ce7a6c 100644 (file)
@@ -65,6 +65,11 @@ struct port_table_attribute {
        int                     index;
 };
 
+static inline int ibdev_is_alive(const struct ib_device *dev) 
+{
+       return dev->reg_state == IB_DEV_REGISTERED;
+}
+
 static ssize_t port_attr_show(struct kobject *kobj,
                              struct attribute *attr, char *buf)
 {
@@ -74,6 +79,8 @@ static ssize_t port_attr_show(struct kobject *kobj,
 
        if (!port_attr->show)
                return -EIO;
+       if (!ibdev_is_alive(p->ibdev))
+               return -ENODEV;
 
        return port_attr->show(p, port_attr, buf);
 }
@@ -581,6 +588,9 @@ static ssize_t show_node_type(struct class_device *cdev, char *buf)
 {
        struct ib_device *dev = container_of(cdev, struct ib_device, class_dev);
 
+       if (!ibdev_is_alive(dev))
+               return -ENODEV;
+
        switch (dev->node_type) {
        case IB_NODE_CA:     return sprintf(buf, "%d: CA\n", dev->node_type);
        case IB_NODE_SWITCH: return sprintf(buf, "%d: switch\n", dev->node_type);
@@ -595,6 +605,9 @@ static ssize_t show_sys_image_guid(struct class_device *cdev, char *buf)
        struct ib_device_attr attr;
        ssize_t ret;
 
+       if (!ibdev_is_alive(dev))
+               return -ENODEV;
+
        ret = ib_query_device(dev, &attr);
        if (ret)
                return ret;
@@ -612,6 +625,9 @@ static ssize_t show_node_guid(struct class_device *cdev, char *buf)
        struct ib_device_attr attr;
        ssize_t ret;
 
+       if (!ibdev_is_alive(dev))
+               return -ENODEV;
+
        ret = ib_query_device(dev, &attr);
        if (ret)
                return ret;
index 021b8f1..2847756 100644 (file)
 #include <linux/file.h>
 #include <linux/mount.h>
 #include <linux/cdev.h>
+#include <linux/idr.h>
 
 #include <asm/uaccess.h>
 
-#include "ucm.h"
+#include <rdma/ib_cm.h>
+#include <rdma/ib_user_cm.h>
 
 MODULE_AUTHOR("Libor Michalek");
 MODULE_DESCRIPTION("InfiniBand userspace Connection Manager access");
 MODULE_LICENSE("Dual BSD/GPL");
 
-static int ucm_debug_level;
+struct ib_ucm_device {
+       int                     devnum;
+       struct cdev             dev;
+       struct class_device     class_dev;
+       struct ib_device        *ib_dev;
+};
+
+struct ib_ucm_file {
+       struct semaphore mutex;
+       struct file *filp;
+       struct ib_ucm_device *device;
+
+       struct list_head  ctxs;
+       struct list_head  events;
+       wait_queue_head_t poll_wait;
+};
+
+struct ib_ucm_context {
+       int                 id;
+       wait_queue_head_t   wait;
+       atomic_t            ref;
+       int                 events_reported;
+
+       struct ib_ucm_file *file;
+       struct ib_cm_id    *cm_id;
+       __u64              uid;
+
+       struct list_head    events;    /* list of pending events. */
+       struct list_head    file_list; /* member in file ctx list */
+};
+
+struct ib_ucm_event {
+       struct ib_ucm_context *ctx;
+       struct list_head file_list; /* member in file event list */
+       struct list_head ctx_list;  /* member in ctx event list */
 
-module_param_named(debug_level, ucm_debug_level, int, 0644);
-MODULE_PARM_DESC(debug_level, "Enable debug tracing if > 0");
+       struct ib_cm_id *cm_id;
+       struct ib_ucm_event_resp resp;
+       void *data;
+       void *info;
+       int data_len;
+       int info_len;
+};
 
 enum {
        IB_UCM_MAJOR = 231,
-       IB_UCM_MINOR = 255
+       IB_UCM_BASE_MINOR = 224,
+       IB_UCM_MAX_DEVICES = 32
 };
 
-#define IB_UCM_DEV MKDEV(IB_UCM_MAJOR, IB_UCM_MINOR)
+#define IB_UCM_BASE_DEV MKDEV(IB_UCM_MAJOR, IB_UCM_BASE_MINOR)
 
-#define PFX "UCM: "
+static void ib_ucm_add_one(struct ib_device *device);
+static void ib_ucm_remove_one(struct ib_device *device);
 
-#define ucm_dbg(format, arg...)                        \
-       do {                                    \
-               if (ucm_debug_level > 0)        \
-                       printk(KERN_DEBUG PFX format, ## arg); \
-       } while (0)
+static struct ib_client ucm_client = {
+       .name   = "ucm",
+       .add    = ib_ucm_add_one,
+       .remove = ib_ucm_remove_one
+};
 
-static struct semaphore ctx_id_mutex;
-static struct idr       ctx_id_table;
+static DECLARE_MUTEX(ctx_id_mutex);
+static DEFINE_IDR(ctx_id_table);
+static DECLARE_BITMAP(dev_map, IB_UCM_MAX_DEVICES);
 
 static struct ib_ucm_context *ib_ucm_ctx_get(struct ib_ucm_file *file, int id)
 {
@@ -152,17 +196,13 @@ static struct ib_ucm_context *ib_ucm_ctx_alloc(struct ib_ucm_file *file)
                goto error;
 
        list_add_tail(&ctx->file_list, &file->ctxs);
-       ucm_dbg("Allocated CM ID <%d>\n", ctx->id);
        return ctx;
 
 error:
        kfree(ctx);
        return NULL;
 }
-/*
- * Event portion of the API, handle CM events
- * and allow event polling.
- */
+
 static void ib_ucm_event_path_get(struct ib_ucm_path_rec *upath,
                                  struct ib_sa_path_rec  *kpath)
 {
@@ -209,6 +249,7 @@ static void ib_ucm_event_req_get(struct ib_ucm_req_event_resp *ureq,
        ureq->retry_count                = kreq->retry_count;
        ureq->rnr_retry_count            = kreq->rnr_retry_count;
        ureq->srq                        = kreq->srq;
+       ureq->port                       = kreq->port;
 
        ib_ucm_event_path_get(&ureq->primary_path, kreq->primary_path);
        ib_ucm_event_path_get(&ureq->alternate_path, kreq->alternate_path);
@@ -295,6 +336,8 @@ static int ib_ucm_event_process(struct ib_cm_event *evt,
        case IB_CM_SIDR_REQ_RECEIVED:
                uvt->resp.u.sidr_req_resp.pkey = 
                                        evt->param.sidr_req_rcvd.pkey;
+               uvt->resp.u.sidr_req_resp.port = 
+                                       evt->param.sidr_req_rcvd.port;
                uvt->data_len = IB_CM_SIDR_REQ_PRIVATE_DATA_SIZE;
                break;
        case IB_CM_SIDR_REP_RECEIVED:
@@ -387,9 +430,7 @@ static ssize_t ib_ucm_event(struct ib_ucm_file *file,
 
        if (copy_from_user(&cmd, inbuf, sizeof(cmd)))
                return -EFAULT;
-       /*
-        * wait
-        */
+
        down(&file->mutex);
        while (list_empty(&file->events)) {
 
@@ -471,7 +512,6 @@ done:
        return result;
 }
 
-
 static ssize_t ib_ucm_create_id(struct ib_ucm_file *file,
                                const char __user *inbuf,
                                int in_len, int out_len)
@@ -494,29 +534,27 @@ static ssize_t ib_ucm_create_id(struct ib_ucm_file *file,
                return -ENOMEM;
 
        ctx->uid = cmd.uid;
-       ctx->cm_id = ib_create_cm_id(ib_ucm_event_handler, ctx);
+       ctx->cm_id = ib_create_cm_id(file->device->ib_dev,
+                                    ib_ucm_event_handler, ctx);
        if (IS_ERR(ctx->cm_id)) {
                result = PTR_ERR(ctx->cm_id);
-               goto err;
+               goto err1;
        }
 
        resp.id = ctx->id;
        if (copy_to_user((void __user *)(unsigned long)cmd.response,
                         &resp, sizeof(resp))) {
                result = -EFAULT;
-               goto err;
+               goto err2;
        }
-
        return 0;
 
-err:
+err2:
+       ib_destroy_cm_id(ctx->cm_id);
+err1:
        down(&ctx_id_mutex);
        idr_remove(&ctx_id_table, ctx->id);
        up(&ctx_id_mutex);
-
-       if (!IS_ERR(ctx->cm_id))
-               ib_destroy_cm_id(ctx->cm_id);
-
        kfree(ctx);
        return result;
 }
@@ -1184,9 +1222,6 @@ static ssize_t ib_ucm_write(struct file *filp, const char __user *buf,
        if (copy_from_user(&hdr, buf, sizeof(hdr)))
                return -EFAULT;
 
-       ucm_dbg("Write. cmd <%d> in <%d> out <%d> len <%Zu>\n",
-               hdr.cmd, hdr.in, hdr.out, len);
-
        if (hdr.cmd < 0 || hdr.cmd >= ARRAY_SIZE(ucm_cmd_table))
                return -EINVAL;
 
@@ -1231,8 +1266,7 @@ static int ib_ucm_open(struct inode *inode, struct file *filp)
 
        filp->private_data = file;
        file->filp = filp;
-
-       ucm_dbg("Created struct\n");
+       file->device = container_of(inode->i_cdev, struct ib_ucm_device, dev);
 
        return 0;
 }
@@ -1263,7 +1297,17 @@ static int ib_ucm_close(struct inode *inode, struct file *filp)
        return 0;
 }
 
-static struct file_operations ib_ucm_fops = {
+static void ib_ucm_release_class_dev(struct class_device *class_dev)
+{
+       struct ib_ucm_device *dev;
+
+       dev = container_of(class_dev, struct ib_ucm_device, class_dev);
+       cdev_del(&dev->dev);
+       clear_bit(dev->devnum, dev_map);
+       kfree(dev);
+}
+
+static struct file_operations ucm_fops = {
        .owner   = THIS_MODULE,
        .open    = ib_ucm_open,
        .release = ib_ucm_close,
@@ -1271,55 +1315,142 @@ static struct file_operations ib_ucm_fops = {
        .poll    = ib_ucm_poll,
 };
 
+static struct class ucm_class = {
+       .name    = "infiniband_cm",
+       .release = ib_ucm_release_class_dev
+};
 
-static struct class *ib_ucm_class;
-static struct cdev       ib_ucm_cdev;
+static ssize_t show_dev(struct class_device *class_dev, char *buf)
+{
+       struct ib_ucm_device *dev;
+       
+       dev = container_of(class_dev, struct ib_ucm_device, class_dev);
+       return print_dev_t(buf, dev->dev.dev);
+}
+static CLASS_DEVICE_ATTR(dev, S_IRUGO, show_dev, NULL);
 
-static int __init ib_ucm_init(void)
+static ssize_t show_ibdev(struct class_device *class_dev, char *buf)
 {
-       int result;
+       struct ib_ucm_device *dev;
+       
+       dev = container_of(class_dev, struct ib_ucm_device, class_dev);
+       return sprintf(buf, "%s\n", dev->ib_dev->name);
+}
+static CLASS_DEVICE_ATTR(ibdev, S_IRUGO, show_ibdev, NULL);
 
-       result = register_chrdev_region(IB_UCM_DEV, 1, "infiniband_cm");
-       if (result) {
-               ucm_dbg("Error <%d> registering dev\n", result);
-               goto err_chr;
-       }
+static void ib_ucm_add_one(struct ib_device *device)
+{
+       struct ib_ucm_device *ucm_dev;
+
+       if (!device->alloc_ucontext)
+               return;
+
+       ucm_dev = kmalloc(sizeof *ucm_dev, GFP_KERNEL);
+       if (!ucm_dev)
+               return;
 
-       cdev_init(&ib_ucm_cdev, &ib_ucm_fops);
+       memset(ucm_dev, 0, sizeof *ucm_dev);
+       ucm_dev->ib_dev = device;
+
+       ucm_dev->devnum = find_first_zero_bit(dev_map, IB_UCM_MAX_DEVICES);
+       if (ucm_dev->devnum >= IB_UCM_MAX_DEVICES)
+               goto err;
+
+       set_bit(ucm_dev->devnum, dev_map);
+
+       cdev_init(&ucm_dev->dev, &ucm_fops);
+       ucm_dev->dev.owner = THIS_MODULE;
+       kobject_set_name(&ucm_dev->dev.kobj, "ucm%d", ucm_dev->devnum);
+       if (cdev_add(&ucm_dev->dev, IB_UCM_BASE_DEV + ucm_dev->devnum, 1))
+               goto err;
 
-       result = cdev_add(&ib_ucm_cdev, IB_UCM_DEV, 1);
-       if (result) {
-               ucm_dbg("Error <%d> adding cdev\n", result);
+       ucm_dev->class_dev.class = &ucm_class;
+       ucm_dev->class_dev.dev = device->dma_device;
+       snprintf(ucm_dev->class_dev.class_id, BUS_ID_SIZE, "ucm%d",
+                ucm_dev->devnum);
+       if (class_device_register(&ucm_dev->class_dev))
                goto err_cdev;
-       }
 
-       ib_ucm_class = class_create(THIS_MODULE, "infiniband_cm");
-       if (IS_ERR(ib_ucm_class)) {
-               result = PTR_ERR(ib_ucm_class);
-               ucm_dbg("Error <%d> creating class\n", result);
+       if (class_device_create_file(&ucm_dev->class_dev,
+                                    &class_device_attr_dev))
+               goto err_class;
+       if (class_device_create_file(&ucm_dev->class_dev,
+                                    &class_device_attr_ibdev))
                goto err_class;
+
+       ib_set_client_data(device, &ucm_client, ucm_dev);
+       return;
+
+err_class:
+       class_device_unregister(&ucm_dev->class_dev);
+err_cdev:
+       cdev_del(&ucm_dev->dev);
+       clear_bit(ucm_dev->devnum, dev_map);
+err:
+       kfree(ucm_dev);
+       return;
+}
+
+static void ib_ucm_remove_one(struct ib_device *device)
+{
+       struct ib_ucm_device *ucm_dev = ib_get_client_data(device, &ucm_client);
+
+       if (!ucm_dev)
+               return;
+
+       class_device_unregister(&ucm_dev->class_dev);
+}
+
+static ssize_t show_abi_version(struct class *class, char *buf)
+{
+       return sprintf(buf, "%d\n", IB_USER_CM_ABI_VERSION);
+}
+static CLASS_ATTR(abi_version, S_IRUGO, show_abi_version, NULL);
+
+static int __init ib_ucm_init(void)
+{
+       int ret;
+
+       ret = register_chrdev_region(IB_UCM_BASE_DEV, IB_UCM_MAX_DEVICES,
+                                    "infiniband_cm");
+       if (ret) {
+               printk(KERN_ERR "ucm: couldn't register device number\n");
+               goto err;
        }
 
-       class_device_create(ib_ucm_class, NULL, IB_UCM_DEV, NULL, "ucm");
+       ret = class_register(&ucm_class);
+       if (ret) {
+               printk(KERN_ERR "ucm: couldn't create class infiniband_cm\n");
+               goto err_chrdev;
+       }
 
-       idr_init(&ctx_id_table);
-       init_MUTEX(&ctx_id_mutex);
+       ret = class_create_file(&ucm_class, &class_attr_abi_version);
+       if (ret) {
+               printk(KERN_ERR "ucm: couldn't create abi_version attribute\n");
+               goto err_class;
+       }
 
+       ret = ib_register_client(&ucm_client);
+       if (ret) {
+               printk(KERN_ERR "ucm: couldn't register client\n");
+               goto err_class;
+       }
        return 0;
+
 err_class:
-       cdev_del(&ib_ucm_cdev);
-err_cdev:
-       unregister_chrdev_region(IB_UCM_DEV, 1);
-err_chr:
-       return result;
+       class_unregister(&ucm_class);
+err_chrdev:
+       unregister_chrdev_region(IB_UCM_BASE_DEV, IB_UCM_MAX_DEVICES);
+err:
+       return ret;
 }
 
 static void __exit ib_ucm_cleanup(void)
 {
-       class_device_destroy(ib_ucm_class, IB_UCM_DEV);
-       class_destroy(ib_ucm_class);
-       cdev_del(&ib_ucm_cdev);
-       unregister_chrdev_region(IB_UCM_DEV, 1);
+       ib_unregister_client(&ucm_client);
+       class_unregister(&ucm_class);
+       unregister_chrdev_region(IB_UCM_BASE_DEV, IB_UCM_MAX_DEVICES);
+       idr_destroy(&ctx_id_table);
 }
 
 module_init(ib_ucm_init);
diff --git a/drivers/infiniband/core/ucm.h b/drivers/infiniband/core/ucm.h
deleted file mode 100644 (file)
index f46f37b..0000000
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * Copyright (c) 2005 Topspin Communications.  All rights reserved.
- * Copyright (c) 2005 Intel Corporation.  All rights reserved.
- *
- * This software is available to you under a choice of one of two
- * licenses.  You may choose to be licensed under the terms of the GNU
- * General Public License (GPL) Version 2, available from the file
- * COPYING in the main directory of this source tree, or the
- * OpenIB.org BSD license below:
- *
- *     Redistribution and use in source and binary forms, with or
- *     without modification, are permitted provided that the following
- *     conditions are met:
- *
- *      - Redistributions of source code must retain the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer.
- *
- *      - Redistributions in binary form must reproduce the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer in the documentation and/or other materials
- *        provided with the distribution.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- *
- * $Id: ucm.h 2208 2005-04-22 23:24:31Z libor $
- */
-
-#ifndef UCM_H
-#define UCM_H
-
-#include <linux/fs.h>
-#include <linux/device.h>
-#include <linux/cdev.h>
-#include <linux/idr.h>
-
-#include <rdma/ib_cm.h>
-#include <rdma/ib_user_cm.h>
-
-struct ib_ucm_file {
-       struct semaphore mutex;
-       struct file *filp;
-
-       struct list_head  ctxs;   /* list of active connections */
-       struct list_head  events; /* list of pending events */
-       wait_queue_head_t poll_wait;
-};
-
-struct ib_ucm_context {
-       int                 id;
-       wait_queue_head_t   wait;
-       atomic_t            ref;
-       int                 events_reported;
-
-       struct ib_ucm_file *file;
-       struct ib_cm_id    *cm_id;
-       __u64              uid;
-
-       struct list_head    events;    /* list of pending events. */
-       struct list_head    file_list; /* member in file ctx list */
-};
-
-struct ib_ucm_event {
-       struct ib_ucm_context *ctx;
-       struct list_head file_list; /* member in file event list */
-       struct list_head ctx_list;  /* member in ctx event list */
-
-       struct ib_cm_id *cm_id;
-       struct ib_ucm_event_resp resp;
-       void *data;
-       void *info;
-       int data_len;
-       int info_len;
-};
-
-#endif /* UCM_H */
index a64d6b4..97128e2 100644 (file)
@@ -64,18 +64,39 @@ enum {
        IB_UMAD_MINOR_BASE = 0
 };
 
+/*
+ * Our lifetime rules for these structs are the following: each time a
+ * device special file is opened, we look up the corresponding struct
+ * ib_umad_port by minor in the umad_port[] table while holding the
+ * port_lock.  If this lookup succeeds, we take a reference on the
+ * ib_umad_port's struct ib_umad_device while still holding the
+ * port_lock; if the lookup fails, we fail the open().  We drop these
+ * references in the corresponding close().
+ *
+ * In addition to references coming from open character devices, there
+ * is one more reference to each ib_umad_device representing the
+ * module's reference taken when allocating the ib_umad_device in
+ * ib_umad_add_one().
+ *
+ * When destroying an ib_umad_device, we clear all of its
+ * ib_umad_ports from umad_port[] while holding port_lock before
+ * dropping the module's reference to the ib_umad_device.  This is
+ * always safe because any open() calls will either succeed and obtain
+ * a reference before we clear the umad_port[] entries, or fail after
+ * we clear the umad_port[] entries.
+ */
+
 struct ib_umad_port {
-       int                    devnum;
-       struct cdev            dev;
-       struct class_device    class_dev;
+       struct cdev           *dev;
+       struct class_device   *class_dev;
 
-       int                    sm_devnum;
-       struct cdev            sm_dev;
-       struct class_device    sm_class_dev;
+       struct cdev           *sm_dev;
+       struct class_device   *sm_class_dev;
        struct semaphore       sm_sem;
 
        struct ib_device      *ib_dev;
        struct ib_umad_device *umad_dev;
+       int                    dev_num;
        u8                     port_num;
 };
 
@@ -96,21 +117,31 @@ struct ib_umad_file {
 };
 
 struct ib_umad_packet {
-       struct ib_ah      *ah;
        struct ib_mad_send_buf *msg;
        struct list_head   list;
        int                length;
-       DECLARE_PCI_UNMAP_ADDR(mapping)
        struct ib_user_mad mad;
 };
 
+static struct class *umad_class;
+
 static const dev_t base_dev = MKDEV(IB_UMAD_MAJOR, IB_UMAD_MINOR_BASE);
-static spinlock_t map_lock;
+
+static DEFINE_SPINLOCK(port_lock);
+static struct ib_umad_port *umad_port[IB_UMAD_MAX_PORTS];
 static DECLARE_BITMAP(dev_map, IB_UMAD_MAX_PORTS * 2);
 
 static void ib_umad_add_one(struct ib_device *device);
 static void ib_umad_remove_one(struct ib_device *device);
 
+static void ib_umad_release_dev(struct kref *ref)
+{
+       struct ib_umad_device *dev =
+               container_of(ref, struct ib_umad_device, ref);
+
+       kfree(dev);
+}
+
 static int queue_packet(struct ib_umad_file *file,
                        struct ib_mad_agent *agent,
                        struct ib_umad_packet *packet)
@@ -139,22 +170,19 @@ static void send_handler(struct ib_mad_agent *agent,
                         struct ib_mad_send_wc *send_wc)
 {
        struct ib_umad_file *file = agent->context;
-       struct ib_umad_packet *timeout, *packet =
-               (void *) (unsigned long) send_wc->wr_id;
+       struct ib_umad_packet *timeout;
+       struct ib_umad_packet *packet = send_wc->send_buf->context[0];
 
-       ib_destroy_ah(packet->msg->send_wr.wr.ud.ah);
+       ib_destroy_ah(packet->msg->ah);
        ib_free_send_mad(packet->msg);
 
        if (send_wc->status == IB_WC_RESP_TIMEOUT_ERR) {
-               timeout = kmalloc(sizeof *timeout + sizeof (struct ib_mad_hdr),
-                                 GFP_KERNEL);
+               timeout = kzalloc(sizeof *timeout + IB_MGMT_MAD_HDR, GFP_KERNEL);
                if (!timeout)
                        goto out;
 
-               memset(timeout, 0, sizeof *timeout + sizeof (struct ib_mad_hdr));
-
-               timeout->length = sizeof (struct ib_mad_hdr);
-               timeout->mad.hdr.id = packet->mad.hdr.id;
+               timeout->length         = IB_MGMT_MAD_HDR;
+               timeout->mad.hdr.id     = packet->mad.hdr.id;
                timeout->mad.hdr.status = ETIMEDOUT;
                memcpy(timeout->mad.data, packet->mad.data,
                       sizeof (struct ib_mad_hdr));
@@ -177,11 +205,10 @@ static void recv_handler(struct ib_mad_agent *agent,
                goto out;
 
        length = mad_recv_wc->mad_len;
-       packet = kmalloc(sizeof *packet + length, GFP_KERNEL);
+       packet = kzalloc(sizeof *packet + length, GFP_KERNEL);
        if (!packet)
                goto out;
 
-       memset(packet, 0, sizeof *packet + length);
        packet->length = length;
 
        ib_coalesce_recv_mad(mad_recv_wc, packet->mad.data);
@@ -247,7 +274,7 @@ static ssize_t ib_umad_read(struct file *filp, char __user *buf,
                else
                        ret = -ENOSPC;
        } else if (copy_to_user(buf, &packet->mad,
-                             packet->length + sizeof (struct ib_user_mad)))
+                               packet->length + sizeof (struct ib_user_mad)))
                ret = -EFAULT;
        else
                ret = packet->length + sizeof (struct ib_user_mad);
@@ -268,26 +295,23 @@ static ssize_t ib_umad_write(struct file *filp, const char __user *buf,
        struct ib_umad_packet *packet;
        struct ib_mad_agent *agent;
        struct ib_ah_attr ah_attr;
-       struct ib_send_wr *bad_wr;
+       struct ib_ah *ah;
        struct ib_rmpp_mad *rmpp_mad;
        u8 method;
        __be64 *tid;
-       int ret, length, hdr_len, data_len, rmpp_hdr_size;
+       int ret, length, hdr_len, copy_offset;
        int rmpp_active = 0;
 
        if (count < sizeof (struct ib_user_mad))
                return -EINVAL;
 
        length = count - sizeof (struct ib_user_mad);
-       packet = kmalloc(sizeof *packet + sizeof(struct ib_mad_hdr) +
-                        sizeof(struct ib_rmpp_hdr), GFP_KERNEL);
+       packet = kmalloc(sizeof *packet + IB_MGMT_RMPP_HDR, GFP_KERNEL);
        if (!packet)
                return -ENOMEM;
 
        if (copy_from_user(&packet->mad, buf,
-                           sizeof (struct ib_user_mad) +
-                           sizeof(struct ib_mad_hdr) +
-                           sizeof(struct ib_rmpp_hdr))) {
+                           sizeof (struct ib_user_mad) + IB_MGMT_RMPP_HDR)) {
                ret = -EFAULT;
                goto err;
        }
@@ -298,8 +322,6 @@ static ssize_t ib_umad_write(struct file *filp, const char __user *buf,
                goto err;
        }
 
-       packet->length = length;
-
        down_read(&file->agent_mutex);
 
        agent = file->agent[packet->mad.hdr.id];
@@ -321,9 +343,9 @@ static ssize_t ib_umad_write(struct file *filp, const char __user *buf,
                ah_attr.grh.traffic_class  = packet->mad.hdr.traffic_class;
        }
 
-       packet->ah = ib_create_ah(agent->qp->pd, &ah_attr);
-       if (IS_ERR(packet->ah)) {
-               ret = PTR_ERR(packet->ah);
+       ah = ib_create_ah(agent->qp->pd, &ah_attr);
+       if (IS_ERR(ah)) {
+               ret = PTR_ERR(ah);
                goto err_up;
        }
 
@@ -337,64 +359,44 @@ static ssize_t ib_umad_write(struct file *filp, const char __user *buf,
 
                /* 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 - hdr_len;
+                       hdr_len = IB_MGMT_SA_HDR;
                } 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);
-                               data_len = length - hdr_len;
+                               hdr_len = IB_MGMT_VENDOR_HDR;
                } else {
                        ret = -EINVAL;
                        goto err_ah;
                }
                rmpp_active = 1;
+               copy_offset = IB_MGMT_RMPP_HDR;
        } else {
-               if (length > sizeof(struct ib_mad)) {
-                       ret = -EINVAL;
-                       goto err_ah;
-               }
-               hdr_len = offsetof(struct ib_mad, data);
-               data_len = length - hdr_len;
+               hdr_len = IB_MGMT_MAD_HDR;
+               copy_offset = IB_MGMT_MAD_HDR;
        }
 
        packet->msg = ib_create_send_mad(agent,
                                         be32_to_cpu(packet->mad.hdr.qpn),
-                                        0, packet->ah, rmpp_active,
-                                        hdr_len, data_len,
+                                        0, rmpp_active,
+                                        hdr_len, length - hdr_len,
                                         GFP_KERNEL);
        if (IS_ERR(packet->msg)) {
                ret = PTR_ERR(packet->msg);
                goto err_ah;
        }
 
-       packet->msg->send_wr.wr.ud.timeout_ms  = packet->mad.hdr.timeout_ms;
-       packet->msg->send_wr.wr.ud.retries = packet->mad.hdr.retries;
-
-       /* Override send WR WRID initialized in ib_create_send_mad */
-       packet->msg->send_wr.wr_id = (unsigned long) packet;
-
-       if (!rmpp_active) {
-               /* Copy message from user into send buffer */
-               if (copy_from_user(packet->msg->mad,
-                                  buf + sizeof(struct ib_user_mad), length)) {
-                       ret = -EFAULT;
-                       goto err_msg;
-               }
-       } else {
-               rmpp_hdr_size = sizeof(struct ib_mad_hdr) +
-                               sizeof(struct ib_rmpp_hdr);
+       packet->msg->ah         = ah;
+       packet->msg->timeout_ms = packet->mad.hdr.timeout_ms;
+       packet->msg->retries    = packet->mad.hdr.retries;
+       packet->msg->context[0] = packet;
 
-               /* Only copy MAD headers (RMPP header in place) */
-               memcpy(packet->msg->mad, packet->mad.data,
-                      sizeof(struct ib_mad_hdr));
-
-               /* Now, copy rest of message from user into send buffer */
-               if (copy_from_user(((struct ib_rmpp_mad *) packet->msg->mad)->data,
-                                  buf + sizeof (struct ib_user_mad) + rmpp_hdr_size,
-                                  length - rmpp_hdr_size)) {
-                       ret = -EFAULT;
-                       goto err_msg;
-               }
+       /* Copy MAD headers (RMPP header in place) */
+       memcpy(packet->msg->mad, packet->mad.data, IB_MGMT_MAD_HDR);
+       /* Now, copy rest of message from user into send buffer */
+       if (copy_from_user(packet->msg->mad + copy_offset,
+                          buf + sizeof (struct ib_user_mad) + copy_offset,
+                          length - copy_offset)) {
+               ret = -EFAULT;
+               goto err_msg;
        }
 
        /*
@@ -403,29 +405,29 @@ static ssize_t ib_umad_write(struct file *filp, const char __user *buf,
         * transaction ID matches the agent being used to send the
         * MAD.
         */
-       method = packet->msg->mad->mad_hdr.method;
+       method = ((struct ib_mad_hdr *) packet->msg->mad)->method;
 
        if (!(method & IB_MGMT_METHOD_RESP)       &&
            method != IB_MGMT_METHOD_TRAP_REPRESS &&
            method != IB_MGMT_METHOD_SEND) {
-               tid = &packet->msg->mad->mad_hdr.tid;
+               tid = &((struct ib_mad_hdr *) packet->msg->mad)->tid;
                *tid = cpu_to_be64(((u64) agent->hi_tid) << 32 |
                                   (be64_to_cpup(tid) & 0xffffffff));
        }
 
-       ret = ib_post_send_mad(agent, &packet->msg->send_wr, &bad_wr);
+       ret = ib_post_send_mad(packet->msg, NULL);
        if (ret)
                goto err_msg;
 
        up_read(&file->agent_mutex);
 
-       return sizeof (struct ib_user_mad_hdr) + packet->length;
+       return count;
 
 err_msg:
        ib_free_send_mad(packet->msg);
 
 err_ah:
-       ib_destroy_ah(packet->ah);
+       ib_destroy_ah(ah);
 
 err_up:
        up_read(&file->agent_mutex);
@@ -565,15 +567,23 @@ static long ib_umad_ioctl(struct file *filp, unsigned int cmd,
 
 static int ib_umad_open(struct inode *inode, struct file *filp)
 {
-       struct ib_umad_port *port =
-               container_of(inode->i_cdev, struct ib_umad_port, dev);
+       struct ib_umad_port *port;
        struct ib_umad_file *file;
 
-       file = kmalloc(sizeof *file, GFP_KERNEL);
-       if (!file)
-               return -ENOMEM;
+       spin_lock(&port_lock);
+       port = umad_port[iminor(inode) - IB_UMAD_MINOR_BASE];
+       if (port)
+               kref_get(&port->umad_dev->ref);
+       spin_unlock(&port_lock);
 
-       memset(file, 0, sizeof *file);
+       if (!port)
+               return -ENXIO;
+
+       file = kzalloc(sizeof *file, GFP_KERNEL);
+       if (!file) {
+               kref_put(&port->umad_dev->ref, ib_umad_release_dev);
+               return -ENOMEM;
+       }
 
        spin_lock_init(&file->recv_lock);
        init_rwsem(&file->agent_mutex);
@@ -589,6 +599,7 @@ static int ib_umad_open(struct inode *inode, struct file *filp)
 static int ib_umad_close(struct inode *inode, struct file *filp)
 {
        struct ib_umad_file *file = filp->private_data;
+       struct ib_umad_device *dev = file->port->umad_dev;
        struct ib_umad_packet *packet, *tmp;
        int i;
 
@@ -603,6 +614,8 @@ static int ib_umad_close(struct inode *inode, struct file *filp)
 
        kfree(file);
 
+       kref_put(&dev->ref, ib_umad_release_dev);
+
        return 0;
 }
 
@@ -619,30 +632,46 @@ static struct file_operations umad_fops = {
 
 static int ib_umad_sm_open(struct inode *inode, struct file *filp)
 {
-       struct ib_umad_port *port =
-               container_of(inode->i_cdev, struct ib_umad_port, sm_dev);
+       struct ib_umad_port *port;
        struct ib_port_modify props = {
                .set_port_cap_mask = IB_PORT_SM
        };
        int ret;
 
+       spin_lock(&port_lock);
+       port = umad_port[iminor(inode) - IB_UMAD_MINOR_BASE - IB_UMAD_MAX_PORTS];
+       if (port)
+               kref_get(&port->umad_dev->ref);
+       spin_unlock(&port_lock);
+
+       if (!port)
+               return -ENXIO;
+
        if (filp->f_flags & O_NONBLOCK) {
-               if (down_trylock(&port->sm_sem))
-                       return -EAGAIN;
+               if (down_trylock(&port->sm_sem)) {
+                       ret = -EAGAIN;
+                       goto fail;
+               }
        } else {
-               if (down_interruptible(&port->sm_sem))
-                       return -ERESTARTSYS;
+               if (down_interruptible(&port->sm_sem)) {
+                       ret = -ERESTARTSYS;
+                       goto fail;
+               }
        }
 
        ret = ib_modify_port(port->ib_dev, port->port_num, 0, &props);
        if (ret) {
                up(&port->sm_sem);
-               return ret;
+               goto fail;
        }
 
        filp->private_data = port;
 
        return 0;
+
+fail:
+       kref_put(&port->umad_dev->ref, ib_umad_release_dev);
+       return ret;
 }
 
 static int ib_umad_sm_close(struct inode *inode, struct file *filp)
@@ -656,6 +685,8 @@ static int ib_umad_sm_close(struct inode *inode, struct file *filp)
        ret = ib_modify_port(port->ib_dev, port->port_num, 0, &props);
        up(&port->sm_sem);
 
+       kref_put(&port->umad_dev->ref, ib_umad_release_dev);
+
        return ret;
 }
 
@@ -671,21 +702,13 @@ static struct ib_client umad_client = {
        .remove = ib_umad_remove_one
 };
 
-static ssize_t show_dev(struct class_device *class_dev, char *buf)
-{
-       struct ib_umad_port *port = class_get_devdata(class_dev);
-
-       if (class_dev == &port->class_dev)
-               return print_dev_t(buf, port->dev.dev);
-       else
-               return print_dev_t(buf, port->sm_dev.dev);
-}
-static CLASS_DEVICE_ATTR(dev, S_IRUGO, show_dev, NULL);
-
 static ssize_t show_ibdev(struct class_device *class_dev, char *buf)
 {
        struct ib_umad_port *port = class_get_devdata(class_dev);
 
+       if (!port)
+               return -ENODEV;
+
        return sprintf(buf, "%s\n", port->ib_dev->name);
 }
 static CLASS_DEVICE_ATTR(ibdev, S_IRUGO, show_ibdev, NULL);
@@ -694,38 +717,13 @@ static ssize_t show_port(struct class_device *class_dev, char *buf)
 {
        struct ib_umad_port *port = class_get_devdata(class_dev);
 
+       if (!port)
+               return -ENODEV;
+
        return sprintf(buf, "%d\n", port->port_num);
 }
 static CLASS_DEVICE_ATTR(port, S_IRUGO, show_port, NULL);
 
-static void ib_umad_release_dev(struct kref *ref)
-{
-       struct ib_umad_device *dev =
-               container_of(ref, struct ib_umad_device, ref);
-
-       kfree(dev);
-}
-
-static void ib_umad_release_port(struct class_device *class_dev)
-{
-       struct ib_umad_port *port = class_get_devdata(class_dev);
-
-       if (class_dev == &port->class_dev) {
-               cdev_del(&port->dev);
-               clear_bit(port->devnum, dev_map);
-       } else {
-               cdev_del(&port->sm_dev);
-               clear_bit(port->sm_devnum, dev_map);
-       }
-
-       kref_put(&port->umad_dev->ref, ib_umad_release_dev);
-}
-
-static struct class umad_class = {
-       .name    = "infiniband_mad",
-       .release = ib_umad_release_port
-};
-
 static ssize_t show_abi_version(struct class *class, char *buf)
 {
        return sprintf(buf, "%d\n", IB_USER_MAD_ABI_VERSION);
@@ -735,91 +733,102 @@ static CLASS_ATTR(abi_version, S_IRUGO, show_abi_version, NULL);
 static int ib_umad_init_port(struct ib_device *device, int port_num,
                             struct ib_umad_port *port)
 {
-       spin_lock(&map_lock);
-       port->devnum = find_first_zero_bit(dev_map, IB_UMAD_MAX_PORTS);
-       if (port->devnum >= IB_UMAD_MAX_PORTS) {
-               spin_unlock(&map_lock);
+       spin_lock(&port_lock);
+       port->dev_num = find_first_zero_bit(dev_map, IB_UMAD_MAX_PORTS);
+       if (port->dev_num >= IB_UMAD_MAX_PORTS) {
+               spin_unlock(&port_lock);
                return -1;
        }
-       port->sm_devnum = find_next_zero_bit(dev_map, IB_UMAD_MAX_PORTS * 2, IB_UMAD_MAX_PORTS);
-       if (port->sm_devnum >= IB_UMAD_MAX_PORTS * 2) {
-               spin_unlock(&map_lock);
-               return -1;
-       }
-       set_bit(port->devnum, dev_map);
-       set_bit(port->sm_devnum, dev_map);
-       spin_unlock(&map_lock);
+       set_bit(port->dev_num, dev_map);
+       spin_unlock(&port_lock);
 
        port->ib_dev   = device;
        port->port_num = port_num;
        init_MUTEX(&port->sm_sem);
 
-       cdev_init(&port->dev, &umad_fops);
-       port->dev.owner = THIS_MODULE;
-       kobject_set_name(&port->dev.kobj, "umad%d", port->devnum);
-       if (cdev_add(&port->dev, base_dev + port->devnum, 1))
+       port->dev = cdev_alloc();
+       if (!port->dev)
                return -1;
-
-       port->class_dev.class = &umad_class;
-       port->class_dev.dev   = device->dma_device;
-
-       snprintf(port->class_dev.class_id, BUS_ID_SIZE, "umad%d", port->devnum);
-
-       if (class_device_register(&port->class_dev))
+       port->dev->owner = THIS_MODULE;
+       port->dev->ops   = &umad_fops;
+       kobject_set_name(&port->dev->kobj, "umad%d", port->dev_num);
+       if (cdev_add(port->dev, base_dev + port->dev_num, 1))
                goto err_cdev;
 
-       class_set_devdata(&port->class_dev, port);
-       kref_get(&port->umad_dev->ref);
+       port->class_dev = class_device_create(umad_class, NULL, port->dev->dev,
+                                             device->dma_device,
+                                             "umad%d", port->dev_num);
+       if (IS_ERR(port->class_dev))
+               goto err_cdev;
 
-       if (class_device_create_file(&port->class_dev, &class_device_attr_dev))
-               goto err_class;
-       if (class_device_create_file(&port->class_dev, &class_device_attr_ibdev))
+       if (class_device_create_file(port->class_dev, &class_device_attr_ibdev))
                goto err_class;
-       if (class_device_create_file(&port->class_dev, &class_device_attr_port))
+       if (class_device_create_file(port->class_dev, &class_device_attr_port))
                goto err_class;
 
-       cdev_init(&port->sm_dev, &umad_sm_fops);
-       port->sm_dev.owner = THIS_MODULE;
-       kobject_set_name(&port->dev.kobj, "issm%d", port->sm_devnum - IB_UMAD_MAX_PORTS);
-       if (cdev_add(&port->sm_dev, base_dev + port->sm_devnum, 1))
-               return -1;
-
-       port->sm_class_dev.class = &umad_class;
-       port->sm_class_dev.dev   = device->dma_device;
-
-       snprintf(port->sm_class_dev.class_id, BUS_ID_SIZE, "issm%d", port->sm_devnum - IB_UMAD_MAX_PORTS);
+       port->sm_dev = cdev_alloc();
+       if (!port->sm_dev)
+               goto err_class;
+       port->sm_dev->owner = THIS_MODULE;
+       port->sm_dev->ops   = &umad_sm_fops;
+       kobject_set_name(&port->dev->kobj, "issm%d", port->dev_num);
+       if (cdev_add(port->sm_dev, base_dev + port->dev_num + IB_UMAD_MAX_PORTS, 1))
+               goto err_sm_cdev;
 
-       if (class_device_register(&port->sm_class_dev))
+       port->sm_class_dev = class_device_create(umad_class, NULL, port->sm_dev->dev,
+                                                device->dma_device,
+                                                "issm%d", port->dev_num);
+       if (IS_ERR(port->sm_class_dev))
                goto err_sm_cdev;
 
-       class_set_devdata(&port->sm_class_dev, port);
-       kref_get(&port->umad_dev->ref);
+       class_set_devdata(port->class_dev,    port);
+       class_set_devdata(port->sm_class_dev, port);
 
-       if (class_device_create_file(&port->sm_class_dev, &class_device_attr_dev))
-               goto err_sm_class;
-       if (class_device_create_file(&port->sm_class_dev, &class_device_attr_ibdev))
+       if (class_device_create_file(port->sm_class_dev, &class_device_attr_ibdev))
                goto err_sm_class;
-       if (class_device_create_file(&port->sm_class_dev, &class_device_attr_port))
+       if (class_device_create_file(port->sm_class_dev, &class_device_attr_port))
                goto err_sm_class;
 
+       spin_lock(&port_lock);
+       umad_port[port->dev_num] = port;
+       spin_unlock(&port_lock);
+
        return 0;
 
 err_sm_class:
-       class_device_unregister(&port->sm_class_dev);
+       class_device_destroy(umad_class, port->sm_dev->dev);
 
 err_sm_cdev:
-       cdev_del(&port->sm_dev);
+       cdev_del(port->sm_dev);
 
 err_class:
-       class_device_unregister(&port->class_dev);
+       class_device_destroy(umad_class, port->dev->dev);
 
 err_cdev:
-       cdev_del(&port->dev);
-       clear_bit(port->devnum, dev_map);
+       cdev_del(port->dev);
+       clear_bit(port->dev_num, dev_map);
 
        return -1;
 }
 
+static void ib_umad_kill_port(struct ib_umad_port *port)
+{
+       class_set_devdata(port->class_dev,    NULL);
+       class_set_devdata(port->sm_class_dev, NULL);
+
+       class_device_destroy(umad_class, port->dev->dev);
+       class_device_destroy(umad_class, port->sm_dev->dev);
+
+       cdev_del(port->dev);
+       cdev_del(port->sm_dev);
+
+       spin_lock(&port_lock);
+       umad_port[port->dev_num] = NULL;
+       spin_unlock(&port_lock);
+
+       clear_bit(port->dev_num, dev_map);
+}
+
 static void ib_umad_add_one(struct ib_device *device)
 {
        struct ib_umad_device *umad_dev;
@@ -832,15 +841,12 @@ static void ib_umad_add_one(struct ib_device *device)
                e = device->phys_port_cnt;
        }
 
-       umad_dev = kmalloc(sizeof *umad_dev +
+       umad_dev = kzalloc(sizeof *umad_dev +
                           (e - s + 1) * sizeof (struct ib_umad_port),
                           GFP_KERNEL);
        if (!umad_dev)
                return;
 
-       memset(umad_dev, 0, sizeof *umad_dev +
-              (e - s + 1) * sizeof (struct ib_umad_port));
-
        kref_init(&umad_dev->ref);
 
        umad_dev->start_port = s;
@@ -858,10 +864,8 @@ static void ib_umad_add_one(struct ib_device *device)
        return;
 
 err:
-       while (--i >= s) {
-               class_device_unregister(&umad_dev->port[i - s].class_dev);
-               class_device_unregister(&umad_dev->port[i - s].sm_class_dev);
-       }
+       while (--i >= s)
+               ib_umad_kill_port(&umad_dev->port[i]);
 
        kref_put(&umad_dev->ref, ib_umad_release_dev);
 }
@@ -874,10 +878,8 @@ static void ib_umad_remove_one(struct ib_device *device)
        if (!umad_dev)
                return;
 
-       for (i = 0; i <= umad_dev->end_port - umad_dev->start_port; ++i) {
-               class_device_unregister(&umad_dev->port[i].class_dev);
-               class_device_unregister(&umad_dev->port[i].sm_class_dev);
-       }
+       for (i = 0; i <= umad_dev->end_port - umad_dev->start_port; ++i)
+               ib_umad_kill_port(&umad_dev->port[i]);
 
        kref_put(&umad_dev->ref, ib_umad_release_dev);
 }
@@ -886,8 +888,6 @@ static int __init ib_umad_init(void)
 {
        int ret;
 
-       spin_lock_init(&map_lock);
-
        ret = register_chrdev_region(base_dev, IB_UMAD_MAX_PORTS * 2,
                                     "infiniband_mad");
        if (ret) {
@@ -895,13 +895,14 @@ static int __init ib_umad_init(void)
                goto out;
        }
 
-       ret = class_register(&umad_class);
-       if (ret) {
+       umad_class = class_create(THIS_MODULE, "infiniband_mad");
+       if (IS_ERR(umad_class)) {
+               ret = PTR_ERR(umad_class);
                printk(KERN_ERR "user_mad: couldn't create class infiniband_mad\n");
                goto out_chrdev;
        }
 
-       ret = class_create_file(&umad_class, &class_attr_abi_version);
+       ret = class_create_file(umad_class, &class_attr_abi_version);
        if (ret) {
                printk(KERN_ERR "user_mad: couldn't create abi_version attribute\n");
                goto out_class;
@@ -916,7 +917,7 @@ static int __init ib_umad_init(void)
        return 0;
 
 out_class:
-       class_unregister(&umad_class);
+       class_destroy(umad_class);
 
 out_chrdev:
        unregister_chrdev_region(base_dev, IB_UMAD_MAX_PORTS * 2);
@@ -928,7 +929,7 @@ out:
 static void __exit ib_umad_cleanup(void)
 {
        ib_unregister_client(&umad_client);
-       class_unregister(&umad_class);
+       class_destroy(umad_class);
        unregister_chrdev_region(base_dev, IB_UMAD_MAX_PORTS * 2);
 }
 
index cc12434..031cdf3 100644 (file)
@@ -3,6 +3,7 @@
  * Copyright (c) 2005 Cisco Systems.  All rights reserved.
  * Copyright (c) 2005 Mellanox Technologies. All rights reserved.
  * Copyright (c) 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2005 PathScale, Inc. All rights reserved.
  *
  * This software is available to you under a choice of one of two
  * licenses.  You may choose to be licensed under the terms of the GNU
 #ifndef UVERBS_H
 #define UVERBS_H
 
-/* Include device.h and fs.h until cdev.h is self-sufficient */
-#include <linux/fs.h>
-#include <linux/device.h>
-#include <linux/cdev.h>
 #include <linux/kref.h>
 #include <linux/idr.h>
 
 #include <rdma/ib_verbs.h>
 #include <rdma/ib_user_verbs.h>
 
+/*
+ * Our lifetime rules for these structs are the following:
+ *
+ * struct ib_uverbs_device: One reference is held by the module and
+ * released in ib_uverbs_remove_one().  Another reference is taken by
+ * ib_uverbs_open() each time the character special file is opened,
+ * and released in ib_uverbs_release_file() when the file is released.
+ *
+ * struct ib_uverbs_file: One reference is held by the VFS and
+ * released when the file is closed.  Another reference is taken when
+ * an asynchronous event queue file is created and released when the
+ * event file is closed.
+ *
+ * struct ib_uverbs_event_file: One reference is held by the VFS and
+ * released when the file is closed.  For asynchronous event files,
+ * another reference is held by the corresponding main context file
+ * and released when that file is closed.  For completion event files,
+ * a reference is taken when a CQ is created that uses the file, and
+ * released when the CQ is destroyed.
+ */
+
 struct ib_uverbs_device {
+       struct kref                             ref;
        int                                     devnum;
-       struct cdev                             dev;
-       struct class_device                     class_dev;
+       struct cdev                            *dev;
+       struct class_device                    *class_dev;
        struct ib_device                       *ib_dev;
-       int                                     num_comp;
+       int                                     num_comp_vectors;
 };
 
 struct ib_uverbs_event_file {
        struct kref                             ref;
+       struct file                            *file;
        struct ib_uverbs_file                  *uverbs_file;
        spinlock_t                              lock;
-       int                                     fd;
        int                                     is_async;
        wait_queue_head_t                       poll_wait;
        struct fasync_struct                   *async_queue;
@@ -73,8 +92,7 @@ struct ib_uverbs_file {
        struct ib_uverbs_device                *device;
        struct ib_ucontext                     *ucontext;
        struct ib_event_handler                 event_handler;
-       struct ib_uverbs_event_file             async_file;
-       struct ib_uverbs_event_file             comp_file[1];
+       struct ib_uverbs_event_file            *async_file;
 };
 
 struct ib_uverbs_event {
@@ -110,10 +128,23 @@ extern struct idr ib_uverbs_cq_idr;
 extern struct idr ib_uverbs_qp_idr;
 extern struct idr ib_uverbs_srq_idr;
 
+struct file *ib_uverbs_alloc_event_file(struct ib_uverbs_file *uverbs_file,
+                                       int is_async, int *fd);
+void ib_uverbs_release_event_file(struct kref *ref);
+struct ib_uverbs_event_file *ib_uverbs_lookup_comp_file(int fd);
+
+void ib_uverbs_release_ucq(struct ib_uverbs_file *file,
+                          struct ib_uverbs_event_file *ev_file,
+                          struct ib_ucq_object *uobj);
+void ib_uverbs_release_uevent(struct ib_uverbs_file *file,
+                             struct ib_uevent_object *uobj);
+
 void ib_uverbs_comp_handler(struct ib_cq *cq, void *cq_context);
 void ib_uverbs_cq_event_handler(struct ib_event *event, void *context_ptr);
 void ib_uverbs_qp_event_handler(struct ib_event *event, void *context_ptr);
 void ib_uverbs_srq_event_handler(struct ib_event *event, void *context_ptr);
+void ib_uverbs_event_handler(struct ib_event_handler *handler,
+                            struct ib_event *event);
 
 int ib_umem_get(struct ib_device *dev, struct ib_umem *mem,
                void *addr, size_t size, int write);
@@ -125,21 +156,26 @@ void ib_umem_release_on_close(struct ib_device *dev, struct ib_umem *umem);
                                 const char __user *buf, int in_len,    \
                                 int out_len)
 
-IB_UVERBS_DECLARE_CMD(query_params);
 IB_UVERBS_DECLARE_CMD(get_context);
 IB_UVERBS_DECLARE_CMD(query_device);
 IB_UVERBS_DECLARE_CMD(query_port);
-IB_UVERBS_DECLARE_CMD(query_gid);
-IB_UVERBS_DECLARE_CMD(query_pkey);
 IB_UVERBS_DECLARE_CMD(alloc_pd);
 IB_UVERBS_DECLARE_CMD(dealloc_pd);
 IB_UVERBS_DECLARE_CMD(reg_mr);
 IB_UVERBS_DECLARE_CMD(dereg_mr);
+IB_UVERBS_DECLARE_CMD(create_comp_channel);
 IB_UVERBS_DECLARE_CMD(create_cq);
+IB_UVERBS_DECLARE_CMD(poll_cq);
+IB_UVERBS_DECLARE_CMD(req_notify_cq);
 IB_UVERBS_DECLARE_CMD(destroy_cq);
 IB_UVERBS_DECLARE_CMD(create_qp);
 IB_UVERBS_DECLARE_CMD(modify_qp);
 IB_UVERBS_DECLARE_CMD(destroy_qp);
+IB_UVERBS_DECLARE_CMD(post_send);
+IB_UVERBS_DECLARE_CMD(post_recv);
+IB_UVERBS_DECLARE_CMD(post_srq_recv);
+IB_UVERBS_DECLARE_CMD(create_ah);
+IB_UVERBS_DECLARE_CMD(destroy_ah);
 IB_UVERBS_DECLARE_CMD(attach_mcast);
 IB_UVERBS_DECLARE_CMD(detach_mcast);
 IB_UVERBS_DECLARE_CMD(create_srq);
index 5624451..8c89abc 100644 (file)
@@ -1,6 +1,7 @@
 /*
  * Copyright (c) 2005 Topspin Communications.  All rights reserved.
  * Copyright (c) 2005 Cisco Systems.  All rights reserved.
+ * Copyright (c) 2005 PathScale, Inc.  All rights reserved.
  *
  * This software is available to you under a choice of one of two
  * licenses.  You may choose to be licensed under the terms of the GNU
@@ -33,6 +34,9 @@
  * $Id: uverbs_cmd.c 2708 2005-06-24 17:27:21Z roland $
  */
 
+#include <linux/file.h>
+#include <linux/fs.h>
+
 #include <asm/uaccess.h>
 
 #include "uverbs.h"
                (udata)->outlen = (olen);                               \
        } while (0)
 
-ssize_t ib_uverbs_query_params(struct ib_uverbs_file *file,
-                              const char __user *buf,
-                              int in_len, int out_len)
-{
-       struct ib_uverbs_query_params      cmd;
-       struct ib_uverbs_query_params_resp resp;
-
-       if (out_len < sizeof resp)
-               return -ENOSPC;
-
-       if (copy_from_user(&cmd, buf, sizeof cmd))
-               return -EFAULT;
-
-       memset(&resp, 0, sizeof resp);
-
-       resp.num_cq_events = file->device->num_comp;
-
-       if (copy_to_user((void __user *) (unsigned long) cmd.response, &resp, sizeof resp))
-           return -EFAULT;
-
-       return in_len;
-}
-
 ssize_t ib_uverbs_get_context(struct ib_uverbs_file *file,
                              const char __user *buf,
                              int in_len, int out_len)
@@ -77,7 +58,7 @@ ssize_t ib_uverbs_get_context(struct ib_uverbs_file *file,
        struct ib_udata                   udata;
        struct ib_device                 *ibdev = file->device->ib_dev;
        struct ib_ucontext               *ucontext;
-       int i;
+       struct file                      *filp;
        int ret;
 
        if (out_len < sizeof resp)
@@ -110,26 +91,42 @@ ssize_t ib_uverbs_get_context(struct ib_uverbs_file *file,
        INIT_LIST_HEAD(&ucontext->srq_list);
        INIT_LIST_HEAD(&ucontext->ah_list);
 
-       resp.async_fd = file->async_file.fd;
-       for (i = 0; i < file->device->num_comp; ++i)
-               if (copy_to_user((void __user *) (unsigned long) cmd.cq_fd_tab +
-                                i * sizeof (__u32),
-                                &file->comp_file[i].fd, sizeof (__u32))) {
-                       ret = -EFAULT;
-                       goto err_free;
-               }
+       resp.num_comp_vectors = file->device->num_comp_vectors;
+
+       filp = ib_uverbs_alloc_event_file(file, 1, &resp.async_fd);
+       if (IS_ERR(filp)) {
+               ret = PTR_ERR(filp);
+               goto err_free;
+       }
 
        if (copy_to_user((void __user *) (unsigned long) cmd.response,
                         &resp, sizeof resp)) {
                ret = -EFAULT;
-               goto err_free;
+               goto err_file;
        }
 
+       file->async_file = filp->private_data;
+
+       INIT_IB_EVENT_HANDLER(&file->event_handler, file->device->ib_dev,
+                             ib_uverbs_event_handler);
+       ret = ib_register_event_handler(&file->event_handler);
+       if (ret)
+               goto err_file;
+
+       kref_get(&file->async_file->ref);
+       kref_get(&file->ref);
        file->ucontext = ucontext;
+
+       fd_install(resp.async_fd, filp);
+
        up(&file->mutex);
 
        return in_len;
 
+err_file:
+       put_unused_fd(resp.async_fd);
+       fput(filp);
+
 err_free:
        ibdev->dealloc_ucontext(ucontext);
 
@@ -255,62 +252,6 @@ ssize_t ib_uverbs_query_port(struct ib_uverbs_file *file,
        return in_len;
 }
 
-ssize_t ib_uverbs_query_gid(struct ib_uverbs_file *file,
-                           const char __user *buf,
-                           int in_len, int out_len)
-{
-       struct ib_uverbs_query_gid      cmd;
-       struct ib_uverbs_query_gid_resp resp;
-       int                             ret;
-
-       if (out_len < sizeof resp)
-               return -ENOSPC;
-
-       if (copy_from_user(&cmd, buf, sizeof cmd))
-               return -EFAULT;
-
-       memset(&resp, 0, sizeof resp);
-
-       ret = ib_query_gid(file->device->ib_dev, cmd.port_num, cmd.index,
-                          (union ib_gid *) resp.gid);
-       if (ret)
-               return ret;
-
-       if (copy_to_user((void __user *) (unsigned long) cmd.response,
-                        &resp, sizeof resp))
-               return -EFAULT;
-
-       return in_len;
-}
-
-ssize_t ib_uverbs_query_pkey(struct ib_uverbs_file *file,
-                            const char __user *buf,
-                            int in_len, int out_len)
-{
-       struct ib_uverbs_query_pkey      cmd;
-       struct ib_uverbs_query_pkey_resp resp;
-       int                              ret;
-
-       if (out_len < sizeof resp)
-               return -ENOSPC;
-
-       if (copy_from_user(&cmd, buf, sizeof cmd))
-               return -EFAULT;
-
-       memset(&resp, 0, sizeof resp);
-
-       ret = ib_query_pkey(file->device->ib_dev, cmd.port_num, cmd.index,
-                           &resp.pkey);
-       if (ret)
-               return ret;
-
-       if (copy_to_user((void __user *) (unsigned long) cmd.response,
-                        &resp, sizeof resp))
-               return -EFAULT;
-
-       return in_len;
-}
-
 ssize_t ib_uverbs_alloc_pd(struct ib_uverbs_file *file,
                           const char __user *buf,
                           int in_len, int out_len)
@@ -349,24 +290,20 @@ ssize_t ib_uverbs_alloc_pd(struct ib_uverbs_file *file,
        pd->uobject = uobj;
        atomic_set(&pd->usecnt, 0);
 
+       down(&ib_uverbs_idr_mutex);
+
 retry:
        if (!idr_pre_get(&ib_uverbs_pd_idr, GFP_KERNEL)) {
                ret = -ENOMEM;
-               goto err_pd;
+               goto err_up;
        }
 
-       down(&ib_uverbs_idr_mutex);
        ret = idr_get_new(&ib_uverbs_pd_idr, pd, &uobj->id);
-       up(&ib_uverbs_idr_mutex);
 
        if (ret == -EAGAIN)
                goto retry;
        if (ret)
-               goto err_pd;
-
-       down(&file->mutex);
-       list_add_tail(&uobj->list, &file->ucontext->pd_list);
-       up(&file->mutex);
+               goto err_up;
 
        memset(&resp, 0, sizeof resp);
        resp.pd_handle = uobj->id;
@@ -374,21 +311,22 @@ retry:
        if (copy_to_user((void __user *) (unsigned long) cmd.response,
                         &resp, sizeof resp)) {
                ret = -EFAULT;
-               goto err_list;
+               goto err_idr;
        }
 
-       return in_len;
-
-err_list:
-       down(&file->mutex);
-       list_del(&uobj->list);
+       down(&file->mutex);
+       list_add_tail(&uobj->list, &file->ucontext->pd_list);
        up(&file->mutex);
 
-       down(&ib_uverbs_idr_mutex);
-       idr_remove(&ib_uverbs_pd_idr, uobj->id);
        up(&ib_uverbs_idr_mutex);
 
-err_pd:
+       return in_len;
+
+err_idr:
+       idr_remove(&ib_uverbs_pd_idr, uobj->id);
+
+err_up:
+       up(&ib_uverbs_idr_mutex);
        ib_dealloc_pd(pd);
 
 err:
@@ -459,6 +397,14 @@ ssize_t ib_uverbs_reg_mr(struct ib_uverbs_file *file,
        if ((cmd.start & ~PAGE_MASK) != (cmd.hca_va & ~PAGE_MASK))
                return -EINVAL;
 
+       /*
+        * Local write permission is required if remote write or
+        * remote atomic permission is also requested.
+        */
+       if (cmd.access_flags & (IB_ACCESS_REMOTE_ATOMIC | IB_ACCESS_REMOTE_WRITE) &&
+           !(cmd.access_flags & IB_ACCESS_LOCAL_WRITE))
+               return -EINVAL;
+
        obj = kmalloc(sizeof *obj, GFP_KERNEL);
        if (!obj)
                return -ENOMEM;
@@ -524,24 +470,22 @@ retry:
 
        resp.mr_handle = obj->uobject.id;
 
-       down(&file->mutex);
-       list_add_tail(&obj->uobject.list, &file->ucontext->mr_list);
-       up(&file->mutex);
-
        if (copy_to_user((void __user *) (unsigned long) cmd.response,
                         &resp, sizeof resp)) {
                ret = -EFAULT;
-               goto err_list;
+               goto err_idr;
        }
 
+       down(&file->mutex);
+       list_add_tail(&obj->uobject.list, &file->ucontext->mr_list);
+       up(&file->mutex);
+
        up(&ib_uverbs_idr_mutex);
 
        return in_len;
 
-err_list:
-       down(&file->mutex);
-       list_del(&obj->uobject.list);
-       up(&file->mutex);
+err_idr:
+       idr_remove(&ib_uverbs_mr_idr, obj->uobject.id);
 
 err_unreg:
        ib_dereg_mr(mr);
@@ -595,6 +539,35 @@ out:
        return ret ? ret : in_len;
 }
 
+ssize_t ib_uverbs_create_comp_channel(struct ib_uverbs_file *file,
+                                     const char __user *buf, int in_len,
+                                     int out_len)
+{
+       struct ib_uverbs_create_comp_channel       cmd;
+       struct ib_uverbs_create_comp_channel_resp  resp;
+       struct file                               *filp;
+
+       if (out_len < sizeof resp)
+               return -ENOSPC;
+
+       if (copy_from_user(&cmd, buf, sizeof cmd))
+               return -EFAULT;
+
+       filp = ib_uverbs_alloc_event_file(file, 0, &resp.fd);
+       if (IS_ERR(filp))
+               return PTR_ERR(filp);
+
+       if (copy_to_user((void __user *) (unsigned long) cmd.response,
+                        &resp, sizeof resp)) {
+               put_unused_fd(resp.fd);
+               fput(filp);
+               return -EFAULT;
+       }
+
+       fd_install(resp.fd, filp);
+       return in_len;
+}
+
 ssize_t ib_uverbs_create_cq(struct ib_uverbs_file *file,
                            const char __user *buf, int in_len,
                            int out_len)
@@ -603,6 +576,7 @@ ssize_t ib_uverbs_create_cq(struct ib_uverbs_file *file,
        struct ib_uverbs_create_cq_resp resp;
        struct ib_udata                 udata;
        struct ib_ucq_object           *uobj;
+       struct ib_uverbs_event_file    *ev_file = NULL;
        struct ib_cq                   *cq;
        int                             ret;
 
@@ -616,9 +590,12 @@ ssize_t ib_uverbs_create_cq(struct ib_uverbs_file *file,
                   (unsigned long) cmd.response + sizeof resp,
                   in_len - sizeof cmd, out_len - sizeof resp);
 
-       if (cmd.event_handler >= file->device->num_comp)
+       if (cmd.comp_vector >= file->device->num_comp_vectors)
                return -EINVAL;
 
+       if (cmd.comp_channel >= 0)
+               ev_file = ib_uverbs_lookup_comp_file(cmd.comp_channel);
+
        uobj = kmalloc(sizeof *uobj, GFP_KERNEL);
        if (!uobj)
                return -ENOMEM;
@@ -641,27 +618,23 @@ ssize_t ib_uverbs_create_cq(struct ib_uverbs_file *file,
        cq->uobject       = &uobj->uobject;
        cq->comp_handler  = ib_uverbs_comp_handler;
        cq->event_handler = ib_uverbs_cq_event_handler;
-       cq->cq_context    = file;
+       cq->cq_context    = ev_file;
        atomic_set(&cq->usecnt, 0);
 
+       down(&ib_uverbs_idr_mutex);
+
 retry:
        if (!idr_pre_get(&ib_uverbs_cq_idr, GFP_KERNEL)) {
                ret = -ENOMEM;
-               goto err_cq;
+               goto err_up;
        }
 
-       down(&ib_uverbs_idr_mutex);
        ret = idr_get_new(&ib_uverbs_cq_idr, cq, &uobj->uobject.id);
-       up(&ib_uverbs_idr_mutex);
 
        if (ret == -EAGAIN)
                goto retry;
        if (ret)
-               goto err_cq;
-
-       down(&file->mutex);
-       list_add_tail(&uobj->uobject.list, &file->ucontext->cq_list);
-       up(&file->mutex);
+               goto err_up;
 
        memset(&resp, 0, sizeof resp);
        resp.cq_handle = uobj->uobject.id;
@@ -670,21 +643,22 @@ retry:
        if (copy_to_user((void __user *) (unsigned long) cmd.response,
                         &resp, sizeof resp)) {
                ret = -EFAULT;
-               goto err_list;
+               goto err_idr;
        }
 
-       return in_len;
-
-err_list:
-       down(&file->mutex);
-       list_del(&uobj->uobject.list);
+       down(&file->mutex);
+       list_add_tail(&uobj->uobject.list, &file->ucontext->cq_list);
        up(&file->mutex);
 
-       down(&ib_uverbs_idr_mutex);
-       idr_remove(&ib_uverbs_cq_idr, uobj->uobject.id);
        up(&ib_uverbs_idr_mutex);
 
-err_cq:
+       return in_len;
+
+err_idr:
+       idr_remove(&ib_uverbs_cq_idr, uobj->uobject.id);
+
+err_up:
+       up(&ib_uverbs_idr_mutex);
        ib_destroy_cq(cq);
 
 err:
@@ -692,6 +666,93 @@ err:
        return ret;
 }
 
+ssize_t ib_uverbs_poll_cq(struct ib_uverbs_file *file,
+                         const char __user *buf, int in_len,
+                         int out_len)
+{
+       struct ib_uverbs_poll_cq       cmd;
+       struct ib_uverbs_poll_cq_resp *resp;
+       struct ib_cq                  *cq;
+       struct ib_wc                  *wc;
+       int                            ret = 0;
+       int                            i;
+       int                            rsize;
+
+       if (copy_from_user(&cmd, buf, sizeof cmd))
+               return -EFAULT;
+
+       wc = kmalloc(cmd.ne * sizeof *wc, GFP_KERNEL);
+       if (!wc)
+               return -ENOMEM;
+
+       rsize = sizeof *resp + cmd.ne * sizeof(struct ib_uverbs_wc);
+       resp = kmalloc(rsize, GFP_KERNEL);
+       if (!resp) {
+               ret = -ENOMEM;
+               goto out_wc;
+       }
+
+       down(&ib_uverbs_idr_mutex);
+       cq = idr_find(&ib_uverbs_cq_idr, cmd.cq_handle);
+       if (!cq || cq->uobject->context != file->ucontext) {
+               ret = -EINVAL;
+               goto out;
+       }
+
+       resp->count = ib_poll_cq(cq, cmd.ne, wc);
+
+       for (i = 0; i < resp->count; i++) {
+               resp->wc[i].wr_id          = wc[i].wr_id;
+               resp->wc[i].status         = wc[i].status;
+               resp->wc[i].opcode         = wc[i].opcode;
+               resp->wc[i].vendor_err     = wc[i].vendor_err;
+               resp->wc[i].byte_len       = wc[i].byte_len;
+               resp->wc[i].imm_data       = wc[i].imm_data;
+               resp->wc[i].qp_num         = wc[i].qp_num;
+               resp->wc[i].src_qp         = wc[i].src_qp;
+               resp->wc[i].wc_flags       = wc[i].wc_flags;
+               resp->wc[i].pkey_index     = wc[i].pkey_index;
+               resp->wc[i].slid           = wc[i].slid;
+               resp->wc[i].sl             = wc[i].sl;
+               resp->wc[i].dlid_path_bits = wc[i].dlid_path_bits;
+               resp->wc[i].port_num       = wc[i].port_num;
+       }
+
+       if (copy_to_user((void __user *) (unsigned long) cmd.response, resp, rsize))
+               ret = -EFAULT;
+
+out:
+       up(&ib_uverbs_idr_mutex);
+       kfree(resp);
+
+out_wc:
+       kfree(wc);
+       return ret ? ret : in_len;
+}
+
+ssize_t ib_uverbs_req_notify_cq(struct ib_uverbs_file *file,
+                               const char __user *buf, int in_len,
+                               int out_len)
+{
+       struct ib_uverbs_req_notify_cq cmd;
+       struct ib_cq                  *cq;
+       int                            ret = -EINVAL;
+
+       if (copy_from_user(&cmd, buf, sizeof cmd))
+               return -EFAULT;
+
+       down(&ib_uverbs_idr_mutex);
+       cq = idr_find(&ib_uverbs_cq_idr, cmd.cq_handle);
+       if (cq && cq->uobject->context == file->ucontext) {
+               ib_req_notify_cq(cq, cmd.solicited_only ?
+                                       IB_CQ_SOLICITED : IB_CQ_NEXT_COMP);
+               ret = in_len;
+       }
+       up(&ib_uverbs_idr_mutex);
+
+       return ret;
+}
+
 ssize_t ib_uverbs_destroy_cq(struct ib_uverbs_file *file,
                             const char __user *buf, int in_len,
                             int out_len)
@@ -700,7 +761,7 @@ ssize_t ib_uverbs_destroy_cq(struct ib_uverbs_file *file,
        struct ib_uverbs_destroy_cq_resp resp;
        struct ib_cq                    *cq;
        struct ib_ucq_object            *uobj;
-       struct ib_uverbs_event          *evt, *tmp;
+       struct ib_uverbs_event_file     *ev_file;
        u64                              user_handle;
        int                              ret = -EINVAL;
 
@@ -716,7 +777,8 @@ ssize_t ib_uverbs_destroy_cq(struct ib_uverbs_file *file,
                goto out;
 
        user_handle = cq->uobject->user_handle;
-       uobj = container_of(cq->uobject, struct ib_ucq_object, uobject);
+       uobj        = container_of(cq->uobject, struct ib_ucq_object, uobject);
+       ev_file     = cq->cq_context;
 
        ret = ib_destroy_cq(cq);
        if (ret)
@@ -728,19 +790,7 @@ ssize_t ib_uverbs_destroy_cq(struct ib_uverbs_file *file,
        list_del(&uobj->uobject.list);
        up(&file->mutex);
 
-       spin_lock_irq(&file->comp_file[0].lock);
-       list_for_each_entry_safe(evt, tmp, &uobj->comp_list, obj_list) {
-               list_del(&evt->list);
-               kfree(evt);
-       }
-       spin_unlock_irq(&file->comp_file[0].lock);
-
-       spin_lock_irq(&file->async_file.lock);
-       list_for_each_entry_safe(evt, tmp, &uobj->async_list, obj_list) {
-               list_del(&evt->list);
-               kfree(evt);
-       }
-       spin_unlock_irq(&file->async_file.lock);
+       ib_uverbs_release_ucq(file, ev_file, uobj);
 
        resp.comp_events_reported  = uobj->comp_events_reported;
        resp.async_events_reported = uobj->async_events_reported;
@@ -859,24 +909,22 @@ retry:
 
        resp.qp_handle = uobj->uobject.id;
 
-       down(&file->mutex);
-       list_add_tail(&uobj->uobject.list, &file->ucontext->qp_list);
-       up(&file->mutex);
-
        if (copy_to_user((void __user *) (unsigned long) cmd.response,
                         &resp, sizeof resp)) {
                ret = -EFAULT;
-               goto err_list;
+               goto err_idr;
        }
 
+       down(&file->mutex);
+       list_add_tail(&uobj->uobject.list, &file->ucontext->qp_list);
+       up(&file->mutex);
+
        up(&ib_uverbs_idr_mutex);
 
        return in_len;
 
-err_list:
-       down(&file->mutex);
-       list_del(&uobj->uobject.list);
-       up(&file->mutex);
+err_idr:
+       idr_remove(&ib_uverbs_qp_idr, uobj->uobject.id);
 
 err_destroy:
        ib_destroy_qp(qp);
@@ -979,7 +1027,6 @@ ssize_t ib_uverbs_destroy_qp(struct ib_uverbs_file *file,
        struct ib_uverbs_destroy_qp_resp resp;
        struct ib_qp                    *qp;
        struct ib_uevent_object         *uobj;
-       struct ib_uverbs_event          *evt, *tmp;
        int                              ret = -EINVAL;
 
        if (copy_from_user(&cmd, buf, sizeof cmd))
@@ -1005,12 +1052,7 @@ ssize_t ib_uverbs_destroy_qp(struct ib_uverbs_file *file,
        list_del(&uobj->uobject.list);
        up(&file->mutex);
 
-       spin_lock_irq(&file->async_file.lock);
-       list_for_each_entry_safe(evt, tmp, &uobj->event_list, obj_list) {
-               list_del(&evt->list);
-               kfree(evt);
-       }
-       spin_unlock_irq(&file->async_file.lock);
+       ib_uverbs_release_uevent(file, uobj);
 
        resp.events_reported = uobj->events_reported;
 
@@ -1026,6 +1068,468 @@ out:
        return ret ? ret : in_len;
 }
 
+ssize_t ib_uverbs_post_send(struct ib_uverbs_file *file,
+                            const char __user *buf, int in_len,
+                            int out_len)
+{
+       struct ib_uverbs_post_send      cmd;
+       struct ib_uverbs_post_send_resp resp;
+       struct ib_uverbs_send_wr       *user_wr;
+       struct ib_send_wr              *wr = NULL, *last, *next, *bad_wr;
+       struct ib_qp                   *qp;
+       int                             i, sg_ind;
+       ssize_t                         ret = -EINVAL;
+
+       if (copy_from_user(&cmd, buf, sizeof cmd))
+               return -EFAULT;
+
+       if (in_len < sizeof cmd + cmd.wqe_size * cmd.wr_count +
+           cmd.sge_count * sizeof (struct ib_uverbs_sge))
+               return -EINVAL;
+
+       if (cmd.wqe_size < sizeof (struct ib_uverbs_send_wr))
+               return -EINVAL;
+
+       user_wr = kmalloc(cmd.wqe_size, GFP_KERNEL);
+       if (!user_wr)
+               return -ENOMEM;
+
+       down(&ib_uverbs_idr_mutex);
+
+       qp = idr_find(&ib_uverbs_qp_idr, cmd.qp_handle);
+       if (!qp || qp->uobject->context != file->ucontext)
+               goto out;
+
+       sg_ind = 0;
+       last = NULL;
+       for (i = 0; i < cmd.wr_count; ++i) {
+               if (copy_from_user(user_wr,
+                                  buf + sizeof cmd + i * cmd.wqe_size,
+                                  cmd.wqe_size)) {
+                       ret = -EFAULT;
+                       goto out;
+               }
+
+               if (user_wr->num_sge + sg_ind > cmd.sge_count) {
+                       ret = -EINVAL;
+                       goto out;
+               }
+
+               next = kmalloc(ALIGN(sizeof *next, sizeof (struct ib_sge)) +
+                              user_wr->num_sge * sizeof (struct ib_sge),
+                              GFP_KERNEL);
+               if (!next) {
+                       ret = -ENOMEM;
+                       goto out;
+               }
+
+               if (!last)
+                       wr = next;
+               else
+                       last->next = next;
+               last = next;
+
+               next->next       = NULL;
+               next->wr_id      = user_wr->wr_id;
+               next->num_sge    = user_wr->num_sge;
+               next->opcode     = user_wr->opcode;
+               next->send_flags = user_wr->send_flags;
+               next->imm_data   = user_wr->imm_data;
+
+               if (qp->qp_type == IB_QPT_UD) {
+                       next->wr.ud.ah = idr_find(&ib_uverbs_ah_idr,
+                                                 user_wr->wr.ud.ah);
+                       if (!next->wr.ud.ah) {
+                               ret = -EINVAL;
+                               goto out;
+                       }
+                       next->wr.ud.remote_qpn  = user_wr->wr.ud.remote_qpn;
+                       next->wr.ud.remote_qkey = user_wr->wr.ud.remote_qkey;
+               } else {
+                       switch (next->opcode) {
+                       case IB_WR_RDMA_WRITE:
+                       case IB_WR_RDMA_WRITE_WITH_IMM:
+                       case IB_WR_RDMA_READ:
+                               next->wr.rdma.remote_addr =
+                                       user_wr->wr.rdma.remote_addr;
+                               next->wr.rdma.rkey        =
+                                       user_wr->wr.rdma.rkey;
+                               break;
+                       case IB_WR_ATOMIC_CMP_AND_SWP:
+                       case IB_WR_ATOMIC_FETCH_AND_ADD:
+                               next->wr.atomic.remote_addr =
+                                       user_wr->wr.atomic.remote_addr;
+                               next->wr.atomic.compare_add =
+                                       user_wr->wr.atomic.compare_add;
+                               next->wr.atomic.swap = user_wr->wr.atomic.swap;
+                               next->wr.atomic.rkey = user_wr->wr.atomic.rkey;
+                               break;
+                       default:
+                               break;
+                       }
+               }
+
+               if (next->num_sge) {
+                       next->sg_list = (void *) next +
+                               ALIGN(sizeof *next, sizeof (struct ib_sge));
+                       if (copy_from_user(next->sg_list,
+                                          buf + sizeof cmd +
+                                          cmd.wr_count * cmd.wqe_size +
+                                          sg_ind * sizeof (struct ib_sge),
+                                          next->num_sge * sizeof (struct ib_sge))) {
+                               ret = -EFAULT;
+                               goto out;
+                       }
+                       sg_ind += next->num_sge;
+               } else
+                       next->sg_list = NULL;
+       }
+
+       resp.bad_wr = 0;
+       ret = qp->device->post_send(qp, wr, &bad_wr);
+       if (ret)
+               for (next = wr; next; next = next->next) {
+                       ++resp.bad_wr;
+                       if (next == bad_wr)
+                               break;
+               }
+
+       if (copy_to_user((void __user *) (unsigned long) cmd.response,
+                        &resp, sizeof resp))
+               ret = -EFAULT;
+
+out:
+       up(&ib_uverbs_idr_mutex);
+
+       while (wr) {
+               next = wr->next;
+               kfree(wr);
+               wr = next;
+       }
+
+       kfree(user_wr);
+
+       return ret ? ret : in_len;
+}
+
+static struct ib_recv_wr *ib_uverbs_unmarshall_recv(const char __user *buf,
+                                                   int in_len,
+                                                   u32 wr_count,
+                                                   u32 sge_count,
+                                                   u32 wqe_size)
+{
+       struct ib_uverbs_recv_wr *user_wr;
+       struct ib_recv_wr        *wr = NULL, *last, *next;
+       int                       sg_ind;
+       int                       i;
+       int                       ret;
+
+       if (in_len < wqe_size * wr_count +
+           sge_count * sizeof (struct ib_uverbs_sge))
+               return ERR_PTR(-EINVAL);
+
+       if (wqe_size < sizeof (struct ib_uverbs_recv_wr))
+               return ERR_PTR(-EINVAL);
+
+       user_wr = kmalloc(wqe_size, GFP_KERNEL);
+       if (!user_wr)
+               return ERR_PTR(-ENOMEM);
+
+       sg_ind = 0;
+       last = NULL;
+       for (i = 0; i < wr_count; ++i) {
+               if (copy_from_user(user_wr, buf + i * wqe_size,
+                                  wqe_size)) {
+                       ret = -EFAULT;
+                       goto err;
+               }
+
+               if (user_wr->num_sge + sg_ind > sge_count) {
+                       ret = -EINVAL;
+                       goto err;
+               }
+
+               next = kmalloc(ALIGN(sizeof *next, sizeof (struct ib_sge)) +
+                              user_wr->num_sge * sizeof (struct ib_sge),
+                              GFP_KERNEL);
+               if (!next) {
+                       ret = -ENOMEM;
+                       goto err;
+               }
+
+               if (!last)
+                       wr = next;
+               else
+                       last->next = next;
+               last = next;
+
+               next->next       = NULL;
+               next->wr_id      = user_wr->wr_id;
+               next->num_sge    = user_wr->num_sge;
+
+               if (next->num_sge) {
+                       next->sg_list = (void *) next +
+                               ALIGN(sizeof *next, sizeof (struct ib_sge));
+                       if (copy_from_user(next->sg_list,
+                                          buf + wr_count * wqe_size +
+                                          sg_ind * sizeof (struct ib_sge),
+                                          next->num_sge * sizeof (struct ib_sge))) {
+                               ret = -EFAULT;
+                               goto err;
+                       }
+                       sg_ind += next->num_sge;
+               } else
+                       next->sg_list = NULL;
+       }
+
+       kfree(user_wr);
+       return wr;
+
+err:
+       kfree(user_wr);
+
+       while (wr) {
+               next = wr->next;
+               kfree(wr);
+               wr = next;
+       }
+
+       return ERR_PTR(ret);
+}
+
+ssize_t ib_uverbs_post_recv(struct ib_uverbs_file *file,
+                            const char __user *buf, int in_len,
+                            int out_len)
+{
+       struct ib_uverbs_post_recv      cmd;
+       struct ib_uverbs_post_recv_resp resp;
+       struct ib_recv_wr              *wr, *next, *bad_wr;
+       struct ib_qp                   *qp;
+       ssize_t                         ret = -EINVAL;
+
+       if (copy_from_user(&cmd, buf, sizeof cmd))
+               return -EFAULT;
+
+       wr = ib_uverbs_unmarshall_recv(buf + sizeof cmd,
+                                      in_len - sizeof cmd, cmd.wr_count,
+                                      cmd.sge_count, cmd.wqe_size);
+       if (IS_ERR(wr))
+               return PTR_ERR(wr);
+
+       down(&ib_uverbs_idr_mutex);
+
+       qp = idr_find(&ib_uverbs_qp_idr, cmd.qp_handle);
+       if (!qp || qp->uobject->context != file->ucontext)
+               goto out;
+
+       resp.bad_wr = 0;
+       ret = qp->device->post_recv(qp, wr, &bad_wr);
+       if (ret)
+               for (next = wr; next; next = next->next) {
+                       ++resp.bad_wr;
+                       if (next == bad_wr)
+                               break;
+               }
+
+
+       if (copy_to_user((void __user *) (unsigned long) cmd.response,
+                        &resp, sizeof resp))
+               ret = -EFAULT;
+
+out:
+       up(&ib_uverbs_idr_mutex);
+
+       while (wr) {
+               next = wr->next;
+               kfree(wr);
+               wr = next;
+       }
+
+       return ret ? ret : in_len;
+}
+
+ssize_t ib_uverbs_post_srq_recv(struct ib_uverbs_file *file,
+                            const char __user *buf, int in_len,
+                            int out_len)
+{
+       struct ib_uverbs_post_srq_recv      cmd;
+       struct ib_uverbs_post_srq_recv_resp resp;
+       struct ib_recv_wr                  *wr, *next, *bad_wr;
+       struct ib_srq                      *srq;
+       ssize_t                             ret = -EINVAL;
+
+       if (copy_from_user(&cmd, buf, sizeof cmd))
+               return -EFAULT;
+
+       wr = ib_uverbs_unmarshall_recv(buf + sizeof cmd,
+                                      in_len - sizeof cmd, cmd.wr_count,
+                                      cmd.sge_count, cmd.wqe_size);
+       if (IS_ERR(wr))
+               return PTR_ERR(wr);
+
+       down(&ib_uverbs_idr_mutex);
+
+       srq = idr_find(&ib_uverbs_srq_idr, cmd.srq_handle);
+       if (!srq || srq->uobject->context != file->ucontext)
+               goto out;
+
+       resp.bad_wr = 0;
+       ret = srq->device->post_srq_recv(srq, wr, &bad_wr);
+       if (ret)
+               for (next = wr; next; next = next->next) {
+                       ++resp.bad_wr;
+                       if (next == bad_wr)
+                               break;
+               }
+
+
+       if (copy_to_user((void __user *) (unsigned long) cmd.response,
+                        &resp, sizeof resp))
+               ret = -EFAULT;
+
+out:
+       up(&ib_uverbs_idr_mutex);
+
+       while (wr) {
+               next = wr->next;
+               kfree(wr);
+               wr = next;
+       }
+
+       return ret ? ret : in_len;
+}
+
+ssize_t ib_uverbs_create_ah(struct ib_uverbs_file *file,
+                           const char __user *buf, int in_len,
+                           int out_len)
+{
+       struct ib_uverbs_create_ah       cmd;
+       struct ib_uverbs_create_ah_resp  resp;
+       struct ib_uobject               *uobj;
+       struct ib_pd                    *pd;
+       struct ib_ah                    *ah;
+       struct ib_ah_attr               attr;
+       int ret;
+
+       if (out_len < sizeof resp)
+               return -ENOSPC;
+
+       if (copy_from_user(&cmd, buf, sizeof cmd))
+               return -EFAULT;
+
+       uobj = kmalloc(sizeof *uobj, GFP_KERNEL);
+       if (!uobj)
+               return -ENOMEM;
+
+       down(&ib_uverbs_idr_mutex);
+
+       pd = idr_find(&ib_uverbs_pd_idr, cmd.pd_handle);
+       if (!pd || pd->uobject->context != file->ucontext) {
+               ret = -EINVAL;
+               goto err_up;
+       }
+
+       uobj->user_handle = cmd.user_handle;
+       uobj->context     = file->ucontext;
+
+       attr.dlid              = cmd.attr.dlid;
+       attr.sl                = cmd.attr.sl;
+       attr.src_path_bits     = cmd.attr.src_path_bits;
+       attr.static_rate       = cmd.attr.static_rate;
+       attr.port_num          = cmd.attr.port_num;
+       attr.grh.flow_label    = cmd.attr.grh.flow_label;
+       attr.grh.sgid_index    = cmd.attr.grh.sgid_index;
+       attr.grh.hop_limit     = cmd.attr.grh.hop_limit;
+       attr.grh.traffic_class = cmd.attr.grh.traffic_class;
+       memcpy(attr.grh.dgid.raw, cmd.attr.grh.dgid, 16);
+
+       ah = ib_create_ah(pd, &attr);
+       if (IS_ERR(ah)) {
+               ret = PTR_ERR(ah);
+               goto err_up;
+       }
+
+       ah->uobject = uobj;
+
+retry:
+       if (!idr_pre_get(&ib_uverbs_ah_idr, GFP_KERNEL)) {
+               ret = -ENOMEM;
+               goto err_destroy;
+       }
+
+       ret = idr_get_new(&ib_uverbs_ah_idr, ah, &uobj->id);
+
+       if (ret == -EAGAIN)
+               goto retry;
+       if (ret)
+               goto err_destroy;
+
+       resp.ah_handle = uobj->id;
+
+       if (copy_to_user((void __user *) (unsigned long) cmd.response,
+                        &resp, sizeof resp)) {
+               ret = -EFAULT;
+               goto err_idr;
+       }
+
+       down(&file->mutex);
+       list_add_tail(&uobj->list, &file->ucontext->ah_list);
+       up(&file->mutex);
+
+       up(&ib_uverbs_idr_mutex);
+
+       return in_len;
+
+err_idr:
+       idr_remove(&ib_uverbs_ah_idr, uobj->id);
+
+err_destroy:
+       ib_destroy_ah(ah);
+
+err_up:
+       up(&ib_uverbs_idr_mutex);
+
+       kfree(uobj);
+       return ret;
+}
+
+ssize_t ib_uverbs_destroy_ah(struct ib_uverbs_file *file,
+                            const char __user *buf, int in_len, int out_len)
+{
+       struct ib_uverbs_destroy_ah cmd;
+       struct ib_ah               *ah;
+       struct ib_uobject          *uobj;
+       int                         ret = -EINVAL;
+
+       if (copy_from_user(&cmd, buf, sizeof cmd))
+               return -EFAULT;
+
+       down(&ib_uverbs_idr_mutex);
+
+       ah = idr_find(&ib_uverbs_ah_idr, cmd.ah_handle);
+       if (!ah || ah->uobject->context != file->ucontext)
+               goto out;
+
+       uobj = ah->uobject;
+
+       ret = ib_destroy_ah(ah);
+       if (ret)
+               goto out;
+
+       idr_remove(&ib_uverbs_ah_idr, cmd.ah_handle);
+
+       down(&file->mutex);
+       list_del(&uobj->list);
+       up(&file->mutex);
+
+       kfree(uobj);
+
+out:
+       up(&ib_uverbs_idr_mutex);
+
+       return ret ? ret : in_len;
+}
+
 ssize_t ib_uverbs_attach_mcast(struct ib_uverbs_file *file,
                               const char __user *buf, int in_len,
                               int out_len)
@@ -1148,24 +1652,22 @@ retry:
 
        resp.srq_handle = uobj->uobject.id;
 
-       down(&file->mutex);
-       list_add_tail(&uobj->uobject.list, &file->ucontext->srq_list);
-       up(&file->mutex);
-
        if (copy_to_user((void __user *) (unsigned long) cmd.response,
                         &resp, sizeof resp)) {
                ret = -EFAULT;
-               goto err_list;
+               goto err_idr;
        }
 
+       down(&file->mutex);
+       list_add_tail(&uobj->uobject.list, &file->ucontext->srq_list);
+       up(&file->mutex);
+
        up(&ib_uverbs_idr_mutex);
 
        return in_len;
 
-err_list:
-       down(&file->mutex);
-       list_del(&uobj->uobject.list);
-       up(&file->mutex);
+err_idr:
+       idr_remove(&ib_uverbs_srq_idr, uobj->uobject.id);
 
 err_destroy:
        ib_destroy_srq(srq);
@@ -1217,7 +1719,6 @@ ssize_t ib_uverbs_destroy_srq(struct ib_uverbs_file *file,
        struct ib_uverbs_destroy_srq_resp resp;
        struct ib_srq                    *srq;
        struct ib_uevent_object          *uobj;
-       struct ib_uverbs_event           *evt, *tmp;
        int                               ret = -EINVAL;
 
        if (copy_from_user(&cmd, buf, sizeof cmd))
@@ -1243,12 +1744,7 @@ ssize_t ib_uverbs_destroy_srq(struct ib_uverbs_file *file,
        list_del(&uobj->uobject.list);
        up(&file->mutex);
 
-       spin_lock_irq(&file->async_file.lock);
-       list_for_each_entry_safe(evt, tmp, &uobj->event_list, obj_list) {
-               list_del(&evt->list);
-               kfree(evt);
-       }
-       spin_unlock_irq(&file->async_file.lock);
+       ib_uverbs_release_uevent(file, uobj);
 
        resp.events_reported = uobj->events_reported;
 
index 1251180..0eb38f4 100644 (file)
@@ -3,6 +3,7 @@
  * Copyright (c) 2005 Cisco Systems.  All rights reserved.
  * Copyright (c) 2005 Mellanox Technologies. All rights reserved.
  * Copyright (c) 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2005 PathScale, Inc. All rights reserved.
  *
  * This software is available to you under a choice of one of two
  * licenses.  You may choose to be licensed under the terms of the GNU
@@ -43,6 +44,7 @@
 #include <linux/poll.h>
 #include <linux/file.h>
 #include <linux/mount.h>
+#include <linux/cdev.h>
 
 #include <asm/uaccess.h>
 
@@ -62,6 +64,8 @@ enum {
 
 #define IB_UVERBS_BASE_DEV     MKDEV(IB_UVERBS_MAJOR, IB_UVERBS_BASE_MINOR)
 
+static struct class *uverbs_class;
+
 DECLARE_MUTEX(ib_uverbs_idr_mutex);
 DEFINE_IDR(ib_uverbs_pd_idr);
 DEFINE_IDR(ib_uverbs_mr_idr);
@@ -72,31 +76,37 @@ DEFINE_IDR(ib_uverbs_qp_idr);
 DEFINE_IDR(ib_uverbs_srq_idr);
 
 static spinlock_t map_lock;
+static struct ib_uverbs_device *dev_table[IB_UVERBS_MAX_DEVICES];
 static DECLARE_BITMAP(dev_map, IB_UVERBS_MAX_DEVICES);
 
 static ssize_t (*uverbs_cmd_table[])(struct ib_uverbs_file *file,
                                     const char __user *buf, int in_len,
                                     int out_len) = {
-       [IB_USER_VERBS_CMD_QUERY_PARAMS]  = ib_uverbs_query_params,
-       [IB_USER_VERBS_CMD_GET_CONTEXT]   = ib_uverbs_get_context,
-       [IB_USER_VERBS_CMD_QUERY_DEVICE]  = ib_uverbs_query_device,
-       [IB_USER_VERBS_CMD_QUERY_PORT]    = ib_uverbs_query_port,
-       [IB_USER_VERBS_CMD_QUERY_GID]     = ib_uverbs_query_gid,
-       [IB_USER_VERBS_CMD_QUERY_PKEY]    = ib_uverbs_query_pkey,
-       [IB_USER_VERBS_CMD_ALLOC_PD]      = ib_uverbs_alloc_pd,
-       [IB_USER_VERBS_CMD_DEALLOC_PD]    = ib_uverbs_dealloc_pd,
-       [IB_USER_VERBS_CMD_REG_MR]        = ib_uverbs_reg_mr,
-       [IB_USER_VERBS_CMD_DEREG_MR]      = ib_uverbs_dereg_mr,
-       [IB_USER_VERBS_CMD_CREATE_CQ]     = ib_uverbs_create_cq,
-       [IB_USER_VERBS_CMD_DESTROY_CQ]    = ib_uverbs_destroy_cq,
-       [IB_USER_VERBS_CMD_CREATE_QP]     = ib_uverbs_create_qp,
-       [IB_USER_VERBS_CMD_MODIFY_QP]     = ib_uverbs_modify_qp,
-       [IB_USER_VERBS_CMD_DESTROY_QP]    = ib_uverbs_destroy_qp,
-       [IB_USER_VERBS_CMD_ATTACH_MCAST]  = ib_uverbs_attach_mcast,
-       [IB_USER_VERBS_CMD_DETACH_MCAST]  = ib_uverbs_detach_mcast,
-       [IB_USER_VERBS_CMD_CREATE_SRQ]    = ib_uverbs_create_srq,
-       [IB_USER_VERBS_CMD_MODIFY_SRQ]    = ib_uverbs_modify_srq,
-       [IB_USER_VERBS_CMD_DESTROY_SRQ]   = ib_uverbs_destroy_srq,
+       [IB_USER_VERBS_CMD_GET_CONTEXT]         = ib_uverbs_get_context,
+       [IB_USER_VERBS_CMD_QUERY_DEVICE]        = ib_uverbs_query_device,
+       [IB_USER_VERBS_CMD_QUERY_PORT]          = ib_uverbs_query_port,
+       [IB_USER_VERBS_CMD_ALLOC_PD]            = ib_uverbs_alloc_pd,
+       [IB_USER_VERBS_CMD_DEALLOC_PD]          = ib_uverbs_dealloc_pd,
+       [IB_USER_VERBS_CMD_REG_MR]              = ib_uverbs_reg_mr,
+       [IB_USER_VERBS_CMD_DEREG_MR]            = ib_uverbs_dereg_mr,
+       [IB_USER_VERBS_CMD_CREATE_COMP_CHANNEL] = ib_uverbs_create_comp_channel,
+       [IB_USER_VERBS_CMD_CREATE_CQ]           = ib_uverbs_create_cq,
+       [IB_USER_VERBS_CMD_POLL_CQ]             = ib_uverbs_poll_cq,
+       [IB_USER_VERBS_CMD_REQ_NOTIFY_CQ]       = ib_uverbs_req_notify_cq,
+       [IB_USER_VERBS_CMD_DESTROY_CQ]          = ib_uverbs_destroy_cq,
+       [IB_USER_VERBS_CMD_CREATE_QP]           = ib_uverbs_create_qp,
+       [IB_USER_VERBS_CMD_MODIFY_QP]           = ib_uverbs_modify_qp,
+       [IB_USER_VERBS_CMD_DESTROY_QP]          = ib_uverbs_destroy_qp,
+       [IB_USER_VERBS_CMD_POST_SEND]           = ib_uverbs_post_send,
+       [IB_USER_VERBS_CMD_POST_RECV]           = ib_uverbs_post_recv,
+       [IB_USER_VERBS_CMD_POST_SRQ_RECV]       = ib_uverbs_post_srq_recv,
+       [IB_USER_VERBS_CMD_CREATE_AH]           = ib_uverbs_create_ah,
+       [IB_USER_VERBS_CMD_DESTROY_AH]          = ib_uverbs_destroy_ah,
+       [IB_USER_VERBS_CMD_ATTACH_MCAST]        = ib_uverbs_attach_mcast,
+       [IB_USER_VERBS_CMD_DETACH_MCAST]        = ib_uverbs_detach_mcast,
+       [IB_USER_VERBS_CMD_CREATE_SRQ]          = ib_uverbs_create_srq,
+       [IB_USER_VERBS_CMD_MODIFY_SRQ]          = ib_uverbs_modify_srq,
+       [IB_USER_VERBS_CMD_DESTROY_SRQ]         = ib_uverbs_destroy_srq,
 };
 
 static struct vfsmount *uverbs_event_mnt;
@@ -104,7 +114,54 @@ static struct vfsmount *uverbs_event_mnt;
 static void ib_uverbs_add_one(struct ib_device *device);
 static void ib_uverbs_remove_one(struct ib_device *device);
 
-static int ib_dealloc_ucontext(struct ib_ucontext *context)
+static void ib_uverbs_release_dev(struct kref *ref)
+{
+       struct ib_uverbs_device *dev =
+               container_of(ref, struct ib_uverbs_device, ref);
+
+       kfree(dev);
+}
+
+void ib_uverbs_release_ucq(struct ib_uverbs_file *file,
+                         struct ib_uverbs_event_file *ev_file,
+                         struct ib_ucq_object *uobj)
+{
+       struct ib_uverbs_event *evt, *tmp;
+
+       if (ev_file) {
+               spin_lock_irq(&ev_file->lock);
+               list_for_each_entry_safe(evt, tmp, &uobj->comp_list, obj_list) {
+                       list_del(&evt->list);
+                       kfree(evt);
+               }
+               spin_unlock_irq(&ev_file->lock);
+
+               kref_put(&ev_file->ref, ib_uverbs_release_event_file);
+       }
+
+       spin_lock_irq(&file->async_file->lock);
+       list_for_each_entry_safe(evt, tmp, &uobj->async_list, obj_list) {
+               list_del(&evt->list);
+               kfree(evt);
+       }
+       spin_unlock_irq(&file->async_file->lock);
+}
+
+void ib_uverbs_release_uevent(struct ib_uverbs_file *file,
+                             struct ib_uevent_object *uobj)
+{
+       struct ib_uverbs_event *evt, *tmp;
+
+       spin_lock_irq(&file->async_file->lock);
+       list_for_each_entry_safe(evt, tmp, &uobj->event_list, obj_list) {
+               list_del(&evt->list);
+               kfree(evt);
+       }
+       spin_unlock_irq(&file->async_file->lock);
+}
+
+static int ib_uverbs_cleanup_ucontext(struct ib_uverbs_file *file,
+                                     struct ib_ucontext *context)
 {
        struct ib_uobject *uobj, *tmp;
 
@@ -113,30 +170,46 @@ static int ib_dealloc_ucontext(struct ib_ucontext *context)
 
        down(&ib_uverbs_idr_mutex);
 
-       /* XXX Free AHs */
+       list_for_each_entry_safe(uobj, tmp, &context->ah_list, list) {
+               struct ib_ah *ah = idr_find(&ib_uverbs_ah_idr, uobj->id);
+               idr_remove(&ib_uverbs_ah_idr, uobj->id);
+               ib_destroy_ah(ah);
+               list_del(&uobj->list);
+               kfree(uobj);
+       }
 
        list_for_each_entry_safe(uobj, tmp, &context->qp_list, list) {
                struct ib_qp *qp = idr_find(&ib_uverbs_qp_idr, uobj->id);
+               struct ib_uevent_object *uevent =
+                       container_of(uobj, struct ib_uevent_object, uobject);
                idr_remove(&ib_uverbs_qp_idr, uobj->id);
                ib_destroy_qp(qp);
                list_del(&uobj->list);
-               kfree(container_of(uobj, struct ib_uevent_object, uobject));
+               ib_uverbs_release_uevent(file, uevent);
+               kfree(uevent);
        }
 
        list_for_each_entry_safe(uobj, tmp, &context->cq_list, list) {
                struct ib_cq *cq = idr_find(&ib_uverbs_cq_idr, uobj->id);
+               struct ib_uverbs_event_file *ev_file = cq->cq_context;
+               struct ib_ucq_object *ucq =
+                       container_of(uobj, struct ib_ucq_object, uobject);
                idr_remove(&ib_uverbs_cq_idr, uobj->id);
                ib_destroy_cq(cq);
                list_del(&uobj->list);
-               kfree(container_of(uobj, struct ib_ucq_object, uobject));
+               ib_uverbs_release_ucq(file, ev_file, ucq);
+               kfree(ucq);
        }
 
        list_for_each_entry_safe(uobj, tmp, &context->srq_list, list) {
                struct ib_srq *srq = idr_find(&ib_uverbs_srq_idr, uobj->id);
+               struct ib_uevent_object *uevent =
+                       container_of(uobj, struct ib_uevent_object, uobject);
                idr_remove(&ib_uverbs_srq_idr, uobj->id);
                ib_destroy_srq(srq);
                list_del(&uobj->list);
-               kfree(container_of(uobj, struct ib_uevent_object, uobject));
+               ib_uverbs_release_uevent(file, uevent);
+               kfree(uevent);
        }
 
        /* XXX Free MWs */
@@ -175,6 +248,8 @@ static void ib_uverbs_release_file(struct kref *ref)
                container_of(ref, struct ib_uverbs_file, ref);
 
        module_put(file->device->ib_dev->owner);
+       kref_put(&file->device->ref, ib_uverbs_release_dev);
+
        kfree(file);
 }
 
@@ -188,25 +263,19 @@ static ssize_t ib_uverbs_event_read(struct file *filp, char __user *buf,
 
        spin_lock_irq(&file->lock);
 
-       while (list_empty(&file->event_list) && file->fd >= 0) {
+       while (list_empty(&file->event_list)) {
                spin_unlock_irq(&file->lock);
 
                if (filp->f_flags & O_NONBLOCK)
                        return -EAGAIN;
 
                if (wait_event_interruptible(file->poll_wait,
-                                            !list_empty(&file->event_list) ||
-                                            file->fd < 0))
+                                            !list_empty(&file->event_list)))
                        return -ERESTARTSYS;
 
                spin_lock_irq(&file->lock);
        }
 
-       if (file->fd < 0) {
-               spin_unlock_irq(&file->lock);
-               return -ENODEV;
-       }
-
        event = list_entry(file->event_list.next, struct ib_uverbs_event, list);
 
        if (file->is_async)
@@ -248,26 +317,19 @@ static unsigned int ib_uverbs_event_poll(struct file *filp,
        poll_wait(filp, &file->poll_wait, wait);
 
        spin_lock_irq(&file->lock);
-       if (file->fd < 0)
-               pollflags = POLLERR;
-       else if (!list_empty(&file->event_list))
+       if (!list_empty(&file->event_list))
                pollflags = POLLIN | POLLRDNORM;
        spin_unlock_irq(&file->lock);
 
        return pollflags;
 }
 
-static void ib_uverbs_event_release(struct ib_uverbs_event_file *file)
+void ib_uverbs_release_event_file(struct kref *ref)
 {
-       struct ib_uverbs_event *entry, *tmp;
+       struct ib_uverbs_event_file *file =
+               container_of(ref, struct ib_uverbs_event_file, ref);
 
-       spin_lock_irq(&file->lock);
-       if (file->fd != -1) {
-               file->fd = -1;
-               list_for_each_entry_safe(entry, tmp, &file->event_list, list)
-                       kfree(entry);
-       }
-       spin_unlock_irq(&file->lock);
+       kfree(file);
 }
 
 static int ib_uverbs_event_fasync(int fd, struct file *filp, int on)
@@ -280,21 +342,30 @@ static int ib_uverbs_event_fasync(int fd, struct file *filp, int on)
 static int ib_uverbs_event_close(struct inode *inode, struct file *filp)
 {
        struct ib_uverbs_event_file *file = filp->private_data;
+       struct ib_uverbs_event *entry, *tmp;
+
+       spin_lock_irq(&file->lock);
+       file->file = NULL;
+       list_for_each_entry_safe(entry, tmp, &file->event_list, list) {
+               if (entry->counter)
+                       list_del(&entry->obj_list);
+               kfree(entry);
+       }
+       spin_unlock_irq(&file->lock);
 
-       ib_uverbs_event_release(file);
        ib_uverbs_event_fasync(-1, filp, 0);
-       kref_put(&file->uverbs_file->ref, ib_uverbs_release_file);
+
+       if (file->is_async) {
+               ib_unregister_event_handler(&file->uverbs_file->event_handler);
+               kref_put(&file->uverbs_file->ref, ib_uverbs_release_file);
+       }
+       kref_put(&file->ref, ib_uverbs_release_event_file);
 
        return 0;
 }
 
 static struct file_operations uverbs_event_fops = {
-       /*
-        * No .owner field since we artificially create event files,
-        * so there is no increment to the module reference count in
-        * the open path.  All event files come from a uverbs command
-        * file, which already takes a module reference, so this is OK.
-        */
+       .owner   = THIS_MODULE,
        .read    = ib_uverbs_event_read,
        .poll    = ib_uverbs_event_poll,
        .release = ib_uverbs_event_close,
@@ -303,27 +374,37 @@ static struct file_operations uverbs_event_fops = {
 
 void ib_uverbs_comp_handler(struct ib_cq *cq, void *cq_context)
 {
-       struct ib_uverbs_file  *file = cq_context;
-       struct ib_ucq_object   *uobj;
-       struct ib_uverbs_event *entry;
-       unsigned long           flags;
+       struct ib_uverbs_event_file    *file = cq_context;
+       struct ib_ucq_object           *uobj;
+       struct ib_uverbs_event         *entry;
+       unsigned long                   flags;
+
+       if (!file)
+               return;
+
+       spin_lock_irqsave(&file->lock, flags);
+       if (!file->file) {
+               spin_unlock_irqrestore(&file->lock, flags);
+               return;
+       }
 
        entry = kmalloc(sizeof *entry, GFP_ATOMIC);
-       if (!entry)
+       if (!entry) {
+               spin_unlock_irqrestore(&file->lock, flags);
                return;
+       }
 
        uobj = container_of(cq->uobject, struct ib_ucq_object, uobject);
 
        entry->desc.comp.cq_handle = cq->uobject->user_handle;
        entry->counter             = &uobj->comp_events_reported;
 
-       spin_lock_irqsave(&file->comp_file[0].lock, flags);
-       list_add_tail(&entry->list, &file->comp_file[0].event_list);
+       list_add_tail(&entry->list, &file->event_list);
        list_add_tail(&entry->obj_list, &uobj->comp_list);
-       spin_unlock_irqrestore(&file->comp_file[0].lock, flags);
+       spin_unlock_irqrestore(&file->lock, flags);
 
-       wake_up_interruptible(&file->comp_file[0].poll_wait);
-       kill_fasync(&file->comp_file[0].async_queue, SIGIO, POLL_IN);
+       wake_up_interruptible(&file->poll_wait);
+       kill_fasync(&file->async_queue, SIGIO, POLL_IN);
 }
 
 static void ib_uverbs_async_handler(struct ib_uverbs_file *file,
@@ -334,32 +415,40 @@ static void ib_uverbs_async_handler(struct ib_uverbs_file *file,
        struct ib_uverbs_event *entry;
        unsigned long flags;
 
+       spin_lock_irqsave(&file->async_file->lock, flags);
+       if (!file->async_file->file) {
+               spin_unlock_irqrestore(&file->async_file->lock, flags);
+               return;
+       }
+
        entry = kmalloc(sizeof *entry, GFP_ATOMIC);
-       if (!entry)
+       if (!entry) {
+               spin_unlock_irqrestore(&file->async_file->lock, flags);
                return;
+       }
 
        entry->desc.async.element    = element;
        entry->desc.async.event_type = event;
        entry->counter               = counter;
 
-       spin_lock_irqsave(&file->async_file.lock, flags);
-       list_add_tail(&entry->list, &file->async_file.event_list);
+       list_add_tail(&entry->list, &file->async_file->event_list);
        if (obj_list)
                list_add_tail(&entry->obj_list, obj_list);
-       spin_unlock_irqrestore(&file->async_file.lock, flags);
+       spin_unlock_irqrestore(&file->async_file->lock, flags);
 
-       wake_up_interruptible(&file->async_file.poll_wait);
-       kill_fasync(&file->async_file.async_queue, SIGIO, POLL_IN);
+       wake_up_interruptible(&file->async_file->poll_wait);
+       kill_fasync(&file->async_file->async_queue, SIGIO, POLL_IN);
 }
 
 void ib_uverbs_cq_event_handler(struct ib_event *event, void *context_ptr)
 {
+       struct ib_uverbs_event_file *ev_file = context_ptr;
        struct ib_ucq_object *uobj;
 
        uobj = container_of(event->element.cq->uobject,
                            struct ib_ucq_object, uobject);
 
-       ib_uverbs_async_handler(context_ptr, uobj->uobject.user_handle,
+       ib_uverbs_async_handler(ev_file->uverbs_file, uobj->uobject.user_handle,
                                event->event, &uobj->async_list,
                                &uobj->async_events_reported);
                                
@@ -389,8 +478,8 @@ void ib_uverbs_srq_event_handler(struct ib_event *event, void *context_ptr)
                                &uobj->events_reported);
 }
 
-static void ib_uverbs_event_handler(struct ib_event_handler *handler,
-                                   struct ib_event *event)
+void ib_uverbs_event_handler(struct ib_event_handler *handler,
+                            struct ib_event *event)
 {
        struct ib_uverbs_file *file =
                container_of(handler, struct ib_uverbs_file, event_handler);
@@ -399,38 +488,90 @@ static void ib_uverbs_event_handler(struct ib_event_handler *handler,
                                NULL, NULL);
 }
 
-static int ib_uverbs_event_init(struct ib_uverbs_event_file *file,
-                               struct ib_uverbs_file *uverbs_file)
+struct file *ib_uverbs_alloc_event_file(struct ib_uverbs_file *uverbs_file,
+                                       int is_async, int *fd)
 {
+       struct ib_uverbs_event_file *ev_file;
        struct file *filp;
+       int ret;
 
-       spin_lock_init(&file->lock);
-       INIT_LIST_HEAD(&file->event_list);
-       init_waitqueue_head(&file->poll_wait);
-       file->uverbs_file = uverbs_file;
-       file->async_queue = NULL;
-
-       file->fd = get_unused_fd();
-       if (file->fd < 0)
-               return file->fd;
+       ev_file = kmalloc(sizeof *ev_file, GFP_KERNEL);
+       if (!ev_file)
+               return ERR_PTR(-ENOMEM);
+
+       kref_init(&ev_file->ref);
+       spin_lock_init(&ev_file->lock);
+       INIT_LIST_HEAD(&ev_file->event_list);
+       init_waitqueue_head(&ev_file->poll_wait);
+       ev_file->uverbs_file = uverbs_file;
+       ev_file->async_queue = NULL;
+       ev_file->is_async    = is_async;
+
+       *fd = get_unused_fd();
+       if (*fd < 0) {
+               ret = *fd;
+               goto err;
+       }
 
        filp = get_empty_filp();
        if (!filp) {
-               put_unused_fd(file->fd);
-               return -ENFILE;
+               ret = -ENFILE;
+               goto err_fd;
        }
 
-       filp->f_op         = &uverbs_event_fops;
+       ev_file->file      = filp;
+
+       /*
+        * fops_get() can't fail here, because we're coming from a
+        * system call on a uverbs file, which will already have a
+        * module reference.
+        */
+       filp->f_op         = fops_get(&uverbs_event_fops);
        filp->f_vfsmnt     = mntget(uverbs_event_mnt);
        filp->f_dentry     = dget(uverbs_event_mnt->mnt_root);
        filp->f_mapping    = filp->f_dentry->d_inode->i_mapping;
        filp->f_flags      = O_RDONLY;
        filp->f_mode       = FMODE_READ;
-       filp->private_data = file;
+       filp->private_data = ev_file;
 
-       fd_install(file->fd, filp);
+       return filp;
 
-       return 0;
+err_fd:
+       put_unused_fd(*fd);
+
+err:
+       kfree(ev_file);
+       return ERR_PTR(ret);
+}
+
+/*
+ * Look up a completion event file by FD.  If lookup is successful,
+ * takes a ref to the event file struct that it returns; if
+ * unsuccessful, returns NULL.
+ */
+struct ib_uverbs_event_file *ib_uverbs_lookup_comp_file(int fd)
+{
+       struct ib_uverbs_event_file *ev_file = NULL;
+       struct file *filp;
+
+       filp = fget(fd);
+       if (!filp)
+               return NULL;
+
+       if (filp->f_op != &uverbs_event_fops)
+               goto out;
+
+       ev_file = filp->private_data;
+       if (ev_file->is_async) {
+               ev_file = NULL;
+               goto out;
+       }
+
+       kref_get(&ev_file->ref);
+
+out:
+       fput(filp);
+       return ev_file;
 }
 
 static ssize_t ib_uverbs_write(struct file *filp, const char __user *buf,
@@ -450,11 +591,11 @@ static ssize_t ib_uverbs_write(struct file *filp, const char __user *buf,
 
        if (hdr.command < 0                             ||
            hdr.command >= ARRAY_SIZE(uverbs_cmd_table) ||
-           !uverbs_cmd_table[hdr.command])
+           !uverbs_cmd_table[hdr.command]              ||
+           !(file->device->ib_dev->uverbs_cmd_mask & (1ull << hdr.command)))
                return -EINVAL;
 
-       if (!file->ucontext                               &&
-           hdr.command != IB_USER_VERBS_CMD_QUERY_PARAMS &&
+       if (!file->ucontext &&
            hdr.command != IB_USER_VERBS_CMD_GET_CONTEXT)
                return -EINVAL;
 
@@ -474,84 +615,57 @@ static int ib_uverbs_mmap(struct file *filp, struct vm_area_struct *vma)
 
 static int ib_uverbs_open(struct inode *inode, struct file *filp)
 {
-       struct ib_uverbs_device *dev =
-               container_of(inode->i_cdev, struct ib_uverbs_device, dev);
+       struct ib_uverbs_device *dev;
        struct ib_uverbs_file *file;
-       int i = 0;
        int ret;
 
-       if (!try_module_get(dev->ib_dev->owner))
-               return -ENODEV;
+       spin_lock(&map_lock);
+       dev = dev_table[iminor(inode) - IB_UVERBS_BASE_MINOR];
+       if (dev)
+               kref_get(&dev->ref);
+       spin_unlock(&map_lock);
+
+       if (!dev)
+               return -ENXIO;
+
+       if (!try_module_get(dev->ib_dev->owner)) {
+               ret = -ENODEV;
+               goto err;
+       }
 
-       file = kmalloc(sizeof *file +
-                      (dev->num_comp - 1) * sizeof (struct ib_uverbs_event_file),
-                      GFP_KERNEL);
+       file = kmalloc(sizeof *file, GFP_KERNEL);
        if (!file) {
                ret = -ENOMEM;
-               goto err;
+               goto err_module;
        }
 
-       file->device = dev;
+       file->device     = dev;
+       file->ucontext   = NULL;
+       file->async_file = NULL;
        kref_init(&file->ref);
        init_MUTEX(&file->mutex);
 
-       file->ucontext = NULL;
-
-       kref_get(&file->ref);
-       ret = ib_uverbs_event_init(&file->async_file, file);
-       if (ret)
-               goto err_kref;
-
-       file->async_file.is_async = 1;
-
-       for (i = 0; i < dev->num_comp; ++i) {
-               kref_get(&file->ref);
-               ret = ib_uverbs_event_init(&file->comp_file[i], file);
-               if (ret)
-                       goto err_async;
-               file->comp_file[i].is_async = 0;
-       }
-
-
        filp->private_data = file;
 
-       INIT_IB_EVENT_HANDLER(&file->event_handler, dev->ib_dev,
-                             ib_uverbs_event_handler);
-       if (ib_register_event_handler(&file->event_handler))
-               goto err_async;
-
        return 0;
 
-err_async:
-       while (i--)
-               ib_uverbs_event_release(&file->comp_file[i]);
-
-       ib_uverbs_event_release(&file->async_file);
-
-err_kref:
-       /*
-        * One extra kref_put() because we took a reference before the
-        * event file creation that failed and got us here.
-        */
-       kref_put(&file->ref, ib_uverbs_release_file);
-       kref_put(&file->ref, ib_uverbs_release_file);
+err_module:
+       module_put(dev->ib_dev->owner);
 
 err:
-       module_put(dev->ib_dev->owner);
+       kref_put(&dev->ref, ib_uverbs_release_dev);
+
        return ret;
 }
 
 static int ib_uverbs_close(struct inode *inode, struct file *filp)
 {
        struct ib_uverbs_file *file = filp->private_data;
-       int i;
 
-       ib_unregister_event_handler(&file->event_handler);
-       ib_uverbs_event_release(&file->async_file);
-       ib_dealloc_ucontext(file->ucontext);
+       ib_uverbs_cleanup_ucontext(file, file->ucontext);
 
-       for (i = 0; i < file->device->num_comp; ++i)
-               ib_uverbs_event_release(&file->comp_file[i]);
+       if (file->async_file)
+               kref_put(&file->async_file->ref, ib_uverbs_release_event_file);
 
        kref_put(&file->ref, ib_uverbs_release_file);
 
@@ -581,27 +695,25 @@ static struct ib_client uverbs_client = {
 
 static ssize_t show_ibdev(struct class_device *class_dev, char *buf)
 {
-       struct ib_uverbs_device *dev =
-               container_of(class_dev, struct ib_uverbs_device, class_dev);
+       struct ib_uverbs_device *dev = class_get_devdata(class_dev);
+
+       if (!dev)
+               return -ENODEV;
 
        return sprintf(buf, "%s\n", dev->ib_dev->name);
 }
 static CLASS_DEVICE_ATTR(ibdev, S_IRUGO, show_ibdev, NULL);
 
-static void ib_uverbs_release_class_dev(struct class_device *class_dev)
+static ssize_t show_dev_abi_version(struct class_device *class_dev, char *buf)
 {
-       struct ib_uverbs_device *dev =
-               container_of(class_dev, struct ib_uverbs_device, class_dev);
+       struct ib_uverbs_device *dev = class_get_devdata(class_dev);
 
-       cdev_del(&dev->dev);
-       clear_bit(dev->devnum, dev_map);
-       kfree(dev);
-}
+       if (!dev)
+               return -ENODEV;
 
-static struct class uverbs_class = {
-       .name    = "infiniband_verbs",
-       .release = ib_uverbs_release_class_dev
-};
+       return sprintf(buf, "%d\n", dev->ib_dev->uverbs_abi_ver);
+}
+static CLASS_DEVICE_ATTR(abi_version, S_IRUGO, show_dev_abi_version, NULL);
 
 static ssize_t show_abi_version(struct class *class, char *buf)
 {
@@ -622,6 +734,8 @@ static void ib_uverbs_add_one(struct ib_device *device)
 
        memset(uverbs_dev, 0, sizeof *uverbs_dev);
 
+       kref_init(&uverbs_dev->ref);
+
        spin_lock(&map_lock);
        uverbs_dev->devnum = find_first_zero_bit(dev_map, IB_UVERBS_MAX_DEVICES);
        if (uverbs_dev->devnum >= IB_UVERBS_MAX_DEVICES) {
@@ -631,41 +745,49 @@ static void ib_uverbs_add_one(struct ib_device *device)
        set_bit(uverbs_dev->devnum, dev_map);
        spin_unlock(&map_lock);
 
-       uverbs_dev->ib_dev   = device;
-       uverbs_dev->num_comp = 1;
+       uverbs_dev->ib_dev           = device;
+       uverbs_dev->num_comp_vectors = 1;
 
-       if (device->mmap)
-               cdev_init(&uverbs_dev->dev, &uverbs_mmap_fops);
-       else
-               cdev_init(&uverbs_dev->dev, &uverbs_fops);
-       uverbs_dev->dev.owner = THIS_MODULE;
-       kobject_set_name(&uverbs_dev->dev.kobj, "uverbs%d", uverbs_dev->devnum);
-       if (cdev_add(&uverbs_dev->dev, IB_UVERBS_BASE_DEV + uverbs_dev->devnum, 1))
+       uverbs_dev->dev = cdev_alloc();
+       if (!uverbs_dev->dev)
                goto err;
+       uverbs_dev->dev->owner = THIS_MODULE;
+       uverbs_dev->dev->ops = device->mmap ? &uverbs_mmap_fops : &uverbs_fops;
+       kobject_set_name(&uverbs_dev->dev->kobj, "uverbs%d", uverbs_dev->devnum);
+       if (cdev_add(uverbs_dev->dev, IB_UVERBS_BASE_DEV + uverbs_dev->devnum, 1))
+               goto err_cdev;
 
-       uverbs_dev->class_dev.class = &uverbs_class;
-       uverbs_dev->class_dev.dev   = device->dma_device;
-       uverbs_dev->class_dev.devt  = uverbs_dev->dev.dev;
-       snprintf(uverbs_dev->class_dev.class_id, BUS_ID_SIZE, "uverbs%d", uverbs_dev->devnum);
-       if (class_device_register(&uverbs_dev->class_dev))
+       uverbs_dev->class_dev = class_device_create(uverbs_class, NULL,
+                                                   uverbs_dev->dev->dev,
+                                                   device->dma_device,
+                                                   "uverbs%d", uverbs_dev->devnum);
+       if (IS_ERR(uverbs_dev->class_dev))
                goto err_cdev;
 
-       if (class_device_create_file(&uverbs_dev->class_dev, &class_device_attr_ibdev))
+       class_set_devdata(uverbs_dev->class_dev, uverbs_dev);
+
+       if (class_device_create_file(uverbs_dev->class_dev, &class_device_attr_ibdev))
                goto err_class;
+       if (class_device_create_file(uverbs_dev->class_dev, &class_device_attr_abi_version))
+               goto err_class;
+
+       spin_lock(&map_lock);
+       dev_table[uverbs_dev->devnum] = uverbs_dev;
+       spin_unlock(&map_lock);
 
        ib_set_client_data(device, &uverbs_client, uverbs_dev);
 
        return;
 
 err_class:
-       class_device_unregister(&uverbs_dev->class_dev);
+       class_device_destroy(uverbs_class, uverbs_dev->dev->dev);
 
 err_cdev:
-       cdev_del(&uverbs_dev->dev);
+       cdev_del(uverbs_dev->dev);
        clear_bit(uverbs_dev->devnum, dev_map);
 
 err:
-       kfree(uverbs_dev);
+       kref_put(&uverbs_dev->ref, ib_uverbs_release_dev);
        return;
 }
 
@@ -676,7 +798,16 @@ static void ib_uverbs_remove_one(struct ib_device *device)
        if (!uverbs_dev)
                return;
 
-       class_device_unregister(&uverbs_dev->class_dev);
+       class_set_devdata(uverbs_dev->class_dev, NULL);
+       class_device_destroy(uverbs_class, uverbs_dev->dev->dev);
+       cdev_del(uverbs_dev->dev);
+
+       spin_lock(&map_lock);
+       dev_table[uverbs_dev->devnum] = NULL;
+       spin_unlock(&map_lock);
+
+       clear_bit(uverbs_dev->devnum, dev_map);
+       kref_put(&uverbs_dev->ref, ib_uverbs_release_dev);
 }
 
 static struct super_block *uverbs_event_get_sb(struct file_system_type *fs_type, int flags,
@@ -706,13 +837,14 @@ static int __init ib_uverbs_init(void)
                goto out;
        }
 
-       ret = class_register(&uverbs_class);
-       if (ret) {
+       uverbs_class = class_create(THIS_MODULE, "infiniband_verbs");
+       if (IS_ERR(uverbs_class)) {
+               ret = PTR_ERR(uverbs_class);
                printk(KERN_ERR "user_verbs: couldn't create class infiniband_verbs\n");
                goto out_chrdev;
        }
 
-       ret = class_create_file(&uverbs_class, &class_attr_abi_version);
+       ret = class_create_file(uverbs_class, &class_attr_abi_version);
        if (ret) {
                printk(KERN_ERR "user_verbs: couldn't create abi_version attribute\n");
                goto out_class;
@@ -746,7 +878,7 @@ out_fs:
        unregister_filesystem(&uverbs_event_fs);
 
 out_class:
-       class_unregister(&uverbs_class);
+       class_destroy(uverbs_class);
 
 out_chrdev:
        unregister_chrdev_region(IB_UVERBS_BASE_DEV, IB_UVERBS_MAX_DEVICES);
@@ -760,8 +892,15 @@ static void __exit ib_uverbs_cleanup(void)
        ib_unregister_client(&uverbs_client);
        mntput(uverbs_event_mnt);
        unregister_filesystem(&uverbs_event_fs);
-       class_unregister(&uverbs_class);
+       class_destroy(uverbs_class);
        unregister_chrdev_region(IB_UVERBS_BASE_DEV, IB_UVERBS_MAX_DEVICES);
+       idr_destroy(&ib_uverbs_pd_idr);
+       idr_destroy(&ib_uverbs_mr_idr);
+       idr_destroy(&ib_uverbs_mw_idr);
+       idr_destroy(&ib_uverbs_ah_idr);
+       idr_destroy(&ib_uverbs_cq_idr);
+       idr_destroy(&ib_uverbs_qp_idr);
+       idr_destroy(&ib_uverbs_srq_idr);
 }
 
 module_init(ib_uverbs_init);
index 5081d90..72d3ef7 100644 (file)
@@ -523,16 +523,22 @@ EXPORT_SYMBOL(ib_dealloc_fmr);
 
 int ib_attach_mcast(struct ib_qp *qp, union ib_gid *gid, u16 lid)
 {
-       return qp->device->attach_mcast ?
-               qp->device->attach_mcast(qp, gid, lid) :
-               -ENOSYS;
+       if (!qp->device->attach_mcast)
+               return -ENOSYS;
+       if (gid->raw[0] != 0xff || qp->qp_type != IB_QPT_UD)
+               return -EINVAL;
+
+       return qp->device->attach_mcast(qp, gid, lid);
 }
 EXPORT_SYMBOL(ib_attach_mcast);
 
 int ib_detach_mcast(struct ib_qp *qp, union ib_gid *gid, u16 lid)
 {
-       return qp->device->detach_mcast ?
-               qp->device->detach_mcast(qp, gid, lid) :
-               -ENOSYS;
+       if (!qp->device->detach_mcast)
+               return -ENOSYS;
+       if (gid->raw[0] != 0xff || qp->qp_type != IB_QPT_UD)
+               return -EINVAL;
+
+       return qp->device->detach_mcast(qp, gid, lid);
 }
 EXPORT_SYMBOL(ib_detach_mcast);
index c44f7ba..47ec5a7 100644 (file)
@@ -7,4 +7,5 @@ obj-$(CONFIG_INFINIBAND_MTHCA) += ib_mthca.o
 ib_mthca-y :=  mthca_main.o mthca_cmd.o mthca_profile.o mthca_reset.o \
                mthca_allocator.o mthca_eq.o mthca_pd.o mthca_cq.o \
                mthca_mr.o mthca_qp.o mthca_av.o mthca_mcg.o mthca_mad.o \
-               mthca_provider.o mthca_memfree.o mthca_uar.o mthca_srq.o
+               mthca_provider.o mthca_memfree.o mthca_uar.o mthca_srq.o \
+               mthca_catas.o
diff --git a/drivers/infiniband/hw/mthca/mthca_catas.c b/drivers/infiniband/hw/mthca/mthca_catas.c
new file mode 100644 (file)
index 0000000..7ac52af
--- /dev/null
@@ -0,0 +1,153 @@
+/*
+ * Copyright (c) 2005 Cisco Systems.  All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id$
+ */
+
+#include "mthca_dev.h"
+
+enum {
+       MTHCA_CATAS_POLL_INTERVAL       = 5 * HZ,
+
+       MTHCA_CATAS_TYPE_INTERNAL       = 0,
+       MTHCA_CATAS_TYPE_UPLINK         = 3,
+       MTHCA_CATAS_TYPE_DDR            = 4,
+       MTHCA_CATAS_TYPE_PARITY         = 5,
+};
+
+static DEFINE_SPINLOCK(catas_lock);
+
+static void handle_catas(struct mthca_dev *dev)
+{
+       struct ib_event event;
+       const char *type;
+       int i;
+
+       event.device = &dev->ib_dev;
+       event.event  = IB_EVENT_DEVICE_FATAL;
+       event.element.port_num = 0;
+
+       ib_dispatch_event(&event);
+
+       switch (swab32(readl(dev->catas_err.map)) >> 24) {
+       case MTHCA_CATAS_TYPE_INTERNAL:
+               type = "internal error";
+               break;
+       case MTHCA_CATAS_TYPE_UPLINK:
+               type = "uplink bus error";
+               break;
+       case MTHCA_CATAS_TYPE_DDR:
+               type = "DDR data error";
+               break;
+       case MTHCA_CATAS_TYPE_PARITY:
+               type = "internal parity error";
+               break;
+       default:
+               type = "unknown error";
+               break;
+       }
+
+       mthca_err(dev, "Catastrophic error detected: %s\n", type);
+       for (i = 0; i < dev->catas_err.size; ++i)
+               mthca_err(dev, "  buf[%02x]: %08x\n",
+                         i, swab32(readl(dev->catas_err.map + i)));
+}
+
+static void poll_catas(unsigned long dev_ptr)
+{
+       struct mthca_dev *dev = (struct mthca_dev *) dev_ptr;
+       unsigned long flags;
+       int i;
+
+       for (i = 0; i < dev->catas_err.size; ++i)
+               if (readl(dev->catas_err.map + i)) {
+                       handle_catas(dev);
+                       return;
+               }
+
+       spin_lock_irqsave(&catas_lock, flags);
+       if (dev->catas_err.stop)
+               mod_timer(&dev->catas_err.timer,
+                         jiffies + MTHCA_CATAS_POLL_INTERVAL);
+       spin_unlock_irqrestore(&catas_lock, flags);
+
+       return;
+}
+
+void mthca_start_catas_poll(struct mthca_dev *dev)
+{
+       unsigned long addr;
+
+       init_timer(&dev->catas_err.timer);
+       dev->catas_err.stop = 0;
+       dev->catas_err.map  = NULL;
+
+       addr = pci_resource_start(dev->pdev, 0) +
+               ((pci_resource_len(dev->pdev, 0) - 1) &
+                dev->catas_err.addr);
+
+       if (!request_mem_region(addr, dev->catas_err.size * 4,
+                               DRV_NAME)) {
+               mthca_warn(dev, "couldn't request catastrophic error region "
+                          "at 0x%lx/0x%x\n", addr, dev->catas_err.size * 4);
+               return;
+       }
+
+       dev->catas_err.map = ioremap(addr, dev->catas_err.size * 4);
+       if (!dev->catas_err.map) {
+               mthca_warn(dev, "couldn't map catastrophic error region "
+                          "at 0x%lx/0x%x\n", addr, dev->catas_err.size * 4);
+               release_mem_region(addr, dev->catas_err.size * 4);
+               return;
+       }
+
+       dev->catas_err.timer.data     = (unsigned long) dev;
+       dev->catas_err.timer.function = poll_catas;
+       dev->catas_err.timer.expires  = jiffies + MTHCA_CATAS_POLL_INTERVAL;
+       add_timer(&dev->catas_err.timer);
+}
+
+void mthca_stop_catas_poll(struct mthca_dev *dev)
+{
+       spin_lock_irq(&catas_lock);
+       dev->catas_err.stop = 1;
+       spin_unlock_irq(&catas_lock);
+
+       del_timer_sync(&dev->catas_err.timer);
+
+       if (dev->catas_err.map) {
+               iounmap(dev->catas_err.map);
+               release_mem_region(pci_resource_start(dev->pdev, 0) +
+                                  ((pci_resource_len(dev->pdev, 0) - 1) &
+                                   dev->catas_err.addr),
+                                  dev->catas_err.size * 4);
+       }
+}
index 378646b..49f211d 100644 (file)
@@ -1,6 +1,7 @@
 /*
  * Copyright (c) 2004, 2005 Topspin Communications.  All rights reserved.
  * Copyright (c) 2005 Mellanox Technologies. All rights reserved.
+ * Copyright (c) 2005 Cisco Systems. All rights reserved.
  *
  * This software is available to you under a choice of one of two
  * licenses.  You may choose to be licensed under the terms of the GNU
@@ -706,9 +707,13 @@ int mthca_QUERY_FW(struct mthca_dev *dev, u8 *status)
 
        MTHCA_GET(lg, outbox, QUERY_FW_MAX_CMD_OFFSET);
        dev->cmd.max_cmds = 1 << lg;
+       MTHCA_GET(dev->catas_err.addr, outbox, QUERY_FW_ERR_START_OFFSET);
+       MTHCA_GET(dev->catas_err.size, outbox, QUERY_FW_ERR_SIZE_OFFSET);
 
        mthca_dbg(dev, "FW version %012llx, max commands %d\n",
                  (unsigned long long) dev->fw_ver, dev->cmd.max_cmds);
+       mthca_dbg(dev, "Catastrophic error buffer at 0x%llx, size 0x%x\n",
+                 (unsigned long long) dev->catas_err.addr, dev->catas_err.size);
 
        if (mthca_is_memfree(dev)) {
                MTHCA_GET(dev->fw.arbel.fw_pages,       outbox, QUERY_FW_SIZE_OFFSET);
@@ -933,9 +938,9 @@ int mthca_QUERY_DEV_LIM(struct mthca_dev *dev,
                goto out;
 
        MTHCA_GET(field, outbox, QUERY_DEV_LIM_MAX_SRQ_SZ_OFFSET);
-       dev_lim->max_srq_sz = 1 << field;
+       dev_lim->max_srq_sz = (1 << field) - 1;
        MTHCA_GET(field, outbox, QUERY_DEV_LIM_MAX_QP_SZ_OFFSET);
-       dev_lim->max_qp_sz = 1 << field;
+       dev_lim->max_qp_sz = (1 << field) - 1;
        MTHCA_GET(field, outbox, QUERY_DEV_LIM_RSVD_QP_OFFSET);
        dev_lim->reserved_qps = 1 << (field & 0xf);
        MTHCA_GET(field, outbox, QUERY_DEV_LIM_MAX_QP_OFFSET);
@@ -1045,6 +1050,8 @@ int mthca_QUERY_DEV_LIM(struct mthca_dev *dev,
                  dev_lim->max_pds, dev_lim->reserved_pds, dev_lim->reserved_uars);
        mthca_dbg(dev, "Max QP/MCG: %d, reserved MGMs: %d\n",
                  dev_lim->max_pds, dev_lim->reserved_mgms);
+       mthca_dbg(dev, "Max CQEs: %d, max WQEs: %d, max SRQ WQEs: %d\n",
+                 dev_lim->max_cq_sz, dev_lim->max_qp_sz, dev_lim->max_srq_sz);
 
        mthca_dbg(dev, "Flags: %08x\n", dev_lim->flags);
 
index 7bff5a8..7e68bd4 100644 (file)
@@ -83,6 +83,8 @@ enum {
        /* Arbel FW gives us these, but we need them for Tavor */
        MTHCA_MPT_ENTRY_SIZE  =  0x40,
        MTHCA_MTT_SEG_SIZE    =  0x40,
+
+       MTHCA_QP_PER_MGM      = 4 * (MTHCA_MGM_ENTRY_SIZE / 16 - 2)
 };
 
 enum {
@@ -128,12 +130,16 @@ struct mthca_limits {
        int      num_uars;
        int      max_sg;
        int      num_qps;
+       int      max_wqes;
+       int      max_qp_init_rdma;
        int      reserved_qps;
        int      num_srqs;
+       int      max_srq_wqes;
        int      reserved_srqs;
        int      num_eecs;
        int      reserved_eecs;
        int      num_cqs;
+       int      max_cqes;
        int      reserved_cqs;
        int      num_eqs;
        int      reserved_eqs;
@@ -148,6 +154,7 @@ struct mthca_limits {
        int      reserved_mcgs;
        int      num_pds;
        int      reserved_pds;
+       u32      flags;
        u8       port_width_cap;
 };
 
@@ -251,6 +258,14 @@ struct mthca_mcg_table {
        struct mthca_icm_table *table;
 };
 
+struct mthca_catas_err {
+       u64                     addr;
+       u32 __iomem            *map;
+       unsigned long           stop;
+       u32                     size;
+       struct timer_list       timer;
+};
+
 struct mthca_dev {
        struct ib_device  ib_dev;
        struct pci_dev   *pdev;
@@ -311,6 +326,8 @@ struct mthca_dev {
        struct mthca_av_table  av_table;
        struct mthca_mcg_table mcg_table;
 
+       struct mthca_catas_err catas_err;
+
        struct mthca_uar       driver_uar;
        struct mthca_db_table *db_tab;
        struct mthca_pd        driver_pd;
@@ -398,6 +415,9 @@ void mthca_cleanup_mcg_table(struct mthca_dev *dev);
 int mthca_register_device(struct mthca_dev *dev);
 void mthca_unregister_device(struct mthca_dev *dev);
 
+void mthca_start_catas_poll(struct mthca_dev *dev);
+void mthca_stop_catas_poll(struct mthca_dev *dev);
+
 int mthca_uar_alloc(struct mthca_dev *dev, struct mthca_uar *uar);
 void mthca_uar_free(struct mthca_dev *dev, struct mthca_uar *uar);
 
@@ -447,6 +467,8 @@ void mthca_cq_clean(struct mthca_dev *dev, u32 cqn, u32 qpn,
 int mthca_alloc_srq(struct mthca_dev *dev, struct mthca_pd *pd,
                    struct ib_srq_attr *attr, struct mthca_srq *srq);
 void mthca_free_srq(struct mthca_dev *dev, struct mthca_srq *srq);
+int mthca_modify_srq(struct ib_srq *ibsrq, struct ib_srq_attr *attr,
+                    enum ib_srq_attr_mask attr_mask);
 void mthca_srq_event(struct mthca_dev *dev, u32 srqn,
                     enum ib_event_type event_type);
 void mthca_free_srq_wqe(struct mthca_srq *srq, u32 wqe_addr);
index 8dfafda..e5a047a 100644 (file)
@@ -83,7 +83,8 @@ enum {
        MTHCA_EVENT_TYPE_PATH_MIG           = 0x01,
        MTHCA_EVENT_TYPE_COMM_EST           = 0x02,
        MTHCA_EVENT_TYPE_SQ_DRAINED         = 0x03,
-       MTHCA_EVENT_TYPE_SRQ_LAST_WQE       = 0x13,
+       MTHCA_EVENT_TYPE_SRQ_QP_LAST_WQE    = 0x13,
+       MTHCA_EVENT_TYPE_SRQ_LIMIT          = 0x14,
        MTHCA_EVENT_TYPE_CQ_ERROR           = 0x04,
        MTHCA_EVENT_TYPE_WQ_CATAS_ERROR     = 0x05,
        MTHCA_EVENT_TYPE_EEC_CATAS_ERROR    = 0x06,
@@ -110,8 +111,9 @@ enum {
                                (1ULL << MTHCA_EVENT_TYPE_LOCAL_CATAS_ERROR)  | \
                                (1ULL << MTHCA_EVENT_TYPE_PORT_CHANGE)        | \
                                (1ULL << MTHCA_EVENT_TYPE_ECC_DETECT))
-#define MTHCA_SRQ_EVENT_MASK    (1ULL << MTHCA_EVENT_TYPE_SRQ_CATAS_ERROR)    | \
-                               (1ULL << MTHCA_EVENT_TYPE_SRQ_LAST_WQE)
+#define MTHCA_SRQ_EVENT_MASK   ((1ULL << MTHCA_EVENT_TYPE_SRQ_CATAS_ERROR)    | \
+                               (1ULL << MTHCA_EVENT_TYPE_SRQ_QP_LAST_WQE)    | \
+                               (1ULL << MTHCA_EVENT_TYPE_SRQ_LIMIT))
 #define MTHCA_CMD_EVENT_MASK    (1ULL << MTHCA_EVENT_TYPE_CMD)
 
 #define MTHCA_EQ_DB_INC_CI     (1 << 24)
@@ -141,6 +143,9 @@ struct mthca_eqe {
                struct {
                        __be32 qpn;
                } __attribute__((packed)) qp;
+               struct {
+                       __be32 srqn;
+               } __attribute__((packed)) srq;
                struct {
                        __be32 cqn;
                        u32    reserved1;
@@ -305,6 +310,16 @@ static int mthca_eq_int(struct mthca_dev *dev, struct mthca_eq *eq)
                                       IB_EVENT_SQ_DRAINED);
                        break;
 
+               case MTHCA_EVENT_TYPE_SRQ_QP_LAST_WQE:
+                       mthca_qp_event(dev, be32_to_cpu(eqe->event.qp.qpn) & 0xffffff,
+                                      IB_EVENT_QP_LAST_WQE_REACHED);
+                       break;
+
+               case MTHCA_EVENT_TYPE_SRQ_LIMIT:
+                       mthca_srq_event(dev, be32_to_cpu(eqe->event.srq.srqn) & 0xffffff,
+                                       IB_EVENT_SRQ_LIMIT_REACHED);
+                       break;
+
                case MTHCA_EVENT_TYPE_WQ_CATAS_ERROR:
                        mthca_qp_event(dev, be32_to_cpu(eqe->event.qp.qpn) & 0xffffff,
                                       IB_EVENT_QP_FATAL);
index 9804174..8561b29 100644 (file)
@@ -46,11 +46,6 @@ enum {
        MTHCA_VENDOR_CLASS2 = 0xa
 };
 
-struct mthca_trap_mad {
-       struct ib_mad *mad;
-       DECLARE_PCI_UNMAP_ADDR(mapping)
-};
-
 static void update_sm_ah(struct mthca_dev *dev,
                         u8 port_num, u16 lid, u8 sl)
 {
@@ -116,49 +111,14 @@ static void forward_trap(struct mthca_dev *dev,
                         struct ib_mad *mad)
 {
        int qpn = mad->mad_hdr.mgmt_class != IB_MGMT_CLASS_SUBN_LID_ROUTED;
-       struct mthca_trap_mad *tmad;
-       struct ib_sge      gather_list;
-       struct ib_send_wr *bad_wr, wr = {
-               .opcode      = IB_WR_SEND,
-               .sg_list     = &gather_list,
-               .num_sge     = 1,
-               .send_flags  = IB_SEND_SIGNALED,
-               .wr          = {
-                        .ud = {
-                                .remote_qpn  = qpn,
-                                .remote_qkey = qpn ? IB_QP1_QKEY : 0,
-                                .timeout_ms  = 0
-                        }
-                }
-       };
+       struct ib_mad_send_buf *send_buf;
        struct ib_mad_agent *agent = dev->send_agent[port_num - 1][qpn];
        int ret;
        unsigned long flags;
 
        if (agent) {
-               tmad = kmalloc(sizeof *tmad, GFP_KERNEL);
-               if (!tmad)
-                       return;
-
-               tmad->mad = kmalloc(sizeof *tmad->mad, GFP_KERNEL);
-               if (!tmad->mad) {
-                       kfree(tmad);
-                       return;
-               }
-
-               memcpy(tmad->mad, mad, sizeof *mad);
-
-               wr.wr.ud.mad_hdr = &tmad->mad->mad_hdr;
-               wr.wr_id         = (unsigned long) tmad;
-
-               gather_list.addr   = dma_map_single(agent->device->dma_device,
-                                                   tmad->mad,
-                                                   sizeof *tmad->mad,
-                                                   DMA_TO_DEVICE);
-               gather_list.length = sizeof *tmad->mad;
-               gather_list.lkey   = to_mpd(agent->qp->pd)->ntmr.ibmr.lkey;
-               pci_unmap_addr_set(tmad, mapping, gather_list.addr);
-
+               send_buf = ib_create_send_mad(agent, qpn, 0, 0, IB_MGMT_MAD_HDR,
+                                             IB_MGMT_MAD_DATA, GFP_ATOMIC);
                /*
                 * We rely here on the fact that MLX QPs don't use the
                 * address handle after the send is posted (this is
@@ -166,21 +126,15 @@ static void forward_trap(struct mthca_dev *dev,
                 * it's OK for our devices).
                 */
                spin_lock_irqsave(&dev->sm_lock, flags);
-               wr.wr.ud.ah      = dev->sm_ah[port_num - 1];
-               if (wr.wr.ud.ah)
-                       ret = ib_post_send_mad(agent, &wr, &bad_wr);
+               memcpy(send_buf->mad, mad, sizeof *mad);
+               if ((send_buf->ah = dev->sm_ah[port_num - 1]))
+                       ret = ib_post_send_mad(send_buf, NULL);
                else
                        ret = -EINVAL;
                spin_unlock_irqrestore(&dev->sm_lock, flags);
 
-               if (ret) {
-                       dma_unmap_single(agent->device->dma_device,
-                                        pci_unmap_addr(tmad, mapping),
-                                        sizeof *tmad->mad,
-                                        DMA_TO_DEVICE);
-                       kfree(tmad->mad);
-                       kfree(tmad);
-               }
+               if (ret)
+                       ib_free_send_mad(send_buf);
        }
 }
 
@@ -267,15 +221,7 @@ int mthca_process_mad(struct ib_device *ibdev,
 static void send_handler(struct ib_mad_agent *agent,
                         struct ib_mad_send_wc *mad_send_wc)
 {
-       struct mthca_trap_mad *tmad =
-               (void *) (unsigned long) mad_send_wc->wr_id;
-
-       dma_unmap_single(agent->device->dma_device,
-                        pci_unmap_addr(tmad, mapping),
-                        sizeof *tmad->mad,
-                        DMA_TO_DEVICE);
-       kfree(tmad->mad);
-       kfree(tmad);
+       ib_free_send_mad(mad_send_wc->send_buf);
 }
 
 int mthca_create_agents(struct mthca_dev *dev)
index 23a3f56..883d1e5 100644 (file)
@@ -162,9 +162,18 @@ static int __devinit mthca_dev_lim(struct mthca_dev *mdev, struct mthca_dev_lim
        mdev->limits.pkey_table_len     = dev_lim->max_pkeys;
        mdev->limits.local_ca_ack_delay = dev_lim->local_ca_ack_delay;
        mdev->limits.max_sg             = dev_lim->max_sg;
+       mdev->limits.max_wqes           = dev_lim->max_qp_sz;
+       mdev->limits.max_qp_init_rdma   = dev_lim->max_requester_per_qp;
        mdev->limits.reserved_qps       = dev_lim->reserved_qps;
+       mdev->limits.max_srq_wqes       = dev_lim->max_srq_sz;
        mdev->limits.reserved_srqs      = dev_lim->reserved_srqs;
        mdev->limits.reserved_eecs      = dev_lim->reserved_eecs;
+       /*
+        * Subtract 1 from the limit because we need to allocate a
+        * spare CQE so the HCA HW can tell the difference between an
+        * empty CQ and a full CQ.
+        */
+       mdev->limits.max_cqes           = dev_lim->max_cq_sz - 1;
        mdev->limits.reserved_cqs       = dev_lim->reserved_cqs;
        mdev->limits.reserved_eqs       = dev_lim->reserved_eqs;
        mdev->limits.reserved_mtts      = dev_lim->reserved_mtts;
@@ -172,6 +181,7 @@ static int __devinit mthca_dev_lim(struct mthca_dev *mdev, struct mthca_dev_lim
        mdev->limits.reserved_uars      = dev_lim->reserved_uars;
        mdev->limits.reserved_pds       = dev_lim->reserved_pds;
        mdev->limits.port_width_cap     = dev_lim->max_port_width;
+       mdev->limits.flags              = dev_lim->flags;
 
        /* IB_DEVICE_RESIZE_MAX_WR not supported by driver.
           May be doable since hardware supports it for SRQ.
@@ -1186,6 +1196,7 @@ MODULE_DEVICE_TABLE(pci, mthca_pci_table);
 
 static struct pci_driver mthca_driver = {
        .name           = DRV_NAME,
+       .owner          = THIS_MODULE,
        .id_table       = mthca_pci_table,
        .probe          = mthca_init_one,
        .remove         = __devexit_p(mthca_remove_one)
index a270760..b47ea7d 100644 (file)
 #include "mthca_dev.h"
 #include "mthca_cmd.h"
 
-enum {
-       MTHCA_QP_PER_MGM = 4 * (MTHCA_MGM_ENTRY_SIZE / 16 - 2)
-};
-
 struct mthca_mgm {
        __be32 next_gid_index;
        u32    reserved[3];
@@ -189,7 +185,12 @@ int mthca_multicast_attach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid)
        }
 
        for (i = 0; i < MTHCA_QP_PER_MGM; ++i)
-               if (!(mgm->qp[i] & cpu_to_be32(1 << 31))) {
+               if (mgm->qp[i] == cpu_to_be32(ibqp->qp_num | (1 << 31))) {
+                       mthca_dbg(dev, "QP %06x already a member of MGM\n", 
+                                 ibqp->qp_num);
+                       err = 0;
+                       goto out;
+               } else if (!(mgm->qp[i] & cpu_to_be32(1 << 31))) {
                        mgm->qp[i] = cpu_to_be32(ibqp->qp_num | (1 << 31));
                        break;
                }
index 9ad8b3b..d72fe95 100644 (file)
@@ -487,7 +487,8 @@ void mthca_cleanup_user_db_tab(struct mthca_dev *dev, struct mthca_uar *uar,
        }
 }
 
-int mthca_alloc_db(struct mthca_dev *dev, int type, u32 qn, __be32 **db)
+int mthca_alloc_db(struct mthca_dev *dev, enum mthca_db_type type,
+                  u32 qn, __be32 **db)
 {
        int group;
        int start, end, dir;
index 29433f2..4fdca26 100644 (file)
@@ -173,7 +173,8 @@ void mthca_cleanup_user_db_tab(struct mthca_dev *dev, struct mthca_uar *uar,
 
 int mthca_init_db_tab(struct mthca_dev *dev);
 void mthca_cleanup_db_tab(struct mthca_dev *dev);
-int mthca_alloc_db(struct mthca_dev *dev, int type, u32 qn, __be32 **db);
+int mthca_alloc_db(struct mthca_dev *dev, enum mthca_db_type type,
+                  u32 qn, __be32 **db);
 void mthca_free_db(struct mthca_dev *dev, int type, int db_index);
 
 #endif /* MTHCA_MEMFREE_H */
index 3f5319a..1b9477e 100644 (file)
@@ -37,6 +37,7 @@
  */
 
 #include <rdma/ib_smi.h>
+#include <rdma/ib_user_verbs.h>
 #include <linux/mm.h>
 
 #include "mthca_dev.h"
@@ -90,15 +91,26 @@ static int mthca_query_device(struct ib_device *ibdev,
 
        props->max_mr_size         = ~0ull;
        props->max_qp              = mdev->limits.num_qps - mdev->limits.reserved_qps;
-       props->max_qp_wr           = 0xffff;
+       props->max_qp_wr           = mdev->limits.max_wqes;
        props->max_sge             = mdev->limits.max_sg;
        props->max_cq              = mdev->limits.num_cqs - mdev->limits.reserved_cqs;
-       props->max_cqe             = 0xffff;
+       props->max_cqe             = mdev->limits.max_cqes;
        props->max_mr              = mdev->limits.num_mpts - mdev->limits.reserved_mrws;
        props->max_pd              = mdev->limits.num_pds - mdev->limits.reserved_pds;
        props->max_qp_rd_atom      = 1 << mdev->qp_table.rdb_shift;
-       props->max_qp_init_rd_atom = 1 << mdev->qp_table.rdb_shift;
+       props->max_qp_init_rd_atom = mdev->limits.max_qp_init_rdma;
+       props->max_res_rd_atom     = props->max_qp_rd_atom * props->max_qp;
+       props->max_srq             = mdev->limits.num_srqs - mdev->limits.reserved_srqs;
+       props->max_srq_wr          = mdev->limits.max_srq_wqes;
+       props->max_srq_sge         = mdev->limits.max_sg;
        props->local_ca_ack_delay  = mdev->limits.local_ca_ack_delay;
+       props->atomic_cap          = mdev->limits.flags & DEV_LIM_FLAG_ATOMIC ? 
+                                       IB_ATOMIC_HCA : IB_ATOMIC_NONE;
+       props->max_pkeys           = mdev->limits.pkey_table_len;
+       props->max_mcast_grp       = mdev->limits.num_mgms + mdev->limits.num_amgms;
+       props->max_mcast_qp_attach = MTHCA_QP_PER_MGM;
+       props->max_total_mcast_qp_attach = props->max_mcast_qp_attach * 
+                                          props->max_mcast_grp;
 
        err = 0;
  out:
@@ -150,9 +162,13 @@ static int mthca_query_port(struct ib_device *ibdev,
        props->gid_tbl_len       = to_mdev(ibdev)->limits.gid_table_len;
        props->max_msg_sz        = 0x80000000;
        props->pkey_tbl_len      = to_mdev(ibdev)->limits.pkey_table_len;
+       props->bad_pkey_cntr     = be16_to_cpup((__be16 *) (out_mad->data + 46));
        props->qkey_viol_cntr    = be16_to_cpup((__be16 *) (out_mad->data + 48));
        props->active_width      = out_mad->data[31] & 0xf;
        props->active_speed      = out_mad->data[35] >> 4;
+       props->max_mtu           = out_mad->data[41] & 0xf;
+       props->active_mtu        = out_mad->data[36] >> 4;
+       props->subnet_timeout    = out_mad->data[51] & 0x1f;
 
  out:
        kfree(in_mad);
@@ -634,6 +650,9 @@ static struct ib_cq *mthca_create_cq(struct ib_device *ibdev, int entries,
        int nent;
        int err;
 
+       if (entries < 1 || entries > to_mdev(ibdev)->limits.max_cqes)
+               return ERR_PTR(-EINVAL);
+
        if (context) {
                if (ib_copy_from_udata(&ucmd, udata, sizeof ucmd))
                        return ERR_PTR(-EFAULT);
@@ -1058,6 +1077,26 @@ int mthca_register_device(struct mthca_dev *dev)
        strlcpy(dev->ib_dev.name, "mthca%d", IB_DEVICE_NAME_MAX);
        dev->ib_dev.owner                = THIS_MODULE;
 
+       dev->ib_dev.uverbs_abi_ver       = MTHCA_UVERBS_ABI_VERSION;
+       dev->ib_dev.uverbs_cmd_mask      =
+               (1ull << IB_USER_VERBS_CMD_GET_CONTEXT)         |
+               (1ull << IB_USER_VERBS_CMD_QUERY_DEVICE)        |
+               (1ull << IB_USER_VERBS_CMD_QUERY_PORT)          |
+               (1ull << IB_USER_VERBS_CMD_ALLOC_PD)            |
+               (1ull << IB_USER_VERBS_CMD_DEALLOC_PD)          |
+               (1ull << IB_USER_VERBS_CMD_REG_MR)              |
+               (1ull << IB_USER_VERBS_CMD_DEREG_MR)            |
+               (1ull << IB_USER_VERBS_CMD_CREATE_COMP_CHANNEL) |
+               (1ull << IB_USER_VERBS_CMD_CREATE_CQ)           |
+               (1ull << IB_USER_VERBS_CMD_DESTROY_CQ)          |
+               (1ull << IB_USER_VERBS_CMD_CREATE_QP)           |
+               (1ull << IB_USER_VERBS_CMD_MODIFY_QP)           |
+               (1ull << IB_USER_VERBS_CMD_DESTROY_QP)          |
+               (1ull << IB_USER_VERBS_CMD_ATTACH_MCAST)        |
+               (1ull << IB_USER_VERBS_CMD_DETACH_MCAST)        |
+               (1ull << IB_USER_VERBS_CMD_CREATE_SRQ)          |
+               (1ull << IB_USER_VERBS_CMD_MODIFY_SRQ)          |
+               (1ull << IB_USER_VERBS_CMD_DESTROY_SRQ);
        dev->ib_dev.node_type            = IB_NODE_CA;
        dev->ib_dev.phys_port_cnt        = dev->limits.num_ports;
        dev->ib_dev.dma_device           = &dev->pdev->dev;
@@ -1077,6 +1116,7 @@ int mthca_register_device(struct mthca_dev *dev)
 
        if (dev->mthca_flags & MTHCA_FLAG_SRQ) {
                dev->ib_dev.create_srq           = mthca_create_srq;
+               dev->ib_dev.modify_srq           = mthca_modify_srq;
                dev->ib_dev.destroy_srq          = mthca_destroy_srq;
 
                if (mthca_is_memfree(dev))
@@ -1135,10 +1175,13 @@ int mthca_register_device(struct mthca_dev *dev)
                }
        }
 
+       mthca_start_catas_poll(dev);
+
        return 0;
 }
 
 void mthca_unregister_device(struct mthca_dev *dev)
 {
+       mthca_stop_catas_poll(dev);
        ib_unregister_device(&dev->ib_dev);
 }
index 5fa0066..62ff091 100644 (file)
@@ -338,8 +338,7 @@ static const struct {
                                [UC]  = (IB_QP_AV                  |
                                         IB_QP_PATH_MTU            |
                                         IB_QP_DEST_QPN            |
-                                        IB_QP_RQ_PSN              |
-                                        IB_QP_MAX_DEST_RD_ATOMIC),
+                                        IB_QP_RQ_PSN),
                                [RC]  = (IB_QP_AV                  |
                                         IB_QP_PATH_MTU            |
                                         IB_QP_DEST_QPN            |
@@ -368,8 +367,7 @@ static const struct {
                        .trans = MTHCA_TRANS_RTR2RTS,
                        .req_param = {
                                [UD]  = IB_QP_SQ_PSN,
-                               [UC]  = (IB_QP_SQ_PSN            |
-                                        IB_QP_MAX_QP_RD_ATOMIC),
+                               [UC]  = IB_QP_SQ_PSN,
                                [RC]  = (IB_QP_TIMEOUT           |
                                         IB_QP_RETRY_CNT         |
                                         IB_QP_RNR_RETRY         |
@@ -446,8 +444,6 @@ static const struct {
                                [UD]  = (IB_QP_PKEY_INDEX            |
                                         IB_QP_QKEY),
                                [UC]  = (IB_QP_AV                    |
-                                        IB_QP_MAX_QP_RD_ATOMIC      |
-                                        IB_QP_MAX_DEST_RD_ATOMIC    |
                                         IB_QP_CUR_STATE             |
                                         IB_QP_ALT_PATH              |
                                         IB_QP_ACCESS_FLAGS          |
@@ -478,7 +474,7 @@ static const struct {
                        .opt_param = {
                                [UD]  = (IB_QP_CUR_STATE             |
                                         IB_QP_QKEY),
-                               [UC]  = (IB_QP_CUR_STATE),
+                               [UC]  = IB_QP_CUR_STATE,
                                [RC]  = (IB_QP_CUR_STATE             |
                                         IB_QP_MIN_RNR_TIMER),
                                [MLX] = (IB_QP_CUR_STATE             |
@@ -1112,8 +1108,10 @@ static int mthca_set_qp_size(struct mthca_dev *dev, struct ib_qp_cap *cap,
                             struct mthca_qp *qp)
 {
        /* Sanity check QP size before proceeding */
-       if (cap->max_send_wr  > 65536 || cap->max_recv_wr  > 65536 ||
-           cap->max_send_sge > 64    || cap->max_recv_sge > 64)
+       if (cap->max_send_wr  > dev->limits.max_wqes ||
+           cap->max_recv_wr  > dev->limits.max_wqes ||
+           cap->max_send_sge > dev->limits.max_sg   ||
+           cap->max_recv_sge > dev->limits.max_sg)
                return -EINVAL;
 
        if (mthca_is_memfree(dev)) {
index 18998d4..64f70aa 100644 (file)
@@ -186,7 +186,8 @@ int mthca_alloc_srq(struct mthca_dev *dev, struct mthca_pd *pd,
        int err;
 
        /* Sanity check SRQ size before proceeding */
-       if (attr->max_wr > 16 << 20 || attr->max_sge > 64)
+       if (attr->max_wr  > dev->limits.max_srq_wqes ||
+           attr->max_sge > dev->limits.max_sg)
                return -EINVAL;
 
        srq->max      = attr->max_wr;
@@ -332,6 +333,29 @@ void mthca_free_srq(struct mthca_dev *dev, struct mthca_srq *srq)
        mthca_free_mailbox(dev, mailbox);
 }
 
+int mthca_modify_srq(struct ib_srq *ibsrq, struct ib_srq_attr *attr,
+                    enum ib_srq_attr_mask attr_mask)
+{      
+       struct mthca_dev *dev = to_mdev(ibsrq->device);
+       struct mthca_srq *srq = to_msrq(ibsrq);
+       int ret;
+       u8 status;
+
+       /* We don't support resizing SRQs (yet?) */
+       if (attr_mask & IB_SRQ_MAX_WR)
+               return -EINVAL;
+
+       if (attr_mask & IB_SRQ_LIMIT) {
+               ret = mthca_ARM_SRQ(dev, srq->srqn, attr->srq_limit, &status);
+               if (ret)
+                       return ret;
+               if (status)
+                       return -EINVAL;
+       }
+
+       return 0;
+}
+
 void mthca_srq_event(struct mthca_dev *dev, u32 srqn,
                     enum ib_event_type event_type)
 {
@@ -354,7 +378,7 @@ void mthca_srq_event(struct mthca_dev *dev, u32 srqn,
 
        event.device      = &dev->ib_dev;
        event.event       = event_type;
-       event.element.srq  = &srq->ibsrq;
+       event.element.srq = &srq->ibsrq;
        srq->ibsrq.event_handler(&event, srq->ibsrq.srq_context);
 
 out:
@@ -415,6 +439,14 @@ int mthca_tavor_post_srq_recv(struct ib_srq *ibsrq, struct ib_recv_wr *wr,
 
                wqe       = get_wqe(srq, ind);
                next_ind  = *wqe_to_link(wqe);
+
+               if (next_ind < 0) {
+                       mthca_err(dev, "SRQ %06x full\n", srq->srqn);
+                       err = -ENOMEM;
+                       *bad_wr = wr;
+                       break;
+               }
+
                prev_wqe  = srq->last;
                srq->last = wqe;
 
@@ -506,6 +538,13 @@ int mthca_arbel_post_srq_recv(struct ib_srq *ibsrq, struct ib_recv_wr *wr,
                wqe       = get_wqe(srq, ind);
                next_ind  = *wqe_to_link(wqe);
 
+               if (next_ind < 0) {
+                       mthca_err(dev, "SRQ %06x full\n", srq->srqn);
+                       err = -ENOMEM;
+                       *bad_wr = wr;
+                       break;
+               }
+
                ((struct mthca_next_seg *) wqe)->nda_op =
                        cpu_to_be32((next_ind << srq->wqe_shift) | 1);
                ((struct mthca_next_seg *) wqe)->ee_nds = 0;
index 41613ec..bb015c6 100644 (file)
 
 #include <linux/types.h>
 
+/*
+ * Increment this value if any changes that break userspace ABI
+ * compatibility are made.
+ */
+#define MTHCA_UVERBS_ABI_VERSION       1
+
 /*
  * Make sure that all structs defined in this file remain laid out so
  * that they pack the same way on 32-bit and 64-bit architectures (to
index 4ea1c1c..c994a91 100644 (file)
@@ -100,7 +100,12 @@ struct ipoib_pseudoheader {
 
 struct ipoib_mcast;
 
-struct ipoib_buf {
+struct ipoib_rx_buf {
+       struct sk_buff *skb;
+       dma_addr_t      mapping;
+};
+
+struct ipoib_tx_buf {
        struct sk_buff *skb;
        DECLARE_PCI_UNMAP_ADDR(mapping)
 };
@@ -150,14 +155,14 @@ struct ipoib_dev_priv {
        unsigned int admin_mtu;
        unsigned int mcast_mtu;
 
-       struct ipoib_buf *rx_ring;
+       struct ipoib_rx_buf *rx_ring;
 
-       spinlock_t        tx_lock;
-       struct ipoib_buf *tx_ring;
-       unsigned          tx_head;
-       unsigned          tx_tail;
-       struct ib_sge     tx_sge;
-       struct ib_send_wr tx_wr;
+       spinlock_t           tx_lock;
+       struct ipoib_tx_buf *tx_ring;
+       unsigned             tx_head;
+       unsigned             tx_tail;
+       struct ib_sge        tx_sge;
+       struct ib_send_wr    tx_wr;
 
        struct ib_wc ibwc[IPOIB_NUM_WC];
 
@@ -277,7 +282,7 @@ int ipoib_mcast_attach(struct net_device *dev, u16 mlid,
 int ipoib_mcast_detach(struct net_device *dev, u16 mlid,
                       union ib_gid *mgid);
 
-int ipoib_qp_create(struct net_device *dev);
+int ipoib_init_qp(struct net_device *dev);
 int ipoib_transport_dev_init(struct net_device *dev, struct ib_device *ca);
 void ipoib_transport_dev_cleanup(struct net_device *dev);
 
index f744009..192fef8 100644 (file)
@@ -95,57 +95,65 @@ void ipoib_free_ah(struct kref *kref)
        }
 }
 
-static inline int ipoib_ib_receive(struct ipoib_dev_priv *priv,
-                                  unsigned int wr_id,
-                                  dma_addr_t addr)
+static int ipoib_ib_post_receive(struct net_device *dev, int id)
 {
-       struct ib_sge list = {
-               .addr    = addr,
-               .length  = IPOIB_BUF_SIZE,
-               .lkey    = priv->mr->lkey,
-       };
-       struct ib_recv_wr param = {
-               .wr_id      = wr_id | IPOIB_OP_RECV,
-               .sg_list    = &list,
-               .num_sge    = 1,
-       };
+       struct ipoib_dev_priv *priv = netdev_priv(dev);
+       struct ib_sge list;
+       struct ib_recv_wr param;
        struct ib_recv_wr *bad_wr;
+       int ret;
+
+       list.addr     = priv->rx_ring[id].mapping;
+       list.length   = IPOIB_BUF_SIZE;
+       list.lkey     = priv->mr->lkey;
+
+       param.next    = NULL;
+       param.wr_id   = id | IPOIB_OP_RECV;
+       param.sg_list = &list;
+       param.num_sge = 1;
+
+       ret = ib_post_recv(priv->qp, &param, &bad_wr);
+       if (unlikely(ret)) {
+               ipoib_warn(priv, "receive failed for buf %d (%d)\n", id, ret);
+               dma_unmap_single(priv->ca->dma_device,
+                                priv->rx_ring[id].mapping,
+                                IPOIB_BUF_SIZE, DMA_FROM_DEVICE);
+               dev_kfree_skb_any(priv->rx_ring[id].skb);
+               priv->rx_ring[id].skb = NULL;
+       }
 
-       return ib_post_recv(priv->qp, &param, &bad_wr);
+       return ret;
 }
 
-static int ipoib_ib_post_receive(struct net_device *dev, int id)
+static int ipoib_alloc_rx_skb(struct net_device *dev, int id)
 {
        struct ipoib_dev_priv *priv = netdev_priv(dev);
        struct sk_buff *skb;
        dma_addr_t addr;
-       int ret;
 
        skb = dev_alloc_skb(IPOIB_BUF_SIZE + 4);
-       if (!skb) {
-               ipoib_warn(priv, "failed to allocate receive buffer\n");
-
-               priv->rx_ring[id].skb = NULL;
+       if (!skb)
                return -ENOMEM;
-       }
-       skb_reserve(skb, 4);    /* 16 byte align IP header */
-       priv->rx_ring[id].skb = skb;
+
+       /*
+        * IB will leave a 40 byte gap for a GRH and IPoIB adds a 4 byte
+        * header.  So we need 4 more bytes to get to 48 and align the
+        * IP header to a multiple of 16.
+        */
+       skb_reserve(skb, 4);
+
        addr = dma_map_single(priv->ca->dma_device,
                              skb->data, IPOIB_BUF_SIZE,
                              DMA_FROM_DEVICE);
-       pci_unmap_addr_set(&priv->rx_ring[id], mapping, addr);
-
-       ret = ipoib_ib_receive(priv, id, addr);
-       if (ret) {
-               ipoib_warn(priv, "ipoib_ib_receive failed for buf %d (%d)\n",
-                          id, ret);
-               dma_unmap_single(priv->ca->dma_device, addr,
-                                IPOIB_BUF_SIZE, DMA_FROM_DEVICE);
+       if (unlikely(dma_mapping_error(addr))) {
                dev_kfree_skb_any(skb);
-               priv->rx_ring[id].skb = NULL;
+               return -EIO;
        }
 
-       return ret;
+       priv->rx_ring[id].skb     = skb;
+       priv->rx_ring[id].mapping = addr;
+
+       return 0;
 }
 
 static int ipoib_ib_post_receives(struct net_device *dev)
@@ -154,6 +162,10 @@ static int ipoib_ib_post_receives(struct net_device *dev)
        int i;
 
        for (i = 0; i < IPOIB_RX_RING_SIZE; ++i) {
+               if (ipoib_alloc_rx_skb(dev, i)) {
+                       ipoib_warn(priv, "failed to allocate receive buffer %d\n", i);
+                       return -ENOMEM;
+               }
                if (ipoib_ib_post_receive(dev, i)) {
                        ipoib_warn(priv, "ipoib_ib_post_receive failed for buf %d\n", i);
                        return -EIO;
@@ -176,28 +188,36 @@ static void ipoib_ib_handle_wc(struct net_device *dev,
                wr_id &= ~IPOIB_OP_RECV;
 
                if (wr_id < IPOIB_RX_RING_SIZE) {
-                       struct sk_buff *skb = priv->rx_ring[wr_id].skb;
-
-                       priv->rx_ring[wr_id].skb = NULL;
+                       struct sk_buff *skb  = priv->rx_ring[wr_id].skb;
+                       dma_addr_t      addr = priv->rx_ring[wr_id].mapping;
 
-                       dma_unmap_single(priv->ca->dma_device,
-                                        pci_unmap_addr(&priv->rx_ring[wr_id],
-                                                       mapping),
-                                        IPOIB_BUF_SIZE,
-                                        DMA_FROM_DEVICE);
-
-                       if (wc->status != IB_WC_SUCCESS) {
+                       if (unlikely(wc->status != IB_WC_SUCCESS)) {
                                if (wc->status != IB_WC_WR_FLUSH_ERR)
                                        ipoib_warn(priv, "failed recv event "
                                                   "(status=%d, wrid=%d vend_err %x)\n",
                                                   wc->status, wr_id, wc->vendor_err);
+                               dma_unmap_single(priv->ca->dma_device, addr,
+                                                IPOIB_BUF_SIZE, DMA_FROM_DEVICE);
                                dev_kfree_skb_any(skb);
+                               priv->rx_ring[wr_id].skb = NULL;
                                return;
                        }
 
+                       /*
+                        * If we can't allocate a new RX buffer, dump
+                        * this packet and reuse the old buffer.
+                        */
+                       if (unlikely(ipoib_alloc_rx_skb(dev, wr_id))) {
+                               ++priv->stats.rx_dropped;
+                               goto repost;
+                       }
+
                        ipoib_dbg_data(priv, "received %d bytes, SLID 0x%04x\n",
                                       wc->byte_len, wc->slid);
 
+                       dma_unmap_single(priv->ca->dma_device, addr,
+                                        IPOIB_BUF_SIZE, DMA_FROM_DEVICE);
+
                        skb_put(skb, wc->byte_len);
                        skb_pull(skb, IB_GRH_BYTES);
 
@@ -220,8 +240,8 @@ static void ipoib_ib_handle_wc(struct net_device *dev,
                                dev_kfree_skb_any(skb);
                        }
 
-                       /* repost receive */
-                       if (ipoib_ib_post_receive(dev, wr_id))
+               repost:
+                       if (unlikely(ipoib_ib_post_receive(dev, wr_id)))
                                ipoib_warn(priv, "ipoib_ib_post_receive failed "
                                           "for buf %d\n", wr_id);
                } else
@@ -229,7 +249,7 @@ static void ipoib_ib_handle_wc(struct net_device *dev,
                                   wr_id);
 
        } else {
-               struct ipoib_buf *tx_req;
+               struct ipoib_tx_buf *tx_req;
                unsigned long flags;
 
                if (wr_id >= IPOIB_TX_RING_SIZE) {
@@ -302,7 +322,7 @@ void ipoib_send(struct net_device *dev, struct sk_buff *skb,
                struct ipoib_ah *address, u32 qpn)
 {
        struct ipoib_dev_priv *priv = netdev_priv(dev);
-       struct ipoib_buf *tx_req;
+       struct ipoib_tx_buf *tx_req;
        dma_addr_t addr;
 
        if (skb->len > dev->mtu + INFINIBAND_ALEN) {
@@ -387,9 +407,9 @@ int ipoib_ib_dev_open(struct net_device *dev)
        struct ipoib_dev_priv *priv = netdev_priv(dev);
        int ret;
 
-       ret = ipoib_qp_create(dev);
+       ret = ipoib_init_qp(dev);
        if (ret) {
-               ipoib_warn(priv, "ipoib_qp_create returned %d\n", ret);
+               ipoib_warn(priv, "ipoib_init_qp returned %d\n", ret);
                return -1;
        }
 
@@ -468,7 +488,7 @@ int ipoib_ib_dev_stop(struct net_device *dev)
        struct ib_qp_attr qp_attr;
        int attr_mask;
        unsigned long begin;
-       struct ipoib_buf *tx_req;
+       struct ipoib_tx_buf *tx_req;
        int i;
 
        /* Kill the existing QP and allocate a new one */
index 6c5bf07..cd4f423 100644 (file)
@@ -637,8 +637,11 @@ static void ipoib_timeout(struct net_device *dev)
 {
        struct ipoib_dev_priv *priv = netdev_priv(dev);
 
-       ipoib_warn(priv, "transmit timeout: latency %ld\n",
-                  jiffies - dev->trans_start);
+       ipoib_warn(priv, "transmit timeout: latency %d msecs\n",
+                  jiffies_to_msecs(jiffies - dev->trans_start));
+       ipoib_warn(priv, "queue stopped %d, tx_head %u, tx_tail %u\n",
+                  netif_queue_stopped(dev),
+                  priv->tx_head, priv->tx_tail);
        /* XXX reset QP, etc. */
 }
 
@@ -729,7 +732,7 @@ int ipoib_dev_init(struct net_device *dev, struct ib_device *ca, int port)
 
        /* Allocate RX/TX "rings" to hold queued skbs */
 
-       priv->rx_ring = kmalloc(IPOIB_RX_RING_SIZE * sizeof (struct ipoib_buf),
+       priv->rx_ring = kmalloc(IPOIB_RX_RING_SIZE * sizeof (struct ipoib_rx_buf),
                                GFP_KERNEL);
        if (!priv->rx_ring) {
                printk(KERN_WARNING "%s: failed to allocate RX ring (%d entries)\n",
@@ -737,9 +740,9 @@ int ipoib_dev_init(struct net_device *dev, struct ib_device *ca, int port)
                goto out;
        }
        memset(priv->rx_ring, 0,
-              IPOIB_RX_RING_SIZE * sizeof (struct ipoib_buf));
+              IPOIB_RX_RING_SIZE * sizeof (struct ipoib_rx_buf));
 
-       priv->tx_ring = kmalloc(IPOIB_TX_RING_SIZE * sizeof (struct ipoib_buf),
+       priv->tx_ring = kmalloc(IPOIB_TX_RING_SIZE * sizeof (struct ipoib_tx_buf),
                                GFP_KERNEL);
        if (!priv->tx_ring) {
                printk(KERN_WARNING "%s: failed to allocate TX ring (%d entries)\n",
@@ -747,7 +750,7 @@ int ipoib_dev_init(struct net_device *dev, struct ib_device *ca, int port)
                goto out_rx_ring_cleanup;
        }
        memset(priv->tx_ring, 0,
-              IPOIB_TX_RING_SIZE * sizeof (struct ipoib_buf));
+              IPOIB_TX_RING_SIZE * sizeof (struct ipoib_tx_buf));
 
        /* priv->tx_head & tx_tail are already 0 */
 
index 79f59d0..b5902a7 100644 (file)
@@ -92,7 +92,7 @@ int ipoib_mcast_detach(struct net_device *dev, u16 mlid, union ib_gid *mgid)
        return ret;
 }
 
-int ipoib_qp_create(struct net_device *dev)
+int ipoib_init_qp(struct net_device *dev)
 {
        struct ipoib_dev_priv *priv = netdev_priv(dev);
        int ret;
@@ -149,10 +149,11 @@ int ipoib_qp_create(struct net_device *dev)
        return 0;
 
 out_fail:
-       ib_destroy_qp(priv->qp);
-       priv->qp = NULL;
+       qp_attr.qp_state = IB_QPS_RESET;
+       if (ib_modify_qp(priv->qp, &qp_attr, IB_QP_STATE))
+               ipoib_warn(priv, "Failed to modify QP to RESET state\n");
 
-       return -EINVAL;
+       return ret;
 }
 
 int ipoib_transport_dev_init(struct net_device *dev, struct ib_device *ca)
index 3d63bc1..4c8fb1f 100644 (file)
@@ -199,7 +199,7 @@ static int __init amikbd_init(void)
        if (!request_mem_region(CIAA_PHYSADDR-1+0xb00, 0x100, "amikeyb"))
                return -EBUSY;
 
-       amikbd_dev = input_dev_allocate();
+       amikbd_dev = input_allocate_device();
        if (!amikbd_dev) {
                printk(KERN_ERR "amikbd: not enough memory for input device\n");
                release_mem_region(CIAA_PHYSADDR - 1 + 0xb00, 0x100);
index 5778220..29d97b1 100644 (file)
@@ -143,7 +143,7 @@ static int __init init_isa_beep(struct sparc_isa_device *isa_dev)
        sparcspkr_dev->name = "Sparc ISA Speaker";
        sparcspkr_dev->event = isa_spkr_event;
 
-       input_register_device(&sparcspkr_dev);
+       input_register_device(sparcspkr_dev);
 
        return 0;
 }
index 25f7ce7..3ace875 100644 (file)
@@ -1033,13 +1033,16 @@ static void wbsd_set_ios(struct mmc_host* mmc, struct mmc_ios* ios)
        }
        else
        {
-               setup &= ~WBSD_DAT3_H;
+               if (setup & WBSD_DAT3_H)
+               {
+                       setup &= ~WBSD_DAT3_H;
 
-               /*
-                * We cannot resume card detection immediatly
-                * because of capacitance and delays in the chip.
-                */
-               mod_timer(&host->ignore_timer, jiffies + HZ/100);
+                       /*
+                        * We cannot resume card detection immediatly
+                        * because of capacitance and delays in the chip.
+                        */
+                       mod_timer(&host->ignore_timer, jiffies + HZ/100);
+               }
        }
        wbsd_write_index(host, WBSD_IDX_SETUP, setup);
 
@@ -1461,8 +1464,10 @@ static int __devinit wbsd_scan(struct wbsd_host* host)
                {
                        id = 0xFFFF;
 
-                       outb(unlock_codes[j], config_ports[i]);
-                       outb(unlock_codes[j], config_ports[i]);
+                       host->config = config_ports[i];
+                       host->unlock_code = unlock_codes[j];
+
+                       wbsd_unlock_config(host);
 
                        outb(WBSD_CONF_ID_HI, config_ports[i]);
                        id = inb(config_ports[i] + 1) << 8;
@@ -1470,13 +1475,13 @@ static int __devinit wbsd_scan(struct wbsd_host* host)
                        outb(WBSD_CONF_ID_LO, config_ports[i]);
                        id |= inb(config_ports[i] + 1);
 
+                       wbsd_lock_config(host);
+
                        for (k = 0;k < sizeof(valid_ids)/sizeof(int);k++)
                        {
                                if (id == valid_ids[k])
                                {
                                        host->chip_id = id;
-                                       host->config = config_ports[i];
-                                       host->unlock_code = unlock_codes[i];
 
                                        return 0;
                                }
@@ -1487,13 +1492,14 @@ static int __devinit wbsd_scan(struct wbsd_host* host)
                                DBG("Unknown hardware (id %x) found at %x\n",
                                        id, config_ports[i]);
                        }
-
-                       outb(LOCK_CODE, config_ports[i]);
                }
 
                release_region(config_ports[i], 2);
        }
 
+       host->config = 0;
+       host->unlock_code = 0;
+
        return -ENODEV;
 }
 
@@ -1699,8 +1705,10 @@ static void __devexit wbsd_release_resources(struct wbsd_host* host)
  * Configure the resources the chip should use.
  */
 
-static void __devinit wbsd_chip_config(struct wbsd_host* host)
+static void wbsd_chip_config(struct wbsd_host* host)
 {
+       wbsd_unlock_config(host);
+
        /*
         * Reset the chip.
         */
@@ -1733,16 +1741,20 @@ static void __devinit wbsd_chip_config(struct wbsd_host* host)
         */
        wbsd_write_config(host, WBSD_CONF_ENABLE, 1);
        wbsd_write_config(host, WBSD_CONF_POWER, 0x20);
+
+       wbsd_lock_config(host);
 }
 
 /*
  * Check that configured resources are correct.
  */
 
-static int __devinit wbsd_chip_validate(struct wbsd_host* host)
+static int wbsd_chip_validate(struct wbsd_host* host)
 {
        int base, irq, dma;
 
+       wbsd_unlock_config(host);
+
        /*
         * Select SD/MMC function.
         */
@@ -1758,6 +1770,8 @@ static int __devinit wbsd_chip_validate(struct wbsd_host* host)
 
        dma = wbsd_read_config(host, WBSD_CONF_DRQ);
 
+       wbsd_lock_config(host);
+
        /*
         * Validate against given configuration.
         */
@@ -1771,6 +1785,20 @@ static int __devinit wbsd_chip_validate(struct wbsd_host* host)
        return 1;
 }
 
+/*
+ * Powers down the SD function
+ */
+
+static void wbsd_chip_poweroff(struct wbsd_host* host)
+{
+       wbsd_unlock_config(host);
+
+       wbsd_write_config(host, WBSD_CONF_DEVICE, DEVICE_SD);
+       wbsd_write_config(host, WBSD_CONF_ENABLE, 0);
+
+       wbsd_lock_config(host);
+}
+
 /*****************************************************************************\
  *                                                                           *
  * Devices setup and shutdown                                                *
@@ -1844,7 +1872,11 @@ static int __devinit wbsd_init(struct device* dev, int base, int irq, int dma,
         */
 #ifdef CONFIG_PM
        if (host->config)
+       {
+               wbsd_unlock_config(host);
                wbsd_write_config(host, WBSD_CONF_PME, 0xA0);
+               wbsd_lock_config(host);
+       }
 #endif
        /*
         * Allow device to initialise itself properly.
@@ -1885,16 +1917,11 @@ static void __devexit wbsd_shutdown(struct device* dev, int pnp)
 
        mmc_remove_host(mmc);
 
+       /*
+        * Power down the SD/MMC function.
+        */
        if (!pnp)
-       {
-               /*
-                * Power down the SD/MMC function.
-                */
-               wbsd_unlock_config(host);
-               wbsd_write_config(host, WBSD_CONF_DEVICE, DEVICE_SD);
-               wbsd_write_config(host, WBSD_CONF_ENABLE, 0);
-               wbsd_lock_config(host);
-       }
+               wbsd_chip_poweroff(host);
 
        wbsd_release_resources(host);
 
@@ -1955,23 +1982,59 @@ static void __devexit wbsd_pnp_remove(struct pnp_dev * dev)
  */
 
 #ifdef CONFIG_PM
+
 static int wbsd_suspend(struct device *dev, pm_message_t state)
 {
-       DBGF("Not yet supported\n");
+       struct mmc_host *mmc = dev_get_drvdata(dev);
+       struct wbsd_host *host;
+       int ret;
+
+       if (!mmc)
+               return 0;
+
+       DBG("Suspending...\n");
+
+       ret = mmc_suspend_host(mmc, state);
+       if (!ret)
+               return ret;
+
+       host = mmc_priv(mmc);
+
+       wbsd_chip_poweroff(host);
 
        return 0;
 }
 
 static int wbsd_resume(struct device *dev)
 {
-       DBGF("Not yet supported\n");
+       struct mmc_host *mmc = dev_get_drvdata(dev);
+       struct wbsd_host *host;
 
-       return 0;
+       if (!mmc)
+               return 0;
+
+       DBG("Resuming...\n");
+
+       host = mmc_priv(mmc);
+
+       wbsd_chip_config(host);
+
+       /*
+        * Allow device to initialise itself properly.
+        */
+       mdelay(5);
+
+       wbsd_init_device(host);
+
+       return mmc_resume_host(mmc);
 }
-#else
+
+#else /* CONFIG_PM */
+
 #define wbsd_suspend NULL
 #define wbsd_resume NULL
-#endif
+
+#endif /* CONFIG_PM */
 
 static struct platform_device *wbsd_device;
 
index 24a76de..2a42add 100644 (file)
@@ -60,3 +60,92 @@ EXPORT_SYMBOL(pci_bus_read_config_dword);
 EXPORT_SYMBOL(pci_bus_write_config_byte);
 EXPORT_SYMBOL(pci_bus_write_config_word);
 EXPORT_SYMBOL(pci_bus_write_config_dword);
+
+static u32 pci_user_cached_config(struct pci_dev *dev, int pos)
+{
+       u32 data;
+
+       data = dev->saved_config_space[pos/sizeof(dev->saved_config_space[0])];
+       data >>= (pos % sizeof(dev->saved_config_space[0])) * 8;
+       return data;
+}
+
+#define PCI_USER_READ_CONFIG(size,type)                                        \
+int pci_user_read_config_##size                                                \
+       (struct pci_dev *dev, int pos, type *val)                       \
+{                                                                      \
+       unsigned long flags;                                            \
+       int ret = 0;                                                    \
+       u32 data = -1;                                                  \
+       if (PCI_##size##_BAD) return PCIBIOS_BAD_REGISTER_NUMBER;       \
+       spin_lock_irqsave(&pci_lock, flags);                            \
+       if (likely(!dev->block_ucfg_access))                            \
+               ret = dev->bus->ops->read(dev->bus, dev->devfn,         \
+                                       pos, sizeof(type), &data);      \
+       else if (pos < sizeof(dev->saved_config_space))                 \
+               data = pci_user_cached_config(dev, pos);                \
+       spin_unlock_irqrestore(&pci_lock, flags);                       \
+       *val = (type)data;                                              \
+       return ret;                                                     \
+}
+
+#define PCI_USER_WRITE_CONFIG(size,type)                               \
+int pci_user_write_config_##size                                       \
+       (struct pci_dev *dev, int pos, type val)                        \
+{                                                                      \
+       unsigned long flags;                                            \
+       int ret = -EIO;                                                 \
+       if (PCI_##size##_BAD) return PCIBIOS_BAD_REGISTER_NUMBER;       \
+       spin_lock_irqsave(&pci_lock, flags);                            \
+       if (likely(!dev->block_ucfg_access))                            \
+               ret = dev->bus->ops->write(dev->bus, dev->devfn,        \
+                                       pos, sizeof(type), val);        \
+       spin_unlock_irqrestore(&pci_lock, flags);                       \
+       return ret;                                                     \
+}
+
+PCI_USER_READ_CONFIG(byte, u8)
+PCI_USER_READ_CONFIG(word, u16)
+PCI_USER_READ_CONFIG(dword, u32)
+PCI_USER_WRITE_CONFIG(byte, u8)
+PCI_USER_WRITE_CONFIG(word, u16)
+PCI_USER_WRITE_CONFIG(dword, u32)
+
+/**
+ * pci_block_user_cfg_access - Block userspace PCI config reads/writes
+ * @dev:       pci device struct
+ *
+ * This function blocks any userspace PCI config accesses from occurring.
+ * When blocked, any writes will be bit bucketed and reads will return the
+ * data saved using pci_save_state for the first 64 bytes of config
+ * space and return 0xff for all other config reads.
+ **/
+void pci_block_user_cfg_access(struct pci_dev *dev)
+{
+       unsigned long flags;
+
+       pci_save_state(dev);
+
+       /* spinlock to synchronize with anyone reading config space now */
+       spin_lock_irqsave(&pci_lock, flags);
+       dev->block_ucfg_access = 1;
+       spin_unlock_irqrestore(&pci_lock, flags);
+}
+EXPORT_SYMBOL_GPL(pci_block_user_cfg_access);
+
+/**
+ * pci_unblock_user_cfg_access - Unblock userspace PCI config reads/writes
+ * @dev:       pci device struct
+ *
+ * This function allows userspace PCI config accesses to resume.
+ **/
+void pci_unblock_user_cfg_access(struct pci_dev *dev)
+{
+       unsigned long flags;
+
+       /* spinlock to synchronize with anyone reading saved config space */
+       spin_lock_irqsave(&pci_lock, flags);
+       dev->block_ucfg_access = 0;
+       spin_unlock_irqrestore(&pci_lock, flags);
+}
+EXPORT_SYMBOL_GPL(pci_unblock_user_cfg_access);
index 424e7de..8e21f6a 100644 (file)
@@ -58,6 +58,9 @@ static LIST_HEAD(bridge_list);
 
 static void handle_hotplug_event_bridge (acpi_handle, u32, void *);
 static void handle_hotplug_event_func (acpi_handle, u32, void *);
+static void acpiphp_sanitize_bus(struct pci_bus *bus);
+static void acpiphp_set_hpp_values(acpi_handle handle, struct pci_bus *bus);
+
 
 /*
  * initialization & terminatation routines
@@ -796,8 +799,13 @@ static int enable_device(struct acpiphp_slot *slot)
                }
        }
 
+       pci_bus_size_bridges(bus);
        pci_bus_assign_resources(bus);
+       acpiphp_sanitize_bus(bus);
+       pci_enable_bridges(bus);
        pci_bus_add_devices(bus);
+       acpiphp_set_hpp_values(DEVICE_ACPI_HANDLE(&bus->self->dev), bus);
+       acpiphp_configure_ioapics(DEVICE_ACPI_HANDLE(&bus->self->dev));
 
        /* associate pci_dev to our representation */
        list_for_each (l, &slot->funcs) {
index e992802..790abad 100644 (file)
@@ -78,11 +78,20 @@ static void __iomem *csr_int_mask;
 
 static int zt5550_hc_config(struct pci_dev *pdev)
 {
+       int ret;
+
        /* Since we know that no boards exist with two HC chips, treat it as an error */
        if(hc_dev) {
                err("too many host controller devices?");
                return -EBUSY;
        }
+
+       ret = pci_enable_device(pdev);
+       if(ret) {
+               err("cannot enable %s\n", pci_name(pdev));
+               return ret;
+       }
+
        hc_dev = pdev;
        dbg("hc_dev = %p", hc_dev);
        dbg("pci resource start %lx", pci_resource_start(hc_dev, 1));
@@ -91,7 +100,8 @@ static int zt5550_hc_config(struct pci_dev *pdev)
        if(!request_mem_region(pci_resource_start(hc_dev, 1),
                                pci_resource_len(hc_dev, 1), MY_NAME)) {
                err("cannot reserve MMIO region");
-               return -ENOMEM;
+               ret = -ENOMEM;
+               goto exit_disable_device;
        }
 
        hc_registers =
@@ -99,9 +109,8 @@ static int zt5550_hc_config(struct pci_dev *pdev)
        if(!hc_registers) {
                err("cannot remap MMIO region %lx @ %lx",
                    pci_resource_len(hc_dev, 1), pci_resource_start(hc_dev, 1));
-               release_mem_region(pci_resource_start(hc_dev, 1),
-                                  pci_resource_len(hc_dev, 1));
-               return -ENODEV;
+               ret = -ENODEV;
+               goto exit_release_region;
        }
 
        csr_hc_index = hc_registers + CSR_HCINDEX;
@@ -124,6 +133,13 @@ static int zt5550_hc_config(struct pci_dev *pdev)
        writeb((u8) ALL_DIRECT_INTS_MASK, csr_int_mask);
        dbg("disabled timer0, timer1 and ENUM interrupts");
        return 0;
+
+exit_release_region:
+       release_mem_region(pci_resource_start(hc_dev, 1),
+                          pci_resource_len(hc_dev, 1));
+exit_disable_device:
+       pci_disable_device(hc_dev);
+       return ret;
 }
 
 static int zt5550_hc_cleanup(void)
@@ -134,6 +150,7 @@ static int zt5550_hc_cleanup(void)
        iounmap(hc_registers);
        release_mem_region(pci_resource_start(hc_dev, 1),
                           pci_resource_len(hc_dev, 1));
+       pci_disable_device(hc_dev);
        return 0;
 }
 
index 8c6d398..9aed8ef 100644 (file)
@@ -794,12 +794,21 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        u32 rc;
        struct controller *ctrl;
        struct pci_func *func;
+       int err;
+
+       err = pci_enable_device(pdev);
+       if (err) {
+               printk(KERN_ERR MY_NAME ": cannot enable PCI device %s (%d)\n",
+                       pci_name(pdev), err);
+               return err;
+       }
 
        // Need to read VID early b/c it's used to differentiate CPQ and INTC discovery
        rc = pci_read_config_word(pdev, PCI_VENDOR_ID, &vendor_id);
        if (rc || ((vendor_id != PCI_VENDOR_ID_COMPAQ) && (vendor_id != PCI_VENDOR_ID_INTEL))) {
                err(msg_HPC_non_compaq_or_intel);
-               return -ENODEV;
+               rc = -ENODEV;
+               goto err_disable_device;
        }
        dbg("Vendor ID: %x\n", vendor_id);
 
@@ -807,7 +816,8 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        dbg("revision: %d\n", rev);
        if (rc || ((vendor_id == PCI_VENDOR_ID_COMPAQ) && (!rev))) {
                err(msg_HPC_rev_error);
-               return -ENODEV;
+               rc = -ENODEV;
+               goto err_disable_device;
        }
 
        /* Check for the proper subsytem ID's
@@ -820,18 +830,20 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
                rc = pci_read_config_word(pdev, PCI_SUBSYSTEM_VENDOR_ID, &subsystem_vid);
                if (rc) {
                        err("%s : pci_read_config_word failed\n", __FUNCTION__);
-                       return rc;
+                       goto err_disable_device;
                }
                dbg("Subsystem Vendor ID: %x\n", subsystem_vid);
                if ((subsystem_vid != PCI_VENDOR_ID_COMPAQ) && (subsystem_vid != PCI_VENDOR_ID_INTEL)) {
                        err(msg_HPC_non_compaq_or_intel);
-                       return -ENODEV;
+                       rc = -ENODEV;
+                       goto err_disable_device;
                }
 
                ctrl = (struct controller *) kmalloc(sizeof(struct controller), GFP_KERNEL);
                if (!ctrl) {
                        err("%s : out of memory\n", __FUNCTION__);
-                       return -ENOMEM;
+                       rc = -ENOMEM;
+                       goto err_disable_device;
                }
                memset(ctrl, 0, sizeof(struct controller));
 
@@ -1264,6 +1276,8 @@ err_free_bus:
        kfree(ctrl->pci_bus);
 err_free_ctrl:
        kfree(ctrl);
+err_disable_device:
+       pci_disable_device(pdev);
        return rc;
 }
 
index 61d94d1..71ea5f9 100644 (file)
@@ -92,9 +92,10 @@ extern struct pci_bus *rpaphp_find_pci_bus(struct device_node *dn);
 extern int rpaphp_claim_resource(struct pci_dev *dev, int resource);
 extern int rpaphp_enable_pci_slot(struct slot *slot);
 extern int register_pci_slot(struct slot *slot);
-extern int rpaphp_unconfig_pci_adapter(struct slot *slot);
 extern int rpaphp_get_pci_adapter_status(struct slot *slot, int is_init, u8 * value);
+
 extern int rpaphp_config_pci_adapter(struct pci_bus *bus);
+extern int rpaphp_unconfig_pci_adapter(struct pci_bus *bus);
 
 /* rpaphp_core.c */
 extern int rpaphp_add_slot(struct device_node *dn);
index c830ff0..cf075c3 100644 (file)
@@ -426,8 +426,11 @@ static int disable_slot(struct hotplug_slot *hotplug_slot)
 
        dbg("DISABLING SLOT %s\n", slot->name);
        down(&rpaphp_sem);
-       retval = rpaphp_unconfig_pci_adapter(slot);
+       retval = rpaphp_unconfig_pci_adapter(slot->bus);
        up(&rpaphp_sem);
+       slot->state = NOT_CONFIGURED;
+       info("%s: devices in slot[%s] unconfigured.\n", __FUNCTION__,
+            slot->name);
 exit:
        dbg("%s - Exit: rc[%d]\n", __FUNCTION__, retval);
        return retval;
index 49e4d10..46c157d 100644 (file)
@@ -319,20 +319,15 @@ static void rpaphp_eeh_remove_bus_device(struct pci_dev *dev)
        return;
 }
 
-int rpaphp_unconfig_pci_adapter(struct slot *slot)
+int rpaphp_unconfig_pci_adapter(struct pci_bus *bus)
 {
        struct pci_dev *dev, *tmp;
-       int retval = 0;
 
-       list_for_each_entry_safe(dev, tmp, slot->pci_devs, bus_list) {
+       list_for_each_entry_safe(dev, tmp, &bus->devices, bus_list) {
                rpaphp_eeh_remove_bus_device(dev);
                pci_remove_bus_device(dev);
        }
-
-       slot->state = NOT_CONFIGURED;
-       info("%s: devices in slot[%s] unconfigured.\n", __FUNCTION__,
-            slot->name);
-       return retval;
+       return 0;
 }
 
 static int setup_pci_hotplug_slot_info(struct slot *slot)
index b7d1c61..abe2cf4 100644 (file)
@@ -32,8 +32,6 @@
 #include <linux/types.h>
 #include <linux/pci.h>
 #include <linux/delay.h>
-#include <asm/semaphore.h>
-#include <asm/io.h>            
 #include "pci_hotplug.h"
 
 #if !defined(MODULE)
@@ -52,42 +50,18 @@ extern int shpchp_debug;
 #define info(format, arg...) printk(KERN_INFO "%s: " format, MY_NAME , ## arg)
 #define warn(format, arg...) printk(KERN_WARNING "%s: " format, MY_NAME , ## arg)
 
-struct pci_func {
-       struct pci_func *next;
-       u8 bus;
-       u8 device;
-       u8 function;
-       u8 is_a_board;
-       u16 status;
-       u8 configured;
-       u8 switch_save;
-       u8 presence_save;
-       u8 pwr_save;
-       u32 base_length[0x06];
-       u8 base_type[0x06];
-       u16 reserved2;
-       u32 config_space[0x20];
-       struct pci_resource *mem_head;
-       struct pci_resource *p_mem_head;
-       struct pci_resource *io_head;
-       struct pci_resource *bus_head;
-       struct pci_dev* pci_dev;
-};
-
 #define SLOT_MAGIC     0x67267321
 struct slot {
        u32 magic;
        struct slot *next;
        u8 bus;
        u8 device;
+       u16 status;
        u32 number;
        u8 is_a_board;
-       u8 configured;
        u8 state;
-       u8 switch_save;
        u8 presence_save;
-       u32 capabilities;
-       u16 reserved2;
+       u8 pwr_save;
        struct timer_list task_event;
        u8 hp_slot;
        struct controller *ctrl;
@@ -96,12 +70,6 @@ struct slot {
        struct list_head        slot_list;
 };
 
-struct pci_resource {
-       struct pci_resource * next;
-       u32 base;
-       u32 length;
-};
-
 struct event_info {
        u32 event_type;
        u8 hp_slot;
@@ -110,13 +78,9 @@ struct event_info {
 struct controller {
        struct controller *next;
        struct semaphore crit_sect;     /* critical section semaphore */
-       void * hpc_ctlr_handle;         /* HPC controller handle */
+       struct php_ctlr_state_s *hpc_ctlr_handle; /* HPC controller handle */
        int num_slots;                  /* Number of slots on ctlr */
        int slot_num_inc;               /* 1 or -1 */
-       struct pci_resource *mem_head;
-       struct pci_resource *p_mem_head;
-       struct pci_resource *io_head;
-       struct pci_resource *bus_head;
        struct pci_dev *pci_dev;
        struct pci_bus *pci_bus;
        struct event_info event_queue[10];
@@ -124,33 +88,21 @@ struct controller {
        struct hpc_ops *hpc_ops;
        wait_queue_head_t queue;        /* sleep & wake process */
        u8 next_event;
-       u8 seg;
        u8 bus;
        u8 device;
        u8 function;
-       u8 rev;
        u8 slot_device_offset;
        u8 add_support;
        enum pci_bus_speed speed;
        u32 first_slot;         /* First physical slot number */
        u8 slot_bus;            /* Bus where the slots handled by this controller sit */
-       u8 push_flag;
-       u16 ctlrcap;
-       u16 vendor_id;
-};
-
-struct irq_mapping {
-       u8 barber_pole;
-       u8 valid_INT;
-       u8 interrupt[4];
 };
 
-struct resource_lists {
-       struct pci_resource *mem_head;
-       struct pci_resource *p_mem_head;
-       struct pci_resource *io_head;
-       struct pci_resource *bus_head;
-       struct irq_mapping *irqs;
+struct hotplug_params {
+       u8      cache_line_size;
+       u8      latency_timer;
+       u8      enable_serr;
+       u8      enable_perr;
 };
 
 /* Define AMD SHPC ID  */
@@ -194,24 +146,16 @@ struct resource_lists {
  * error Messages
  */
 #define msg_initialization_err "Initialization failure, error=%d\n"
-#define msg_HPC_rev_error      "Unsupported revision of the PCI hot plug controller found.\n"
-#define msg_HPC_non_shpc       "The PCI hot plug controller is not supported by this driver.\n"
-#define msg_HPC_not_supported  "This system is not supported by this version of shpcphd mdoule. Upgrade to a newer version of shpchpd\n"
-#define msg_unable_to_save     "Unable to store PCI hot plug add resource information. This system must be rebooted before adding any PCI devices.\n"
 #define msg_button_on          "PCI slot #%d - powering on due to button press.\n"
 #define msg_button_off         "PCI slot #%d - powering off due to button press.\n"
 #define msg_button_cancel      "PCI slot #%d - action canceled due to button press.\n"
-#define msg_button_ignore      "PCI slot #%d - button press ignored.  (action in progress...)\n"
 
 /* sysfs functions for the hotplug controller info */
 extern void shpchp_create_ctrl_files   (struct controller *ctrl);
 
 /* controller functions */
-extern int     shpchprm_find_available_resources(struct controller *ctrl);
 extern int     shpchp_event_start_thread(void);
 extern void    shpchp_event_stop_thread(void);
-extern struct  pci_func *shpchp_slot_create(unsigned char busnumber);
-extern struct  pci_func *shpchp_slot_find(unsigned char bus, unsigned char device, unsigned char index);
 extern int     shpchp_enable_slot(struct slot *slot);
 extern int     shpchp_disable_slot(struct slot *slot);
 
@@ -220,29 +164,20 @@ extern u8 shpchp_handle_switch_change(u8 hp_slot, void *inst_id);
 extern u8      shpchp_handle_presence_change(u8 hp_slot, void *inst_id);
 extern u8      shpchp_handle_power_fault(u8 hp_slot, void *inst_id);
 
-/* resource functions */
-extern int     shpchp_resource_sort_and_combine(struct pci_resource **head);
-
 /* pci functions */
-extern int     shpchp_set_irq(u8 bus_num, u8 dev_num, u8 int_pin, u8 irq_num);
-/*extern int   shpchp_get_bus_dev(struct controller *ctrl, u8 *bus_num, u8 *dev_num, struct slot *slot);*/
 extern int     shpchp_save_config(struct controller *ctrl, int busnumber, int num_ctlr_slots, int first_device_num);
-extern int     shpchp_save_used_resources(struct controller *ctrl, struct pci_func * func, int flag);
-extern int     shpchp_save_slot_config(struct controller *ctrl, struct pci_func * new_slot);
-extern void    shpchp_destroy_board_resources(struct pci_func * func);
-extern int     shpchp_return_board_resources(struct pci_func * func, struct resource_lists * resources);
-extern void    shpchp_destroy_resource_list(struct resource_lists * resources);
-extern int     shpchp_configure_device(struct controller* ctrl, struct pci_func* func);
-extern int     shpchp_unconfigure_device(struct pci_func* func);
+extern int     shpchp_configure_device(struct slot *p_slot);
+extern int     shpchp_unconfigure_device(struct slot *p_slot);
+extern void    get_hp_hw_control_from_firmware(struct pci_dev *dev);
+extern void    get_hp_params_from_firmware(struct pci_dev *dev,
+               struct hotplug_params *hpp);
+extern int     shpchprm_get_physical_slot_number(struct controller *ctrl,
+               u32 *sun, u8 busnum, u8 devnum);
+extern void    shpchp_remove_ctrl_files(struct controller *ctrl);
 
 
 /* Global variables */
 extern struct controller *shpchp_ctrl_list;
-extern struct pci_func *shpchp_slot_list[256];
-
-/* These are added to support AMD shpc */
-extern u8 shpchp_nic_irq;
-extern u8 shpchp_disk_irq;
 
 struct ctrl_reg {
        volatile u32 base_offset;
@@ -298,7 +233,7 @@ enum ctrl_offsets {
        SLOT11 =        offsetof(struct ctrl_reg, slot11),
        SLOT12 =        offsetof(struct ctrl_reg, slot12),
 };
-typedef u8(*php_intr_callback_t) (unsigned int change_id, void *instance_id);
+typedef u8(*php_intr_callback_t) (u8 hp_slot, void *instance_id);
 struct php_ctlr_state_s {
        struct php_ctlr_state_s *pnext;
        struct pci_dev *pci_dev;
@@ -359,12 +294,9 @@ static inline struct slot *shpchp_find_slot (struct controller *ctrl, u8 device)
 
        p_slot = ctrl->slot;
 
-       dbg("p_slot = %p\n", p_slot);
-
        while (p_slot && (p_slot->device != device)) {
                tmp_slot = p_slot;
                p_slot = p_slot->next;
-               dbg("In while loop, p_slot = %p\n", p_slot);
        }
        if (p_slot == NULL) {
                err("ERROR: shpchp_find_slot device=0x%x\n", device);
@@ -379,8 +311,6 @@ static inline int wait_for_ctrl_irq (struct controller *ctrl)
     DECLARE_WAITQUEUE(wait, current);
        int retval = 0;
 
-       dbg("%s : start\n",__FUNCTION__);
-
        add_wait_queue(&ctrl->queue, &wait);
 
        if (!shpchp_poll_mode) {
@@ -394,19 +324,9 @@ static inline int wait_for_ctrl_irq (struct controller *ctrl)
        if (signal_pending(current))
                retval =  -EINTR;
 
-       dbg("%s : end\n", __FUNCTION__);
        return retval;
 }
 
-/* Puts node back in the resource list pointed to by head */
-static inline void return_resource(struct pci_resource **head, struct pci_resource *node)
-{
-       if (!node || !head)
-               return;
-       node->next = *head;
-       *head = node;
-}
-
 #define SLOT_NAME_SIZE 10
 
 static inline void make_slot_name(char *buffer, int buffer_size, struct slot *slot)
@@ -420,11 +340,7 @@ enum php_ctlr_type {
        ACPI
 };
 
-int shpc_init( struct controller *ctrl, struct pci_dev *pdev,
-               php_intr_callback_t attention_button_callback,
-               php_intr_callback_t switch_change_callback,
-               php_intr_callback_t presence_change_callback,
-               php_intr_callback_t power_fault_callback);
+int shpc_init( struct controller *ctrl, struct pci_dev *pdev);
 
 int shpc_get_ctlr_slot_config( struct controller *ctrl,
                int *num_ctlr_slots,
@@ -437,8 +353,6 @@ struct hpc_ops {
        int     (*power_on_slot )               (struct slot *slot);
        int     (*slot_enable )                 (struct slot *slot);
        int     (*slot_disable )                (struct slot *slot);
-       int     (*enable_all_slots)             (struct slot *slot);
-       int     (*pwr_on_all_slots)             (struct slot *slot);
        int     (*set_bus_speed_mode)   (struct slot *slot, enum pci_bus_speed speed);
        int     (*get_power_status)             (struct slot *slot, u8 *status);
        int     (*get_attention_status) (struct slot *slot, u8 *status);
index 6f7d8a2..63628e0 100644 (file)
  *
  */
 
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/kernel.h>
 #include <linux/types.h>
-#include <linux/proc_fs.h>
-#include <linux/slab.h>
-#include <linux/workqueue.h>
 #include <linux/pci.h>
-#include <linux/init.h>
-#include <asm/uaccess.h>
 #include "shpchp.h"
-#include "shpchprm.h"
 
 /* Global variables */
 int shpchp_debug;
 int shpchp_poll_mode;
 int shpchp_poll_time;
 struct controller *shpchp_ctrl_list;   /* = NULL */
-struct pci_func *shpchp_slot_list[256];
 
 #define DRIVER_VERSION "0.4"
 #define DRIVER_AUTHOR  "Dan Zink <dan.zink@compaq.com>, Greg Kroah-Hartman <greg@kroah.com>, Dely Sy <dely.l.sy@intel.com>"
@@ -113,8 +105,6 @@ static int init_slots(struct controller *ctrl)
        u32 slot_number, sun;
        int result = -ENOMEM;
 
-       dbg("%s\n",__FUNCTION__);
-
        number_of_slots = ctrl->num_slots;
        slot_device = ctrl->slot_device_offset;
        slot_number = ctrl->first_slot;
@@ -352,6 +342,17 @@ static int get_cur_bus_speed (struct hotplug_slot *hotplug_slot, enum pci_bus_sp
        return 0;
 }
 
+static int is_shpc_capable(struct pci_dev *dev)
+{
+       if ((dev->vendor == PCI_VENDOR_ID_AMD) || (dev->device ==
+                               PCI_DEVICE_ID_AMD_GOLAM_7450))
+               return 1;
+       if (pci_find_capability(dev, PCI_CAP_ID_SHPC))
+               return 1;
+
+       return 0;
+}
+
 static int shpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
        int rc;
@@ -360,6 +361,9 @@ static int shpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        int first_device_num;   /* first PCI device number supported by this SHPC */
        int num_ctlr_slots;     /* number of slots supported by this SHPC */
 
+       if (!is_shpc_capable(pdev))
+               return -ENODEV;
+
        ctrl = (struct controller *) kmalloc(sizeof(struct controller), GFP_KERNEL);
        if (!ctrl) {
                err("%s : out of memory\n", __FUNCTION__);
@@ -367,19 +371,12 @@ static int shpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        }
        memset(ctrl, 0, sizeof(struct controller));
 
-       dbg("DRV_thread pid = %d\n", current->pid);
-
-       rc = shpc_init(ctrl, pdev,
-                       (php_intr_callback_t) shpchp_handle_attention_button,
-                       (php_intr_callback_t) shpchp_handle_switch_change,
-                       (php_intr_callback_t) shpchp_handle_presence_change,
-                       (php_intr_callback_t) shpchp_handle_power_fault);
+       rc = shpc_init(ctrl, pdev);
        if (rc) {
                dbg("%s: controller initialization failed\n", SHPC_MODULE_NAME);
                goto err_out_free_ctrl;
        }
 
-       dbg("%s: controller initialization success\n", __FUNCTION__);
        ctrl->pci_dev = pdev;  /* pci_dev of the P2P bridge */
 
        pci_set_drvdata(pdev, ctrl);
@@ -411,23 +408,8 @@ static int shpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        first_device_num = ctrl->slot_device_offset;
        num_ctlr_slots = ctrl->num_slots;
 
-       /* Store PCI Config Space for all devices on this bus */
-       rc = shpchp_save_config(ctrl, ctrl->slot_bus, num_ctlr_slots, first_device_num);
-       if (rc) {
-               err("%s: unable to save PCI configuration data, error %d\n", __FUNCTION__, rc);
-               goto err_out_free_ctrl_bus;
-       }
-
-       /* Get IO, memory, and IRQ resources for new devices */
-       rc = shpchprm_find_available_resources(ctrl);
-       ctrl->add_support = !rc;
+       ctrl->add_support = 1;
        
-       if (rc) {
-               dbg("shpchprm_find_available_resources = %#x\n", rc);
-               err("unable to locate PCI configuration resources for hot plug add.\n");
-               goto err_out_free_ctrl_bus;
-       }
-
        /* Setup the slot information structures */
        rc = init_slots(ctrl);
        if (rc) {
@@ -477,7 +459,6 @@ err_out_none:
 
 static int shpc_start_thread(void)
 {
-       int loop;
        int retval = 0;
        
        dbg("Initialize + Start the notification/polling mechanism \n");
@@ -488,48 +469,21 @@ static int shpc_start_thread(void)
                return retval;
        }
 
-       dbg("Initialize slot lists\n");
-       /* One slot list for each bus in the system */
-       for (loop = 0; loop < 256; loop++) {
-               shpchp_slot_list[loop] = NULL;
-       }
-
        return retval;
 }
 
-static inline void __exit
-free_shpchp_res(struct pci_resource *res)
-{
-       struct pci_resource *tres;
-
-       while (res) {
-               tres = res;
-               res = res->next;
-               kfree(tres);
-       }
-}
-
 static void __exit unload_shpchpd(void)
 {
-       struct pci_func *next;
-       struct pci_func *TempSlot;
-       int loop;
        struct controller *ctrl;
        struct controller *tctrl;
 
        ctrl = shpchp_ctrl_list;
 
        while (ctrl) {
+               shpchp_remove_ctrl_files(ctrl);
                cleanup_slots(ctrl);
 
-               free_shpchp_res(ctrl->io_head);
-               free_shpchp_res(ctrl->mem_head);
-               free_shpchp_res(ctrl->p_mem_head);
-               free_shpchp_res(ctrl->bus_head);
-
                kfree (ctrl->pci_bus);
-
-               dbg("%s: calling release_ctlr\n", __FUNCTION__);
                ctrl->hpc_ops->release_ctlr(ctrl);
 
                tctrl = ctrl;
@@ -538,20 +492,6 @@ static void __exit unload_shpchpd(void)
                kfree(tctrl);
        }
 
-       for (loop = 0; loop < 256; loop++) {
-               next = shpchp_slot_list[loop];
-               while (next != NULL) {
-                       free_shpchp_res(next->io_head);
-                       free_shpchp_res(next->mem_head);
-                       free_shpchp_res(next->p_mem_head);
-                       free_shpchp_res(next->bus_head);
-
-                       TempSlot = next;
-                       next = next->next;
-                       kfree(TempSlot);
-               }
-       }
-
        /* Stop the notification mechanism */
        shpchp_event_stop_thread();
 
@@ -596,20 +536,14 @@ static int __init shpcd_init(void)
        if (retval)
                goto error_hpc_init;
 
-       retval = shpchprm_init(PCI);
-       if (!retval) {
-               retval = pci_register_driver(&shpc_driver);
-               dbg("%s: pci_register_driver = %d\n", __FUNCTION__, retval);
-               info(DRIVER_DESC " version: " DRIVER_VERSION "\n");
-       }
+       retval = pci_register_driver(&shpc_driver);
+       dbg("%s: pci_register_driver = %d\n", __FUNCTION__, retval);
+       info(DRIVER_DESC " version: " DRIVER_VERSION "\n");
 
 error_hpc_init:
        if (retval) {
-               shpchprm_cleanup();
                shpchp_event_stop_thread();
-       } else
-               shpchprm_print_pirt();
-
+       }
        return retval;
 }
 
@@ -618,9 +552,6 @@ static void __exit shpcd_cleanup(void)
        dbg("unload_shpchpd()\n");
        unload_shpchpd();
 
-       shpchprm_cleanup();
-
-       dbg("pci_unregister_driver\n");
        pci_unregister_driver(&shpc_driver);
 
        info(DRIVER_DESC " version: " DRIVER_VERSION " unloaded\n");
index 91c9903..5861935 100644 (file)
  *
  */
 
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/types.h>
-#include <linux/slab.h>
-#include <linux/workqueue.h>
-#include <linux/interrupt.h>
-#include <linux/delay.h>
-#include <linux/wait.h>
 #include <linux/smp_lock.h>
 #include <linux/pci.h>
+#include "../pci.h"
 #include "shpchp.h"
-#include "shpchprm.h"
 
-static u32 configure_new_device(struct controller *ctrl, struct pci_func *func,
-       u8 behind_bridge, struct resource_lists *resources, u8 bridge_bus, u8 bridge_dev);
-static int configure_new_function( struct controller *ctrl, struct pci_func *func,
-       u8 behind_bridge, struct resource_lists *resources, u8 bridge_bus, u8 bridge_dev);
 static void interrupt_event_handler(struct controller *ctrl);
 
 static struct semaphore event_semaphore;       /* mutex for process loop (up if something to process) */
@@ -52,28 +42,22 @@ static struct semaphore event_exit;         /* guard ensure thread has exited before ca
 static int event_finished;
 static unsigned long pushbutton_pending;       /* = 0 */
 
-u8 shpchp_disk_irq;
-u8 shpchp_nic_irq;
-
 u8 shpchp_handle_attention_button(u8 hp_slot, void *inst_id)
 {
        struct controller *ctrl = (struct controller *) inst_id;
        struct slot *p_slot;
        u8 rc = 0;
        u8 getstatus;
-       struct pci_func *func;
        struct event_info *taskInfo;
 
        /* Attention Button Change */
        dbg("shpchp:  Attention button interrupt received.\n");
        
-       func = shpchp_slot_find(ctrl->slot_bus, (hp_slot + ctrl->slot_device_offset), 0);
-
        /* This is the structure that tells the worker thread what to do */
        taskInfo = &(ctrl->event_queue[ctrl->next_event]);
        p_slot = shpchp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset);
 
-       p_slot->hpc_ops->get_adapter_status(p_slot, &(func->presence_save));
+       p_slot->hpc_ops->get_adapter_status(p_slot, &(p_slot->presence_save));
        p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
        
        ctrl->next_event = (ctrl->next_event + 1) % 10;
@@ -118,14 +102,11 @@ u8 shpchp_handle_switch_change(u8 hp_slot, void *inst_id)
        struct slot *p_slot;
        u8 rc = 0;
        u8 getstatus;
-       struct pci_func *func;
        struct event_info *taskInfo;
 
        /* Switch Change */
        dbg("shpchp:  Switch interrupt received.\n");
 
-       func = shpchp_slot_find(ctrl->slot_bus, (hp_slot + ctrl->slot_device_offset), 0);
-
        /* This is the structure that tells the worker thread
         * what to do
         */
@@ -135,19 +116,18 @@ u8 shpchp_handle_switch_change(u8 hp_slot, void *inst_id)
 
        rc++;
        p_slot = shpchp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset);
-       p_slot->hpc_ops->get_adapter_status(p_slot, &(func->presence_save));
+       p_slot->hpc_ops->get_adapter_status(p_slot, &(p_slot->presence_save));
        p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
        dbg("%s: Card present %x Power status %x\n", __FUNCTION__,
-               func->presence_save, func->pwr_save);
+               p_slot->presence_save, p_slot->pwr_save);
 
        if (getstatus) {
                /*
                 * Switch opened
                 */
                info("Latch open on Slot(%d)\n", ctrl->first_slot + hp_slot);
-               func->switch_save = 0;
                taskInfo->event_type = INT_SWITCH_OPEN;
-               if (func->pwr_save && func->presence_save) {
+               if (p_slot->pwr_save && p_slot->presence_save) {
                        taskInfo->event_type = INT_POWER_FAULT;
                        err("Surprise Removal of card\n");
                }
@@ -156,7 +136,6 @@ u8 shpchp_handle_switch_change(u8 hp_slot, void *inst_id)
                 *  Switch closed
                 */
                info("Latch close on Slot(%d)\n", ctrl->first_slot + hp_slot);
-               func->switch_save = 0x10;
                taskInfo->event_type = INT_SWITCH_CLOSE;
        }
 
@@ -172,14 +151,11 @@ u8 shpchp_handle_presence_change(u8 hp_slot, void *inst_id)
        struct slot *p_slot;
        u8 rc = 0;
        /*u8 temp_byte;*/
-       struct pci_func *func;
        struct event_info *taskInfo;
 
        /* Presence Change */
        dbg("shpchp:  Presence/Notify input change.\n");
 
-       func = shpchp_slot_find(ctrl->slot_bus, (hp_slot + ctrl->slot_device_offset), 0);
-
        /* This is the structure that tells the worker thread
         * what to do
         */
@@ -193,8 +169,8 @@ u8 shpchp_handle_presence_change(u8 hp_slot, void *inst_id)
        /* 
         * Save the presence state
         */
-       p_slot->hpc_ops->get_adapter_status(p_slot, &(func->presence_save));
-       if (func->presence_save) {
+       p_slot->hpc_ops->get_adapter_status(p_slot, &(p_slot->presence_save));
+       if (p_slot->presence_save) {
                /*
                 * Card Present
                 */
@@ -219,14 +195,11 @@ u8 shpchp_handle_power_fault(u8 hp_slot, void *inst_id)
        struct controller *ctrl = (struct controller *) inst_id;
        struct slot *p_slot;
        u8 rc = 0;
-       struct pci_func *func;
        struct event_info *taskInfo;
 
        /* Power fault */
        dbg("shpchp:  Power fault interrupt received.\n");
 
-       func = shpchp_slot_find(ctrl->slot_bus, (hp_slot + ctrl->slot_device_offset), 0);
-
        /* This is the structure that tells the worker thread
         * what to do
         */
@@ -242,7 +215,7 @@ u8 shpchp_handle_power_fault(u8 hp_slot, void *inst_id)
                 * Power fault Cleared
                 */
                info("Power fault cleared on Slot(%d)\n", ctrl->first_slot + hp_slot);
-               func->status = 0x00;
+               p_slot->status = 0x00;
                taskInfo->event_type = INT_POWER_FAULT_CLEAR;
        } else {
                /*
@@ -251,7 +224,7 @@ u8 shpchp_handle_power_fault(u8 hp_slot, void *inst_id)
                info("Power fault on Slot(%d)\n", ctrl->first_slot + hp_slot);
                taskInfo->event_type = INT_POWER_FAULT;
                /* set power fault status for this board */
-               func->status = 0xFF;
+               p_slot->status = 0xFF;
                info("power fault bit %x set\n", hp_slot);
        }
        if (rc)
@@ -260,799 +233,13 @@ u8 shpchp_handle_power_fault(u8 hp_slot, void *inst_id)
        return rc;
 }
 
-
-/*
- * sort_by_size
- *
- * Sorts nodes on the list by their length.
- * Smallest first.
- *
- */
-static int sort_by_size(struct pci_resource **head)
-{
-       struct pci_resource *current_res;
-       struct pci_resource *next_res;
-       int out_of_order = 1;
-
-       if (!(*head))
-               return(1);
-
-       if (!((*head)->next))
-               return(0);
-
-       while (out_of_order) {
-               out_of_order = 0;
-
-               /* Special case for swapping list head */
-               if (((*head)->next) &&
-                   ((*head)->length > (*head)->next->length)) {
-                       out_of_order++;
-                       current_res = *head;
-                       *head = (*head)->next;
-                       current_res->next = (*head)->next;
-                       (*head)->next = current_res;
-               }
-
-               current_res = *head;
-
-               while (current_res->next && current_res->next->next) {
-                       if (current_res->next->length > current_res->next->next->length) {
-                               out_of_order++;
-                               next_res = current_res->next;
-                               current_res->next = current_res->next->next;
-                               current_res = current_res->next;
-                               next_res->next = current_res->next;
-                               current_res->next = next_res;
-                       } else
-                               current_res = current_res->next;
-               }
-       }  /* End of out_of_order loop */
-
-       return(0);
-}
-
-
-/*
- * sort_by_max_size
- *
- * Sorts nodes on the list by their length.
- * Largest first.
- *
- */
-static int sort_by_max_size(struct pci_resource **head)
-{
-       struct pci_resource *current_res;
-       struct pci_resource *next_res;
-       int out_of_order = 1;
-
-       if (!(*head))
-               return(1);
-
-       if (!((*head)->next))
-               return(0);
-
-       while (out_of_order) {
-               out_of_order = 0;
-
-               /* Special case for swapping list head */
-               if (((*head)->next) &&
-                   ((*head)->length < (*head)->next->length)) {
-                       out_of_order++;
-                       current_res = *head;
-                       *head = (*head)->next;
-                       current_res->next = (*head)->next;
-                       (*head)->next = current_res;
-               }
-
-               current_res = *head;
-
-               while (current_res->next && current_res->next->next) {
-                       if (current_res->next->length < current_res->next->next->length) {
-                               out_of_order++;
-                               next_res = current_res->next;
-                               current_res->next = current_res->next->next;
-                               current_res = current_res->next;
-                               next_res->next = current_res->next;
-                               current_res->next = next_res;
-                       } else
-                               current_res = current_res->next;
-               }
-       }  /* End of out_of_order loop */
-
-       return(0);
-}
-
-
-/*
- * do_pre_bridge_resource_split
- *
- *     Returns zero or one node of resources that aren't in use
- *
- */
-static struct pci_resource *do_pre_bridge_resource_split (struct pci_resource **head, struct pci_resource **orig_head, u32 alignment)
-{
-       struct pci_resource *prevnode = NULL;
-       struct pci_resource *node;
-       struct pci_resource *split_node;
-       u32 rc;
-       u32 temp_dword;
-       dbg("do_pre_bridge_resource_split\n");
-
-       if (!(*head) || !(*orig_head))
-               return(NULL);
-
-       rc = shpchp_resource_sort_and_combine(head);
-
-       if (rc)
-               return(NULL);
-
-       if ((*head)->base != (*orig_head)->base)
-               return(NULL);
-
-       if ((*head)->length == (*orig_head)->length)
-               return(NULL);
-
-
-       /* If we got here, there the bridge requires some of the resource, but
-        *  we may be able to split some off of the front
-        */     
-       node = *head;
-
-       if (node->length & (alignment -1)) {
-               /* This one isn't an aligned length, so we'll make a new entry
-                * and split it up.
-                */
-               split_node = kmalloc(sizeof(*split_node), GFP_KERNEL);
-
-               if (!split_node)
-                       return(NULL);
-
-               temp_dword = (node->length | (alignment-1)) + 1 - alignment;
-
-               split_node->base = node->base;
-               split_node->length = temp_dword;
-
-               node->length -= temp_dword;
-               node->base += split_node->length;
-
-               /* Put it in the list */
-               *head = split_node;
-               split_node->next = node;
-       }
-
-       if (node->length < alignment) {
-               return(NULL);
-       }
-
-       /* Now unlink it */
-       if (*head == node) {
-               *head = node->next;
-               node->next = NULL;
-       } else {
-               prevnode = *head;
-               while (prevnode->next != node)
-                       prevnode = prevnode->next;
-
-               prevnode->next = node->next;
-               node->next = NULL;
-       }
-
-       return(node);
-}
-
-
-/*
- * do_bridge_resource_split
- *
- *     Returns zero or one node of resources that aren't in use
- *
- */
-static struct pci_resource *do_bridge_resource_split (struct pci_resource **head, u32 alignment)
-{
-       struct pci_resource *prevnode = NULL;
-       struct pci_resource *node;
-       u32 rc;
-       u32 temp_dword;
-
-       if (!(*head))
-               return(NULL);
-
-       rc = shpchp_resource_sort_and_combine(head);
-
-       if (rc)
-               return(NULL);
-
-       node = *head;
-
-       while (node->next) {
-               prevnode = node;
-               node = node->next;
-               kfree(prevnode);
-       }
-
-       if (node->length < alignment) {
-               kfree(node);
-               return(NULL);
-       }
-
-       if (node->base & (alignment - 1)) {
-               /* Short circuit if adjusted size is too small */
-               temp_dword = (node->base | (alignment-1)) + 1;
-               if ((node->length - (temp_dword - node->base)) < alignment) {
-                       kfree(node);
-                       return(NULL);
-               }
-
-               node->length -= (temp_dword - node->base);
-               node->base = temp_dword;
-       }
-
-       if (node->length & (alignment - 1)) {
-               /* There's stuff in use after this node */
-               kfree(node);
-               return(NULL);
-       }
-
-       return(node);
-}
-
-
-/*
- * get_io_resource
- *
- * this function sorts the resource list by size and then
- * returns the first node of "size" length that is not in the
- * ISA aliasing window.  If it finds a node larger than "size"
- * it will split it up.
- *
- * size must be a power of two.
- */
-static struct pci_resource *get_io_resource (struct pci_resource **head, u32 size)
-{
-       struct pci_resource *prevnode;
-       struct pci_resource *node;
-       struct pci_resource *split_node = NULL;
-       u32 temp_dword;
-
-       if (!(*head))
-               return(NULL);
-
-       if ( shpchp_resource_sort_and_combine(head) )
-               return(NULL);
-
-       if ( sort_by_size(head) )
-               return(NULL);
-
-       for (node = *head; node; node = node->next) {
-               if (node->length < size)
-                       continue;
-
-               if (node->base & (size - 1)) {
-                       /* This one isn't base aligned properly
-                          so we'll make a new entry and split it up */
-                       temp_dword = (node->base | (size-1)) + 1;
-
-                       /*/ Short circuit if adjusted size is too small */
-                       if ((node->length - (temp_dword - node->base)) < size)
-                               continue;
-
-                       split_node = kmalloc(sizeof(*split_node), GFP_KERNEL);
-
-                       if (!split_node)
-                               return(NULL);
-
-                       split_node->base = node->base;
-                       split_node->length = temp_dword - node->base;
-                       node->base = temp_dword;
-                       node->length -= split_node->length;
-
-                       /* Put it in the list */
-                       split_node->next = node->next;
-                       node->next = split_node;
-               } /* End of non-aligned base */
-
-               /* Don't need to check if too small since we already did */
-               if (node->length > size) {
-                       /* This one is longer than we need
-                          so we'll make a new entry and split it up */
-                       split_node = kmalloc(sizeof(*split_node), GFP_KERNEL);
-
-                       if (!split_node)
-                               return(NULL);
-
-                       split_node->base = node->base + size;
-                       split_node->length = node->length - size;
-                       node->length = size;
-
-                       /* Put it in the list */
-                       split_node->next = node->next;
-                       node->next = split_node;
-               }  /* End of too big on top end */
-
-               /* For IO make sure it's not in the ISA aliasing space */
-               if (node->base & 0x300L)
-                       continue;
-
-               /* If we got here, then it is the right size 
-                  Now take it out of the list */
-               if (*head == node) {
-                       *head = node->next;
-               } else {
-                       prevnode = *head;
-                       while (prevnode->next != node)
-                               prevnode = prevnode->next;
-
-                       prevnode->next = node->next;
-               }
-               node->next = NULL;
-               /* Stop looping */
-               break;
-       }
-
-       return(node);
-}
-
-
-/*
- * get_max_resource
- *
- * Gets the largest node that is at least "size" big from the
- * list pointed to by head.  It aligns the node on top and bottom
- * to "size" alignment before returning it.
- * J.I. modified to put max size limits of; 64M->32M->16M->8M->4M->1M
- *  This is needed to avoid allocating entire ACPI _CRS res to one child bridge/slot.
- */
-static struct pci_resource *get_max_resource (struct pci_resource **head, u32 size)
-{
-       struct pci_resource *max;
-       struct pci_resource *temp;
-       struct pci_resource *split_node;
-       u32 temp_dword;
-       u32 max_size[] = { 0x4000000, 0x2000000, 0x1000000, 0x0800000, 0x0400000, 0x0200000, 0x0100000, 0x00 };
-       int i;
-
-       if (!(*head))
-               return(NULL);
-
-       if (shpchp_resource_sort_and_combine(head))
-               return(NULL);
-
-       if (sort_by_max_size(head))
-               return(NULL);
-
-       for (max = *head;max; max = max->next) {
-
-               /* If not big enough we could probably just bail, 
-                  instead we'll continue to the next. */
-               if (max->length < size)
-                       continue;
-
-               if (max->base & (size - 1)) {
-                       /* This one isn't base aligned properly
-                          so we'll make a new entry and split it up */
-                       temp_dword = (max->base | (size-1)) + 1;
-
-                       /* Short circuit if adjusted size is too small */
-                       if ((max->length - (temp_dword - max->base)) < size)
-                               continue;
-
-                       split_node = kmalloc(sizeof(*split_node), GFP_KERNEL);
-
-                       if (!split_node)
-                               return(NULL);
-
-                       split_node->base = max->base;
-                       split_node->length = temp_dword - max->base;
-                       max->base = temp_dword;
-                       max->length -= split_node->length;
-
-                       /* Put it next in the list */
-                       split_node->next = max->next;
-                       max->next = split_node;
-               }
-
-               if ((max->base + max->length) & (size - 1)) {
-                       /* This one isn't end aligned properly at the top
-                          so we'll make a new entry and split it up */
-                       split_node = kmalloc(sizeof(*split_node), GFP_KERNEL);
-
-                       if (!split_node)
-                               return(NULL);
-                       temp_dword = ((max->base + max->length) & ~(size - 1));
-                       split_node->base = temp_dword;
-                       split_node->length = max->length + max->base
-                                            - split_node->base;
-                       max->length -= split_node->length;
-
-                       /* Put it in the list */
-                       split_node->next = max->next;
-                       max->next = split_node;
-               }
-
-               /* Make sure it didn't shrink too much when we aligned it */
-               if (max->length < size)
-                       continue;
-
-               for ( i = 0; max_size[i] > size; i++) {
-                       if (max->length > max_size[i]) {
-                               split_node = kmalloc(sizeof(*split_node),
-                                                       GFP_KERNEL);
-                               if (!split_node)
-                                       break;  /* return (NULL); */
-                               split_node->base = max->base + max_size[i];
-                               split_node->length = max->length - max_size[i];
-                               max->length = max_size[i];
-                               /* Put it next in the list */
-                               split_node->next = max->next;
-                               max->next = split_node;
-                               break;
-                       }
-               }
-
-               /* Now take it out of the list */
-               temp = (struct pci_resource*) *head;
-               if (temp == max) {
-                       *head = max->next;
-               } else {
-                       while (temp && temp->next != max) {
-                               temp = temp->next;
-                       }
-
-                       temp->next = max->next;
-               }
-
-               max->next = NULL;
-               return(max);
-       }
-
-       /* If we get here, we couldn't find one */
-       return(NULL);
-}
-
-
-/*
- * get_resource
- *
- * this function sorts the resource list by size and then
- * returns the first node of "size" length.  If it finds a node
- * larger than "size" it will split it up.
- *
- * size must be a power of two.
- */
-static struct pci_resource *get_resource (struct pci_resource **head, u32 size)
-{
-       struct pci_resource *prevnode;
-       struct pci_resource *node;
-       struct pci_resource *split_node;
-       u32 temp_dword;
-
-       if (!(*head))
-               return(NULL);
-
-       if ( shpchp_resource_sort_and_combine(head) )
-               return(NULL);
-
-       if ( sort_by_size(head) )
-               return(NULL);
-
-       for (node = *head; node; node = node->next) {
-               dbg("%s: req_size =0x%x node=%p, base=0x%x, length=0x%x\n",
-                   __FUNCTION__, size, node, node->base, node->length);
-               if (node->length < size)
-                       continue;
-
-               if (node->base & (size - 1)) {
-                       dbg("%s: not aligned\n", __FUNCTION__);
-                       /* this one isn't base aligned properly
-                          so we'll make a new entry and split it up */
-                       temp_dword = (node->base | (size-1)) + 1;
-
-                       /* Short circuit if adjusted size is too small */
-                       if ((node->length - (temp_dword - node->base)) < size)
-                               continue;
-
-                       split_node = kmalloc(sizeof(*split_node), GFP_KERNEL);
-
-                       if (!split_node)
-                               return(NULL);
-
-                       split_node->base = node->base;
-                       split_node->length = temp_dword - node->base;
-                       node->base = temp_dword;
-                       node->length -= split_node->length;
-
-                       /* Put it in the list */
-                       split_node->next = node->next;
-                       node->next = split_node;
-               } /* End of non-aligned base */
-
-               /* Don't need to check if too small since we already did */
-               if (node->length > size) {
-                       dbg("%s: too big\n", __FUNCTION__);
-                       /* this one is longer than we need
-                          so we'll make a new entry and split it up */
-                       split_node = kmalloc(sizeof(*split_node), GFP_KERNEL);
-
-                       if (!split_node)
-                               return(NULL);
-
-                       split_node->base = node->base + size;
-                       split_node->length = node->length - size;
-                       node->length = size;
-
-                       /* Put it in the list */
-                       split_node->next = node->next;
-                       node->next = split_node;
-               }  /* End of too big on top end */
-
-               dbg("%s: got one!!!\n", __FUNCTION__);
-               /* If we got here, then it is the right size
-                  Now take it out of the list */
-               if (*head == node) {
-                       *head = node->next;
-               } else {
-                       prevnode = *head;
-                       while (prevnode->next != node)
-                               prevnode = prevnode->next;
-
-                       prevnode->next = node->next;
-               }
-               node->next = NULL;
-               /* Stop looping */
-               break;
-       }
-       return(node);
-}
-
-
-/*
- * shpchp_resource_sort_and_combine
- *
- * Sorts all of the nodes in the list in ascending order by
- * their base addresses.  Also does garbage collection by
- * combining adjacent nodes.
- *
- * returns 0 if success
- */
-int shpchp_resource_sort_and_combine(struct pci_resource **head)
-{
-       struct pci_resource *node1;
-       struct pci_resource *node2;
-       int out_of_order = 1;
-
-       dbg("%s: head = %p, *head = %p\n", __FUNCTION__, head, *head);
-
-       if (!(*head))
-               return(1);
-
-       dbg("*head->next = %p\n",(*head)->next);
-
-       if (!(*head)->next)
-               return(0);      /* only one item on the list, already sorted! */
-
-       dbg("*head->base = 0x%x\n",(*head)->base);
-       dbg("*head->next->base = 0x%x\n",(*head)->next->base);
-       while (out_of_order) {
-               out_of_order = 0;
-
-               /* Special case for swapping list head */
-               if (((*head)->next) &&
-                   ((*head)->base > (*head)->next->base)) {
-                       node1 = *head;
-                       (*head) = (*head)->next;
-                       node1->next = (*head)->next;
-                       (*head)->next = node1;
-                       out_of_order++;
-               }
-
-               node1 = (*head);
-
-               while (node1->next && node1->next->next) {
-                       if (node1->next->base > node1->next->next->base) {
-                               out_of_order++;
-                               node2 = node1->next;
-                               node1->next = node1->next->next;
-                               node1 = node1->next;
-                               node2->next = node1->next;
-                               node1->next = node2;
-                       } else
-                               node1 = node1->next;
-               }
-       }  /* End of out_of_order loop */
-
-       node1 = *head;
-
-       while (node1 && node1->next) {
-               if ((node1->base + node1->length) == node1->next->base) {
-                       /* Combine */
-                       dbg("8..\n");
-                       node1->length += node1->next->length;
-                       node2 = node1->next;
-                       node1->next = node1->next->next;
-                       kfree(node2);
-               } else
-                       node1 = node1->next;
-       }
-
-       return(0);
-}
-
-
-/**
- * shpchp_slot_create - Creates a node and adds it to the proper bus.
- * @busnumber - bus where new node is to be located
- *
- * Returns pointer to the new node or NULL if unsuccessful
- */
-struct pci_func *shpchp_slot_create(u8 busnumber)
-{
-       struct pci_func *new_slot;
-       struct pci_func *next;
-
-       new_slot = kmalloc(sizeof(*new_slot), GFP_KERNEL);
-
-       if (new_slot == NULL) {
-               return(new_slot);
-       }
-
-       memset(new_slot, 0, sizeof(struct pci_func));
-
-       new_slot->next = NULL;
-       new_slot->configured = 1;
-
-       if (shpchp_slot_list[busnumber] == NULL) {
-               shpchp_slot_list[busnumber] = new_slot;
-       } else {
-               next = shpchp_slot_list[busnumber];
-               while (next->next != NULL)
-                       next = next->next;
-               next->next = new_slot;
-       }
-       return(new_slot);
-}
-
-
-/*
- * slot_remove - Removes a node from the linked list of slots.
- * @old_slot: slot to remove
- *
- * Returns 0 if successful, !0 otherwise.
- */
-static int slot_remove(struct pci_func * old_slot)
-{
-       struct pci_func *next;
-
-       if (old_slot == NULL)
-               return(1);
-
-       next = shpchp_slot_list[old_slot->bus];
-
-       if (next == NULL) {
-               return(1);
-       }
-
-       if (next == old_slot) {
-               shpchp_slot_list[old_slot->bus] = old_slot->next;
-               shpchp_destroy_board_resources(old_slot);
-               kfree(old_slot);
-               return(0);
-       }
-
-       while ((next->next != old_slot) && (next->next != NULL)) {
-               next = next->next;
-       }
-
-       if (next->next == old_slot) {
-               next->next = old_slot->next;
-               shpchp_destroy_board_resources(old_slot);
-               kfree(old_slot);
-               return(0);
-       } else
-               return(2);
-}
-
-
-/**
- * bridge_slot_remove - Removes a node from the linked list of slots.
- * @bridge: bridge to remove
- *
- * Returns 0 if successful, !0 otherwise.
- */
-static int bridge_slot_remove(struct pci_func *bridge)
-{
-       u8 subordinateBus, secondaryBus;
-       u8 tempBus;
-       struct pci_func *next;
-
-       if (bridge == NULL)
-               return(1);
-
-       secondaryBus = (bridge->config_space[0x06] >> 8) & 0xFF;
-       subordinateBus = (bridge->config_space[0x06] >> 16) & 0xFF;
-
-       for (tempBus = secondaryBus; tempBus <= subordinateBus; tempBus++) {
-               next = shpchp_slot_list[tempBus];
-
-               while (!slot_remove(next)) {
-                       next = shpchp_slot_list[tempBus];
-               }
-       }
-
-       next = shpchp_slot_list[bridge->bus];
-
-       if (next == NULL) {
-               return(1);
-       }
-
-       if (next == bridge) {
-               shpchp_slot_list[bridge->bus] = bridge->next;
-               kfree(bridge);
-               return(0);
-       }
-
-       while ((next->next != bridge) && (next->next != NULL)) {
-               next = next->next;
-       }
-
-       if (next->next == bridge) {
-               next->next = bridge->next;
-               kfree(bridge);
-               return(0);
-       } else
-               return(2);
-}
-
-
-/**
- * shpchp_slot_find - Looks for a node by bus, and device, multiple functions accessed
- * @bus: bus to find
- * @device: device to find
- * @index: is 0 for first function found, 1 for the second...
- *
- * Returns pointer to the node if successful, %NULL otherwise.
- */
-struct pci_func *shpchp_slot_find(u8 bus, u8 device, u8 index)
-{
-       int found = -1;
-       struct pci_func *func;
-
-       func = shpchp_slot_list[bus];
-
-       if ((func == NULL) || ((func->device == device) && (index == 0)))
-               return(func);
-
-       if (func->device == device)
-               found++;
-
-       while (func->next != NULL) {
-               func = func->next;
-
-               if (func->device == device)
-                       found++;
-
-               if (found == index)
-                       return(func);
-       }
-
-       return(NULL);
-}
-
-static int is_bridge(struct pci_func * func)
-{
-       /* Check the header type */
-       if (((func->config_space[0x03] >> 16) & 0xFF) == 0x01)
-               return 1;
-       else
-               return 0;
-}
-
-
 /* The following routines constitute the bulk of the 
    hotplug controller logic
  */
-static u32 change_bus_speed(struct controller *ctrl, struct slot *p_slot, enum pci_bus_speed speed)
+static int change_bus_speed(struct controller *ctrl, struct slot *p_slot,
+               enum pci_bus_speed speed)
 { 
-       u32 rc = 0;
+       int rc = 0;
 
        dbg("%s: change to speed %d\n", __FUNCTION__, speed);
        down(&ctrl->crit_sect);
@@ -1074,10 +261,11 @@ static u32 change_bus_speed(struct controller *ctrl, struct slot *p_slot, enum p
        return rc;
 }
 
-static u32 fix_bus_speed(struct controller *ctrl, struct slot *pslot, u8 flag, 
-enum pci_bus_speed asp, enum pci_bus_speed bsp, enum pci_bus_speed msp)
+static int fix_bus_speed(struct controller *ctrl, struct slot *pslot,
+               u8 flag, enum pci_bus_speed asp, enum pci_bus_speed bsp,
+               enum pci_bus_speed msp)
 { 
-       u32 rc = 0;
+       int rc = 0;
        
        if (flag != 0) { /* Other slots on the same bus are occupied */
                if ( asp < bsp ) {
@@ -1116,23 +304,20 @@ enum pci_bus_speed asp, enum pci_bus_speed bsp, enum pci_bus_speed msp)
  * Configures board
  *
  */
-static u32 board_added(struct pci_func * func, struct controller * ctrl)
+static int board_added(struct slot *p_slot)
 {
        u8 hp_slot;
        u8 slots_not_empty = 0;
-       int index;
-       u32 temp_register = 0xFFFFFFFF;
-       u32 retval, rc = 0;
-       struct pci_func *new_func = NULL;
-       struct slot *p_slot;
-       struct resource_lists res_lists;
+       int rc = 0;
        enum pci_bus_speed adapter_speed, bus_speed, max_bus_speed;
        u8 pi, mode;
+       struct controller *ctrl = p_slot->ctrl;
 
-       p_slot = shpchp_find_slot(ctrl, func->device);
-       hp_slot = func->device - ctrl->slot_device_offset;
+       hp_slot = p_slot->device - ctrl->slot_device_offset;
 
-       dbg("%s: func->device, slot_offset, hp_slot = %d, %d ,%d\n", __FUNCTION__, func->device, ctrl->slot_device_offset, hp_slot);
+       dbg("%s: p_slot->device, slot_offset, hp_slot = %d, %d ,%d\n",
+                       __FUNCTION__, p_slot->device,
+                       ctrl->slot_device_offset, hp_slot);
 
        /* Wait for exclusive access to hardware */
        down(&ctrl->crit_sect);
@@ -1320,143 +505,68 @@ static u32 board_added(struct pci_func * func, struct controller * ctrl)
        up(&ctrl->crit_sect);
 
        /* Wait for ~1 second */
-       dbg("%s: before long_delay\n", __FUNCTION__);
        wait_for_ctrl_irq (ctrl);
-       dbg("%s: after long_delay\n", __FUNCTION__);
 
-       dbg("%s: func status = %x\n", __FUNCTION__, func->status);
+       dbg("%s: slot status = %x\n", __FUNCTION__, p_slot->status);
        /* Check for a power fault */
-       if (func->status == 0xFF) {
+       if (p_slot->status == 0xFF) {
                /* power fault occurred, but it was benign */
-               temp_register = 0xFFFFFFFF;
-               dbg("%s: temp register set to %x by power fault\n", __FUNCTION__, temp_register);
+               dbg("%s: power fault\n", __FUNCTION__);
                rc = POWER_FAILURE;
-               func->status = 0;
-       } else {
-               /* Get vendor/device ID u32 */
-               rc = pci_bus_read_config_dword (ctrl->pci_dev->subordinate, PCI_DEVFN(func->device, func->function), 
-                       PCI_VENDOR_ID, &temp_register);
-               dbg("%s: pci_bus_read_config_dword returns %d\n", __FUNCTION__, rc);
-               dbg("%s: temp_register is %x\n", __FUNCTION__, temp_register);
-
-               if (rc != 0) {
-                       /* Something's wrong here */
-                       temp_register = 0xFFFFFFFF;
-                       dbg("%s: temp register set to %x by error\n", __FUNCTION__, temp_register);
-               }
-               /* Preset return code.  It will be changed later if things go okay. */
-               rc = NO_ADAPTER_PRESENT;
+               p_slot->status = 0;
+               goto err_exit;
        }
 
-       /* All F's is an empty slot or an invalid board */
-       if (temp_register != 0xFFFFFFFF) {        /* Check for a board in the slot */
-               res_lists.io_head = ctrl->io_head;
-               res_lists.mem_head = ctrl->mem_head;
-               res_lists.p_mem_head = ctrl->p_mem_head;
-               res_lists.bus_head = ctrl->bus_head;
-               res_lists.irqs = NULL;
+       if (shpchp_configure_device(p_slot)) {
+               err("Cannot add device at 0x%x:0x%x\n", p_slot->bus,
+                               p_slot->device);
+               goto err_exit;
+       }
 
-               rc = configure_new_device(ctrl, func, 0, &res_lists, 0, 0);
-               dbg("%s: back from configure_new_device\n", __FUNCTION__);
+       p_slot->status = 0;
+       p_slot->is_a_board = 0x01;
+       p_slot->pwr_save = 1;
 
-               ctrl->io_head = res_lists.io_head;
-               ctrl->mem_head = res_lists.mem_head;
-               ctrl->p_mem_head = res_lists.p_mem_head;
-               ctrl->bus_head = res_lists.bus_head;
+       /* Wait for exclusive access to hardware */
+       down(&ctrl->crit_sect);
 
-               shpchp_resource_sort_and_combine(&(ctrl->mem_head));
-               shpchp_resource_sort_and_combine(&(ctrl->p_mem_head));
-               shpchp_resource_sort_and_combine(&(ctrl->io_head));
-               shpchp_resource_sort_and_combine(&(ctrl->bus_head));
+       p_slot->hpc_ops->green_led_on(p_slot);
 
-               if (rc) {
-                       /* Wait for exclusive access to hardware */
-                       down(&ctrl->crit_sect);
-
-                       /* turn off slot, turn on Amber LED, turn off Green LED */
-                       retval = p_slot->hpc_ops->slot_disable(p_slot);
-                       if (retval) {
-                               err("%s: Issue of Slot Enable command failed\n", __FUNCTION__);
-                               /* Done with exclusive hardware access */
-                               up(&ctrl->crit_sect);
-                               return retval;
-                       }
-                       /* Wait for the command to complete */
-                       wait_for_ctrl_irq (ctrl);
-
-                       retval = p_slot->hpc_ops->check_cmd_status(ctrl);
-                       if (retval) {
-                               err("%s: Failed to disable slot, error code(%d)\n", __FUNCTION__, retval);
-                               /* Done with exclusive hardware access */
-                               up(&ctrl->crit_sect);
-                               return retval;  
-                       }
-
-                       /* Done with exclusive hardware access */
-                       up(&ctrl->crit_sect);
-
-                       return(rc);
-               }
-               shpchp_save_slot_config(ctrl, func);
-
-               func->status = 0;
-               func->switch_save = 0x10;
-               func->is_a_board = 0x01;
-               func->pwr_save = 1;
-
-               /* Next, we will instantiate the linux pci_dev structures 
-                * (with appropriate driver notification, if already present) 
-                */
-               index = 0;
-               do {
-                       new_func = shpchp_slot_find(ctrl->slot_bus, func->device, index++);
-                       if (new_func && !new_func->pci_dev) {
-                               dbg("%s:call pci_hp_configure_dev\n", __FUNCTION__);
-                               shpchp_configure_device(ctrl, new_func);
-                       }
-               } while (new_func);
-
-               /* Wait for exclusive access to hardware */
-               down(&ctrl->crit_sect);
+       /* Wait for the command to complete */
+       wait_for_ctrl_irq (ctrl);
 
-               p_slot->hpc_ops->green_led_on(p_slot);
+       /* Done with exclusive hardware access */
+       up(&ctrl->crit_sect);
 
-               /* Wait for the command to complete */
-               wait_for_ctrl_irq (ctrl);
+       return 0;
 
+err_exit:
+       /* Wait for exclusive access to hardware */
+       down(&ctrl->crit_sect);
 
+       /* turn off slot, turn on Amber LED, turn off Green LED */
+       rc = p_slot->hpc_ops->slot_disable(p_slot);
+       if (rc) {
+               err("%s: Issue of Slot Disable command failed\n", __FUNCTION__);
                /* Done with exclusive hardware access */
                up(&ctrl->crit_sect);
+               return rc;
+       }
+       /* Wait for the command to complete */
+       wait_for_ctrl_irq (ctrl);
 
-       } else {
-               /* Wait for exclusive access to hardware */
-               down(&ctrl->crit_sect);
-
-               /* turn off slot, turn on Amber LED, turn off Green LED */
-               rc = p_slot->hpc_ops->slot_disable(p_slot);
-               if (rc) {
-                       err("%s: Issue of Slot Disable command failed\n", __FUNCTION__);
-                       /* Done with exclusive hardware access */
-                       up(&ctrl->crit_sect);
-                       return rc;
-               }
-               /* Wait for the command to complete */
-               wait_for_ctrl_irq (ctrl);
-
-               rc = p_slot->hpc_ops->check_cmd_status(ctrl);
-               if (rc) {
-                       err("%s: Failed to disable slot, error code(%d)\n", __FUNCTION__, rc);
-                       /* Done with exclusive hardware access */
-                       up(&ctrl->crit_sect);
-                       return rc;  
-               }
-
+       rc = p_slot->hpc_ops->check_cmd_status(ctrl);
+       if (rc) {
+               err("%s: Failed to disable slot, error code(%d)\n", __FUNCTION__, rc);
                /* Done with exclusive hardware access */
                up(&ctrl->crit_sect);
-
-               return(rc);
+               return rc;
        }
-       return 0;
+
+       /* Done with exclusive hardware access */
+       up(&ctrl->crit_sect);
+
+       return(rc);
 }
 
 
@@ -1464,55 +574,23 @@ static u32 board_added(struct pci_func * func, struct controller * ctrl)
  * remove_board - Turns off slot and LED's
  *
  */
-static u32 remove_board(struct pci_func *func, struct controller *ctrl)
+static int remove_board(struct slot *p_slot)
 {
-       int index;
-       u8 skip = 0;
-       u8 device;
+       struct controller *ctrl = p_slot->ctrl;
        u8 hp_slot;
-       u32 rc;
-       struct resource_lists res_lists;
-       struct pci_func *temp_func;
-       struct slot *p_slot;
-
-       if (func == NULL)
-               return(1);
+       int rc;
 
-       if (shpchp_unconfigure_device(func))
+       if (shpchp_unconfigure_device(p_slot))
                return(1);
 
-       device = func->device;
-
-       hp_slot = func->device - ctrl->slot_device_offset;
+       hp_slot = p_slot->device - ctrl->slot_device_offset;
        p_slot = shpchp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset);
 
        dbg("In %s, hp_slot = %d\n", __FUNCTION__, hp_slot);
 
-       if ((ctrl->add_support) &&
-               !(func->bus_head || func->mem_head || func->p_mem_head || func->io_head)) {
-               /* Here we check to see if we've saved any of the board's
-                * resources already.  If so, we'll skip the attempt to
-                * determine what's being used.
-                */
-               index = 0;
-
-               temp_func = func;
-
-               while ((temp_func = shpchp_slot_find(temp_func->bus, temp_func->device, index++))) {
-                       if (temp_func->bus_head || temp_func->mem_head
-                           || temp_func->p_mem_head || temp_func->io_head) {
-                               skip = 1;
-                               break;
-                       }
-               }
-
-               if (!skip)
-                       rc = shpchp_save_used_resources(ctrl, func, DISABLE_CARD);
-       }
        /* Change status to shutdown */
-       if (func->is_a_board)
-               func->status = 0x01;
-       func->configured = 0;
+       if (p_slot->is_a_board)
+               p_slot->status = 0x01;
 
        /* Wait for exclusive access to hardware */
        down(&ctrl->crit_sect);
@@ -1549,55 +627,8 @@ static u32 remove_board(struct pci_func *func, struct controller *ctrl)
        /* Done with exclusive hardware access */
        up(&ctrl->crit_sect);
 
-       if (ctrl->add_support) {
-               while (func) {
-                       res_lists.io_head = ctrl->io_head;
-                       res_lists.mem_head = ctrl->mem_head;
-                       res_lists.p_mem_head = ctrl->p_mem_head;
-                       res_lists.bus_head = ctrl->bus_head;
-
-                       dbg("Returning resources to ctlr lists for (B/D/F) = (%#x/%#x/%#x)\n", func->bus, 
-                               func->device, func->function);
-
-                       shpchp_return_board_resources(func, &res_lists);
-
-                       ctrl->io_head = res_lists.io_head;
-                       ctrl->mem_head = res_lists.mem_head;
-                       ctrl->p_mem_head = res_lists.p_mem_head;
-                       ctrl->bus_head = res_lists.bus_head;
-
-                       shpchp_resource_sort_and_combine(&(ctrl->mem_head));
-                       shpchp_resource_sort_and_combine(&(ctrl->p_mem_head));
-                       shpchp_resource_sort_and_combine(&(ctrl->io_head));
-                       shpchp_resource_sort_and_combine(&(ctrl->bus_head));
-
-                       if (is_bridge(func)) {
-                               dbg("PCI Bridge Hot-Remove s:b:d:f(%02x:%02x:%02x:%02x)\n", ctrl->seg, func->bus, 
-                                       func->device, func->function);
-                               bridge_slot_remove(func);
-                       } else
-                               dbg("PCI Function Hot-Remove s:b:d:f(%02x:%02x:%02x:%02x)\n", ctrl->seg, func->bus, 
-                                       func->device, func->function);
-                               slot_remove(func);
-
-                       func = shpchp_slot_find(ctrl->slot_bus, device, 0);
-               }
-
-               /* Setup slot structure with entry for empty slot */
-               func = shpchp_slot_create(ctrl->slot_bus);
-
-               if (func == NULL) {
-                       return(1);
-               }
-
-               func->bus = ctrl->slot_bus;
-               func->device = device;
-               func->function = 0;
-               func->configured = 0;
-               func->switch_save = 0x10;
-               func->pwr_save = 0;
-               func->is_a_board = 0;
-       }
+       p_slot->pwr_save = 0;
+       p_slot->is_a_board = 0;
 
        return 0;
 }
@@ -1633,13 +664,11 @@ static void shpchp_pushbutton_thread (unsigned long slot)
        p_slot->hpc_ops->get_power_status(p_slot, &getstatus);
        if (getstatus) {
                p_slot->state = POWEROFF_STATE;
-               dbg("In power_down_board, b:d(%x:%x)\n", p_slot->bus, p_slot->device);
 
                shpchp_disable_slot(p_slot);
                p_slot->state = STATIC_STATE;
        } else {
                p_slot->state = POWERON_STATE;
-               dbg("In add_board, b:d(%x:%x)\n", p_slot->bus, p_slot->device);
 
                if (shpchp_enable_slot(p_slot)) {
                        /* Wait for exclusive access to hardware */
@@ -1701,7 +730,6 @@ int shpchp_event_start_thread (void)
                err ("Can't start up our event thread\n");
                return -1;
        }
-       dbg("Our event thread pid = %d\n", pid);
        return 0;
 }
 
@@ -1709,9 +737,7 @@ int shpchp_event_start_thread (void)
 void shpchp_event_stop_thread (void)
 {
        event_finished = 1;
-       dbg("event_thread finish command given\n");
        up(&event_semaphore);
-       dbg("wait for event_thread to exit\n");
        down(&event_exit);
 }
 
@@ -1739,12 +765,10 @@ static void interrupt_event_handler(struct controller *ctrl)
 {
        int loop = 0;
        int change = 1;
-       struct pci_func *func;
        u8 hp_slot;
        u8 getstatus;
        struct slot *p_slot;
 
-       dbg("%s:\n", __FUNCTION__);
        while (change) {
                change = 0;
 
@@ -1754,12 +778,8 @@ static void interrupt_event_handler(struct controller *ctrl)
                                        ctrl->event_queue[loop].event_type);
                                hp_slot = ctrl->event_queue[loop].hp_slot;
 
-                               func = shpchp_slot_find(ctrl->slot_bus, (hp_slot + ctrl->slot_device_offset), 0);
-
                                p_slot = shpchp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset);
 
-                               dbg("%s: hp_slot %d, func %p, p_slot %p\n", __FUNCTION__, hp_slot, func, p_slot);
-
                                if (ctrl->event_queue[loop].event_type == INT_BUTTON_CANCEL) {
                                        dbg("%s: button cancel\n", __FUNCTION__);
                                        del_timer(&p_slot->task_event);
@@ -1880,13 +900,6 @@ int shpchp_enable_slot (struct slot *p_slot)
 {
        u8 getstatus = 0;
        int rc;
-       struct pci_func *func;
-
-       func = shpchp_slot_find(p_slot->bus, p_slot->device, 0);
-       if (!func) {
-               dbg("%s: Error! slot NULL\n", __FUNCTION__);
-               return -ENODEV;
-       }
 
        /* Check to see if (latch closed, card present, power off) */
        down(&p_slot->ctrl->crit_sect);
@@ -1910,72 +923,34 @@ int shpchp_enable_slot (struct slot *p_slot)
        }
        up(&p_slot->ctrl->crit_sect);
 
-       slot_remove(func);
-
-       func = shpchp_slot_create(p_slot->bus);
-       if (func == NULL)
-               return -ENOMEM;
-
-       func->bus = p_slot->bus;
-       func->device = p_slot->device;
-       func->function = 0;
-       func->configured = 0;
-       func->is_a_board = 1;
+       p_slot->is_a_board = 1;
 
        /* We have to save the presence info for these slots */
-       p_slot->hpc_ops->get_adapter_status(p_slot, &(func->presence_save));
-       p_slot->hpc_ops->get_power_status(p_slot, &(func->pwr_save));
-       dbg("%s: func->pwr_save %x\n", __FUNCTION__, func->pwr_save);
+       p_slot->hpc_ops->get_adapter_status(p_slot, &(p_slot->presence_save));
+       p_slot->hpc_ops->get_power_status(p_slot, &(p_slot->pwr_save));
+       dbg("%s: p_slot->pwr_save %x\n", __FUNCTION__, p_slot->pwr_save);
        p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
-       func->switch_save = !getstatus? 0x10:0;
 
-       rc = board_added(func, p_slot->ctrl);
+       rc = board_added(p_slot);
        if (rc) {
-               if (is_bridge(func))
-                       bridge_slot_remove(func);
-               else
-                       slot_remove(func);
-
-               /* Setup slot structure with entry for empty slot */
-               func = shpchp_slot_create(p_slot->bus);
-               if (func == NULL)
-                       return -ENOMEM; /* Out of memory */
-
-               func->bus = p_slot->bus;
-               func->device = p_slot->device;
-               func->function = 0;
-               func->configured = 0;
-               func->is_a_board = 1;
-
-               /* We have to save the presence info for these slots */
-               p_slot->hpc_ops->get_adapter_status(p_slot, &(func->presence_save));
+               p_slot->hpc_ops->get_adapter_status(p_slot,
+                               &(p_slot->presence_save));
                p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
-               func->switch_save = !getstatus? 0x10:0;
        }
 
-       if (p_slot)
-               update_slot_info(p_slot);
-
+       update_slot_info(p_slot);
        return rc;
 }
 
 
 int shpchp_disable_slot (struct slot *p_slot)
 {
-       u8 class_code, header_type, BCR;
-       u8 index = 0;
        u8 getstatus = 0;
-       u32 rc = 0;
        int ret = 0;
-       unsigned int devfn;
-       struct pci_bus *pci_bus;
-       struct pci_func *func;
 
        if (!p_slot->ctrl)
                return -ENODEV;
 
-       pci_bus = p_slot->ctrl->pci_dev->subordinate;
-
        /* Check to see if (latch closed, card present, power on) */
        down(&p_slot->ctrl->crit_sect);
 
@@ -1999,849 +974,8 @@ int shpchp_disable_slot (struct slot *p_slot)
        }
        up(&p_slot->ctrl->crit_sect);
 
-       func = shpchp_slot_find(p_slot->bus, p_slot->device, index++);
-
-       /* Make sure there are no video controllers here
-        * for all func of p_slot
-        */
-       while (func && !rc) {
-               pci_bus->number = func->bus;
-               devfn = PCI_DEVFN(func->device, func->function);
-
-               /* Check the Class Code */
-               rc = pci_bus_read_config_byte (pci_bus, devfn, 0x0B, &class_code);
-               if (rc)
-                       return -ENODEV;
-
-               if (class_code == PCI_BASE_CLASS_DISPLAY) {
-                       /* Display/Video adapter (not supported) */
-                       rc = REMOVE_NOT_SUPPORTED;
-               } else {
-                       /* See if it's a bridge */
-                       rc = pci_bus_read_config_byte (pci_bus, devfn, PCI_HEADER_TYPE, &header_type);
-                       if (rc)
-                               return -ENODEV;
-
-                       /* If it's a bridge, check the VGA Enable bit */
-                       if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) {
-                               rc = pci_bus_read_config_byte (pci_bus, devfn, PCI_BRIDGE_CONTROL, &BCR);
-                               if (rc)
-                                       return -ENODEV;
-
-                               /* If the VGA Enable bit is set, remove isn't supported */
-                               if (BCR & PCI_BRIDGE_CTL_VGA) {
-                                       rc = REMOVE_NOT_SUPPORTED;
-                               }
-                       }
-               }
-
-               func = shpchp_slot_find(p_slot->bus, p_slot->device, index++);
-       }
-
-       func = shpchp_slot_find(p_slot->bus, p_slot->device, 0);
-       if ((func != NULL) && !rc) {
-               rc = remove_board(func, p_slot->ctrl);
-       } else if (!rc)
-               rc = -ENODEV;
-
-       if (p_slot)
-               update_slot_info(p_slot);
-
-       return rc;
-}
-
-
-/**
- * configure_new_device - Configures the PCI header information of one board.
- *
- * @ctrl: pointer to controller structure
- * @func: pointer to function structure
- * @behind_bridge: 1 if this is a recursive call, 0 if not
- * @resources: pointer to set of resource lists
- *
- * Returns 0 if success
- *
- */
-static u32 configure_new_device (struct controller * ctrl, struct pci_func * func,
-       u8 behind_bridge, struct resource_lists * resources, u8 bridge_bus, u8 bridge_dev)
-{
-       u8 temp_byte, function, max_functions, stop_it;
-       int rc;
-       u32 ID;
-       struct pci_func *new_slot;
-       struct pci_bus lpci_bus, *pci_bus;
-       int index;
-
-       new_slot = func;
-
-       dbg("%s\n", __FUNCTION__);
-       memcpy(&lpci_bus, ctrl->pci_dev->subordinate, sizeof(lpci_bus));
-       pci_bus = &lpci_bus;
-       pci_bus->number = func->bus;
-
-       /* Check for Multi-function device */
-       rc = pci_bus_read_config_byte(pci_bus, PCI_DEVFN(func->device, func->function), 0x0E, &temp_byte);
-       if (rc) {
-               dbg("%s: rc = %d\n", __FUNCTION__, rc);
-               return rc;
-       }
-
-       if (temp_byte & 0x80)   /* Multi-function device */
-               max_functions = 8;
-       else
-               max_functions = 1;
-
-       function = 0;
-
-       do {
-               rc = configure_new_function(ctrl, new_slot, behind_bridge, resources, bridge_bus, bridge_dev);
-
-               if (rc) {
-                       dbg("configure_new_function failed %d\n",rc);
-                       index = 0;
-
-                       while (new_slot) {
-                               new_slot = shpchp_slot_find(new_slot->bus, new_slot->device, index++);
-
-                               if (new_slot)
-                                       shpchp_return_board_resources(new_slot, resources);
-                       }
-
-                       return(rc);
-               }
-
-               function++;
-
-               stop_it = 0;
-
-               /*  The following loop skips to the next present function
-                *  and creates a board structure
-                */
-
-               while ((function < max_functions) && (!stop_it)) {
-                       pci_bus_read_config_dword(pci_bus, PCI_DEVFN(func->device, function), 0x00, &ID);
-
-                       if (ID == 0xFFFFFFFF) {   /* There's nothing there. */
-                               function++;
-                       } else {  /* There's something there */
-                               /* Setup slot structure. */
-                               new_slot = shpchp_slot_create(func->bus);
-
-                               if (new_slot == NULL) {
-                                       /* Out of memory */
-                                       return(1);
-                               }
-
-                               new_slot->bus = func->bus;
-                               new_slot->device = func->device;
-                               new_slot->function = function;
-                               new_slot->is_a_board = 1;
-                               new_slot->status = 0;
-
-                               stop_it++;
-                       }
-               }
-
-       } while (function < max_functions);
-       dbg("returning from configure_new_device\n");
-
-       return 0;
-}
-
-
-/*
- * Configuration logic that involves the hotplug data structures and 
- * their bookkeeping
- */
-
-
-/**
- * configure_new_function - Configures the PCI header information of one device
- *
- * @ctrl: pointer to controller structure
- * @func: pointer to function structure
- * @behind_bridge: 1 if this is a recursive call, 0 if not
- * @resources: pointer to set of resource lists
- *
- * Calls itself recursively for bridged devices.
- * Returns 0 if success
- *
- */
-static int configure_new_function (struct controller * ctrl, struct pci_func * func,
-       u8 behind_bridge, struct resource_lists *resources, u8 bridge_bus, u8 bridge_dev)
-{
-       int cloop;
-       u8 temp_byte;
-       u8 device;
-       u8 class_code;
-       u16 temp_word;
-       u32 rc;
-       u32 temp_register;
-       u32 base;
-       u32 ID;
-       unsigned int devfn;
-       struct pci_resource *mem_node;
-       struct pci_resource *p_mem_node;
-       struct pci_resource *io_node;
-       struct pci_resource *bus_node;
-       struct pci_resource *hold_mem_node;
-       struct pci_resource *hold_p_mem_node;
-       struct pci_resource *hold_IO_node;
-       struct pci_resource *hold_bus_node;
-       struct irq_mapping irqs;
-       struct pci_func *new_slot;
-       struct pci_bus lpci_bus, *pci_bus;
-       struct resource_lists temp_resources;
-#if defined(CONFIG_X86_64)
-       u8 IRQ=0;
-#endif
-
-       memcpy(&lpci_bus, ctrl->pci_dev->subordinate, sizeof(lpci_bus));
-       pci_bus = &lpci_bus;
-       pci_bus->number = func->bus;
-       devfn = PCI_DEVFN(func->device, func->function);
-
-       /* Check for Bridge */
-       rc = pci_bus_read_config_byte (pci_bus, devfn, PCI_HEADER_TYPE, &temp_byte);
-       if (rc)
-               return rc;
-
-       if ((temp_byte & 0x7F) == PCI_HEADER_TYPE_BRIDGE) { /* PCI-PCI Bridge */
-               /* set Primary bus */
-               dbg("set Primary bus = 0x%x\n", func->bus);
-               rc = pci_bus_write_config_byte(pci_bus, devfn, PCI_PRIMARY_BUS, func->bus);
-               if (rc)
-                       return rc;
-
-               /* find range of busses to use */
-               bus_node = get_max_resource(&resources->bus_head, 1L);
-
-               /* If we don't have any busses to allocate, we can't continue */
-               if (!bus_node) {
-                       err("Got NO bus resource to use\n");
-                       return -ENOMEM;
-               }
-               dbg("Got ranges of buses to use: base:len=0x%x:%x\n", bus_node->base, bus_node->length);
-
-               /* set Secondary bus */
-               temp_byte = (u8)bus_node->base;
-               dbg("set Secondary bus = 0x%x\n", temp_byte);
-               rc = pci_bus_write_config_byte(pci_bus, devfn, PCI_SECONDARY_BUS, temp_byte);
-               if (rc)
-                       return rc;
-
-               /* set subordinate bus */
-               temp_byte = (u8)(bus_node->base + bus_node->length - 1);
-               dbg("set subordinate bus = 0x%x\n", temp_byte);
-               rc = pci_bus_write_config_byte (pci_bus, devfn, PCI_SUBORDINATE_BUS, temp_byte);
-               if (rc)
-                       return rc;
-
-               /* Set HP parameters (Cache Line Size, Latency Timer) */
-               rc = shpchprm_set_hpp(ctrl, func, PCI_HEADER_TYPE_BRIDGE);
-               if (rc)
-                       return rc;
-
-               /* Setup the IO, memory, and prefetchable windows */
-
-               io_node = get_max_resource(&(resources->io_head), 0x1000L);
-               if (io_node) {
-                       dbg("io_node(base, len, next) (%x, %x, %p)\n", io_node->base, io_node->length, io_node->next);
-               }
-
-               mem_node = get_max_resource(&(resources->mem_head), 0x100000L);
-               if (mem_node) {
-                       dbg("mem_node(base, len, next) (%x, %x, %p)\n", mem_node->base, mem_node->length, mem_node->next);
-               }
-
-               if (resources->p_mem_head)
-                       p_mem_node = get_max_resource(&(resources->p_mem_head), 0x100000L);
-               else {
-                       /*
-                        * In some platform implementation, MEM and PMEM are not
-                        *  distinguished, and hence ACPI _CRS has only MEM entries
-                        *  for both MEM and PMEM.
-                        */
-                       dbg("using MEM for PMEM\n");
-                       p_mem_node = get_max_resource(&(resources->mem_head), 0x100000L);
-               }
-               if (p_mem_node) {
-                       dbg("p_mem_node(base, len, next) (%x, %x, %p)\n", p_mem_node->base, p_mem_node->length, p_mem_node->next);
-               }
-
-               /* set up the IRQ info */
-               if (!resources->irqs) {
-                       irqs.barber_pole = 0;
-                       irqs.interrupt[0] = 0;
-                       irqs.interrupt[1] = 0;
-                       irqs.interrupt[2] = 0;
-                       irqs.interrupt[3] = 0;
-                       irqs.valid_INT = 0;
-               } else {
-                       irqs.barber_pole = resources->irqs->barber_pole;
-                       irqs.interrupt[0] = resources->irqs->interrupt[0];
-                       irqs.interrupt[1] = resources->irqs->interrupt[1];
-                       irqs.interrupt[2] = resources->irqs->interrupt[2];
-                       irqs.interrupt[3] = resources->irqs->interrupt[3];
-                       irqs.valid_INT = resources->irqs->valid_INT;
-               }
-
-               /* set up resource lists that are now aligned on top and bottom
-                * for anything behind the bridge.
-                */
-               temp_resources.bus_head = bus_node;
-               temp_resources.io_head = io_node;
-               temp_resources.mem_head = mem_node;
-               temp_resources.p_mem_head = p_mem_node;
-               temp_resources.irqs = &irqs;
-
-               /* Make copies of the nodes we are going to pass down so that
-                * if there is a problem,we can just use these to free resources
-                */
-               hold_bus_node = kmalloc(sizeof(*hold_bus_node), GFP_KERNEL);
-               hold_IO_node = kmalloc(sizeof(*hold_IO_node), GFP_KERNEL);
-               hold_mem_node = kmalloc(sizeof(*hold_mem_node), GFP_KERNEL);
-               hold_p_mem_node = kmalloc(sizeof(*hold_p_mem_node), GFP_KERNEL);
-
-               if (!hold_bus_node || !hold_IO_node || !hold_mem_node || !hold_p_mem_node) {
-                       kfree(hold_bus_node);
-                       kfree(hold_IO_node);
-                       kfree(hold_mem_node);
-                       kfree(hold_p_mem_node);
-
-                       return 1;
-               }
-
-               memcpy(hold_bus_node, bus_node, sizeof(struct pci_resource));
-
-               bus_node->base += 1;
-               bus_node->length -= 1;
-               bus_node->next = NULL;
-
-               /* If we have IO resources copy them and fill in the bridge's
-                * IO range registers
-                */
-               if (io_node) {
-                       memcpy(hold_IO_node, io_node, sizeof(struct pci_resource));
-                       io_node->next = NULL;
-
-                       /* set IO base and Limit registers */
-                       RES_CHECK(io_node->base, 8);
-                       temp_byte = (u8)(io_node->base >> 8);
-                       rc = pci_bus_write_config_byte(pci_bus, devfn, PCI_IO_BASE, temp_byte);
-
-                       RES_CHECK(io_node->base + io_node->length - 1, 8);
-                       temp_byte = (u8)((io_node->base + io_node->length - 1) >> 8);
-                       rc = pci_bus_write_config_byte(pci_bus, devfn, PCI_IO_LIMIT, temp_byte);
-               } else {
-                       kfree(hold_IO_node);
-                       hold_IO_node = NULL;
-               }
-
-               /* If we have memory resources copy them and fill in the bridge's
-                * memory range registers.  Otherwise, fill in the range
-                * registers with values that disable them.
-                */
-               if (mem_node) {
-                       memcpy(hold_mem_node, mem_node, sizeof(struct pci_resource));
-                       mem_node->next = NULL;
-
-                       /* set Mem base and Limit registers */
-                       RES_CHECK(mem_node->base, 16);
-                       temp_word = (u32)(mem_node->base >> 16);
-                       rc = pci_bus_write_config_word(pci_bus, devfn, PCI_MEMORY_BASE, temp_word);
-
-                       RES_CHECK(mem_node->base + mem_node->length - 1, 16);
-                       temp_word = (u32)((mem_node->base + mem_node->length - 1) >> 16);
-                       rc = pci_bus_write_config_word(pci_bus, devfn, PCI_MEMORY_LIMIT, temp_word);
-               } else {
-                       temp_word = 0xFFFF;
-                       rc = pci_bus_write_config_word(pci_bus, devfn, PCI_MEMORY_BASE, temp_word);
-
-                       temp_word = 0x0000;
-                       rc = pci_bus_write_config_word(pci_bus, devfn, PCI_MEMORY_LIMIT, temp_word);
-
-                       kfree(hold_mem_node);
-                       hold_mem_node = NULL;
-               }
-
-               /* If we have prefetchable memory resources copy them and 
-                * fill in the bridge's memory range registers.  Otherwise,
-                * fill in the range registers with values that disable them.
-                */
-               if (p_mem_node) {
-                       memcpy(hold_p_mem_node, p_mem_node, sizeof(struct pci_resource));
-                       p_mem_node->next = NULL;
-
-                       /* set Pre Mem base and Limit registers */
-                       RES_CHECK(p_mem_node->base, 16);
-                       temp_word = (u32)(p_mem_node->base >> 16);
-                       rc = pci_bus_write_config_word(pci_bus, devfn, PCI_PREF_MEMORY_BASE, temp_word);
-
-                       RES_CHECK(p_mem_node->base + p_mem_node->length - 1, 16);
-                       temp_word = (u32)((p_mem_node->base + p_mem_node->length - 1) >> 16);
-                       rc = pci_bus_write_config_word(pci_bus, devfn, PCI_PREF_MEMORY_LIMIT, temp_word);
-               } else {
-                       temp_word = 0xFFFF;
-                       rc = pci_bus_write_config_word(pci_bus, devfn, PCI_PREF_MEMORY_BASE, temp_word);
-
-                       temp_word = 0x0000;
-                       rc = pci_bus_write_config_word(pci_bus, devfn, PCI_PREF_MEMORY_LIMIT, temp_word);
-
-                       kfree(hold_p_mem_node);
-                       hold_p_mem_node = NULL;
-               }
-
-               /* Adjust this to compensate for extra adjustment in first loop */
-               irqs.barber_pole--;
-
-               rc = 0;
-
-               /* Here we actually find the devices and configure them */
-               for (device = 0; (device <= 0x1F) && !rc; device++) {
-                       irqs.barber_pole = (irqs.barber_pole + 1) & 0x03;
-
-                       ID = 0xFFFFFFFF;
-                       pci_bus->number = hold_bus_node->base;
-                       pci_bus_read_config_dword(pci_bus, PCI_DEVFN(device, 0),
-                                       PCI_VENDOR_ID, &ID);
-                       pci_bus->number = func->bus;
-
-                       if (ID != 0xFFFFFFFF) {   /*  device Present */
-                               /* Setup slot structure. */
-                               new_slot = shpchp_slot_create(hold_bus_node->base);
-
-                               if (new_slot == NULL) {
-                                       /* Out of memory */
-                                       rc = -ENOMEM;
-                                       continue;
-                               }
-
-                               new_slot->bus = hold_bus_node->base;
-                               new_slot->device = device;
-                               new_slot->function = 0;
-                               new_slot->is_a_board = 1;
-                               new_slot->status = 0;
-
-                               rc = configure_new_device(ctrl, new_slot, 1, &temp_resources, func->bus, func->device);
-                               dbg("configure_new_device rc=0x%x\n",rc);
-                       }       /* End of IF (device in slot?) */
-               }               /* End of FOR loop */
-
-               if (rc) {
-                       shpchp_destroy_resource_list(&temp_resources);
-
-                       return_resource(&(resources->bus_head), hold_bus_node);
-                       return_resource(&(resources->io_head), hold_IO_node);
-                       return_resource(&(resources->mem_head), hold_mem_node);
-                       return_resource(&(resources->p_mem_head), hold_p_mem_node);
-                       return(rc);
-               }
-
-               /* save the interrupt routing information */
-               if (resources->irqs) {
-                       resources->irqs->interrupt[0] = irqs.interrupt[0];
-                       resources->irqs->interrupt[1] = irqs.interrupt[1];
-                       resources->irqs->interrupt[2] = irqs.interrupt[2];
-                       resources->irqs->interrupt[3] = irqs.interrupt[3];
-                       resources->irqs->valid_INT = irqs.valid_INT;
-               } else if (!behind_bridge) {
-                       /* We need to hook up the interrupts here */
-                       for (cloop = 0; cloop < 4; cloop++) {
-                               if (irqs.valid_INT & (0x01 << cloop)) {
-                                       rc = shpchp_set_irq(func->bus, func->device,
-                                                          0x0A + cloop, irqs.interrupt[cloop]);
-                                       if (rc) {
-                                               shpchp_destroy_resource_list (&temp_resources);
-                                               return_resource(&(resources->bus_head), hold_bus_node);
-                                               return_resource(&(resources->io_head), hold_IO_node);
-                                               return_resource(&(resources->mem_head), hold_mem_node);
-                                               return_resource(&(resources->p_mem_head), hold_p_mem_node);
-                                               return rc;
-                                       }
-                               }
-                       }       /* end of for loop */
-               }
-
-               /* Return unused bus resources
-                * First use the temporary node to store information for the board
-                */
-               if (hold_bus_node && bus_node && temp_resources.bus_head) {
-                       hold_bus_node->length = bus_node->base - hold_bus_node->base;
-
-                       hold_bus_node->next = func->bus_head;
-                       func->bus_head = hold_bus_node;
-
-                       temp_byte = (u8)(temp_resources.bus_head->base - 1);
-
-                       /* set subordinate bus */
-                       dbg("re-set subordinate bus = 0x%x\n", temp_byte);
-                       rc = pci_bus_write_config_byte (pci_bus, devfn, PCI_SUBORDINATE_BUS, temp_byte);
-
-                       if (temp_resources.bus_head->length == 0) {
-                               kfree(temp_resources.bus_head);
-                               temp_resources.bus_head = NULL;
-                       } else {
-                               dbg("return bus res of b:d(0x%x:%x) base:len(0x%x:%x)\n",
-                                       func->bus, func->device, temp_resources.bus_head->base, temp_resources.bus_head->length);
-                               return_resource(&(resources->bus_head), temp_resources.bus_head);
-                       }
-               }
-
-               /* If we have IO space available and there is some left,
-                * return the unused portion
-                */
-               if (hold_IO_node && temp_resources.io_head) {
-                       io_node = do_pre_bridge_resource_split(&(temp_resources.io_head),
-                                                              &hold_IO_node, 0x1000);
-
-                       /* Check if we were able to split something off */
-                       if (io_node) {
-                               hold_IO_node->base = io_node->base + io_node->length;
-
-                               RES_CHECK(hold_IO_node->base, 8);
-                               temp_byte = (u8)((hold_IO_node->base) >> 8);
-                               rc = pci_bus_write_config_byte (pci_bus, devfn, PCI_IO_BASE, temp_byte);
-
-                               return_resource(&(resources->io_head), io_node);
-                       }
-
-                       io_node = do_bridge_resource_split(&(temp_resources.io_head), 0x1000);
-
-                       /*  Check if we were able to split something off */
-                       if (io_node) {
-                               /* First use the temporary node to store information for the board */
-                               hold_IO_node->length = io_node->base - hold_IO_node->base;
-
-                               /* If we used any, add it to the board's list */
-                               if (hold_IO_node->length) {
-                                       hold_IO_node->next = func->io_head;
-                                       func->io_head = hold_IO_node;
-
-                                       RES_CHECK(io_node->base - 1, 8);
-                                       temp_byte = (u8)((io_node->base - 1) >> 8);
-                                       rc = pci_bus_write_config_byte (pci_bus, devfn, PCI_IO_LIMIT, temp_byte);
-
-                                       return_resource(&(resources->io_head), io_node);
-                               } else {
-                                       /* it doesn't need any IO */
-                                       temp_byte = 0x00;
-                                       rc = pci_bus_write_config_byte(pci_bus, devfn, PCI_IO_LIMIT, temp_byte);
-
-                                       return_resource(&(resources->io_head), io_node);
-                                       kfree(hold_IO_node);
-                               }
-                       } else {
-                               /* it used most of the range */
-                               hold_IO_node->next = func->io_head;
-                               func->io_head = hold_IO_node;
-                       }
-               } else if (hold_IO_node) {
-                       /* it used the whole range */
-                       hold_IO_node->next = func->io_head;
-                       func->io_head = hold_IO_node;
-               }
-
-               /* If we have memory space available and there is some left,
-                * return the unused portion
-                */
-               if (hold_mem_node && temp_resources.mem_head) {
-                       mem_node = do_pre_bridge_resource_split(&(temp_resources.mem_head), &hold_mem_node, 0x100000L);
-
-                       /* Check if we were able to split something off */
-                       if (mem_node) {
-                               hold_mem_node->base = mem_node->base + mem_node->length;
-
-                               RES_CHECK(hold_mem_node->base, 16);
-                               temp_word = (u32)((hold_mem_node->base) >> 16);
-                               rc = pci_bus_write_config_word (pci_bus, devfn, PCI_MEMORY_BASE, temp_word);
-
-                               return_resource(&(resources->mem_head), mem_node);
-                       }
-
-                       mem_node = do_bridge_resource_split(&(temp_resources.mem_head), 0x100000L);
-
-                       /* Check if we were able to split something off */
-                       if (mem_node) {
-                               /* First use the temporary node to store information for the board */
-                               hold_mem_node->length = mem_node->base - hold_mem_node->base;
-
-                               if (hold_mem_node->length) {
-                                       hold_mem_node->next = func->mem_head;
-                                       func->mem_head = hold_mem_node;
-
-                                       /* configure end address */
-                                       RES_CHECK(mem_node->base - 1, 16);
-                                       temp_word = (u32)((mem_node->base - 1) >> 16);
-                                       rc = pci_bus_write_config_word (pci_bus, devfn, PCI_MEMORY_LIMIT, temp_word);
-
-                                       /* Return unused resources to the pool */
-                                       return_resource(&(resources->mem_head), mem_node);
-                               } else {
-                                       /* it doesn't need any Mem */
-                                       temp_word = 0x0000;
-                                       rc = pci_bus_write_config_word (pci_bus, devfn, PCI_MEMORY_LIMIT, temp_word);
-
-                                       return_resource(&(resources->mem_head), mem_node);
-                                       kfree(hold_mem_node);
-                               }
-                       } else {
-                               /* it used most of the range */
-                               hold_mem_node->next = func->mem_head;
-                               func->mem_head = hold_mem_node;
-                       }
-               } else if (hold_mem_node) {
-                       /* it used the whole range */
-                       hold_mem_node->next = func->mem_head;
-                       func->mem_head = hold_mem_node;
-               }
-
-               /* If we have prefetchable memory space available and there is some 
-                * left at the end, return the unused portion
-                */
-               if (hold_p_mem_node && temp_resources.p_mem_head) {
-                       p_mem_node = do_pre_bridge_resource_split(&(temp_resources.p_mem_head),
-                                                                 &hold_p_mem_node, 0x100000L);
-
-                       /* Check if we were able to split something off */
-                       if (p_mem_node) {
-                               hold_p_mem_node->base = p_mem_node->base + p_mem_node->length;
-
-                               RES_CHECK(hold_p_mem_node->base, 16);
-                               temp_word = (u32)((hold_p_mem_node->base) >> 16);
-                               rc = pci_bus_write_config_word (pci_bus, devfn, PCI_PREF_MEMORY_BASE, temp_word);
-
-                               return_resource(&(resources->p_mem_head), p_mem_node);
-                       }
-
-                       p_mem_node = do_bridge_resource_split(&(temp_resources.p_mem_head), 0x100000L);
-
-                       /* Check if we were able to split something off */
-                       if (p_mem_node) {
-                               /* First use the temporary node to store information for the board */
-                               hold_p_mem_node->length = p_mem_node->base - hold_p_mem_node->base;
-
-                               /* If we used any, add it to the board's list */
-                               if (hold_p_mem_node->length) {
-                                       hold_p_mem_node->next = func->p_mem_head;
-                                       func->p_mem_head = hold_p_mem_node;
-
-                                       RES_CHECK(p_mem_node->base - 1, 16);
-                                       temp_word = (u32)((p_mem_node->base - 1) >> 16);
-                                       rc = pci_bus_write_config_word (pci_bus, devfn, PCI_PREF_MEMORY_LIMIT, temp_word);
-
-                                       return_resource(&(resources->p_mem_head), p_mem_node);
-                               } else {
-                                       /* it doesn't need any PMem */
-                                       temp_word = 0x0000;
-                                       rc = pci_bus_write_config_word (pci_bus, devfn, PCI_PREF_MEMORY_LIMIT, temp_word);
-
-                                       return_resource(&(resources->p_mem_head), p_mem_node);
-                                       kfree(hold_p_mem_node);
-                               }
-                       } else {
-                               /* it used the most of the range */
-                               hold_p_mem_node->next = func->p_mem_head;
-                               func->p_mem_head = hold_p_mem_node;
-                       }
-               } else if (hold_p_mem_node) {
-                       /* it used the whole range */
-                       hold_p_mem_node->next = func->p_mem_head;
-                       func->p_mem_head = hold_p_mem_node;
-               }
-
-               /* We should be configuring an IRQ and the bridge's base address
-                * registers if it needs them.  Although we have never seen such
-                * a device
-                */
-
-               shpchprm_enable_card(ctrl, func, PCI_HEADER_TYPE_BRIDGE);
-
-               dbg("PCI Bridge Hot-Added s:b:d:f(%02x:%02x:%02x:%02x)\n", ctrl->seg, func->bus, func->device, func->function);
-       } else if ((temp_byte & 0x7F) == PCI_HEADER_TYPE_NORMAL) {
-               /* Standard device */
-               u64     base64;
-               rc = pci_bus_read_config_byte (pci_bus, devfn, 0x0B, &class_code);
-
-               if (class_code == PCI_BASE_CLASS_DISPLAY)
-                       return (DEVICE_TYPE_NOT_SUPPORTED);
-
-               /* Figure out IO and memory needs */
-               for (cloop = PCI_BASE_ADDRESS_0; cloop <= PCI_BASE_ADDRESS_5; cloop += 4) {
-                       temp_register = 0xFFFFFFFF;
-
-                       rc = pci_bus_write_config_dword (pci_bus, devfn, cloop, temp_register);
-                       rc = pci_bus_read_config_dword(pci_bus, devfn, cloop, &temp_register);
-                       dbg("Bar[%x]=0x%x on bus:dev:func(0x%x:%x:%x)\n", cloop, temp_register, func->bus, func->device, 
-                               func->function);
-
-                       if (!temp_register)
-                               continue;
-
-                       base64 = 0L;
-                       if (temp_register & PCI_BASE_ADDRESS_SPACE_IO) {
-                               /* Map IO */
-
-                               /* set base = amount of IO space */
-                               base = temp_register & 0xFFFFFFFC;
-                               base = ~base + 1;
-
-                               dbg("NEED IO length(0x%x)\n", base);
-                               io_node = get_io_resource(&(resources->io_head),(ulong)base);
-
-                               /* allocate the resource to the board */
-                               if (io_node) {
-                                       dbg("Got IO base=0x%x(length=0x%x)\n", io_node->base, io_node->length);
-                                       base = (u32)io_node->base;
-                                       io_node->next = func->io_head;
-                                       func->io_head = io_node;
-                               } else {
-                                       err("Got NO IO resource(length=0x%x)\n", base);
-                                       return -ENOMEM;
-                               }
-                       } else {        /* map MEM */
-                               int prefetchable = 1;
-                               struct pci_resource **res_node = &func->p_mem_head;
-                               char *res_type_str = "PMEM";
-                               u32     temp_register2;
-
-                               if (!(temp_register & PCI_BASE_ADDRESS_MEM_PREFETCH)) {
-                                       prefetchable = 0;
-                                       res_node = &func->mem_head;
-                                       res_type_str++;
-                               }
-
-                               base = temp_register & 0xFFFFFFF0;
-                               base = ~base + 1;
-
-                               switch (temp_register & PCI_BASE_ADDRESS_MEM_TYPE_MASK) {
-                               case PCI_BASE_ADDRESS_MEM_TYPE_32:
-                                       dbg("NEED 32 %s bar=0x%x(length=0x%x)\n", res_type_str, temp_register, base);
-
-                                       if (prefetchable && resources->p_mem_head)
-                                               mem_node=get_resource(&(resources->p_mem_head), (ulong)base);
-                                       else {
-                                               if (prefetchable)
-                                                       dbg("using MEM for PMEM\n");
-                                               mem_node=get_resource(&(resources->mem_head), (ulong)base);
-                                       }
-
-                                       /* allocate the resource to the board */
-                                       if (mem_node) {
-                                               base = (u32)mem_node->base; 
-                                               mem_node->next = *res_node;
-                                               *res_node = mem_node;
-                                               dbg("Got 32 %s base=0x%x(length=0x%x)\n", res_type_str, mem_node->base, 
-                                                       mem_node->length);
-                                       } else {
-                                               err("Got NO 32 %s resource(length=0x%x)\n", res_type_str, base);
-                                               return -ENOMEM;
-                                       }
-                                       break;
-                               case PCI_BASE_ADDRESS_MEM_TYPE_64:
-                                       rc = pci_bus_read_config_dword(pci_bus, devfn, cloop+4, &temp_register2);
-                                       dbg("NEED 64 %s bar=0x%x:%x(length=0x%x)\n", res_type_str, temp_register2, 
-                                               temp_register, base);
-
-                                       if (prefetchable && resources->p_mem_head)
-                                               mem_node = get_resource(&(resources->p_mem_head), (ulong)base);
-                                       else {
-                                               if (prefetchable)
-                                                       dbg("using MEM for PMEM\n");
-                                               mem_node = get_resource(&(resources->mem_head), (ulong)base);
-                                       }
-
-                                       /* allocate the resource to the board */
-                                       if (mem_node) {
-                                               base64 = mem_node->base; 
-                                               mem_node->next = *res_node;
-                                               *res_node = mem_node;
-                                               dbg("Got 64 %s base=0x%x:%x(length=%x)\n", res_type_str, (u32)(base64 >> 32), 
-                                                       (u32)base64, mem_node->length);
-                                       } else {
-                                               err("Got NO 64 %s resource(length=0x%x)\n", res_type_str, base);
-                                               return -ENOMEM;
-                                       }
-                                       break;
-                               default:
-                                       dbg("reserved BAR type=0x%x\n", temp_register);
-                                       break;
-                               }
-
-                       }
-
-                       if (base64) {
-                               rc = pci_bus_write_config_dword(pci_bus, devfn, cloop, (u32)base64);
-                               cloop += 4;
-                               base64 >>= 32;
-
-                               if (base64) {
-                                       dbg("%s: high dword of base64(0x%x) set to 0\n", __FUNCTION__, (u32)base64);
-                                       base64 = 0x0L;
-                               }
-
-                               rc = pci_bus_write_config_dword(pci_bus, devfn, cloop, (u32)base64);
-                       } else {
-                               rc = pci_bus_write_config_dword(pci_bus, devfn, cloop, base);
-                       }
-               }               /* End of base register loop */
-
-#if defined(CONFIG_X86_64)
-               /* Figure out which interrupt pin this function uses */
-               rc = pci_bus_read_config_byte (pci_bus, devfn, PCI_INTERRUPT_PIN, &temp_byte);
-
-               /* If this function needs an interrupt and we are behind a bridge
-                  and the pin is tied to something that's alread mapped,
-                  set this one the same
-                */
-               if (temp_byte && resources->irqs && 
-                   (resources->irqs->valid_INT & 
-                    (0x01 << ((temp_byte + resources->irqs->barber_pole - 1) & 0x03)))) {
-                       /* We have to share with something already set up */
-                       IRQ = resources->irqs->interrupt[(temp_byte + resources->irqs->barber_pole - 1) & 0x03];
-               } else {
-                       /* Program IRQ based on card type */
-                       rc = pci_bus_read_config_byte (pci_bus, devfn, 0x0B, &class_code);
-
-                       if (class_code == PCI_BASE_CLASS_STORAGE) {
-                               IRQ = shpchp_disk_irq;
-                       } else {
-                               IRQ = shpchp_nic_irq;
-                       }
-               }
-
-               /* IRQ Line */
-               rc = pci_bus_write_config_byte (pci_bus, devfn, PCI_INTERRUPT_LINE, IRQ);
-
-               if (!behind_bridge) {
-                       rc = shpchp_set_irq(func->bus, func->device, temp_byte + 0x09, IRQ);
-                       if (rc)
-                               return(1);
-               } else {
-                       /* TBD - this code may also belong in the other clause of this If statement */
-                       resources->irqs->interrupt[(temp_byte + resources->irqs->barber_pole - 1) & 0x03] = IRQ;
-                       resources->irqs->valid_INT |= 0x01 << (temp_byte + resources->irqs->barber_pole - 1) & 0x03;
-               }
-#endif
-               /* Disable ROM base Address */
-               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);
-               if (rc)
-                       return rc;
-
-               shpchprm_enable_card(ctrl, func, PCI_HEADER_TYPE_NORMAL);
-
-               dbg("PCI function Hot-Added s:b:d:f(%02x:%02x:%02x:%02x)\n", ctrl->seg, func->bus, func->device, func->function);
-       }                       /* End of Not-A-Bridge else */
-       else {
-               /* It's some strange type of PCI adapter (Cardbus?) */
-               return(DEVICE_TYPE_NOT_SUPPORTED);
-       }
-
-       func->configured = 1;
-
-       return 0;
+       ret = remove_board(p_slot);
+       update_slot_info(p_slot);
+       return ret;
 }
 
index 8d98410..40905a6 100644 (file)
  *
  */
 
-#include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/types.h>
-#include <linux/slab.h>
-#include <linux/vmalloc.h>
-#include <linux/interrupt.h>
-#include <linux/spinlock.h>
-#include <linux/delay.h>
 #include <linux/pci.h>
-#include <asm/system.h>
 #include "shpchp.h"
 
 #ifdef DEBUG
@@ -282,7 +275,7 @@ static void start_int_poll_timer(struct php_ctlr_state_s *php_ctlr, int seconds)
 
 static int shpc_write_cmd(struct slot *slot, u8 t_slot, u8 cmd)
 {
-       struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
+       struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle;
        u16 cmd_status;
        int retval = 0;
        u16 temp_word;
@@ -320,7 +313,6 @@ static int shpc_write_cmd(struct slot *slot, u8 t_slot, u8 cmd)
         * command. 
         */
        writew(temp_word, php_ctlr->creg + CMD);
-       dbg("%s: temp_word written %x\n", __FUNCTION__, temp_word);
 
        DBG_LEAVE_ROUTINE 
        return retval;
@@ -328,7 +320,7 @@ static int shpc_write_cmd(struct slot *slot, u8 t_slot, u8 cmd)
 
 static int hpc_check_cmd_status(struct controller *ctrl)
 {
-       struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) ctrl->hpc_ctlr_handle;
+       struct php_ctlr_state_s *php_ctlr = ctrl->hpc_ctlr_handle;
        u16 cmd_status;
        int retval = 0;
 
@@ -368,7 +360,7 @@ static int hpc_check_cmd_status(struct controller *ctrl)
 
 static int hpc_get_attention_status(struct slot *slot, u8 *status)
 {
-       struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
+       struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle;
        u32 slot_reg;
        u16 slot_status;
        u8 atten_led_state;
@@ -408,7 +400,7 @@ static int hpc_get_attention_status(struct slot *slot, u8 *status)
 
 static int hpc_get_power_status(struct slot * slot, u8 *status)
 {
-       struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
+       struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle;
        u32 slot_reg;
        u16 slot_status;
        u8 slot_state;
@@ -450,7 +442,7 @@ static int hpc_get_power_status(struct slot * slot, u8 *status)
 
 static int hpc_get_latch_status(struct slot *slot, u8 *status)
 {
-       struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
+       struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle;
        u32 slot_reg;
        u16 slot_status;
 
@@ -473,7 +465,7 @@ static int hpc_get_latch_status(struct slot *slot, u8 *status)
 
 static int hpc_get_adapter_status(struct slot *slot, u8 *status)
 {
-       struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
+       struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle;
        u32 slot_reg;
        u16 slot_status;
        u8 card_state;
@@ -496,7 +488,7 @@ static int hpc_get_adapter_status(struct slot *slot, u8 *status)
 
 static int hpc_get_prog_int(struct slot *slot, u8 *prog_int)
 {
-       struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
+       struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle;
 
        DBG_ENTER_ROUTINE 
        
@@ -513,7 +505,7 @@ static int hpc_get_prog_int(struct slot *slot, u8 *prog_int)
 
 static int hpc_get_adapter_speed(struct slot *slot, enum pci_bus_speed *value)
 {
-       struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
+       struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle;
        u32 slot_reg;
        u16 slot_status, sec_bus_status;
        u8 m66_cap, pcix_cap, pi;
@@ -594,7 +586,7 @@ static int hpc_get_adapter_speed(struct slot *slot, enum pci_bus_speed *value)
 
 static int hpc_get_mode1_ECC_cap(struct slot *slot, u8 *mode)
 {
-       struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
+       struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle;
        u16 sec_bus_status;
        u8 pi;
        int retval = 0;
@@ -623,7 +615,7 @@ static int hpc_get_mode1_ECC_cap(struct slot *slot, u8 *mode)
 
 static int hpc_query_power_fault(struct slot * slot)
 {
-       struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
+       struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle;
        u32 slot_reg;
        u16 slot_status;
        u8 pwr_fault_state, status;
@@ -647,7 +639,7 @@ static int hpc_query_power_fault(struct slot * slot)
 
 static int hpc_set_attention_status(struct slot *slot, u8 value)
 {
-       struct php_ctlr_state_s *php_ctlr =(struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
+       struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle;
        u8 slot_cmd = 0;
        int rc = 0;
 
@@ -683,7 +675,7 @@ static int hpc_set_attention_status(struct slot *slot, u8 value)
 
 static void hpc_set_green_led_on(struct slot *slot)
 {
-       struct php_ctlr_state_s *php_ctlr =(struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
+       struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle;
        u8 slot_cmd;
 
        if (!slot->ctrl->hpc_ctlr_handle) {
@@ -705,7 +697,7 @@ static void hpc_set_green_led_on(struct slot *slot)
 
 static void hpc_set_green_led_off(struct slot *slot)
 {
-       struct php_ctlr_state_s *php_ctlr =(struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
+       struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle;
        u8 slot_cmd;
 
        if (!slot->ctrl->hpc_ctlr_handle) {
@@ -727,7 +719,7 @@ static void hpc_set_green_led_off(struct slot *slot)
 
 static void hpc_set_green_led_blink(struct slot *slot)
 {
-       struct php_ctlr_state_s *php_ctlr =(struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
+       struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle;
        u8 slot_cmd;
 
        if (!slot->ctrl->hpc_ctlr_handle) {
@@ -754,7 +746,7 @@ int shpc_get_ctlr_slot_config(struct controller *ctrl,
        int *updown,            /* physical_slot_num increament: 1 or -1        */
        int *flags)
 {
-       struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) ctrl->hpc_ctlr_handle;
+       struct php_ctlr_state_s *php_ctlr = ctrl->hpc_ctlr_handle;
 
        DBG_ENTER_ROUTINE 
 
@@ -776,7 +768,7 @@ int shpc_get_ctlr_slot_config(struct controller *ctrl,
 
 static void hpc_release_ctlr(struct controller *ctrl)
 {
-       struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) ctrl->hpc_ctlr_handle;
+       struct php_ctlr_state_s *php_ctlr = ctrl->hpc_ctlr_handle;
        struct php_ctlr_state_s *p, *p_prev;
 
        DBG_ENTER_ROUTINE 
@@ -796,10 +788,8 @@ static void hpc_release_ctlr(struct controller *ctrl)
                }
        }
        if (php_ctlr->pci_dev) {
-               dbg("%s: before calling iounmap & release_mem_region\n", __FUNCTION__);
                iounmap(php_ctlr->creg);
                release_mem_region(pci_resource_start(php_ctlr->pci_dev, 0), pci_resource_len(php_ctlr->pci_dev, 0));
-               dbg("%s: before calling iounmap & release_mem_region\n", __FUNCTION__);
                php_ctlr->pci_dev = NULL;
        }
 
@@ -828,7 +818,7 @@ DBG_LEAVE_ROUTINE
 
 static int hpc_power_on_slot(struct slot * slot)
 {
-       struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
+       struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle;
        u8 slot_cmd;
        int retval = 0;
 
@@ -859,7 +849,7 @@ static int hpc_power_on_slot(struct slot * slot)
 
 static int hpc_slot_enable(struct slot * slot)
 {
-       struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
+       struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle;
        u8 slot_cmd;
        int retval = 0;
 
@@ -890,7 +880,7 @@ static int hpc_slot_enable(struct slot * slot)
 
 static int hpc_slot_disable(struct slot * slot)
 {
-       struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
+       struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle;
        u8 slot_cmd;
        int retval = 0;
 
@@ -920,51 +910,12 @@ static int hpc_slot_disable(struct slot * slot)
        return retval;
 }
 
-static int hpc_enable_all_slots( struct slot *slot )
-{
-       int retval = 0;
-
-       DBG_ENTER_ROUTINE 
-       
-       if (!slot->ctrl->hpc_ctlr_handle) {
-               err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
-               return -1;
-       }
-
-       retval = shpc_write_cmd(slot, 0, SET_ENABLE_ALL);
-       if (retval) {
-               err("%s: Write command failed!\n", __FUNCTION__);
-               return -1;
-       }
-
-       DBG_LEAVE_ROUTINE
-
-       return retval;
-}
-
-static int hpc_pwr_on_all_slots(struct slot *slot)
-{
-       int retval = 0;
-
-       DBG_ENTER_ROUTINE 
-
-       retval = shpc_write_cmd(slot, 0, SET_PWR_ON_ALL);
-
-       if (retval) {
-               err("%s: Write command failed!\n", __FUNCTION__);
-               return -1;
-       }
-
-       DBG_LEAVE_ROUTINE
-       return retval;
-}
-
 static int hpc_set_bus_speed_mode(struct slot * slot, enum pci_bus_speed value)
 {
        u8 slot_cmd;
        u8 pi;
        int retval = 0;
-       struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
+       struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle;
 
        DBG_ENTER_ROUTINE 
        
@@ -1089,18 +1040,13 @@ static irqreturn_t shpc_isr(int IRQ, void *dev_id, struct pt_regs *regs)
 
        if (!intr_loc)
                return IRQ_NONE;
-       dbg("%s: shpc_isr proceeds\n", __FUNCTION__);
        dbg("%s: intr_loc = %x\n",__FUNCTION__, intr_loc); 
 
        if(!shpchp_poll_mode) {
                /* Mask Global Interrupt Mask - see implementation note on p. 139 */
                /* of SHPC spec rev 1.0*/
                temp_dword = readl(php_ctlr->creg + SERR_INTR_ENABLE);
-               dbg("%s: Before masking global interrupt, temp_dword = %x\n",
-                       __FUNCTION__, temp_dword); 
                temp_dword |= 0x00000001;
-               dbg("%s: After masking global interrupt, temp_dword = %x\n",
-                       __FUNCTION__, temp_dword); 
                writel(temp_dword, php_ctlr->creg + SERR_INTR_ENABLE);
 
                intr_loc2 = readl(php_ctlr->creg + INTR_LOC);  
@@ -1114,11 +1060,7 @@ static irqreturn_t shpc_isr(int IRQ, void *dev_id, struct pt_regs *regs)
                 * Detect bit in Controller SERR-INT register
                 */
                temp_dword = readl(php_ctlr->creg + SERR_INTR_ENABLE);
-               dbg("%s: Before clearing CCIP, temp_dword = %x\n",
-                       __FUNCTION__, temp_dword); 
                temp_dword &= 0xfffeffff;
-               dbg("%s: After clearing CCIP, temp_dword = %x\n",
-                       __FUNCTION__, temp_dword); 
                writel(temp_dword, php_ctlr->creg + SERR_INTR_ENABLE);
                wake_up_interruptible(&ctrl->queue);
        }
@@ -1126,11 +1068,7 @@ static irqreturn_t shpc_isr(int IRQ, void *dev_id, struct pt_regs *regs)
        if ((intr_loc = (intr_loc >> 1)) == 0) {
                /* Unmask Global Interrupt Mask */
                temp_dword = readl(php_ctlr->creg + SERR_INTR_ENABLE);
-               dbg("%s: 1-Before unmasking global interrupt, temp_dword = %x\n",
-                       __FUNCTION__, temp_dword); 
                temp_dword &= 0xfffffffe;
-               dbg("%s: 1-After unmasking global interrupt, temp_dword = %x\n",
-                       __FUNCTION__, temp_dword); 
                writel(temp_dword, php_ctlr->creg + SERR_INTR_ENABLE);
 
                return IRQ_NONE;
@@ -1140,11 +1078,9 @@ static irqreturn_t shpc_isr(int IRQ, void *dev_id, struct pt_regs *regs)
        /* To find out which slot has interrupt pending */
                if ((intr_loc >> hp_slot) & 0x01) {
                        temp_dword = readl(php_ctlr->creg + SLOT1 + (4*hp_slot));
-                       dbg("%s: Slot %x with intr, temp_dword = %x\n",
-                               __FUNCTION__, hp_slot, temp_dword); 
+                       dbg("%s: Slot %x with intr, slot register = %x\n",
+                               __FUNCTION__, hp_slot, temp_dword);
                        temp_byte = (temp_dword >> 16) & 0xFF;
-                       dbg("%s: Slot with intr, temp_byte = %x\n",
-                               __FUNCTION__, temp_byte); 
                        if ((php_ctlr->switch_change_callback) && (temp_byte & 0x08))
                                schedule_flag += php_ctlr->switch_change_callback(
                                        hp_slot, php_ctlr->callback_instance_id);
@@ -1160,8 +1096,6 @@ static irqreturn_t shpc_isr(int IRQ, void *dev_id, struct pt_regs *regs)
                        
                        /* Clear all slot events */
                        temp_dword = 0xe01f3fff;
-                       dbg("%s: Clearing slot events, temp_dword = %x\n",
-                               __FUNCTION__, temp_dword); 
                        writel(temp_dword, php_ctlr->creg + SLOT1 + (4*hp_slot));
 
                        intr_loc2 = readl(php_ctlr->creg + INTR_LOC);  
@@ -1171,11 +1105,7 @@ static irqreturn_t shpc_isr(int IRQ, void *dev_id, struct pt_regs *regs)
        if (!shpchp_poll_mode) {
                /* Unmask Global Interrupt Mask */
                temp_dword = readl(php_ctlr->creg + SERR_INTR_ENABLE);
-               dbg("%s: 2-Before unmasking global interrupt, temp_dword = %x\n",
-                       __FUNCTION__, temp_dword); 
                temp_dword &= 0xfffffffe;
-               dbg("%s: 2-After unmasking global interrupt, temp_dword = %x\n",
-                       __FUNCTION__, temp_dword); 
                writel(temp_dword, php_ctlr->creg + SERR_INTR_ENABLE);
        }
        
@@ -1184,7 +1114,7 @@ static irqreturn_t shpc_isr(int IRQ, void *dev_id, struct pt_regs *regs)
 
 static int hpc_get_max_bus_speed (struct slot *slot, enum pci_bus_speed *value)
 {
-       struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
+       struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle;
        enum pci_bus_speed bus_speed = PCI_SPEED_UNKNOWN;
        int retval = 0;
        u8 pi;
@@ -1253,7 +1183,7 @@ static int hpc_get_max_bus_speed (struct slot *slot, enum pci_bus_speed *value)
 
 static int hpc_get_cur_bus_speed (struct slot *slot, enum pci_bus_speed *value)
 {
-       struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
+       struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle;
        enum pci_bus_speed bus_speed = PCI_SPEED_UNKNOWN;
        u16 sec_bus_status;
        int retval = 0;
@@ -1367,8 +1297,6 @@ static struct hpc_ops shpchp_hpc_ops = {
        .power_on_slot                  = hpc_power_on_slot,
        .slot_enable                    = hpc_slot_enable,
        .slot_disable                   = hpc_slot_disable,
-       .enable_all_slots               = hpc_enable_all_slots,
-       .pwr_on_all_slots               = hpc_pwr_on_all_slots,
        .set_bus_speed_mode             = hpc_set_bus_speed_mode,         
        .set_attention_status   = hpc_set_attention_status,
        .get_power_status               = hpc_get_power_status,
@@ -1391,12 +1319,7 @@ static struct hpc_ops shpchp_hpc_ops = {
        .check_cmd_status               = hpc_check_cmd_status,
 };
 
-int shpc_init(struct controller * ctrl,
-               struct pci_dev * pdev,
-               php_intr_callback_t attention_button_callback,
-               php_intr_callback_t switch_change_callback,
-               php_intr_callback_t presence_change_callback,
-               php_intr_callback_t power_fault_callback)
+int shpc_init(struct controller * ctrl, struct pci_dev * pdev)
 {
        struct php_ctlr_state_s *php_ctlr, *p;
        void *instance_id = ctrl;
@@ -1405,7 +1328,6 @@ int shpc_init(struct controller * ctrl,
        static int first = 1;
        u32 shpc_cap_offset, shpc_base_offset;
        u32 tempdword, slot_reg;
-       u16 vendor_id, device_id;
        u8 i;
 
        DBG_ENTER_ROUTINE
@@ -1422,21 +1344,8 @@ int shpc_init(struct controller * ctrl,
 
        php_ctlr->pci_dev = pdev;       /* save pci_dev in context */
 
-       rc = pci_read_config_word(pdev, PCI_VENDOR_ID, &vendor_id);
-       dbg("%s: Vendor ID: %x\n",__FUNCTION__, vendor_id);
-       if (rc) {
-               err("%s: unable to read PCI configuration data\n", __FUNCTION__);
-               goto abort_free_ctlr;
-       }
-
-       rc = pci_read_config_word(pdev, PCI_DEVICE_ID, &device_id);
-       dbg("%s: Device ID: %x\n",__FUNCTION__, device_id);
-       if (rc) {
-               err("%s: unable to read PCI configuration data\n", __FUNCTION__);
-               goto abort_free_ctlr;
-       }
-
-       if ((vendor_id == PCI_VENDOR_ID_AMD) || (device_id == PCI_DEVICE_ID_AMD_GOLAM_7450)) {
+       if ((pdev->vendor == PCI_VENDOR_ID_AMD) || (pdev->device ==
+                               PCI_DEVICE_ID_AMD_GOLAM_7450)) {
                shpc_base_offset = 0;  /* amd shpc driver doesn't use this; assume 0 */
        } else {
                if ((shpc_cap_offset = pci_find_capability(pdev, PCI_CAP_ID_SHPC)) == 0) {
@@ -1469,7 +1378,8 @@ int shpc_init(struct controller * ctrl,
                                err("%s : pci_read_config_dword failed\n", __FUNCTION__);
                                goto abort_free_ctlr;
                        }
-                       dbg("%s: offset %d: tempdword %x\n", __FUNCTION__,i, tempdword);
+                       dbg("%s: offset %d: value %x\n", __FUNCTION__,i,
+                                       tempdword);
                }
        }
 
@@ -1478,13 +1388,6 @@ int shpc_init(struct controller * ctrl,
                first = 0;
        }
 
-       dbg("pdev = %p: b:d:f:irq=0x%x:%x:%x:%x\n", pdev, pdev->bus->number, PCI_SLOT(pdev->devfn), 
-               PCI_FUNC(pdev->devfn), pdev->irq);
-       for ( rc = 0; rc < DEVICE_COUNT_RESOURCE; rc++)
-               if (pci_resource_len(pdev, rc) > 0)
-                       dbg("pci resource[%d] start=0x%lx(len=0x%lx), shpc_base_offset %x\n", rc,
-                               pci_resource_start(pdev, rc), pci_resource_len(pdev, rc), shpc_base_offset);
-
        info("HPC vendor_id %x device_id %x ss_vid %x ss_did %x\n", pdev->vendor, pdev->device, pdev->subsystem_vendor, 
                pdev->subsystem_device);
        
@@ -1504,7 +1407,6 @@ int shpc_init(struct controller * ctrl,
                goto abort_free_ctlr;
        }
        dbg("%s: php_ctlr->creg %p\n", __FUNCTION__, php_ctlr->creg);
-       dbg("%s: physical addr %p\n", __FUNCTION__, (void*)pci_resource_start(pdev, 0));
 
        init_MUTEX(&ctrl->crit_sect);
        /* Setup wait queue */
@@ -1512,13 +1414,10 @@ int shpc_init(struct controller * ctrl,
 
        /* Find the IRQ */
        php_ctlr->irq = pdev->irq;
-       dbg("HPC interrupt = %d\n", php_ctlr->irq);
-
-       /* Save interrupt callback info */
-       php_ctlr->attention_button_callback = attention_button_callback;
-       php_ctlr->switch_change_callback = switch_change_callback;
-       php_ctlr->presence_change_callback = presence_change_callback;
-       php_ctlr->power_fault_callback = power_fault_callback;
+       php_ctlr->attention_button_callback = shpchp_handle_attention_button,
+       php_ctlr->switch_change_callback = shpchp_handle_switch_change;
+       php_ctlr->presence_change_callback = shpchp_handle_presence_change;
+       php_ctlr->power_fault_callback = shpchp_handle_power_fault;
        php_ctlr->callback_instance_id = instance_id;
 
        /* Return PCI Controller Info */
@@ -1556,7 +1455,6 @@ int shpc_init(struct controller * ctrl,
                if (rc) {
                        info("Can't get msi for the hotplug controller\n");
                        info("Use INTx for the hotplug controller\n");
-                       dbg("%s: rc = %x\n", __FUNCTION__, rc);
                } else
                        php_ctlr->irq = pdev->irq;
                
@@ -1566,9 +1464,11 @@ int shpc_init(struct controller * ctrl,
                        err("Can't get irq %d for the hotplug controller\n", php_ctlr->irq);
                        goto abort_free_ctlr;
                }
-               /* Execute OSHP method here */
        }
-       dbg("%s: Before adding HPC to HPC list\n", __FUNCTION__);
+       dbg("%s: HPC at b:d:f:irq=0x%x:%x:%x:%x\n", __FUNCTION__,
+                       pdev->bus->number, PCI_SLOT(pdev->devfn),
+                       PCI_FUNC(pdev->devfn), pdev->irq);
+       get_hp_hw_control_from_firmware(pdev);
 
        /*  Add this HPC instance into the HPC list */
        spin_lock(&list_lock);
@@ -1607,7 +1507,6 @@ int shpc_init(struct controller * ctrl,
                dbg("%s: SERR_INTR_ENABLE = %x\n", __FUNCTION__, tempdword);
        }
 
-       dbg("%s: Leaving shpc_init\n", __FUNCTION__);
        DBG_LEAVE_ROUTINE
        return 0;
 
index d867099..b8e95ac 100644 (file)
  *
  */
 
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/types.h>
-#include <linux/slab.h>
-#include <linux/workqueue.h>
-#include <linux/proc_fs.h>
 #include <linux/pci.h>
 #include "../pci.h"
 #include "shpchp.h"
-#ifndef CONFIG_IA64
-#include "../../../arch/i386/pci/pci.h"    /* horrible hack showing how processor dependant we are... */
-#endif
 
-int shpchp_configure_device (struct controller* ctrl, struct pci_func* func)  
+void program_fw_provided_values(struct pci_dev *dev)
 {
-       unsigned char bus;
-       struct pci_bus *child;
-       int num;
-
-       if (func->pci_dev == NULL)
-               func->pci_dev = pci_find_slot(func->bus, PCI_DEVFN(func->device, func->function));
-
-       /* Still NULL ? Well then scan for it ! */
-       if (func->pci_dev == NULL) {
-               num = pci_scan_slot(ctrl->pci_dev->subordinate, PCI_DEVFN(func->device, func->function));
-               if (num) {
-                       dbg("%s: subordiante %p number %x\n", __FUNCTION__, ctrl->pci_dev->subordinate,
-                               ctrl->pci_dev->subordinate->number);
-                       pci_bus_add_devices(ctrl->pci_dev->subordinate);
-               }
-               
-               func->pci_dev = pci_find_slot(func->bus, PCI_DEVFN(func->device, func->function));
-               if (func->pci_dev == NULL) {
-                       dbg("ERROR: pci_dev still null\n");
-                       return 0;
+       u16 pci_cmd, pci_bctl;
+       struct pci_dev *cdev;
+       struct hotplug_params hpp = {0x8, 0x40, 0, 0}; /* defaults */
+
+       /* Program hpp values for this device */
+       if (!(dev->hdr_type == PCI_HEADER_TYPE_NORMAL ||
+                       (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE &&
+                       (dev->class >> 8) == PCI_CLASS_BRIDGE_PCI)))
+               return;
+
+       get_hp_params_from_firmware(dev, &hpp);
+
+       pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, hpp.cache_line_size);
+       pci_write_config_byte(dev, PCI_LATENCY_TIMER, hpp.latency_timer);
+       pci_read_config_word(dev, PCI_COMMAND, &pci_cmd);
+       if (hpp.enable_serr)
+               pci_cmd |= PCI_COMMAND_SERR;
+       else
+               pci_cmd &= ~PCI_COMMAND_SERR;
+       if (hpp.enable_perr)
+               pci_cmd |= PCI_COMMAND_PARITY;
+       else
+               pci_cmd &= ~PCI_COMMAND_PARITY;
+       pci_write_config_word(dev, PCI_COMMAND, pci_cmd);
+
+       /* Program bridge control value and child devices */
+       if ((dev->class >> 8) == PCI_CLASS_BRIDGE_PCI) {
+               pci_write_config_byte(dev, PCI_SEC_LATENCY_TIMER,
+                               hpp.latency_timer);
+               pci_read_config_word(dev, PCI_BRIDGE_CONTROL, &pci_bctl);
+               if (hpp.enable_serr)
+                       pci_bctl |= PCI_BRIDGE_CTL_SERR;
+               else
+                       pci_bctl &= ~PCI_BRIDGE_CTL_SERR;
+               if (hpp.enable_perr)
+                       pci_bctl |= PCI_BRIDGE_CTL_PARITY;
+               else
+                       pci_bctl &= ~PCI_BRIDGE_CTL_PARITY;
+               pci_write_config_word(dev, PCI_BRIDGE_CONTROL, pci_bctl);
+               if (dev->subordinate) {
+                       list_for_each_entry(cdev, &dev->subordinate->devices,
+                                       bus_list)
+                               program_fw_provided_values(cdev);
                }
        }
-
-       if (func->pci_dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
-               pci_read_config_byte(func->pci_dev, PCI_SECONDARY_BUS, &bus);
-               child = pci_add_new_bus(func->pci_dev->bus, (func->pci_dev), bus);
-               pci_do_scan_bus(child);
-
-       }
-
-       return 0;
 }
 
-
-int shpchp_unconfigure_device(struct pci_func* func) 
+int shpchp_configure_device(struct slot *p_slot)
 {
-       int rc = 0;
-       int j;
-       
-       dbg("%s: bus/dev/func = %x/%x/%x\n", __FUNCTION__, func->bus,
-                               func->device, func->function);
-
-       for (j=0; j<8 ; j++) {
-               struct pci_dev* temp = pci_find_slot(func->bus,
-                               (func->device << 3) | j);
-               if (temp) {
-                       pci_remove_bus_device(temp);
-               }
+       struct pci_dev *dev;
+       struct pci_bus *parent = p_slot->ctrl->pci_dev->subordinate;
+       int num, fn;
+
+       dev = pci_find_slot(p_slot->bus, PCI_DEVFN(p_slot->device, 0));
+       if (dev) {
+               err("Device %s already exists at %x:%x, cannot hot-add\n",
+                               pci_name(dev), p_slot->bus, p_slot->device);
+               return -EINVAL;
        }
-       return rc;
-}
-
-/*
- * shpchp_set_irq
- *
- * @bus_num: bus number of PCI device
- * @dev_num: device number of PCI device
- * @slot: pointer to u8 where slot number will be returned
- */
-int shpchp_set_irq (u8 bus_num, u8 dev_num, u8 int_pin, u8 irq_num)
-{
-#if defined(CONFIG_X86) && !defined(CONFIG_X86_IO_APIC) && !defined(CONFIG_X86_64)
-       int rc;
-       u16 temp_word;
-       struct pci_dev fakedev;
-       struct pci_bus fakebus;
 
-       fakedev.devfn = dev_num << 3;
-       fakedev.bus = &fakebus;
-       fakebus.number = bus_num;
-       dbg("%s: dev %d, bus %d, pin %d, num %d\n",
-           __FUNCTION__, dev_num, bus_num, int_pin, irq_num);
-       rc = pcibios_set_irq_routing(&fakedev, int_pin - 0x0a, irq_num);
-       dbg("%s: rc %d\n", __FUNCTION__, rc);
-       if (!rc)
-               return !rc;
-
-       /* set the Edge Level Control Register (ELCR) */
-       temp_word = inb(0x4d0);
-       temp_word |= inb(0x4d1) << 8;
-
-       temp_word |= 0x01 << irq_num;
-
-       /* This should only be for x86 as it sets the Edge Level Control Register */
-       outb((u8) (temp_word & 0xFF), 0x4d0);
-       outb((u8) ((temp_word & 0xFF00) >> 8), 0x4d1);
-#endif
-       return 0;
-}
-
-/* More PCI configuration routines; this time centered around hotplug controller */
-
-
-/*
- * shpchp_save_config
- *
- * Reads configuration for all slots in a PCI bus and saves info.
- *
- * Note:  For non-hot plug busses, the slot # saved is the device #
- *
- * returns 0 if success
- */
-int shpchp_save_config(struct controller *ctrl, int busnumber, int num_ctlr_slots, int first_device_num)
-{
-       int rc;
-       u8 class_code;
-       u8 header_type;
-       u32 ID;
-       u8 secondary_bus;
-       struct pci_func *new_slot;
-       int sub_bus;
-       int FirstSupported;
-       int LastSupported;
-       int max_functions;
-       int function;
-       u8 DevError;
-       int device = 0;
-       int cloop = 0;
-       int stop_it;
-       int index;
-       int is_hot_plug = num_ctlr_slots || first_device_num;
-       struct pci_bus lpci_bus, *pci_bus;
-
-       dbg("%s: num_ctlr_slots = %d, first_device_num = %d\n", __FUNCTION__,
-                               num_ctlr_slots, first_device_num);
-
-       memcpy(&lpci_bus, ctrl->pci_dev->subordinate, sizeof(lpci_bus));
-       pci_bus = &lpci_bus;
-
-       dbg("%s: num_ctlr_slots = %d, first_device_num = %d\n", __FUNCTION__,
-                               num_ctlr_slots, first_device_num);
-
-       /*   Decide which slots are supported */
-       if (is_hot_plug) {
-               /*********************************
-                *  is_hot_plug is the slot mask
-                *********************************/
-               FirstSupported = first_device_num;
-               LastSupported = FirstSupported + num_ctlr_slots - 1;
-       } else {
-               FirstSupported = 0;
-               LastSupported = 0x1F;
+       num = pci_scan_slot(parent, PCI_DEVFN(p_slot->device, 0));
+       if (num == 0) {
+               err("No new device found\n");
+               return -ENODEV;
        }
 
-       dbg("FirstSupported = %d, LastSupported = %d\n", FirstSupported,
-                                       LastSupported);
-
-       /*   Save PCI configuration space for all devices in supported slots */
-       pci_bus->number = busnumber;
-       for (device = FirstSupported; device <= LastSupported; device++) {
-               ID = 0xFFFFFFFF;
-               rc = pci_bus_read_config_dword(pci_bus, PCI_DEVFN(device, 0),
-                                       PCI_VENDOR_ID, &ID);
-
-               if (ID != 0xFFFFFFFF) {   /*  device in slot */
-                       rc = pci_bus_read_config_byte(pci_bus, PCI_DEVFN(device, 0),
-                                       0x0B, &class_code);
-                       if (rc)
-                               return rc;
-
-                       rc = pci_bus_read_config_byte(pci_bus, PCI_DEVFN(device, 0),
-                                       PCI_HEADER_TYPE, &header_type);
-                       if (rc)
-                               return rc;
-
-                       dbg("class_code = %x, header_type = %x\n", class_code, header_type);
-
-                       /* If multi-function device, set max_functions to 8 */
-                       if (header_type & 0x80)
-                               max_functions = 8;
-                       else
-                               max_functions = 1;
-
-                       function = 0;
-
-                       do {
-                               DevError = 0;
-
-                               if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) {   /* P-P Bridge */
-                                       /* Recurse the subordinate bus
-                                        * get the subordinate bus number
-                                        */
-                                       rc = pci_bus_read_config_byte(pci_bus,
-                                               PCI_DEVFN(device, function), 
-                                               PCI_SECONDARY_BUS, &secondary_bus);
-                                       if (rc) {
-                                               return rc;
-                                       } else {
-                                               sub_bus = (int) secondary_bus;
-
-                                               /* Save secondary bus cfg spc with this recursive call. */
-                                               rc = shpchp_save_config(ctrl, sub_bus, 0, 0);
-                                               if (rc)
-                                                       return rc;
-                                       }
-                               }
-
-                               index = 0;
-                               new_slot = shpchp_slot_find(busnumber, device, index++);
-
-                               dbg("new_slot = %p\n", new_slot);
-
-                               while (new_slot && (new_slot->function != (u8) function)) {
-                                       new_slot = shpchp_slot_find(busnumber, device, index++);
-                                       dbg("new_slot = %p\n", new_slot);
-                               }
-                               if (!new_slot) {
-                                       /* Setup slot structure. */
-                                       new_slot = shpchp_slot_create(busnumber);
-                                       dbg("new_slot = %p\n", new_slot);
-
-                                       if (new_slot == NULL)
-                                               return(1);
-                               }
-
-                               new_slot->bus = (u8) busnumber;
-                               new_slot->device = (u8) device;
-                               new_slot->function = (u8) function;
-                               new_slot->is_a_board = 1;
-                               new_slot->switch_save = 0x10;
-                               new_slot->pwr_save = 1;
-                               /* In case of unsupported board */
-                               new_slot->status = DevError;
-                               new_slot->pci_dev = pci_find_slot(new_slot->bus,
-                                       (new_slot->device << 3) | new_slot->function);
-                               dbg("new_slot->pci_dev = %p\n", new_slot->pci_dev);
-
-                               for (cloop = 0; cloop < 0x20; cloop++) {
-                                       rc = pci_bus_read_config_dword(pci_bus,
-                                               PCI_DEVFN(device, function), 
-                                               cloop << 2,
-                                               (u32 *) &(new_slot->config_space [cloop]));
-                                       /* dbg("new_slot->config_space[%x] = %x\n",
-                                               cloop, new_slot->config_space[cloop]); */
-                                       if (rc)
-                                               return rc;
-                               }
-
-                               function++;
-
-                               stop_it = 0;
-
-                               /*  this loop skips to the next present function
-                                *  reading in Class Code and Header type.
-                                */
-
-                               while ((function < max_functions)&&(!stop_it)) {
-                                       rc = pci_bus_read_config_dword(pci_bus,
-                                               PCI_DEVFN(device, function),
-                                               PCI_VENDOR_ID, &ID);
-
-                                       if (ID == 0xFFFFFFFF) {  /* nothing there. */
-                                               function++;
-                                               dbg("Nothing there\n");
-                                       } else {  /* Something there */
-                                               rc = pci_bus_read_config_byte(pci_bus,
-                                                       PCI_DEVFN(device, function), 
-                                                       0x0B, &class_code);
-                                               if (rc)
-                                                       return rc;
-
-                                               rc = pci_bus_read_config_byte(pci_bus,
-                                                       PCI_DEVFN(device, function), 
-                                                       PCI_HEADER_TYPE, &header_type);
-                                               if (rc)
-                                                       return rc;
-
-                                               dbg("class_code = %x, header_type = %x\n",
-                                                       class_code, header_type);
-                                               stop_it++;
-                                       }
-                               }
-
-                       } while (function < max_functions);
-                       /* End of IF (device in slot?) */
-               } else if (is_hot_plug) {
-                       /* Setup slot structure with entry for empty slot */
-                       new_slot = shpchp_slot_create(busnumber);
-
-                       if (new_slot == NULL) {
-                               return(1);
-                       }
-                       dbg("new_slot = %p\n", new_slot);
-
-                       new_slot->bus = (u8) busnumber;
-                       new_slot->device = (u8) device;
-                       new_slot->function = 0;
-                       new_slot->is_a_board = 0;
-                       new_slot->presence_save = 0;
-                       new_slot->switch_save = 0;
+       for (fn = 0; fn < 8; fn++) {
+               if (!(dev = pci_find_slot(p_slot->bus,
+                                       PCI_DEVFN(p_slot->device, fn))))
+                       continue;
+               if ((dev->class >> 16) == PCI_BASE_CLASS_DISPLAY) {
+                       err("Cannot hot-add display device %s\n",
+                                       pci_name(dev));
+                       continue;
                }
-       }                       /* End of FOR loop */
-
-       return(0);
-}
-
-
-/*
- * shpchp_save_slot_config
- *
- * Saves configuration info for all PCI devices in a given slot
- * including subordinate busses.
- *
- * returns 0 if success
- */
-int shpchp_save_slot_config(struct controller *ctrl, struct pci_func * new_slot)
-{
-       int rc;
-       u8 class_code;
-       u8 header_type;
-       u32 ID;
-       u8 secondary_bus;
-       int sub_bus;
-       int max_functions;
-       int function;
-       int cloop = 0;
-       int stop_it;
-       struct pci_bus lpci_bus, *pci_bus;
-       memcpy(&lpci_bus, ctrl->pci_dev->subordinate, sizeof(lpci_bus));
-       pci_bus = &lpci_bus;
-       pci_bus->number = new_slot->bus;
-
-       ID = 0xFFFFFFFF;
-
-       pci_bus_read_config_dword(pci_bus, PCI_DEVFN(new_slot->device, 0),
-                                       PCI_VENDOR_ID, &ID);
-
-       if (ID != 0xFFFFFFFF) {   /*  device in slot */
-               pci_bus_read_config_byte(pci_bus, PCI_DEVFN(new_slot->device, 0),
-                                       0x0B, &class_code);
-
-               pci_bus_read_config_byte(pci_bus, PCI_DEVFN(new_slot->device, 0),
-                                       PCI_HEADER_TYPE, &header_type);
-
-               if (header_type & 0x80) /* Multi-function device */
-                       max_functions = 8;
-               else
-                       max_functions = 1;
-
-               function = 0;
-
-               do {
-                       if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) {     /* PCI-PCI Bridge */
-                               /*  Recurse the subordinate bus */
-                               pci_bus_read_config_byte(pci_bus,
-                                       PCI_DEVFN(new_slot->device, function), 
-                                       PCI_SECONDARY_BUS, &secondary_bus);
-
-                               sub_bus = (int) secondary_bus;
-
-                               /* Save the config headers for the secondary bus. */
-                               rc = shpchp_save_config(ctrl, sub_bus, 0, 0);
-
-                               if (rc)
-                                       return rc;
-
-                       }       /* End of IF */
-
-                       new_slot->status = 0;
-
-                       for (cloop = 0; cloop < 0x20; cloop++) {
-                               pci_bus_read_config_dword(pci_bus,
-                                       PCI_DEVFN(new_slot->device, function), 
-                                       cloop << 2,
-                                       (u32 *) &(new_slot->config_space [cloop]));
+               if ((dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) ||
+                               (dev->hdr_type == PCI_HEADER_TYPE_CARDBUS)) {
+                       /* Find an unused bus number for the new bridge */
+                       struct pci_bus *child;
+                       unsigned char busnr, start = parent->secondary;
+                       unsigned char end = parent->subordinate;
+                       for (busnr = start; busnr <= end; busnr++) {
+                               if (!pci_find_bus(pci_domain_nr(parent),
+                                                       busnr))
+                                       break;
                        }
-
-                       function++;
-
-                       stop_it = 0;
-
-                       /*  this loop skips to the next present function
-                        *  reading in the Class Code and the Header type.
-                        */
-
-                       while ((function < max_functions) && (!stop_it)) {
-                               pci_bus_read_config_dword(pci_bus,
-                                       PCI_DEVFN(new_slot->device, function),
-                                       PCI_VENDOR_ID, &ID);
-
-                               if (ID == 0xFFFFFFFF) {  /* nothing there. */
-                                       function++;
-                               } else {  /* Something there */
-                                       pci_bus_read_config_byte(pci_bus,
-                                               PCI_DEVFN(new_slot->device, function),
-                                               0x0B, &class_code);
-
-                                       pci_bus_read_config_byte(pci_bus,
-                                               PCI_DEVFN(new_slot->device, function),
-                                               PCI_HEADER_TYPE, &header_type);
-
-                                       stop_it++;
-                               }
+                       if (busnr >= end) {
+                               err("No free bus for hot-added bridge\n");
+                               continue;
                        }
-
-               } while (function < max_functions);
-       }                       /* End of IF (device in slot?) */
-       else {
-               return 2;
+                       child = pci_add_new_bus(parent, dev, busnr);
+                       if (!child) {
+                               err("Cannot add new bus for %s\n",
+                                               pci_name(dev));
+                               continue;
+                       }
+                       child->subordinate = pci_do_scan_bus(child);
+                       pci_bus_size_bridges(child);
+               }
+               program_fw_provided_values(dev);
        }
 
+       pci_bus_assign_resources(parent);
+       pci_bus_add_devices(parent);
+       pci_enable_bridges(parent);
        return 0;
 }
 
-
-/*
- * shpchp_save_used_resources
- *
- * Stores used resource information for existing boards.  this is
- * for boards that were in the system when this driver was loaded.
- * this function is for hot plug ADD
- *
- * returns 0 if success
- * if disable  == 1(DISABLE_CARD),
- *  it loops for all functions of the slot and disables them.
- * else, it just get resources of the function and return.
- */
-int shpchp_save_used_resources(struct controller *ctrl, struct pci_func *func, int disable)
+int shpchp_unconfigure_device(struct slot *p_slot)
 {
-       u8 cloop;
-       u8 header_type;
-       u8 secondary_bus;
-       u8 temp_byte;
-       u16 command;
-       u16 save_command;
-       u16 w_base, w_length;
-       u32 temp_register;
-       u32 save_base;
-       u32 base, length;
-       u64 base64 = 0;
-       int index = 0;
-       unsigned int devfn;
-       struct pci_resource *mem_node = NULL;
-       struct pci_resource *p_mem_node = NULL;
-       struct pci_resource *t_mem_node;
-       struct pci_resource *io_node;
-       struct pci_resource *bus_node;
-       struct pci_bus lpci_bus, *pci_bus;
-       memcpy(&lpci_bus, ctrl->pci_dev->subordinate, sizeof(lpci_bus));
-       pci_bus = &lpci_bus;
-
-       if (disable)
-               func = shpchp_slot_find(func->bus, func->device, index++);
-
-       while ((func != NULL) && func->is_a_board) {
-               pci_bus->number = func->bus;
-               devfn = PCI_DEVFN(func->device, func->function);
-
-               /* Save the command register */
-               pci_bus_read_config_word(pci_bus, devfn, PCI_COMMAND, &save_command);
+       int rc = 0;
+       int j;
+       u8 bctl = 0;
+       
+       dbg("%s: bus/dev = %x/%x\n", __FUNCTION__, p_slot->bus, p_slot->device);
 
-               if (disable) {
-                       /* disable card */
-                       command = 0x00;
-                       pci_bus_write_config_word(pci_bus, devfn, PCI_COMMAND, command);
+       for (j=0; j<8 ; j++) {
+               struct pci_dev* temp = pci_find_slot(p_slot->bus,
+                               (p_slot->device << 3) | j);
+               if (!temp)
+                       continue;
+               if ((temp->class >> 16) == PCI_BASE_CLASS_DISPLAY) {
+                       err("Cannot remove display device %s\n",
+                                       pci_name(temp));
+                       continue;
                }
-
-               /* Check for Bridge */
-               pci_bus_read_config_byte(pci_bus, devfn, PCI_HEADER_TYPE, &header_type);
-
-               if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) {     /* PCI-PCI Bridge */
-                       dbg("Save_used_res of PCI bridge b:d=0x%x:%x, sc=0x%x\n",
-                                       func->bus, func->device, save_command);
-                       if (disable) {
-                               /* Clear Bridge Control Register */
-                               command = 0x00;
-                               pci_bus_write_config_word(pci_bus, devfn, PCI_BRIDGE_CONTROL, command);
+               if (temp->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
+                       pci_read_config_byte(temp, PCI_BRIDGE_CONTROL, &bctl);
+                       if (bctl & PCI_BRIDGE_CTL_VGA) {
+                               err("Cannot remove display device %s\n",
+                                               pci_name(temp));
+                               continue;
                        }
-
-                       pci_bus_read_config_byte(pci_bus, devfn, PCI_SECONDARY_BUS, &secondary_bus);
-                       pci_bus_read_config_byte(pci_bus, devfn, PCI_SUBORDINATE_BUS, &temp_byte);
-
-                       bus_node = kmalloc(sizeof(struct pci_resource),
-                                               GFP_KERNEL);
-                       if (!bus_node)
-                               return -ENOMEM;
-
-                       bus_node->base = (ulong)secondary_bus;
-                       bus_node->length = (ulong)(temp_byte - secondary_bus + 1);
-
-                       bus_node->next = func->bus_head;
-                       func->bus_head = bus_node;
-
-                       /* Save IO base and Limit registers */
-                       pci_bus_read_config_byte(pci_bus, devfn, PCI_IO_BASE, &temp_byte);
-                       base = temp_byte;
-                       pci_bus_read_config_byte(pci_bus, devfn, PCI_IO_LIMIT, &temp_byte);
-                       length = temp_byte;
-
-                       if ((base <= length) && (!disable || (save_command & PCI_COMMAND_IO))) {
-                               io_node = kmalloc(sizeof(struct pci_resource),
-                                                       GFP_KERNEL);
-                               if (!io_node)
-                                       return -ENOMEM;
-
-                               io_node->base = (ulong)(base & PCI_IO_RANGE_MASK) << 8;
-                               io_node->length = (ulong)(length - base + 0x10) << 8;
-
-                               io_node->next = func->io_head;
-                               func->io_head = io_node;
-                       }
-
-                       /* Save memory base and Limit registers */
-                       pci_bus_read_config_word(pci_bus, devfn, PCI_MEMORY_BASE, &w_base);
-                       pci_bus_read_config_word(pci_bus, devfn, PCI_MEMORY_LIMIT, &w_length);
-
-                       if ((w_base <= w_length) && (!disable || (save_command & PCI_COMMAND_MEMORY))) {
-                               mem_node = kmalloc(sizeof(struct pci_resource),
-                                               GFP_KERNEL);
-                               if (!mem_node)
-                                       return -ENOMEM;
-
-                               mem_node->base = (ulong)w_base << 16;
-                               mem_node->length = (ulong)(w_length - w_base + 0x10) << 16;
-
-                               mem_node->next = func->mem_head;
-                               func->mem_head = mem_node;
-                       }
-                       /* Save prefetchable memory base and Limit registers */
-                       pci_bus_read_config_word(pci_bus, devfn, PCI_PREF_MEMORY_BASE, &w_base);
-                       pci_bus_read_config_word(pci_bus, devfn, PCI_PREF_MEMORY_LIMIT, &w_length);
-
-                       if ((w_base <= w_length) && (!disable || (save_command & PCI_COMMAND_MEMORY))) {
-                               p_mem_node = kmalloc(sizeof(struct pci_resource),
-                                               GFP_KERNEL);
-                               if (!p_mem_node)
-                                       return -ENOMEM;
-
-                               p_mem_node->base = (ulong)w_base << 16;
-                               p_mem_node->length = (ulong)(w_length - w_base + 0x10) << 16;
-
-                               p_mem_node->next = func->p_mem_head;
-                               func->p_mem_head = p_mem_node;
-                       }
-               } else if ((header_type & 0x7F) == PCI_HEADER_TYPE_NORMAL) {
-                       dbg("Save_used_res of PCI adapter b:d=0x%x:%x, sc=0x%x\n",
-                                       func->bus, func->device, save_command);
-
-                       /* Figure out IO and memory base lengths */
-                       for (cloop = PCI_BASE_ADDRESS_0; cloop <= PCI_BASE_ADDRESS_5; cloop += 4) {
-                               pci_bus_read_config_dword(pci_bus, devfn, cloop, &save_base);
-
-                               temp_register = 0xFFFFFFFF;
-                               pci_bus_write_config_dword(pci_bus, devfn, cloop, temp_register);
-                               pci_bus_read_config_dword(pci_bus, devfn, cloop, &temp_register);
-
-                               if (!disable)
-                                       pci_bus_write_config_dword(pci_bus, devfn, cloop, save_base);
-
-                               if (!temp_register)
-                                       continue;
-
-                               base = temp_register;
-
-                               if ((base & PCI_BASE_ADDRESS_SPACE_IO) &&
-                                               (!disable || (save_command & PCI_COMMAND_IO))) {
-                                       /* IO base */
-                                       /* set temp_register = amount of IO space requested */
-                                       base = base & 0xFFFFFFFCL;
-                                       base = (~base) + 1;
-
-                                       io_node =  kmalloc(sizeof (struct pci_resource),
-                                                               GFP_KERNEL);
-                                       if (!io_node)
-                                               return -ENOMEM;
-
-                                       io_node->base = (ulong)save_base & PCI_BASE_ADDRESS_IO_MASK;
-                                       io_node->length = (ulong)base;
-                                       dbg("sur adapter: IO bar=0x%x(length=0x%x)\n",
-                                               io_node->base, io_node->length);
-
-                                       io_node->next = func->io_head;
-                                       func->io_head = io_node;
-                               } else {  /* map Memory */
-                                       int prefetchable = 1;
-                                       /* struct pci_resources **res_node; */
-                                       char *res_type_str = "PMEM";
-                                       u32 temp_register2;
-
-                                       t_mem_node = kmalloc(sizeof (struct pci_resource),
-                                                               GFP_KERNEL);
-                                       if (!t_mem_node)
-                                               return -ENOMEM;
-
-                                       if (!(base & PCI_BASE_ADDRESS_MEM_PREFETCH) &&
-                                                       (!disable || (save_command & PCI_COMMAND_MEMORY))) {
-                                               prefetchable = 0;
-                                               mem_node = t_mem_node;
-                                               res_type_str++;
-                                       } else
-                                               p_mem_node = t_mem_node;
-
-                                       base = base & 0xFFFFFFF0L;
-                                       base = (~base) + 1;
-
-                                       switch (temp_register & PCI_BASE_ADDRESS_MEM_TYPE_MASK) {
-                                       case PCI_BASE_ADDRESS_MEM_TYPE_32:
-                                               if (prefetchable) {
-                                                       p_mem_node->base = (ulong)save_base & PCI_BASE_ADDRESS_MEM_MASK;
-                                                       p_mem_node->length = (ulong)base;
-                                                       dbg("sur adapter: 32 %s bar=0x%x(length=0x%x)\n",
-                                                               res_type_str, 
-                                                               p_mem_node->base,
-                                                               p_mem_node->length);
-
-                                                       p_mem_node->next = func->p_mem_head;
-                                                       func->p_mem_head = p_mem_node;
-                                               } else {
-                                                       mem_node->base = (ulong)save_base & PCI_BASE_ADDRESS_MEM_MASK;
-                                                       mem_node->length = (ulong)base;
-                                                       dbg("sur adapter: 32 %s bar=0x%x(length=0x%x)\n",
-                                                               res_type_str, 
-                                                               mem_node->base,
-                                                               mem_node->length);
-
-                                                       mem_node->next = func->mem_head;
-                                                       func->mem_head = mem_node;
-                                               }
-                                               break;
-                                       case PCI_BASE_ADDRESS_MEM_TYPE_64:
-                                               pci_bus_read_config_dword(pci_bus, devfn, cloop+4, &temp_register2);
-                                               base64 = temp_register2;
-                                               base64 = (base64 << 32) | save_base;
-
-                                               if (temp_register2) {
-                                                       dbg("sur adapter: 64 %s high dword of base64(0x%x:%x) masked to 0\n", 
-                                                               res_type_str, temp_register2, (u32)base64);
-                                                       base64 &= 0x00000000FFFFFFFFL;
-                                               }
-
-                                               if (prefetchable) {
-                                                       p_mem_node->base = base64 & PCI_BASE_ADDRESS_MEM_MASK;
-                                                       p_mem_node->length = base;
-                                                       dbg("sur adapter: 64 %s base=0x%x(len=0x%x)\n",
-                                                               res_type_str, 
-                                                               p_mem_node->base,
-                                                               p_mem_node->length);
-
-                                                       p_mem_node->next = func->p_mem_head;
-                                                       func->p_mem_head = p_mem_node;
-                                               } else {
-                                                       mem_node->base = base64 & PCI_BASE_ADDRESS_MEM_MASK;
-                                                       mem_node->length = base;
-                                                       dbg("sur adapter: 64 %s base=0x%x(len=0x%x)\n",
-                                                               res_type_str, 
-                                                               mem_node->base,
-                                                               mem_node->length);
-
-                                                       mem_node->next = func->mem_head;
-                                                       func->mem_head = mem_node;
-                                               }
-                                               cloop += 4;
-                                               break;
-                                       default:
-                                               dbg("asur: reserved BAR type=0x%x\n",
-                                                       temp_register);
-                                               break;
-                                       }
-                               } 
-                       }       /* End of base register loop */
-               } else {        /* Some other unknown header type */
-                       dbg("Save_used_res of PCI unknown type b:d=0x%x:%x. skip.\n",
-                                       func->bus, func->device);
                }
-
-               /* find the next device in this slot */
-               if (!disable)
-                       break;
-               func = shpchp_slot_find(func->bus, func->device, index++);
+               pci_remove_bus_device(temp);
        }
-
-       return 0;
-}
-
-/**
- * kfree_resource_list: release memory of all list members
- * @res: resource list to free
- */
-static inline void
-return_resource_list(struct pci_resource **func, struct pci_resource **res)
-{
-       struct pci_resource *node;
-       struct pci_resource *t_node;
-
-       node = *func;
-       *func = NULL;
-       while (node) {
-               t_node = node->next;
-               return_resource(res, node);
-               node = t_node;
-       }
-}
-
-/*
- * shpchp_return_board_resources
- *
- * this routine returns all resources allocated to a board to
- * the available pool.
- *
- * returns 0 if success
- */
-int shpchp_return_board_resources(struct pci_func * func,
-                                       struct resource_lists * resources)
-{
-       int rc;
-       dbg("%s\n", __FUNCTION__);
-
-       if (!func)
-               return 1;
-
-       return_resource_list(&(func->io_head),&(resources->io_head));
-       return_resource_list(&(func->mem_head),&(resources->mem_head));
-       return_resource_list(&(func->p_mem_head),&(resources->p_mem_head));
-       return_resource_list(&(func->bus_head),&(resources->bus_head));
-
-       rc = shpchp_resource_sort_and_combine(&(resources->mem_head));
-       rc |= shpchp_resource_sort_and_combine(&(resources->p_mem_head));
-       rc |= shpchp_resource_sort_and_combine(&(resources->io_head));
-       rc |= shpchp_resource_sort_and_combine(&(resources->bus_head));
-
        return rc;
 }
 
-/**
- * kfree_resource_list: release memory of all list members
- * @res: resource list to free
- */
-static inline void
-kfree_resource_list(struct pci_resource **r)
-{
-       struct pci_resource *res, *tres;
-
-       res = *r;
-       *r = NULL;
-
-       while (res) {
-               tres = res;
-               res = res->next;
-               kfree(tres);
-       }
-}
-
-/**
- * shpchp_destroy_resource_list: put node back in the resource list
- * @resources: list to put nodes back
- */
-void shpchp_destroy_resource_list(struct resource_lists *resources)
-{
-       kfree_resource_list(&(resources->io_head));
-       kfree_resource_list(&(resources->mem_head));
-       kfree_resource_list(&(resources->p_mem_head));
-       kfree_resource_list(&(resources->bus_head));
-}
-
-/**
- * shpchp_destroy_board_resources: put node back in the resource list
- * @resources: list to put nodes back
- */
-void shpchp_destroy_board_resources(struct pci_func * func)
-{
-       kfree_resource_list(&(func->io_head));
-       kfree_resource_list(&(func->mem_head));
-       kfree_resource_list(&(func->p_mem_head));
-       kfree_resource_list(&(func->bus_head));
-}
index c9445eb..f5cfbf2 100644 (file)
  *
  */
 
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/types.h>
-#include <linux/proc_fs.h>
-#include <linux/workqueue.h>
 #include <linux/pci.h>
 #include "shpchp.h"
 
 
 static ssize_t show_ctrl (struct device *dev, struct device_attribute *attr, char *buf)
 {
-       struct pci_dev *pci_dev;
-       struct controller *ctrl;
+       struct pci_dev *pdev;
        char * out = buf;
-       int index;
-       struct pci_resource *res;
+       int index, busnr;
+       struct resource *res;
+       struct pci_bus *bus;
 
-       pci_dev = container_of (dev, struct pci_dev, dev);
-       ctrl = pci_get_drvdata(pci_dev);
+       pdev = container_of (dev, struct pci_dev, dev);
+       bus = pdev->subordinate;
 
        out += sprintf(buf, "Free resources: memory\n");
-       index = 11;
-       res = ctrl->mem_head;
-       while (res && index--) {
-               out += sprintf(out, "start = %8.8x, length = %8.8x\n", res->base, res->length);
-               res = res->next;
+       for (index = 0; index < PCI_BUS_NUM_RESOURCES; index++) {
+               res = bus->resource[index];
+               if (res && (res->flags & IORESOURCE_MEM) &&
+                               !(res->flags & IORESOURCE_PREFETCH)) {
+                       out += sprintf(out, "start = %8.8lx, length = %8.8lx\n",
+                                       res->start, (res->end - res->start));
+               }
        }
        out += sprintf(out, "Free resources: prefetchable memory\n");
-       index = 11;
-       res = ctrl->p_mem_head;
-       while (res && index--) {
-               out += sprintf(out, "start = %8.8x, length = %8.8x\n", res->base, res->length);
-               res = res->next;
+       for (index = 0; index < PCI_BUS_NUM_RESOURCES; index++) {
+               res = bus->resource[index];
+               if (res && (res->flags & IORESOURCE_MEM) &&
+                              (res->flags & IORESOURCE_PREFETCH)) {
+                       out += sprintf(out, "start = %8.8lx, length = %8.8lx\n",
+                                       res->start, (res->end - res->start));
+               }
        }
        out += sprintf(out, "Free resources: IO\n");
-       index = 11;
-       res = ctrl->io_head;
-       while (res && index--) {
-               out += sprintf(out, "start = %8.8x, length = %8.8x\n", res->base, res->length);
-               res = res->next;
+       for (index = 0; index < PCI_BUS_NUM_RESOURCES; index++) {
+               res = bus->resource[index];
+               if (res && (res->flags & IORESOURCE_IO)) {
+                       out += sprintf(out, "start = %8.8lx, length = %8.8lx\n",
+                                       res->start, (res->end - res->start));
+               }
        }
        out += sprintf(out, "Free resources: bus numbers\n");
-       index = 11;
-       res = ctrl->bus_head;
-       while (res && index--) {
-               out += sprintf(out, "start = %8.8x, length = %8.8x\n", res->base, res->length);
-               res = res->next;
+       for (busnr = bus->secondary; busnr <= bus->subordinate; busnr++) {
+               if (!pci_find_bus(pci_domain_nr(bus), busnr))
+                       break;
        }
+       if (busnr < bus->subordinate)
+               out += sprintf(out, "start = %8.8x, length = %8.8x\n",
+                               busnr, (bus->subordinate - busnr));
 
        return out - buf;
 }
 static DEVICE_ATTR (ctrl, S_IRUGO, show_ctrl, NULL);
 
-static ssize_t show_dev (struct device *dev, struct device_attribute *attr, char *buf)
+void shpchp_create_ctrl_files (struct controller *ctrl)
 {
-       struct pci_dev *pci_dev;
-       struct controller *ctrl;
-       char * out = buf;
-       int index;
-       struct pci_resource *res;
-       struct pci_func *new_slot;
-       struct slot *slot;
-
-       pci_dev = container_of (dev, struct pci_dev, dev);
-       ctrl = pci_get_drvdata(pci_dev);
-
-       slot=ctrl->slot;
-
-       while (slot) {
-               new_slot = shpchp_slot_find(slot->bus, slot->device, 0);
-               if (!new_slot)
-                       break;
-               out += sprintf(out, "assigned resources: memory\n");
-               index = 11;
-               res = new_slot->mem_head;
-               while (res && index--) {
-                       out += sprintf(out, "start = %8.8x, length = %8.8x\n", res->base, res->length);
-                       res = res->next;
-               }
-               out += sprintf(out, "assigned resources: prefetchable memory\n");
-               index = 11;
-               res = new_slot->p_mem_head;
-               while (res && index--) {
-                       out += sprintf(out, "start = %8.8x, length = %8.8x\n", res->base, res->length);
-                       res = res->next;
-               }
-               out += sprintf(out, "assigned resources: IO\n");
-               index = 11;
-               res = new_slot->io_head;
-               while (res && index--) {
-                       out += sprintf(out, "start = %8.8x, length = %8.8x\n", res->base, res->length);
-                       res = res->next;
-               }
-               out += sprintf(out, "assigned resources: bus numbers\n");
-               index = 11;
-               res = new_slot->bus_head;
-               while (res && index--) {
-                       out += sprintf(out, "start = %8.8x, length = %8.8x\n", res->base, res->length);
-                       res = res->next;
-               }
-               slot=slot->next;
-       }
-
-       return out - buf;
+       device_create_file (&ctrl->pci_dev->dev, &dev_attr_ctrl);
 }
-static DEVICE_ATTR (dev, S_IRUGO, show_dev, NULL);
 
-void shpchp_create_ctrl_files (struct controller *ctrl)
+void shpchp_remove_ctrl_files(struct controller *ctrl)
 {
-       device_create_file (&ctrl->pci_dev->dev, &dev_attr_ctrl);
-       device_create_file (&ctrl->pci_dev->dev, &dev_attr_dev);
+       device_remove_file(&ctrl->pci_dev->dev, &dev_attr_ctrl);
 }
diff --git a/drivers/pci/hotplug/shpchprm.h b/drivers/pci/hotplug/shpchprm.h
deleted file mode 100644 (file)
index 057b192..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * SHPCHPRM : SHPCHP Resource Manager for ACPI/non-ACPI platform
- *
- * Copyright (C) 1995,2001 Compaq Computer Corporation
- * Copyright (C) 2001 Greg Kroah-Hartman (greg@kroah.com)
- * Copyright (C) 2001 IBM Corp.
- * Copyright (C) 2003-2004 Intel Corporation
- *
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or (at
- * your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
- * NON INFRINGEMENT.  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.
- *
- * Send feedback to <greg@kroah.com>, <kristen.c.accardi@intel.com>
- *
- */
-
-#ifndef _SHPCHPRM_H_
-#define _SHPCHPRM_H_
-
-#ifdef CONFIG_HOTPLUG_PCI_SHPC_PHPRM_LEGACY
-#include "shpchprm_legacy.h"
-#else
-#include "shpchprm_nonacpi.h"
-#endif
-
-int shpchprm_init(enum php_ctlr_type ct);
-void shpchprm_cleanup(void);
-int shpchprm_print_pirt(void);
-int shpchprm_find_available_resources(struct controller *ctrl);
-int shpchprm_set_hpp(struct controller *ctrl, struct pci_func *func, u8 card_type);
-void shpchprm_enable_card(struct controller *ctrl, struct pci_func *func, u8 card_type);
-int shpchprm_get_physical_slot_number(struct controller *ctrl, u32 *sun, u8 busnum, u8 devnum);
-
-#ifdef DEBUG
-#define RES_CHECK(this, bits)  \
-       { if (((this) & (bits - 1))) \
-               printk("%s:%d ERR: potential res loss!\n", __FUNCTION__, __LINE__); }
-#else
-#define RES_CHECK(this, bits)
-#endif
-
-#endif                         /* _SHPCHPRM_H_ */
index d37b316..17145e5 100644 (file)
  *
  */
 
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/types.h>
 #include <linux/pci.h>
-#include <linux/init.h>
-#include <linux/acpi.h>
-#include <linux/efi.h>
-#include <asm/uaccess.h>
-#include <asm/system.h>
-#ifdef CONFIG_IA64
-#include <asm/iosapic.h>
-#endif
 #include <acpi/acpi.h>
 #include <acpi/acpi_bus.h>
 #include <acpi/actypes.h>
 #include "shpchp.h"
-#include "shpchprm.h"
-
-#define        PCI_MAX_BUS             0x100
-#define        ACPI_STA_DEVICE_PRESENT 0x01
 
 #define        METHOD_NAME__SUN        "_SUN"
 #define        METHOD_NAME__HPP        "_HPP"
 #define        METHOD_NAME_OSHP        "OSHP"
 
-#define        PHP_RES_BUS             0xA0
-#define        PHP_RES_IO              0xA1
-#define        PHP_RES_MEM             0xA2
-#define        PHP_RES_PMEM            0xA3
-
-#define        BRIDGE_TYPE_P2P         0x00
-#define        BRIDGE_TYPE_HOST        0x01
-
-/* this should go to drivers/acpi/include/ */
-struct acpi__hpp {
-       u8      cache_line_size;
-       u8      latency_timer;
-       u8      enable_serr;
-       u8      enable_perr;
-};
-
-struct acpi_php_slot {
-       struct acpi_php_slot    *next;
-       struct acpi_bridge      *bridge;
-       acpi_handle             handle;
-       int     seg;
-       int     bus;
-       int     dev;
-       int     fun;
-       u32     sun;
-       struct pci_resource *mem_head;
-       struct pci_resource *p_mem_head;
-       struct pci_resource *io_head;
-       struct pci_resource *bus_head;
-       void    *slot_ops;      /* _STA, _EJx, etc */
-       struct slot *slot;
-};             /* per func */
-
-struct acpi_bridge {
-       struct acpi_bridge      *parent;
-       struct acpi_bridge      *next;
-       struct acpi_bridge      *child;
-       acpi_handle     handle;
-       int seg;
-       int pbus;                               /* pdev->bus->number            */
-       int pdevice;                            /* PCI_SLOT(pdev->devfn)        */
-       int pfunction;                          /* PCI_DEVFN(pdev->devfn)       */
-       int bus;                                /* pdev->subordinate->number    */
-       struct acpi__hpp                *_hpp;
-       struct acpi_php_slot    *slots;
-       struct pci_resource     *tmem_head;     /* total from crs       */
-       struct pci_resource     *tp_mem_head;   /* total from crs       */
-       struct pci_resource     *tio_head;      /* total from crs       */
-       struct pci_resource     *tbus_head;     /* total from crs       */
-       struct pci_resource     *mem_head;      /* available    */
-       struct pci_resource     *p_mem_head;    /* available    */
-       struct pci_resource     *io_head;       /* available    */
-       struct pci_resource     *bus_head;      /* available    */
-       int scanned;
-       int type;
-};
-
-static struct acpi_bridge *acpi_bridges_head;
-
 static u8 * acpi_path_name( acpi_handle        handle)
 {
        acpi_status             status;
@@ -124,82 +52,43 @@ static u8 * acpi_path_name( acpi_handle    handle)
                return path_name;       
 }
 
-static void acpi_get__hpp ( struct acpi_bridge *ab);
-static void acpi_run_oshp ( struct acpi_bridge *ab);
-
-static int acpi_add_slot_to_php_slots(
-       struct acpi_bridge      *ab,
-       int                             bus_num,
-       acpi_handle             handle,
-       u32                             adr,
-       u32                             sun
-       )
-{
-       struct acpi_php_slot    *aps;
-       static long     samesun = -1;
-
-       aps = (struct acpi_php_slot *) kmalloc (sizeof(struct acpi_php_slot), GFP_KERNEL);
-       if (!aps) {
-               err ("acpi_shpchprm: alloc for aps fail\n");
-               return -1;
-       }
-       memset(aps, 0, sizeof(struct acpi_php_slot));
-
-       aps->handle = handle;
-       aps->bus = bus_num;
-       aps->dev = (adr >> 16) & 0xffff;
-       aps->fun = adr & 0xffff;
-       aps->sun = sun;
-
-       aps->next = ab->slots;  /* cling to the bridge */
-       aps->bridge = ab;
-       ab->slots = aps;
-
-       ab->scanned += 1;
-       if (!ab->_hpp)
-               acpi_get__hpp(ab);
-
-       acpi_run_oshp(ab);
-
-       if (sun != samesun) {
-               info("acpi_shpchprm:   Slot sun(%x) at s:b:d:f=0x%02x:%02x:%02x:%02x\n", aps->sun, ab->seg, 
-                       aps->bus, aps->dev, aps->fun);
-               samesun = sun;
-       }
-       return 0;
-}
-
-static void acpi_get__hpp ( struct acpi_bridge *ab)
+static acpi_status
+acpi_run_hpp(acpi_handle handle, struct hotplug_params *hpp)
 {
        acpi_status             status;
        u8                      nui[4];
        struct acpi_buffer      ret_buf = { 0, NULL};
        union acpi_object       *ext_obj, *package;
-       u8                      *path_name = acpi_path_name(ab->handle);
+       u8                      *path_name = acpi_path_name(handle);
        int                     i, len = 0;
 
        /* get _hpp */
-       status = acpi_evaluate_object(ab->handle, METHOD_NAME__HPP, NULL, &ret_buf);
+       status = acpi_evaluate_object(handle, METHOD_NAME__HPP, NULL, &ret_buf);
        switch (status) {
        case AE_BUFFER_OVERFLOW:
                ret_buf.pointer = kmalloc (ret_buf.length, GFP_KERNEL);
                if (!ret_buf.pointer) {
-                       err ("acpi_shpchprm:%s alloc for _HPP fail\n", path_name);
-                       return;
+                       err ("%s:%s alloc for _HPP fail\n", __FUNCTION__,
+                                       path_name);
+                       return AE_NO_MEMORY;
                }
-               status = acpi_evaluate_object(ab->handle, METHOD_NAME__HPP, NULL, &ret_buf);
+               status = acpi_evaluate_object(handle, METHOD_NAME__HPP,
+                               NULL, &ret_buf);
                if (ACPI_SUCCESS(status))
                        break;
        default:
                if (ACPI_FAILURE(status)) {
-                       err("acpi_shpchprm:%s _HPP fail=0x%x\n", path_name, status);
-                       return;
+                       dbg("%s:%s _HPP fail=0x%x\n", __FUNCTION__,
+                                       path_name, status);
+                       return status;
                }
        }
 
        ext_obj = (union acpi_object *) ret_buf.pointer;
        if (ext_obj->type != ACPI_TYPE_PACKAGE) {
-               err ("acpi_shpchprm:%s _HPP obj not a package\n", path_name);
+               err ("%s:%s _HPP obj not a package\n", __FUNCTION__,
+                               path_name);
+               status = AE_ERROR;
                goto free_and_return;
        }
 
@@ -212,1353 +101,41 @@ static void acpi_get__hpp ( struct acpi_bridge  *ab)
                        nui[i] = (u8)ext_obj->integer.value;
                        break;
                default:
-                       err ("acpi_shpchprm:%s _HPP obj type incorrect\n", path_name);
+                       err ("%s:%s _HPP obj type incorrect\n", __FUNCTION__,
+                                       path_name);
+                       status = AE_ERROR;
                        goto free_and_return;
                }
        }
 
-       ab->_hpp = kmalloc (sizeof (struct acpi__hpp), GFP_KERNEL);
-       if (!ab->_hpp) {
-               err ("acpi_shpchprm:%s alloc for _HPP failed\n", path_name);
-               goto free_and_return;
-       }
-       memset(ab->_hpp, 0, sizeof(struct acpi__hpp));
+       hpp->cache_line_size = nui[0];
+       hpp->latency_timer = nui[1];
+       hpp->enable_serr = nui[2];
+       hpp->enable_perr = nui[3];
 
-       ab->_hpp->cache_line_size       = nui[0];
-       ab->_hpp->latency_timer         = nui[1];
-       ab->_hpp->enable_serr           = nui[2];
-       ab->_hpp->enable_perr           = nui[3];
-
-       dbg("  _HPP: cache_line_size=0x%x\n", ab->_hpp->cache_line_size);
-       dbg("  _HPP: latency timer  =0x%x\n", ab->_hpp->latency_timer);
-       dbg("  _HPP: enable SERR    =0x%x\n", ab->_hpp->enable_serr);
-       dbg("  _HPP: enable PERR    =0x%x\n", ab->_hpp->enable_perr);
+       dbg("  _HPP: cache_line_size=0x%x\n", hpp->cache_line_size);
+       dbg("  _HPP: latency timer  =0x%x\n", hpp->latency_timer);
+       dbg("  _HPP: enable SERR    =0x%x\n", hpp->enable_serr);
+       dbg("  _HPP: enable PERR    =0x%x\n", hpp->enable_perr);
 
 free_and_return:
        kfree(ret_buf.pointer);
-}
-
-static void acpi_run_oshp ( struct acpi_bridge *ab)
-{
-       acpi_status             status;
-       u8                      *path_name = acpi_path_name(ab->handle);
-
-       /* run OSHP */
-       status = acpi_evaluate_object(ab->handle, METHOD_NAME_OSHP, NULL, NULL);
-       if (ACPI_FAILURE(status)) {
-               err("acpi_pciehprm:%s OSHP fails=0x%x\n", path_name, status);
-       } else
-               dbg("acpi_pciehprm:%s OSHP passes =0x%x\n", path_name, status);
-       return;
-}
-
-static acpi_status acpi_evaluate_crs(
-       acpi_handle             handle,
-       struct acpi_resource    **retbuf
-       )
-{
-       acpi_status             status;
-       struct acpi_buffer              crsbuf;
-       u8                      *path_name = acpi_path_name(handle);
-
-       crsbuf.length  = 0;
-       crsbuf.pointer = NULL;
-
-       status = acpi_get_current_resources (handle, &crsbuf);
-
-       switch (status) {
-       case AE_BUFFER_OVERFLOW:
-               break;          /* found */
-       case AE_NOT_FOUND:
-               dbg("acpi_shpchprm:%s _CRS not found\n", path_name);
-               return status;
-       default:
-               err ("acpi_shpchprm:%s _CRS fail=0x%x\n", path_name, status);
-               return status;
-       }
-
-       crsbuf.pointer = kmalloc (crsbuf.length, GFP_KERNEL);
-       if (!crsbuf.pointer) {
-               err ("acpi_shpchprm: alloc %ld bytes for %s _CRS fail\n", (ulong)crsbuf.length, path_name);
-               return AE_NO_MEMORY;
-       }
-
-       status = acpi_get_current_resources (handle, &crsbuf);
-       if (ACPI_FAILURE(status)) {
-               err("acpi_shpchprm: %s _CRS fail=0x%x.\n", path_name, status);
-               kfree(crsbuf.pointer);
-               return status;
-       }
-
-       *retbuf = crsbuf.pointer;
-
-       return status;
-}
-
-static void free_pci_resource ( struct pci_resource    *aprh)
-{
-       struct pci_resource     *res, *next;
-
-       for (res = aprh; res; res = next) {
-               next = res->next;
-               kfree(res);
-       }
-}
-
-static void print_pci_resource ( struct pci_resource   *aprh)
-{
-       struct pci_resource     *res;
-
-       for (res = aprh; res; res = res->next)
-               dbg("        base= 0x%x length= 0x%x\n", res->base, res->length);
-}
-
-static void print_slot_resources( struct acpi_php_slot *aps)
-{
-       if (aps->bus_head) {
-               dbg("    BUS Resources:\n");
-               print_pci_resource (aps->bus_head);
-       }
-
-       if (aps->io_head) {
-               dbg("    IO Resources:\n");
-               print_pci_resource (aps->io_head);
-       }
-
-       if (aps->mem_head) {
-               dbg("    MEM Resources:\n");
-               print_pci_resource (aps->mem_head);
-       }
-
-       if (aps->p_mem_head) {
-               dbg("    PMEM Resources:\n");
-               print_pci_resource (aps->p_mem_head);
-       }
-}
-
-static void print_pci_resources( struct acpi_bridge    *ab)
-{
-       if (ab->tbus_head) {
-               dbg("    Total BUS Resources:\n");
-               print_pci_resource (ab->tbus_head);
-       }
-       if (ab->bus_head) {
-               dbg("    BUS Resources:\n");
-               print_pci_resource (ab->bus_head);
-       }
-
-       if (ab->tio_head) {
-               dbg("    Total IO Resources:\n");
-               print_pci_resource (ab->tio_head);
-       }
-       if (ab->io_head) {
-               dbg("    IO Resources:\n");
-               print_pci_resource (ab->io_head);
-       }
-
-       if (ab->tmem_head) {
-               dbg("    Total MEM Resources:\n");
-               print_pci_resource (ab->tmem_head);
-       }
-       if (ab->mem_head) {
-               dbg("    MEM Resources:\n");
-               print_pci_resource (ab->mem_head);
-       }
-
-       if (ab->tp_mem_head) {
-               dbg("    Total PMEM Resources:\n");
-               print_pci_resource (ab->tp_mem_head);
-       }
-       if (ab->p_mem_head) {
-               dbg("    PMEM Resources:\n");
-               print_pci_resource (ab->p_mem_head);
-       }
-       if (ab->_hpp) {
-               dbg("    _HPP: cache_line_size=0x%x\n", ab->_hpp->cache_line_size);
-               dbg("    _HPP: latency timer  =0x%x\n", ab->_hpp->latency_timer);
-               dbg("    _HPP: enable SERR    =0x%x\n", ab->_hpp->enable_serr);
-               dbg("    _HPP: enable PERR    =0x%x\n", ab->_hpp->enable_perr);
-       }
-}
-
-static int shpchprm_delete_resource(
-       struct pci_resource **aprh,
-       ulong base,
-       ulong size)
-{
-       struct pci_resource *res;
-       struct pci_resource *prevnode;
-       struct pci_resource *split_node;
-       ulong tbase;
-
-       shpchp_resource_sort_and_combine(aprh);
-
-       for (res = *aprh; res; res = res->next) {
-               if (res->base > base)
-                       continue;
-
-               if ((res->base + res->length) < (base + size))
-                       continue;
-
-               if (res->base < base) {
-                       tbase = base;
-
-                       if ((res->length - (tbase - res->base)) < size)
-                               continue;
-
-                       split_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
-                       if (!split_node)
-                               return -ENOMEM;
-
-                       split_node->base = res->base;
-                       split_node->length = tbase - res->base;
-                       res->base = tbase;
-                       res->length -= split_node->length;
-
-                       split_node->next = res->next;
-                       res->next = split_node;
-               }
-
-               if (res->length >= size) {
-                       split_node = (struct pci_resource*) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
-                       if (!split_node)
-                               return -ENOMEM;
-
-                       split_node->base = res->base + size;
-                       split_node->length = res->length - size;
-                       res->length = size;
-
-                       split_node->next = res->next;
-                       res->next = split_node;
-               }
-
-               if (*aprh == res) {
-                       *aprh = res->next;
-               } else {
-                       prevnode = *aprh;
-                       while (prevnode->next != res)
-                               prevnode = prevnode->next;
-
-                       prevnode->next = res->next;
-               }
-               res->next = NULL;
-               kfree(res);
-               break;
-       }
-
-       return 0;
-}
-
-static int shpchprm_delete_resources(
-       struct pci_resource **aprh,
-       struct pci_resource *this
-       )
-{
-       struct pci_resource *res;
-
-       for (res = this; res; res = res->next)
-               shpchprm_delete_resource(aprh, res->base, res->length);
-
-       return 0;
-}
-
-static int shpchprm_add_resource(
-       struct pci_resource **aprh,
-       ulong base,
-       ulong size)
-{
-       struct pci_resource *res;
-
-       for (res = *aprh; res; res = res->next) {
-               if ((res->base + res->length) == base) {
-                       res->length += size;
-                       size = 0L;
-                       break;
-               }
-               if (res->next == *aprh)
-                       break;
-       }
-
-       if (size) {
-               res = kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
-               if (!res) {
-                       err ("acpi_shpchprm: alloc for res fail\n");
-                       return -ENOMEM;
-               }
-               memset(res, 0, sizeof (struct pci_resource));
-
-               res->base = base;
-               res->length = size;
-               res->next = *aprh;
-               *aprh = res;
-       }
-
-       return 0;
-}
-
-static int shpchprm_add_resources(
-       struct pci_resource **aprh,
-       struct pci_resource *this
-       )
-{
-       struct pci_resource *res;
-       int     rc = 0;
-
-       for (res = this; res && !rc; res = res->next)
-               rc = shpchprm_add_resource(aprh, res->base, res->length);
-
-       return rc;
-}
-
-static void acpi_parse_io (
-       struct acpi_bridge              *ab,
-       union acpi_resource_data        *data
-       )
-{
-       struct acpi_resource_io *dataio;
-       dataio = (struct acpi_resource_io *) data;
-
-       dbg("Io Resource\n");
-       dbg("  %d bit decode\n", ACPI_DECODE_16 == dataio->io_decode ? 16:10);
-       dbg("  Range minimum base: %08X\n", dataio->min_base_address);
-       dbg("  Range maximum base: %08X\n", dataio->max_base_address);
-       dbg("  Alignment: %08X\n", dataio->alignment);
-       dbg("  Range Length: %08X\n", dataio->range_length);
-}
-
-static void acpi_parse_fixed_io (
-       struct acpi_bridge              *ab,
-       union acpi_resource_data        *data
-       )
-{
-       struct acpi_resource_fixed_io  *datafio;
-       datafio = (struct acpi_resource_fixed_io *) data;
-
-       dbg("Fixed Io Resource\n");
-       dbg("  Range base address: %08X", datafio->base_address);
-       dbg("  Range length: %08X", datafio->range_length);
-}
-
-static void acpi_parse_address16_32 (
-       struct acpi_bridge              *ab,
-       union acpi_resource_data        *data,
-       acpi_resource_type              id
-       )
-{
-       /* 
-        * acpi_resource_address16 == acpi_resource_address32
-        * acpi_resource_address16 *data16 = (acpi_resource_address16 *) data;
-        */
-       struct acpi_resource_address32 *data32 = (struct acpi_resource_address32 *) data;
-       struct pci_resource **aprh, **tprh;
-
-       if (id == ACPI_RSTYPE_ADDRESS16)
-               dbg("acpi_shpchprm:16-Bit Address Space Resource\n");
-       else
-               dbg("acpi_shpchprm:32-Bit Address Space Resource\n");
-
-       switch (data32->resource_type) {
-       case ACPI_MEMORY_RANGE: 
-               dbg("  Resource Type: Memory Range\n");
-               aprh = &ab->mem_head;
-               tprh = &ab->tmem_head;
-
-               switch (data32->attribute.memory.cache_attribute) {
-               case ACPI_NON_CACHEABLE_MEMORY:
-                       dbg("  Type Specific: Noncacheable memory\n");
-                       break; 
-               case ACPI_CACHABLE_MEMORY:
-                       dbg("  Type Specific: Cacheable memory\n");
-                       break; 
-               case ACPI_WRITE_COMBINING_MEMORY:
-                       dbg("  Type Specific: Write-combining memory\n");
-                       break; 
-               case ACPI_PREFETCHABLE_MEMORY:
-                       aprh = &ab->p_mem_head;
-                       dbg("  Type Specific: Prefetchable memory\n");
-                       break; 
-               default:
-                       dbg("  Type Specific: Invalid cache attribute\n");
-                       break;
-               }
-
-               dbg("  Type Specific: Read%s\n", ACPI_READ_WRITE_MEMORY == data32->attribute.memory.read_write_attribute ? "/Write":" Only");
-               break;
-
-       case ACPI_IO_RANGE: 
-               dbg("  Resource Type: I/O Range\n");
-               aprh = &ab->io_head;
-               tprh = &ab->tio_head;
-
-               switch (data32->attribute.io.range_attribute) {
-               case ACPI_NON_ISA_ONLY_RANGES:
-                       dbg("  Type Specific: Non-ISA Io Addresses\n");
-                       break; 
-               case ACPI_ISA_ONLY_RANGES:
-                       dbg("  Type Specific: ISA Io Addresses\n");
-                       break; 
-               case ACPI_ENTIRE_RANGE:
-                       dbg("  Type Specific: ISA and non-ISA Io Addresses\n");
-                       break; 
-               default:
-                       dbg("  Type Specific: Invalid range attribute\n");
-                       break;
-               }
-               break;
-
-       case ACPI_BUS_NUMBER_RANGE: 
-               dbg("  Resource Type: Bus Number Range(fixed)\n");
-               /* fixup to be compatible with the rest of php driver */
-               data32->min_address_range++;
-               data32->address_length--;
-               aprh = &ab->bus_head;
-               tprh = &ab->tbus_head;
-               break; 
-       default: 
-               dbg("  Resource Type: Invalid resource type. Exiting.\n");
-               return;
-       }
-
-       dbg("  Resource %s\n", ACPI_CONSUMER == data32->producer_consumer ? "Consumer":"Producer");
-       dbg("  %s decode\n", ACPI_SUB_DECODE == data32->decode ? "Subtractive":"Positive");
-       dbg("  Min address is %s fixed\n", ACPI_ADDRESS_FIXED == data32->min_address_fixed ? "":"not");
-       dbg("  Max address is %s fixed\n", ACPI_ADDRESS_FIXED == data32->max_address_fixed ? "":"not");
-       dbg("  Granularity: %08X\n", data32->granularity);
-       dbg("  Address range min: %08X\n", data32->min_address_range);
-       dbg("  Address range max: %08X\n", data32->max_address_range);
-       dbg("  Address translation offset: %08X\n", data32->address_translation_offset);
-       dbg("  Address Length: %08X\n", data32->address_length);
-
-       if (0xFF != data32->resource_source.index) {
-               dbg("  Resource Source Index: %X\n", data32->resource_source.index);
-               /* dbg("  Resource Source: %s\n", data32->resource_source.string_ptr); */
-       }
-
-       shpchprm_add_resource(aprh, data32->min_address_range, data32->address_length);
-}
-
-static acpi_status acpi_parse_crs(
-       struct acpi_bridge      *ab,
-       struct acpi_resource    *crsbuf
-       )
-{
-       acpi_status             status = AE_OK;
-       struct acpi_resource    *resource = crsbuf;
-       u8                      count = 0;
-       u8                      done = 0;
-
-       while (!done) {
-               dbg("acpi_shpchprm: PCI bus 0x%x Resource structure %x.\n", ab->bus, count++);
-               switch (resource->id) {
-               case ACPI_RSTYPE_IRQ:
-                       dbg("Irq -------- Resource\n");
-                       break; 
-               case ACPI_RSTYPE_DMA:
-                       dbg("DMA -------- Resource\n");
-                       break; 
-               case ACPI_RSTYPE_START_DPF:
-                       dbg("Start DPF -------- Resource\n");
-                       break; 
-               case ACPI_RSTYPE_END_DPF:
-                       dbg("End DPF -------- Resource\n");
-                       break; 
-               case ACPI_RSTYPE_IO:
-                       acpi_parse_io (ab, &resource->data);
-                       break; 
-               case ACPI_RSTYPE_FIXED_IO:
-                       acpi_parse_fixed_io (ab, &resource->data);
-                       break; 
-               case ACPI_RSTYPE_VENDOR:
-                       dbg("Vendor -------- Resource\n");
-                       break; 
-               case ACPI_RSTYPE_END_TAG:
-                       dbg("End_tag -------- Resource\n");
-                       done = 1;
-                       break; 
-               case ACPI_RSTYPE_MEM24:
-                       dbg("Mem24 -------- Resource\n");
-                       break; 
-               case ACPI_RSTYPE_MEM32:
-                       dbg("Mem32 -------- Resource\n");
-                       break; 
-               case ACPI_RSTYPE_FIXED_MEM32:
-                       dbg("Fixed Mem32 -------- Resource\n");
-                       break; 
-               case ACPI_RSTYPE_ADDRESS16:
-                       acpi_parse_address16_32(ab, &resource->data, ACPI_RSTYPE_ADDRESS16);
-                       break; 
-               case ACPI_RSTYPE_ADDRESS32:
-                       acpi_parse_address16_32(ab, &resource->data, ACPI_RSTYPE_ADDRESS32);
-                       break; 
-               case ACPI_RSTYPE_ADDRESS64:
-                       info("Address64 -------- Resource unparsed\n");
-                       break; 
-               case ACPI_RSTYPE_EXT_IRQ:
-                       dbg("Ext Irq -------- Resource\n");
-                       break; 
-               default:
-                       dbg("Invalid -------- resource type 0x%x\n", resource->id);
-                       break;
-               }
-
-               resource = (struct acpi_resource *) ((char *)resource + resource->length);
-       }
-
        return status;
 }
 
-static acpi_status acpi_get_crs( struct acpi_bridge    *ab)
+static void acpi_run_oshp(acpi_handle handle)
 {
-       acpi_status             status;
-       struct acpi_resource    *crsbuf;
-
-       status = acpi_evaluate_crs(ab->handle, &crsbuf);
-       if (ACPI_SUCCESS(status)) {
-               status = acpi_parse_crs(ab, crsbuf);
-               kfree(crsbuf);
-
-               shpchp_resource_sort_and_combine(&ab->bus_head);
-               shpchp_resource_sort_and_combine(&ab->io_head);
-               shpchp_resource_sort_and_combine(&ab->mem_head);
-               shpchp_resource_sort_and_combine(&ab->p_mem_head);
-
-               shpchprm_add_resources (&ab->tbus_head, ab->bus_head);
-               shpchprm_add_resources (&ab->tio_head, ab->io_head);
-               shpchprm_add_resources (&ab->tmem_head, ab->mem_head);
-               shpchprm_add_resources (&ab->tp_mem_head, ab->p_mem_head);
-       }
-
-       return status;
-}
-
-/* find acpi_bridge downword from ab.  */
-static struct acpi_bridge *
-find_acpi_bridge_by_bus(
-       struct acpi_bridge *ab,
-       int seg,
-       int bus         /* pdev->subordinate->number */
-       )
-{
-       struct acpi_bridge      *lab = NULL;
-
-       if (!ab)
-               return NULL;
-
-       if ((ab->bus == bus) && (ab->seg == seg))
-               return ab;
-
-       if (ab->child)
-               lab = find_acpi_bridge_by_bus(ab->child, seg, bus);
-
-       if (!lab)
-       if (ab->next)
-               lab = find_acpi_bridge_by_bus(ab->next, seg, bus);
-
-       return lab;
-}
-
-/*
- * Build a device tree of ACPI PCI Bridges
- */
-static void shpchprm_acpi_register_a_bridge (
-       struct acpi_bridge      **head,
-       struct acpi_bridge      *pab,   /* parent bridge to which child bridge is added */
-       struct acpi_bridge      *cab    /* child bridge to add */
-       )
-{
-       struct acpi_bridge      *lpab;
-       struct acpi_bridge      *lcab;
-
-       lpab = find_acpi_bridge_by_bus(*head, pab->seg, pab->bus);
-       if (!lpab) {
-               if (!(pab->type & BRIDGE_TYPE_HOST))
-                       warn("PCI parent bridge s:b(%x:%x) not in list.\n", pab->seg, pab->bus);
-               pab->next = *head;
-               *head = pab;
-               lpab = pab;
-       }
-
-       if ((cab->type & BRIDGE_TYPE_HOST) && (pab == cab))
-               return;
-
-       lcab = find_acpi_bridge_by_bus(*head, cab->seg, cab->bus);
-       if (lcab) {
-               if ((pab->bus != lcab->parent->bus) || (lcab->bus != cab->bus))
-                       err("PCI child bridge s:b(%x:%x) in list with diff parent.\n", cab->seg, cab->bus);
-               return;
-       } else
-               lcab = cab;
-
-       lcab->parent = lpab;
-       lcab->next = lpab->child;
-       lpab->child = lcab;
-}
-
-static acpi_status shpchprm_acpi_build_php_slots_callback(
-       acpi_handle     handle,
-       u32             Level,
-       void            *context,
-       void            **retval
-       )
-{
-       ulong           bus_num;
-       ulong           seg_num;
-       ulong           sun, adr;
-       ulong           padr = 0;
-       acpi_handle             phandle = NULL;
-       struct acpi_bridge      *pab = (struct acpi_bridge *)context;
-       struct acpi_bridge      *lab;
        acpi_status             status;
        u8                      *path_name = acpi_path_name(handle);
 
-       /* get _SUN */
-       status = acpi_evaluate_integer(handle, METHOD_NAME__SUN, NULL, &sun);
-       switch(status) {
-       case AE_NOT_FOUND:
-               return AE_OK;
-       default:
-               if (ACPI_FAILURE(status)) {
-                       err("acpi_shpchprm:%s _SUN fail=0x%x\n", path_name, status);
-                       return status;
-               }
-       }
-
-       /* get _ADR. _ADR must exist if _SUN exists */
-       status = acpi_evaluate_integer(handle, METHOD_NAME__ADR, NULL, &adr);
-       if (ACPI_FAILURE(status)) {
-               err("acpi_shpchprm:%s _ADR fail=0x%x\n", path_name, status);
-               return status;
-       }
-
-       dbg("acpi_shpchprm:%s sun=0x%08x adr=0x%08x\n", path_name, (u32)sun, (u32)adr);
-
-       status = acpi_get_parent(handle, &phandle);
+       /* run OSHP */
+       status = acpi_evaluate_object(handle, METHOD_NAME_OSHP, NULL, NULL);
        if (ACPI_FAILURE(status)) {
-               err("acpi_shpchprm:%s get_parent fail=0x%x\n", path_name, status);
-               return (status);
-       }
-
-       bus_num = pab->bus;
-       seg_num = pab->seg;
-
-       if (pab->bus == bus_num) {
-               lab = pab;
+               err("%s:%s OSHP fails=0x%x\n", __FUNCTION__, path_name,
+                               status);
        } else {
-               dbg("WARN: pab is not parent\n");
-               lab = find_acpi_bridge_by_bus(pab, seg_num, bus_num);
-               if (!lab) {
-                       dbg("acpi_shpchprm: alloc new P2P bridge(%x) for sun(%08x)\n", (u32)bus_num, (u32)sun);
-                       lab = (struct acpi_bridge *)kmalloc(sizeof(struct acpi_bridge), GFP_KERNEL);
-                       if (!lab) {
-                               err("acpi_shpchprm: alloc for ab fail\n");
-                               return AE_NO_MEMORY;
-                       }
-                       memset(lab, 0, sizeof(struct acpi_bridge));
-
-                       lab->handle = phandle;
-                       lab->pbus = pab->bus;
-                       lab->pdevice = (int)(padr >> 16) & 0xffff;
-                       lab->pfunction = (int)(padr & 0xffff);
-                       lab->bus = (int)bus_num;
-                       lab->scanned = 0;
-                       lab->type = BRIDGE_TYPE_P2P;
-
-                       shpchprm_acpi_register_a_bridge (&acpi_bridges_head, pab, lab);
-               } else
-                       dbg("acpi_shpchprm: found P2P bridge(%x) for sun(%08x)\n", (u32)bus_num, (u32)sun);
+               dbg("%s:%s OSHP passes\n", __FUNCTION__, path_name);
        }
-
-       acpi_add_slot_to_php_slots(lab, (int)bus_num, handle, (u32)adr, (u32)sun);
-       return (status);
-}
-
-static int shpchprm_acpi_build_php_slots(
-       struct acpi_bridge      *ab,
-       u32                     depth
-       )
-{
-       acpi_status     status;
-       u8              *path_name = acpi_path_name(ab->handle);
-
-       /* Walk down this pci bridge to get _SUNs if any behind P2P */
-       status = acpi_walk_namespace ( ACPI_TYPE_DEVICE,
-                               ab->handle,
-                               depth,
-                               shpchprm_acpi_build_php_slots_callback,
-                               ab,
-                               NULL );
-       if (ACPI_FAILURE(status)) {
-               dbg("acpi_shpchprm:%s walk for _SUN on pci bridge seg:bus(%x:%x) fail=0x%x\n", path_name, ab->seg, ab->bus, status);
-               return -1;
-       }
-
-       return 0;
-}
-
-static void build_a_bridge(
-       struct acpi_bridge      *pab,
-       struct acpi_bridge      *ab
-       )
-{
-       u8              *path_name = acpi_path_name(ab->handle);
-
-       shpchprm_acpi_register_a_bridge (&acpi_bridges_head, pab, ab);
-
-       switch (ab->type) {
-       case BRIDGE_TYPE_HOST:
-               dbg("acpi_shpchprm: Registered PCI HOST Bridge(%02x)    on s:b:d:f(%02x:%02x:%02x:%02x) [%s]\n",
-                       ab->bus, ab->seg, ab->pbus, ab->pdevice, ab->pfunction, path_name);
-               break;
-       case BRIDGE_TYPE_P2P:
-               dbg("acpi_shpchprm: Registered PCI  P2P Bridge(%02x-%02x) on s:b:d:f(%02x:%02x:%02x:%02x) [%s]\n",
-                       ab->pbus, ab->bus, ab->seg, ab->pbus, ab->pdevice, ab->pfunction, path_name);
-               break;
-       };
-
-       /* build any immediate PHP slots under this pci bridge */
-       shpchprm_acpi_build_php_slots(ab, 1);
-}
-
-static struct acpi_bridge * add_p2p_bridge(
-       acpi_handle handle,
-       struct acpi_bridge      *pab,   /* parent */
-       ulong   adr
-       )
-{
-       struct acpi_bridge      *ab;
-       struct pci_dev  *pdev;
-       ulong           devnum, funcnum;
-       u8                      *path_name = acpi_path_name(handle);
-
-       ab = (struct acpi_bridge *) kmalloc (sizeof(struct acpi_bridge), GFP_KERNEL);
-       if (!ab) {
-               err("acpi_shpchprm: alloc for ab fail\n");
-               return NULL;
-       }
-       memset(ab, 0, sizeof(struct acpi_bridge));
-
-       devnum = (adr >> 16) & 0xffff;
-       funcnum = adr & 0xffff;
-
-       pdev = pci_find_slot(pab->bus, PCI_DEVFN(devnum, funcnum));
-       if (!pdev || !pdev->subordinate) {
-               err("acpi_shpchprm:%s is not a P2P Bridge\n", path_name);
-               kfree(ab);
-               return NULL;
-       }
-
-       ab->handle = handle;
-       ab->seg = pab->seg;
-       ab->pbus = pab->bus;            /* or pdev->bus->number */
-       ab->pdevice = devnum;           /* or PCI_SLOT(pdev->devfn) */
-       ab->pfunction = funcnum;        /* or PCI_FUNC(pdev->devfn) */
-       ab->bus = pdev->subordinate->number;
-       ab->scanned = 0;
-       ab->type = BRIDGE_TYPE_P2P;
-
-       dbg("acpi_shpchprm: P2P(%x-%x) on pci=b:d:f(%x:%x:%x) acpi=b:d:f(%x:%x:%x) [%s]\n",
-               pab->bus, ab->bus, pdev->bus->number, PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn),
-               pab->bus, (u32)devnum, (u32)funcnum, path_name);
-
-       build_a_bridge(pab, ab);
-
-       return ab;
-}
-
-static acpi_status scan_p2p_bridge(
-       acpi_handle             handle,
-       u32                     Level,
-       void                    *context,
-       void                    **retval
-       )
-{
-       struct acpi_bridge      *pab = (struct acpi_bridge *)context;
-       struct acpi_bridge      *ab;
-       acpi_status             status;
-       ulong           adr = 0;
-       u8                      *path_name = acpi_path_name(handle);
-       ulong           devnum, funcnum;
-       struct pci_dev  *pdev;
-
-       /* get device, function */
-       status = acpi_evaluate_integer(handle, METHOD_NAME__ADR, NULL, &adr);
-       if (ACPI_FAILURE(status)) {
-               if (status != AE_NOT_FOUND)
-                       err("acpi_shpchprm:%s _ADR fail=0x%x\n", path_name, status);
-               return AE_OK;
-       }
-
-       devnum = (adr >> 16) & 0xffff;
-       funcnum = adr & 0xffff;
-
-       pdev = pci_find_slot(pab->bus, PCI_DEVFN(devnum, funcnum));
-       if (!pdev)
-               return AE_OK;
-       if (!pdev->subordinate)
-               return AE_OK;
-
-       ab = add_p2p_bridge(handle, pab, adr);
-       if (ab) {
-               status = acpi_walk_namespace ( ACPI_TYPE_DEVICE,
-                                       handle,
-                                       (u32)1,
-                                       scan_p2p_bridge,
-                                       ab,
-                                       NULL);
-               if (ACPI_FAILURE(status))
-                       dbg("acpi_shpchprm:%s find_p2p fail=0x%x\n", path_name, status);
-       }
-
-       return AE_OK;
-}
-
-static struct acpi_bridge * add_host_bridge(
-       acpi_handle handle,
-       ulong   segnum,
-       ulong   busnum
-       )
-{
-       ulong                   adr = 0;
-       acpi_status             status;
-       struct acpi_bridge      *ab;
-       u8                      *path_name = acpi_path_name(handle);
-
-       /* get device, function: host br adr is always 0000 though.  */
-       status = acpi_evaluate_integer(handle, METHOD_NAME__ADR, NULL, &adr);
-       if (ACPI_FAILURE(status)) {
-               err("acpi_shpchprm:%s _ADR fail=0x%x\n", path_name, status);
-               return NULL;
-       }
-       dbg("acpi_shpchprm: ROOT PCI seg(0x%x)bus(0x%x)dev(0x%x)func(0x%x) [%s]\n", (u32)segnum, (u32)busnum, 
-               (u32)(adr >> 16) & 0xffff, (u32)adr & 0xffff, path_name);
-
-       ab = (struct acpi_bridge *) kmalloc (sizeof(struct acpi_bridge), GFP_KERNEL);
-       if (!ab) {
-               err("acpi_shpchprm: alloc for ab fail\n");
-               return NULL;
-       }
-       memset(ab, 0, sizeof(struct acpi_bridge));
-
-       ab->handle = handle;
-       ab->seg = (int)segnum;
-       ab->bus = ab->pbus = (int)busnum;
-       ab->pdevice = (int)(adr >> 16) & 0xffff;
-       ab->pfunction = (int)(adr & 0xffff);
-       ab->scanned = 0;
-       ab->type = BRIDGE_TYPE_HOST;
-
-       /* get root pci bridge's current resources */
-       status = acpi_get_crs(ab);
-       if (ACPI_FAILURE(status)) {
-               err("acpi_shpchprm:%s evaluate _CRS fail=0x%x\n", path_name, status);
-               kfree(ab);
-               return NULL;
-       }
-       build_a_bridge(ab, ab);
-
-       return ab;
-}
-
-static acpi_status acpi_scan_from_root_pci_callback (
-       acpi_handle     handle,
-       u32                     Level,
-       void            *context,
-       void            **retval
-       )
-{
-       ulong           segnum = 0;
-       ulong           busnum = 0;
-       acpi_status             status;
-       struct acpi_bridge      *ab;
-       u8                      *path_name = acpi_path_name(handle);
-
-       /* get bus number of this pci root bridge */
-       status = acpi_evaluate_integer(handle, METHOD_NAME__SEG, NULL, &segnum);
-       if (ACPI_FAILURE(status)) {
-               if (status != AE_NOT_FOUND) {
-                       err("acpi_shpchprm:%s evaluate _SEG fail=0x%x\n", path_name, status);
-                       return status;
-               }
-               segnum = 0;
-       }
-
-       /* get bus number of this pci root bridge */
-       status = acpi_evaluate_integer(handle, METHOD_NAME__BBN, NULL, &busnum);
-       if (ACPI_FAILURE(status)) {
-               err("acpi_shpchprm:%s evaluate _BBN fail=0x%x\n", path_name, status);
-               return (status);
-       }
-
-       ab = add_host_bridge(handle, segnum, busnum);
-       if (ab) {
-               status = acpi_walk_namespace ( ACPI_TYPE_DEVICE,
-                                       handle,
-                                       1,
-                                       scan_p2p_bridge,
-                                       ab,
-                                       NULL);
-               if (ACPI_FAILURE(status))
-                       dbg("acpi_shpchprm:%s find_p2p fail=0x%x\n", path_name, status);
-       }
-
-       return AE_OK;
-}
-
-static int shpchprm_acpi_scan_pci (void)
-{
-       acpi_status     status;
-
-       /*
-        * TBD: traverse LDM device tree with the help of
-        *  unified ACPI augmented for php device population.
-        */
-       status = acpi_get_devices ( PCI_ROOT_HID_STRING,
-                               acpi_scan_from_root_pci_callback,
-                               NULL,
-                               NULL );
-       if (ACPI_FAILURE(status)) {
-               err("acpi_shpchprm:get_device PCI ROOT HID fail=0x%x\n", status);
-               return -1;
-       }
-
-       return 0;
-}
-
-int shpchprm_init(enum php_ctlr_type ctlr_type)
-{
-       int     rc;
-
-       if (ctlr_type != PCI)
-               return -ENODEV;
-
-       dbg("shpchprm ACPI init <enter>\n");
-       acpi_bridges_head = NULL;
-
-       /* construct PCI bus:device tree of acpi_handles */
-       rc = shpchprm_acpi_scan_pci();
-       if (rc)
-               return rc;
-
-       dbg("shpchprm ACPI init %s\n", (rc)?"fail":"success");
-       return rc;
-}
-
-static void free_a_slot(struct acpi_php_slot *aps)
-{
-       dbg("        free a php func of slot(0x%02x) on PCI b:d:f=0x%02x:%02x:%02x\n", aps->sun, aps->bus, aps->dev, aps->fun);
-
-       free_pci_resource (aps->io_head);
-       free_pci_resource (aps->bus_head);
-       free_pci_resource (aps->mem_head);
-       free_pci_resource (aps->p_mem_head);
-
-       kfree(aps);
-}
-
-static void free_a_bridge( struct acpi_bridge  *ab)
-{
-       struct acpi_php_slot    *aps, *next;
-
-       switch (ab->type) {
-       case BRIDGE_TYPE_HOST:
-               dbg("Free ACPI PCI HOST Bridge(%x) [%s] on s:b:d:f(%x:%x:%x:%x)\n",
-                       ab->bus, acpi_path_name(ab->handle), ab->seg, ab->pbus, ab->pdevice, ab->pfunction);
-               break;
-       case BRIDGE_TYPE_P2P:
-               dbg("Free ACPI PCI P2P Bridge(%x-%x) [%s] on s:b:d:f(%x:%x:%x:%x)\n",
-                       ab->pbus, ab->bus, acpi_path_name(ab->handle), ab->seg, ab->pbus, ab->pdevice, ab->pfunction);
-               break;
-       };
-
-       /* free slots first */
-       for (aps = ab->slots; aps; aps = next) {
-               next = aps->next;
-               free_a_slot(aps);
-       }
-
-       free_pci_resource (ab->io_head);
-       free_pci_resource (ab->tio_head);
-       free_pci_resource (ab->bus_head);
-       free_pci_resource (ab->tbus_head);
-       free_pci_resource (ab->mem_head);
-       free_pci_resource (ab->tmem_head);
-       free_pci_resource (ab->p_mem_head);
-       free_pci_resource (ab->tp_mem_head);
-
-       kfree(ab);
-}
-
-static void shpchprm_free_bridges ( struct acpi_bridge *ab)
-{
-       if (!ab)
-               return;
-
-       if (ab->child)
-               shpchprm_free_bridges (ab->child);
-
-       if (ab->next)
-               shpchprm_free_bridges (ab->next);
-
-       free_a_bridge(ab);
-}
-
-void shpchprm_cleanup(void)
-{
-       shpchprm_free_bridges (acpi_bridges_head);
-}
-
-static int get_number_of_slots (
-       struct acpi_bridge      *ab,
-       int                             selfonly
-       )
-{
-       struct acpi_php_slot    *aps;
-       int     prev_slot = -1;
-       int     slot_num = 0;
-
-       for ( aps = ab->slots; aps; aps = aps->next)
-               if (aps->dev != prev_slot) {
-                       prev_slot = aps->dev;
-                       slot_num++;
-               }
-
-       if (ab->child)
-               slot_num += get_number_of_slots (ab->child, 0);
-
-       if (selfonly)
-               return slot_num;
-
-       if (ab->next)
-               slot_num += get_number_of_slots (ab->next, 0);
-
-       return slot_num;
-}
-
-static int print_acpi_resources (struct acpi_bridge    *ab)
-{
-       struct acpi_php_slot    *aps;
-       int     i;
-
-       switch (ab->type) {
-       case BRIDGE_TYPE_HOST:
-               dbg("PCI HOST Bridge (%x) [%s]\n", ab->bus, acpi_path_name(ab->handle));
-               break;
-       case BRIDGE_TYPE_P2P:
-               dbg("PCI P2P Bridge (%x-%x) [%s]\n", ab->pbus, ab->bus, acpi_path_name(ab->handle));
-               break;
-       };
-
-       print_pci_resources (ab);
-
-       for ( i = -1, aps = ab->slots; aps; aps = aps->next) {
-               if (aps->dev == i)
-                       continue;
-               dbg("  Slot sun(%x) s:b:d:f(%02x:%02x:%02x:%02x)\n", aps->sun, aps->seg, aps->bus, aps->dev, aps->fun);
-               print_slot_resources(aps);
-               i = aps->dev;
-       }
-
-       if (ab->child)
-               print_acpi_resources (ab->child);
-
-       if (ab->next)
-               print_acpi_resources (ab->next);
-
-       return 0;
-}
-
-int shpchprm_print_pirt(void)
-{
-       dbg("SHPCHPRM ACPI Slots\n");
-       if (acpi_bridges_head)
-               print_acpi_resources (acpi_bridges_head);
-       return 0;
-}
-
-static struct acpi_php_slot * get_acpi_slot (
-       struct acpi_bridge *ab,
-       u32 sun
-       )
-{
-       struct acpi_php_slot    *aps = NULL;
-
-       for ( aps = ab->slots; aps; aps = aps->next)
-               if (aps->sun == sun)
-                       return aps;
-
-       if (!aps && ab->child) {
-               aps = (struct acpi_php_slot *)get_acpi_slot (ab->child, sun);
-               if (aps)
-                       return aps;
-       }
-
-       if (!aps && ab->next) {
-               aps = (struct acpi_php_slot *)get_acpi_slot (ab->next, sun);
-               if (aps)
-                       return aps;
-       }
-
-       return aps;
-
-}
-
-#if 0
-static void * shpchprm_get_slot(struct slot *slot)
-{
-       struct acpi_bridge      *ab = acpi_bridges_head;
-       struct acpi_php_slot    *aps = get_acpi_slot (ab, slot->number);
-
-       aps->slot = slot;
-
-       dbg("Got acpi slot sun(%x): s:b:d:f(%x:%x:%x:%x)\n", aps->sun, aps->seg, aps->bus, aps->dev, aps->fun);
-
-       return (void *)aps;
-}
-#endif
-
-static void shpchprm_dump_func_res( struct pci_func *fun)
-{
-       struct pci_func *func = fun;
-
-       if (func->bus_head) {
-               dbg(":    BUS Resources:\n");
-               print_pci_resource (func->bus_head);
-       }
-       if (func->io_head) {
-               dbg(":    IO Resources:\n");
-               print_pci_resource (func->io_head);
-       }
-       if (func->mem_head) {
-               dbg(":    MEM Resources:\n");
-               print_pci_resource (func->mem_head);
-       }
-       if (func->p_mem_head) {
-               dbg(":    PMEM Resources:\n");
-               print_pci_resource (func->p_mem_head);
-       }
-}
-
-static void shpchprm_dump_ctrl_res( struct controller *ctlr)
-{
-       struct controller *ctrl = ctlr;
-
-       if (ctrl->bus_head) {
-               dbg(":    BUS Resources:\n");
-               print_pci_resource (ctrl->bus_head);
-       }
-       if (ctrl->io_head) {
-               dbg(":    IO Resources:\n");
-               print_pci_resource (ctrl->io_head);
-       }
-       if (ctrl->mem_head) {
-               dbg(":    MEM Resources:\n");
-               print_pci_resource (ctrl->mem_head);
-       }
-       if (ctrl->p_mem_head) {
-               dbg(":    PMEM Resources:\n");
-               print_pci_resource (ctrl->p_mem_head);
-       }
-}
-
-static int shpchprm_get_used_resources (
-       struct controller *ctrl,
-       struct pci_func *func
-       )
-{
-       return shpchp_save_used_resources (ctrl, func, !DISABLE_CARD);
-}
-
-static int configure_existing_function(
-       struct controller *ctrl,
-       struct pci_func *func
-       )
-{
-       int rc;
-
-       /* see how much resources the func has used. */
-       rc = shpchprm_get_used_resources (ctrl, func);
-
-       if (!rc) {
-               /* subtract the resources used by the func from ctrl resources */
-               rc  = shpchprm_delete_resources (&ctrl->bus_head, func->bus_head);
-               rc |= shpchprm_delete_resources (&ctrl->io_head, func->io_head);
-               rc |= shpchprm_delete_resources (&ctrl->mem_head, func->mem_head);
-               rc |= shpchprm_delete_resources (&ctrl->p_mem_head, func->p_mem_head);
-               if (rc)
-                       warn("aCEF: cannot del used resources\n");
-       } else
-               err("aCEF: cannot get used resources\n");
-
-       return rc;
-}
-
-static int bind_pci_resources_to_slots ( struct controller *ctrl)
-{
-       struct pci_func *func, new_func;
-       int busn = ctrl->slot_bus;
-       int devn, funn;
-       u32     vid;
-
-       for (devn = 0; devn < 32; devn++) {
-               for (funn = 0; funn < 8; funn++) {
-                       /*
-                       if (devn == ctrl->device && funn == ctrl->function)
-                               continue;
-                       */
-                       /* find out if this entry is for an occupied slot */
-                       vid = 0xFFFFFFFF;
-                       pci_bus_read_config_dword(ctrl->pci_dev->subordinate, PCI_DEVFN(devn, funn), PCI_VENDOR_ID, &vid);
-
-                       if (vid != 0xFFFFFFFF) {
-                               func = shpchp_slot_find(busn, devn, funn);
-                               if (!func) {
-                                       memset(&new_func, 0, sizeof(struct pci_func));
-                                       new_func.bus = busn;
-                                       new_func.device = devn;
-                                       new_func.function = funn;
-                                       new_func.is_a_board = 1;
-                                       configure_existing_function(ctrl, &new_func);
-                                       shpchprm_dump_func_res(&new_func);
-                               } else {
-                                       configure_existing_function(ctrl, func);
-                                       shpchprm_dump_func_res(func);
-                               }
-                               dbg("aCCF:existing PCI 0x%x Func ResourceDump\n", ctrl->bus);
-                       }
-               }
-       }
-
-       return 0;
-}
-
-static int bind_pci_resources(
-       struct controller       *ctrl,
-       struct acpi_bridge      *ab
-       )
-{
-       int     status = 0;
-
-       if (ab->bus_head) {
-               dbg("bapr:  BUS Resources add on PCI 0x%x\n", ab->bus);
-               status = shpchprm_add_resources (&ctrl->bus_head, ab->bus_head);
-               if (shpchprm_delete_resources (&ab->bus_head, ctrl->bus_head))
-                       warn("bapr:  cannot sub BUS Resource on PCI 0x%x\n", ab->bus);
-               if (status) {
-                       err("bapr:  BUS Resource add on PCI 0x%x: fail=0x%x\n", ab->bus, status);
-                       return status;
-               }
-       } else
-               info("bapr:  No BUS Resource on PCI 0x%x.\n", ab->bus);
-
-       if (ab->io_head) {
-               dbg("bapr:  IO Resources add on PCI 0x%x\n", ab->bus);
-               status = shpchprm_add_resources (&ctrl->io_head, ab->io_head);
-               if (shpchprm_delete_resources (&ab->io_head, ctrl->io_head))
-                       warn("bapr:  cannot sub IO Resource on PCI 0x%x\n", ab->bus);
-               if (status) {
-                       err("bapr:  IO Resource add on PCI 0x%x: fail=0x%x\n", ab->bus, status);
-                       return status;
-               }
-       } else
-               info("bapr:  No  IO Resource on PCI 0x%x.\n", ab->bus);
-
-       if (ab->mem_head) {
-               dbg("bapr:  MEM Resources add on PCI 0x%x\n", ab->bus);
-               status = shpchprm_add_resources (&ctrl->mem_head, ab->mem_head);
-               if (shpchprm_delete_resources (&ab->mem_head, ctrl->mem_head))
-                       warn("bapr:  cannot sub MEM Resource on PCI 0x%x\n", ab->bus);
-               if (status) {
-                       err("bapr:  MEM Resource add on PCI 0x%x: fail=0x%x\n", ab->bus, status);
-                       return status;
-               }
-       } else
-               info("bapr:  No MEM Resource on PCI 0x%x.\n", ab->bus);
-
-       if (ab->p_mem_head) {
-               dbg("bapr:  PMEM Resources add on PCI 0x%x\n", ab->bus);
-               status = shpchprm_add_resources (&ctrl->p_mem_head, ab->p_mem_head);
-               if (shpchprm_delete_resources (&ab->p_mem_head, ctrl->p_mem_head))
-                       warn("bapr:  cannot sub PMEM Resource on PCI 0x%x\n", ab->bus);
-               if (status) {
-                       err("bapr:  PMEM Resource add on PCI 0x%x: fail=0x%x\n", ab->bus, status);
-                       return status;
-               }
-       } else
-               info("bapr:  No PMEM Resource on PCI 0x%x.\n", ab->bus);
-
-       return status;
-}
-
-static int no_pci_resources( struct acpi_bridge *ab)
-{
-       return !(ab->p_mem_head || ab->mem_head || ab->io_head || ab->bus_head);
-}
-
-static int find_pci_bridge_resources (
-       struct controller *ctrl,
-       struct acpi_bridge *ab
-       )
-{
-       int     rc = 0;
-       struct pci_func func;
-
-       memset(&func, 0, sizeof(struct pci_func));
-
-       func.bus = ab->pbus;
-       func.device = ab->pdevice;
-       func.function = ab->pfunction;
-       func.is_a_board = 1;
-
-       /* Get used resources for this PCI bridge */
-       rc = shpchp_save_used_resources (ctrl, &func, !DISABLE_CARD);
-
-       ab->io_head = func.io_head;
-       ab->mem_head = func.mem_head;
-       ab->p_mem_head = func.p_mem_head;
-       ab->bus_head = func.bus_head;
-       if (ab->bus_head)
-               shpchprm_delete_resource(&ab->bus_head, ctrl->bus, 1);
-
-       return rc;
-}
-
-static int get_pci_resources_from_bridge(
-       struct controller *ctrl,
-       struct acpi_bridge *ab
-       )
-{
-       int     rc = 0;
-
-       dbg("grfb:  Get Resources for PCI 0x%x from actual PCI bridge 0x%x.\n", ctrl->bus, ab->bus);
-
-       rc = find_pci_bridge_resources (ctrl, ab);
-
-       shpchp_resource_sort_and_combine(&ab->bus_head);
-       shpchp_resource_sort_and_combine(&ab->io_head);
-       shpchp_resource_sort_and_combine(&ab->mem_head);
-       shpchp_resource_sort_and_combine(&ab->p_mem_head);
-
-       shpchprm_add_resources (&ab->tbus_head, ab->bus_head);
-       shpchprm_add_resources (&ab->tio_head, ab->io_head);
-       shpchprm_add_resources (&ab->tmem_head, ab->mem_head);
-       shpchprm_add_resources (&ab->tp_mem_head, ab->p_mem_head);
-
-       return rc;
-}
-
-static int get_pci_resources(
-       struct controller       *ctrl,
-       struct acpi_bridge      *ab
-       )
-{
-       int     rc = 0;
-
-       if (no_pci_resources(ab)) {
-               dbg("spbr:PCI 0x%x has no resources. Get parent resources.\n", ab->bus);
-               rc = get_pci_resources_from_bridge(ctrl, ab);
-       }
-
-       return rc;
 }
 
 int shpchprm_get_physical_slot_number(struct controller *ctrl, u32 *sun, u8 busnum, u8 devnum)
@@ -1570,144 +147,40 @@ int shpchprm_get_physical_slot_number(struct controller *ctrl, u32 *sun, u8 busn
        return 0;
 }
 
-/*
- * Get resources for this ctrl.
- *  1. get total resources from ACPI _CRS or bridge (this ctrl)
- *  2. find used resources of existing adapters
- *     3. subtract used resources from total resources
- */
-int shpchprm_find_available_resources( struct controller *ctrl)
+void get_hp_hw_control_from_firmware(struct pci_dev *dev)
 {
-       int rc = 0;
-       struct acpi_bridge      *ab;
-
-       ab = find_acpi_bridge_by_bus(acpi_bridges_head, ctrl->seg, ctrl->pci_dev->subordinate->number);
-       if (!ab) {
-               err("pfar:cannot locate acpi bridge of PCI 0x%x.\n", ctrl->pci_dev->subordinate->number);
-               return -1;
-       }
-       if (no_pci_resources(ab)) {
-               rc = get_pci_resources(ctrl, ab);
-               if (rc) {
-                       err("pfar:cannot get pci resources of PCI 0x%x.\n",ctrl->pci_dev->subordinate->number);
-                       return -1;
-               }
-       }
-
-       rc = bind_pci_resources(ctrl, ab);
-       dbg("pfar:pre-Bind PCI 0x%x Ctrl Resource Dump\n", ctrl->pci_dev->subordinate->number);
-       shpchprm_dump_ctrl_res(ctrl);
-
-       bind_pci_resources_to_slots (ctrl);
-
-       dbg("pfar:post-Bind PCI 0x%x Ctrl Resource Dump\n", ctrl->pci_dev->subordinate->number);
-       shpchprm_dump_ctrl_res(ctrl);
-
-       return rc;
-}
-
-int shpchprm_set_hpp(
-       struct controller *ctrl,
-       struct pci_func *func,
-       u8      card_type
-       )
-{
-       struct acpi_bridge      *ab;
-       struct pci_bus lpci_bus, *pci_bus;
-       int                             rc = 0;
-       unsigned int    devfn;
-       u8                              cls= 0x08;      /* default cache line size      */
-       u8                              lt = 0x40;      /* default latency timer        */
-       u8                              ep = 0;
-       u8                              es = 0;
-
-       memcpy(&lpci_bus, ctrl->pci_bus, sizeof(lpci_bus));
-       pci_bus = &lpci_bus;
-       pci_bus->number = func->bus;
-       devfn = PCI_DEVFN(func->device, func->function);
-
-       ab = find_acpi_bridge_by_bus(acpi_bridges_head, ctrl->seg, ctrl->slot_bus);
-
-       if (ab) {
-               if (ab->_hpp) {
-                       lt  = (u8)ab->_hpp->latency_timer;
-                       cls = (u8)ab->_hpp->cache_line_size;
-                       ep  = (u8)ab->_hpp->enable_perr;
-                       es  = (u8)ab->_hpp->enable_serr;
-               } else
-                       dbg("_hpp: no _hpp for B/D/F=%#x/%#x/%#x. use default value\n", func->bus, func->device, func->function);
-       } else
-               dbg("_hpp: no acpi bridge for B/D/F = %#x/%#x/%#x. use default value\n", func->bus, func->device, func->function);
-
-
-       if (card_type == PCI_HEADER_TYPE_BRIDGE) {
-               /* set subordinate Latency Timer */
-               rc |= pci_bus_write_config_byte(pci_bus, devfn, PCI_SEC_LATENCY_TIMER, lt);
-       }
-
-       /* set base Latency Timer */
-       rc |= pci_bus_write_config_byte(pci_bus, devfn, PCI_LATENCY_TIMER, lt);
-       dbg("  set latency timer  =0x%02x: %x\n", lt, rc);
-
-       rc |= pci_bus_write_config_byte(pci_bus, devfn, PCI_CACHE_LINE_SIZE, cls);
-       dbg("  set cache_line_size=0x%02x: %x\n", cls, rc);
-
-       return rc;
+       /*
+        * OSHP is an optional ACPI firmware control method. If present,
+        * we need to run it to inform BIOS that we will control SHPC
+        * hardware from now on.
+        */
+       acpi_handle handle = DEVICE_ACPI_HANDLE(&(dev->dev));
+       if (!handle)
+               return;
+       acpi_run_oshp(handle);
 }
 
-void shpchprm_enable_card(
-       struct controller *ctrl,
-       struct pci_func *func,
-       u8 card_type)
+void get_hp_params_from_firmware(struct pci_dev *dev,
+               struct hotplug_params *hpp)
 {
-       u16 command, cmd, bcommand, bcmd;
-       struct pci_bus lpci_bus, *pci_bus;
-       struct acpi_bridge      *ab;
-       unsigned int devfn;
-       int rc;
-
-       memcpy(&lpci_bus, ctrl->pci_bus, sizeof(lpci_bus));
-       pci_bus = &lpci_bus;
-       pci_bus->number = func->bus;
-       devfn = PCI_DEVFN(func->device, func->function);
-
-       rc = pci_bus_read_config_word(pci_bus, devfn, PCI_COMMAND, &command);
-
-       if (card_type == PCI_HEADER_TYPE_BRIDGE) {
-               rc = pci_bus_read_config_word(pci_bus, devfn, PCI_BRIDGE_CONTROL, &bcommand);
-       }
+       acpi_status status = AE_NOT_FOUND;
+       struct pci_dev *pdev = dev;
 
-       cmd = command  = command | PCI_COMMAND_MASTER | PCI_COMMAND_INVALIDATE
-               | PCI_COMMAND_IO | PCI_COMMAND_MEMORY;
-       bcmd = bcommand  = bcommand | PCI_BRIDGE_CTL_NO_ISA;
-
-       ab = find_acpi_bridge_by_bus(acpi_bridges_head, ctrl->seg, ctrl->slot_bus);
-       if (ab) {
-               if (ab->_hpp) {
-                       if (ab->_hpp->enable_perr) {
-                               command |= PCI_COMMAND_PARITY;
-                               bcommand |= PCI_BRIDGE_CTL_PARITY;
-                       } else {
-                               command &= ~PCI_COMMAND_PARITY;
-                               bcommand &= ~PCI_BRIDGE_CTL_PARITY;
-                       }
-                       if (ab->_hpp->enable_serr) {
-                               command |= PCI_COMMAND_SERR;
-                               bcommand |= PCI_BRIDGE_CTL_SERR;
-                       } else {
-                               command &= ~PCI_COMMAND_SERR;
-                               bcommand &= ~PCI_BRIDGE_CTL_SERR;
-                       }
-               } else
-                       dbg("no _hpp for B/D/F = %#x/%#x/%#x.\n", func->bus, func->device, func->function);
-       } else
-               dbg("no acpi bridge for B/D/F = %#x/%#x/%#x.\n", func->bus, func->device, func->function);
-
-       if (command != cmd) {
-               rc = pci_bus_write_config_word(pci_bus, devfn, PCI_COMMAND, command);
-       }
-       if ((card_type == PCI_HEADER_TYPE_BRIDGE) && (bcommand != bcmd)) {
-               rc = pci_bus_write_config_word(pci_bus, devfn, PCI_BRIDGE_CONTROL, bcommand);
+       /*
+        * _HPP settings apply to all child buses, until another _HPP is
+        * encountered. If we don't find an _HPP for the input pci dev,
+        * look for it in the parent device scope since that would apply to
+        * this pci dev. If we don't find any _HPP, use hardcoded defaults
+        */
+       while (pdev && (ACPI_FAILURE(status))) {
+               acpi_handle handle = DEVICE_ACPI_HANDLE(&(pdev->dev));
+               if (!handle)
+                       break;
+               status = acpi_run_hpp(handle, hpp);
+               if (!(pdev->bus->parent))
+                       break;
+               /* Check if a parent object supports _HPP */
+               pdev = pdev->bus->parent->self;
        }
 }
 
index ba6c549..ed6c125 100644 (file)
  *
  */
 
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/types.h>
 #include <linux/pci.h>
-#include <linux/init.h>
-#include <asm/uaccess.h>
-#ifdef CONFIG_IA64
-#include <asm/iosapic.h>
-#endif
 #include "shpchp.h"
-#include "shpchprm.h"
-#include "shpchprm_legacy.h"
-
-static void __iomem *shpchp_rom_start;
-static u16 unused_IRQ;
-
-void shpchprm_cleanup(void)
-{
-       if (shpchp_rom_start)
-               iounmap(shpchp_rom_start);
-}
-
-int shpchprm_print_pirt(void)
-{
-       return 0;
-}
 
 int shpchprm_get_physical_slot_number(struct controller *ctrl, u32 *sun, u8 busnum, u8 devnum)
 {
@@ -63,377 +41,14 @@ int shpchprm_get_physical_slot_number(struct controller *ctrl, u32 *sun, u8 busn
        return 0;
 }
 
-/* Find the Hot Plug Resource Table in the specified region of memory */
-static void __iomem *detect_HRT_floating_pointer(void __iomem *begin, void __iomem *end)
+void get_hp_params_from_firmware(struct pci_dev *dev,
+               struct hotplug_params *hpp)
 {
-       void __iomem *fp;
-       void __iomem *endp;
-       u8 temp1, temp2, temp3, temp4;
-       int status = 0;
-
-       endp = (end - sizeof(struct hrt) + 1);
-
-       for (fp = begin; fp <= endp; fp += 16) {
-               temp1 = readb(fp + SIG0);
-               temp2 = readb(fp + SIG1);
-               temp3 = readb(fp + SIG2);
-               temp4 = readb(fp + SIG3);
-               if (temp1 == '$' && temp2 == 'H' && temp3 == 'R' && temp4 == 'T') {
-                       status = 1;
-                       break;
-               }
-       }
-
-       if (!status)
-               fp = NULL;
-
-       dbg("Discovered Hotplug Resource Table at %p\n", fp);
-       return fp;
+       return;
 }
 
-/*
- * shpchprm_find_available_resources
- *
- *  Finds available memory, IO, and IRQ resources for programming
- *  devices which may be added to the system
- *  this function is for hot plug ADD!
- *
- * returns 0 if success
- */
-int shpchprm_find_available_resources(struct controller *ctrl)
+void get_hp_hw_control_from_firmware(struct pci_dev *dev)
 {
-       u8 populated_slot;
-       u8 bridged_slot;
-       void __iomem *one_slot;
-       struct pci_func *func = NULL;
-       int i = 10, index = 0;
-       u32 temp_dword, rc;
-       ulong temp_ulong;
-       struct pci_resource *mem_node;
-       struct pci_resource *p_mem_node;
-       struct pci_resource *io_node;
-       struct pci_resource *bus_node;
-       void __iomem *rom_resource_table;
-       struct pci_bus lpci_bus, *pci_bus;
-       u8 cfgspc_irq, temp;
-
-       memcpy(&lpci_bus, ctrl->pci_bus, sizeof(lpci_bus));
-       pci_bus = &lpci_bus;
-       rom_resource_table = detect_HRT_floating_pointer(shpchp_rom_start, shpchp_rom_start + 0xffff);
-       dbg("rom_resource_table = %p\n", rom_resource_table);
-       if (rom_resource_table == NULL)
-               return -ENODEV;
-
-       /* Sum all resources and setup resource maps */
-       unused_IRQ = readl(rom_resource_table + UNUSED_IRQ);
-       dbg("unused_IRQ = %x\n", unused_IRQ);
-
-       temp = 0;
-       while (unused_IRQ) {
-               if (unused_IRQ & 1) {
-                       shpchp_disk_irq = temp;
-                       break;
-               }
-               unused_IRQ = unused_IRQ >> 1;
-               temp++;
-       }
-
-       dbg("shpchp_disk_irq= %d\n", shpchp_disk_irq);
-       unused_IRQ = unused_IRQ >> 1;
-       temp++;
-
-       while (unused_IRQ) {
-               if (unused_IRQ & 1) {
-                       shpchp_nic_irq = temp;
-                       break;
-               }
-               unused_IRQ = unused_IRQ >> 1;
-               temp++;
-       }
-
-       dbg("shpchp_nic_irq= %d\n", shpchp_nic_irq);
-       unused_IRQ = readl(rom_resource_table + PCIIRQ);
-
-       temp = 0;
-
-       pci_read_config_byte(ctrl->pci_dev, PCI_INTERRUPT_LINE, &cfgspc_irq);
-
-       if (!shpchp_nic_irq) {
-               shpchp_nic_irq = cfgspc_irq;
-       }
-
-       if (!shpchp_disk_irq) {
-               shpchp_disk_irq = cfgspc_irq;
-       }
-
-       dbg("shpchp_disk_irq, shpchp_nic_irq= %d, %d\n", shpchp_disk_irq, shpchp_nic_irq);
-
-       one_slot = rom_resource_table + sizeof(struct hrt);
-
-       i = readb(rom_resource_table + NUMBER_OF_ENTRIES);
-       dbg("number_of_entries = %d\n", i);
-
-       if (!readb(one_slot + SECONDARY_BUS))
-               return (1);
-
-       dbg("dev|IO base|length|MEMbase|length|PM base|length|PB SB MB\n");
-
-       while (i && readb(one_slot + SECONDARY_BUS)) {
-               u8 dev_func = readb(one_slot + DEV_FUNC);
-               u8 primary_bus = readb(one_slot + PRIMARY_BUS);
-               u8 secondary_bus = readb(one_slot + SECONDARY_BUS);
-               u8 max_bus = readb(one_slot + MAX_BUS);
-               u16 io_base = readw(one_slot + IO_BASE);
-               u16 io_length = readw(one_slot + IO_LENGTH);
-               u16 mem_base = readw(one_slot + MEM_BASE);
-               u16 mem_length = readw(one_slot + MEM_LENGTH);
-               u16 pre_mem_base = readw(one_slot + PRE_MEM_BASE);
-               u16 pre_mem_length = readw(one_slot + PRE_MEM_LENGTH);
-
-               dbg("%2.2x |  %4.4x | %4.4x |  %4.4x | %4.4x |  %4.4x | %4.4x |%2.2x %2.2x %2.2x\n",
-                               dev_func, io_base, io_length, mem_base, mem_length, pre_mem_base, pre_mem_length,
-                               primary_bus, secondary_bus, max_bus);
-
-               /* If this entry isn't for our controller's bus, ignore it */
-               if (primary_bus != ctrl->slot_bus) {
-                       i--;
-                       one_slot += sizeof(struct slot_rt);
-                       continue;
-               }
-               /* find out if this entry is for an occupied slot */
-               temp_dword = 0xFFFFFFFF;
-               pci_bus->number = primary_bus;
-               pci_bus_read_config_dword(pci_bus, dev_func, PCI_VENDOR_ID, &temp_dword);
-
-               dbg("temp_D_word = %x\n", temp_dword);
-
-               if (temp_dword != 0xFFFFFFFF) {
-                       index = 0;
-                       func = shpchp_slot_find(primary_bus, dev_func >> 3, 0);
-
-                       while (func && (func->function != (dev_func & 0x07))) {
-                               dbg("func = %p b:d:f(%x:%x:%x)\n", func, primary_bus, dev_func >> 3, index);
-                               func = shpchp_slot_find(primary_bus, dev_func >> 3, index++);
-                       }
-
-                       /* If we can't find a match, skip this table entry */
-                       if (!func) {
-                               i--;
-                               one_slot += sizeof(struct slot_rt);
-                               continue;
-                       }
-                       /* this may not work and shouldn't be used */
-                       if (secondary_bus != primary_bus)
-                               bridged_slot = 1;
-                       else
-                               bridged_slot = 0;
-
-                       populated_slot = 1;
-               } else {
-                       populated_slot = 0;
-                       bridged_slot = 0;
-               }
-               dbg("slot populated =%s \n", populated_slot?"yes":"no");
-
-               /* If we've got a valid IO base, use it */
-
-               temp_ulong = io_base + io_length;
-
-               if ((io_base) && (temp_ulong <= 0x10000)) {
-                       io_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
-                       if (!io_node)
-                               return -ENOMEM;
-
-                       io_node->base = (ulong)io_base;
-                       io_node->length = (ulong)io_length;
-                       dbg("found io_node(base, length) = %x, %x\n", io_node->base, io_node->length);
-
-                       if (!populated_slot) {
-                               io_node->next = ctrl->io_head;
-                               ctrl->io_head = io_node;
-                       } else {
-                               io_node->next = func->io_head;
-                               func->io_head = io_node;
-                       }
-               }
-
-               /* If we've got a valid memory base, use it */
-               temp_ulong = mem_base + mem_length;
-               if ((mem_base) && (temp_ulong <= 0x10000)) {
-                       mem_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
-                       if (!mem_node)
-                               return -ENOMEM;
-
-                       mem_node->base = (ulong)mem_base << 16;
-                       mem_node->length = (ulong)(mem_length << 16);
-                       dbg("found mem_node(base, length) = %x, %x\n", mem_node->base, mem_node->length);
-
-                       if (!populated_slot) {
-                               mem_node->next = ctrl->mem_head;
-                               ctrl->mem_head = mem_node;
-                       } else {
-                               mem_node->next = func->mem_head;
-                               func->mem_head = mem_node;
-                       }
-               }
-
-               /*
-                * If we've got a valid prefetchable memory base, and
-                * the base + length isn't greater than 0xFFFF
-                */
-               temp_ulong = pre_mem_base + pre_mem_length;
-               if ((pre_mem_base) && (temp_ulong <= 0x10000)) {
-                       p_mem_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
-                       if (!p_mem_node)
-                               return -ENOMEM;
-
-                       p_mem_node->base = (ulong)pre_mem_base << 16;
-                       p_mem_node->length = (ulong)pre_mem_length << 16;
-                       dbg("found p_mem_node(base, length) = %x, %x\n", p_mem_node->base, p_mem_node->length);
-
-                       if (!populated_slot) {
-                               p_mem_node->next = ctrl->p_mem_head;
-                               ctrl->p_mem_head = p_mem_node;
-                       } else {
-                               p_mem_node->next = func->p_mem_head;
-                               func->p_mem_head = p_mem_node;
-                       }
-               }
-
-               /*
-                * If we've got a valid bus number, use it
-                * The second condition is to ignore bus numbers on
-                * populated slots that don't have PCI-PCI bridges
-                */
-               if (secondary_bus && (secondary_bus != primary_bus)) {
-                       bus_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
-                       if (!bus_node)
-                               return -ENOMEM;
-
-                       bus_node->base = (ulong)secondary_bus;
-                       bus_node->length = (ulong)(max_bus - secondary_bus + 1);
-                       dbg("found bus_node(base, length) = %x, %x\n", bus_node->base, bus_node->length);
-
-                       if (!populated_slot) {
-                               bus_node->next = ctrl->bus_head;
-                               ctrl->bus_head = bus_node;
-                       } else {
-                               bus_node->next = func->bus_head;
-                               func->bus_head = bus_node;
-                       }
-               }
-
-               i--;
-               one_slot += sizeof(struct slot_rt);
-       }
-
-       /* If all of the following fail, we don't have any resources for hot plug add */
-       rc = 1;
-       rc &= shpchp_resource_sort_and_combine(&(ctrl->mem_head));
-       rc &= shpchp_resource_sort_and_combine(&(ctrl->p_mem_head));
-       rc &= shpchp_resource_sort_and_combine(&(ctrl->io_head));
-       rc &= shpchp_resource_sort_and_combine(&(ctrl->bus_head));
-
-       return (rc);
+       return;
 }
 
-int shpchprm_set_hpp(
-       struct controller *ctrl,
-       struct pci_func *func,
-       u8      card_type)
-{
-       u32 rc;
-       u8 temp_byte;
-       struct pci_bus lpci_bus, *pci_bus;
-       unsigned int    devfn;
-       memcpy(&lpci_bus, ctrl->pci_bus, sizeof(lpci_bus));
-       pci_bus = &lpci_bus;
-       pci_bus->number = func->bus;
-       devfn = PCI_DEVFN(func->device, func->function);
-
-       temp_byte = 0x40;       /* hard coded value for LT */
-       if (card_type == PCI_HEADER_TYPE_BRIDGE) {
-               /* set subordinate Latency Timer */
-               rc = pci_bus_write_config_byte(pci_bus, devfn, PCI_SEC_LATENCY_TIMER, temp_byte);
-               if (rc) {
-                       dbg("%s: set secondary LT error. b:d:f(%02x:%02x:%02x)\n", __FUNCTION__, func->bus, 
-                               func->device, func->function);
-                       return rc;
-               }
-       }
-
-       /* set base Latency Timer */
-       rc = pci_bus_write_config_byte(pci_bus, devfn, PCI_LATENCY_TIMER, temp_byte);
-       if (rc) {
-               dbg("%s: set LT error. b:d:f(%02x:%02x:%02x)\n", __FUNCTION__, func->bus, func->device, func->function);
-               return rc;
-       }
-
-       /* set Cache Line size */
-       temp_byte = 0x08;       /* hard coded value for CLS */
-       rc = pci_bus_write_config_byte(pci_bus, devfn, PCI_CACHE_LINE_SIZE, temp_byte);
-       if (rc) {
-               dbg("%s: set CLS error. b:d:f(%02x:%02x:%02x)\n", __FUNCTION__, func->bus, func->device, func->function);
-       }
-
-       /* set enable_perr */
-       /* set enable_serr */
-
-       return rc;
-}
-
-void shpchprm_enable_card(
-       struct controller *ctrl,
-       struct pci_func *func,
-       u8 card_type)
-{
-       u16 command, bcommand;
-       struct pci_bus lpci_bus, *pci_bus;
-       unsigned int devfn;
-       int rc;
-
-       memcpy(&lpci_bus, ctrl->pci_bus, sizeof(lpci_bus));
-       pci_bus = &lpci_bus;
-       pci_bus->number = func->bus;
-       devfn = PCI_DEVFN(func->device, func->function);
-
-       rc = pci_bus_read_config_word(pci_bus, devfn, PCI_COMMAND, &command);
-       command |= PCI_COMMAND_PARITY | PCI_COMMAND_SERR
-               | PCI_COMMAND_MASTER | PCI_COMMAND_INVALIDATE
-               | PCI_COMMAND_IO | PCI_COMMAND_MEMORY;
-       rc = pci_bus_write_config_word(pci_bus, devfn, PCI_COMMAND, command);
-
-       if (card_type == PCI_HEADER_TYPE_BRIDGE) {
-               rc = pci_bus_read_config_word(pci_bus, devfn, PCI_BRIDGE_CONTROL, &bcommand);
-               bcommand |= PCI_BRIDGE_CTL_PARITY | PCI_BRIDGE_CTL_SERR
-                       | PCI_BRIDGE_CTL_NO_ISA;
-               rc = pci_bus_write_config_word(pci_bus, devfn, PCI_BRIDGE_CONTROL, bcommand);
-       }
-}
-
-static int legacy_shpchprm_init_pci(void)
-{
-       shpchp_rom_start = ioremap(ROM_PHY_ADDR, ROM_PHY_LEN);
-       if (!shpchp_rom_start) {
-               err("Could not ioremap memory region for ROM\n");
-               return -EIO;
-       }
-
-       return 0;
-}
-
-int shpchprm_init(enum php_ctlr_type ctrl_type)
-{
-       int retval;
-
-       switch (ctrl_type) {
-       case PCI:
-               retval = legacy_shpchprm_init_pci();
-               break;
-       default:
-               retval = -ENODEV;
-               break;
-       }
-
-       return retval;
-}
diff --git a/drivers/pci/hotplug/shpchprm_legacy.h b/drivers/pci/hotplug/shpchprm_legacy.h
deleted file mode 100644 (file)
index 21bda74..0000000
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- * SHPCHPRM Legacy: PHP Resource Manager for Non-ACPI/Legacy platform using HRT
- *
- * Copyright (C) 1995,2001 Compaq Computer Corporation
- * Copyright (C) 2001 Greg Kroah-Hartman (greg@kroah.com)
- * Copyright (C) 2001 IBM Corp.
- * Copyright (C) 2003-2004 Intel Corporation
- *
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or (at
- * your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
- * NON INFRINGEMENT.  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.
- *
- * Send feedback to <greg@kroah.com>, <kristen.c.accardi@intel.com>
- *
- */
-
-#ifndef _SHPCHPRM_LEGACY_H_
-#define _SHPCHPRM_LEGACY_H_
-
-#define ROM_PHY_ADDR   0x0F0000
-#define ROM_PHY_LEN    0x00FFFF
-
-struct slot_rt {
-       u8 dev_func;
-       u8 primary_bus;
-       u8 secondary_bus;
-       u8 max_bus;
-       u16 io_base;
-       u16 io_length;
-       u16 mem_base;
-       u16 mem_length;
-       u16 pre_mem_base;
-       u16 pre_mem_length;
-} __attribute__ ((packed));
-
-/* offsets to the hotplug slot resource table registers based on the above structure layout */
-enum slot_rt_offsets {
-       DEV_FUNC = offsetof(struct slot_rt, dev_func),
-       PRIMARY_BUS = offsetof(struct slot_rt, primary_bus),
-       SECONDARY_BUS = offsetof(struct slot_rt, secondary_bus),
-       MAX_BUS = offsetof(struct slot_rt, max_bus),
-       IO_BASE = offsetof(struct slot_rt, io_base),
-       IO_LENGTH = offsetof(struct slot_rt, io_length),
-       MEM_BASE = offsetof(struct slot_rt, mem_base),
-       MEM_LENGTH = offsetof(struct slot_rt, mem_length),
-       PRE_MEM_BASE = offsetof(struct slot_rt, pre_mem_base),
-       PRE_MEM_LENGTH = offsetof(struct slot_rt, pre_mem_length),
-};
-
-struct hrt {
-       char sig0;
-       char sig1;
-       char sig2;
-       char sig3;
-       u16 unused_IRQ;
-       u16 PCIIRQ;
-       u8 number_of_entries;
-       u8 revision;
-       u16 reserved1;
-       u32 reserved2;
-} __attribute__ ((packed));
-
-/* offsets to the hotplug resource table registers based on the above structure layout */
-enum hrt_offsets {
-       SIG0 = offsetof(struct hrt, sig0),
-       SIG1 = offsetof(struct hrt, sig1),
-       SIG2 = offsetof(struct hrt, sig2),
-       SIG3 = offsetof(struct hrt, sig3),
-       UNUSED_IRQ = offsetof(struct hrt, unused_IRQ),
-       PCIIRQ = offsetof(struct hrt, PCIIRQ),
-       NUMBER_OF_ENTRIES = offsetof(struct hrt, number_of_entries),
-       REVISION = offsetof(struct hrt, revision),
-       HRT_RESERVED1 = offsetof(struct hrt, reserved1),
-       HRT_RESERVED2 = offsetof(struct hrt, reserved2),
-};
-
-struct irq_info {
-       u8 bus, devfn;          /* bus, device and function */
-       struct {
-               u8 link;        /* IRQ line ID, chipset dependent, 0=not routed */
-               u16 bitmap;     /* Available IRQs */
-       } __attribute__ ((packed)) irq[4];
-       u8 slot;                /* slot number, 0=onboard */
-       u8 rfu;
-} __attribute__ ((packed));
-
-struct irq_routing_table {
-       u32 signature;          /* PIRQ_SIGNATURE should be here */
-       u16 version;            /* PIRQ_VERSION */
-       u16 size;                       /* Table size in bytes */
-       u8 rtr_bus, rtr_devfn;  /* Where the interrupt router lies */
-       u16 exclusive_irqs;     /* IRQs devoted exclusively to PCI usage */
-       u16 rtr_vendor, rtr_device;     /* Vendor and device ID of interrupt router */
-       u32 miniport_data;      /* Crap */
-       u8 rfu[11];
-       u8 checksum;            /* Modulo 256 checksum must give zero */
-       struct irq_info slots[0];
-} __attribute__ ((packed));
-
-#endif                         /* _SHPCHPRM_LEGACY_H_ */
index 5f75ef7..d70fe54 100644 (file)
 #include <linux/kernel.h>
 #include <linux/types.h>
 #include <linux/pci.h>
-#include <linux/init.h>
-#include <asm/uaccess.h>
-#ifdef CONFIG_IA64
-#include <asm/iosapic.h>
-#endif
 #include "shpchp.h"
-#include "shpchprm.h"
-#include "shpchprm_nonacpi.h"
-
-void shpchprm_cleanup(void)
-{
-       return;
-}
-
-int shpchprm_print_pirt(void)
-{
-       return 0;
-}
 
 int shpchprm_get_physical_slot_number(struct controller *ctrl, u32 *sun, u8 busnum, u8 devnum)
 {
@@ -60,375 +43,13 @@ int shpchprm_get_physical_slot_number(struct controller *ctrl, u32 *sun, u8 busn
        return 0;
 }
 
-static void print_pci_resource ( struct pci_resource   *aprh)
-{
-       struct pci_resource     *res;
-
-       for (res = aprh; res; res = res->next)
-               dbg("        base= 0x%x length= 0x%x\n", res->base, res->length);
-}
-
-
-static void phprm_dump_func_res( struct pci_func *fun)
-{
-       struct pci_func *func = fun;
-
-       if (func->bus_head) {
-               dbg(":    BUS Resources:\n");
-               print_pci_resource (func->bus_head);
-       }
-       if (func->io_head) {
-               dbg(":    IO Resources:\n");
-               print_pci_resource (func->io_head);
-       }
-       if (func->mem_head) {
-               dbg(":    MEM Resources:\n");
-               print_pci_resource (func->mem_head);
-       }
-       if (func->p_mem_head) {
-               dbg(":    PMEM Resources:\n");
-               print_pci_resource (func->p_mem_head);
-       }
-}
-
-static int phprm_get_used_resources (
-       struct controller *ctrl,
-       struct pci_func *func
-       )
-{
-       return shpchp_save_used_resources (ctrl, func, !DISABLE_CARD);
-}
-
-static int phprm_delete_resource(
-       struct pci_resource **aprh,
-       ulong base,
-       ulong size)
-{
-       struct pci_resource *res;
-       struct pci_resource *prevnode;
-       struct pci_resource *split_node;
-       ulong tbase;
-
-       shpchp_resource_sort_and_combine(aprh);
-
-       for (res = *aprh; res; res = res->next) {
-               if (res->base > base)
-                       continue;
-
-               if ((res->base + res->length) < (base + size))
-                       continue;
-
-               if (res->base < base) {
-                       tbase = base;
-
-                       if ((res->length - (tbase - res->base)) < size)
-                               continue;
-
-                       split_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
-                       if (!split_node)
-                               return -ENOMEM;
-
-                       split_node->base = res->base;
-                       split_node->length = tbase - res->base;
-                       res->base = tbase;
-                       res->length -= split_node->length;
-
-                       split_node->next = res->next;
-                       res->next = split_node;
-               }
-
-               if (res->length >= size) {
-                       split_node = (struct pci_resource*) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
-                       if (!split_node)
-                               return -ENOMEM;
-
-                       split_node->base = res->base + size;
-                       split_node->length = res->length - size;
-                       res->length = size;
-
-                       split_node->next = res->next;
-                       res->next = split_node;
-               }
-
-               if (*aprh == res) {
-                       *aprh = res->next;
-               } else {
-                       prevnode = *aprh;
-                       while (prevnode->next != res)
-                               prevnode = prevnode->next;
-
-                       prevnode->next = res->next;
-               }
-               res->next = NULL;
-               kfree(res);
-               break;
-       }
-
-       return 0;
-}
-
-
-static int phprm_delete_resources(
-       struct pci_resource **aprh,
-       struct pci_resource *this
-       )
-{
-       struct pci_resource *res;
-
-       for (res = this; res; res = res->next)
-               phprm_delete_resource(aprh, res->base, res->length);
-
-       return 0;
-}
-
-
-static int configure_existing_function(
-       struct controller *ctrl,
-       struct pci_func *func
-       )
-{
-       int rc;
-
-       /* see how much resources the func has used. */
-       rc = phprm_get_used_resources (ctrl, func);
-
-       if (!rc) {
-               /* subtract the resources used by the func from ctrl resources */
-               rc  = phprm_delete_resources (&ctrl->bus_head, func->bus_head);
-               rc |= phprm_delete_resources (&ctrl->io_head, func->io_head);
-               rc |= phprm_delete_resources (&ctrl->mem_head, func->mem_head);
-               rc |= phprm_delete_resources (&ctrl->p_mem_head, func->p_mem_head);
-               if (rc)
-                       warn("aCEF: cannot del used resources\n");
-       } else
-               err("aCEF: cannot get used resources\n");
-
-       return rc;
-}
-
-static int bind_pci_resources_to_slots ( struct controller *ctrl)
+void get_hp_params_from_firmware(struct pci_dev *dev,
+               struct hotplug_params *hpp)
 {
-       struct pci_func *func, new_func;
-       int busn = ctrl->slot_bus;
-       int devn, funn;
-       u32     vid;
-
-       for (devn = 0; devn < 32; devn++) {
-               for (funn = 0; funn < 8; funn++) {
-                       /*
-                       if (devn == ctrl->device && funn == ctrl->function)
-                               continue;
-                        */
-                       /* find out if this entry is for an occupied slot */
-                       vid = 0xFFFFFFFF;
-
-                       pci_bus_read_config_dword(ctrl->pci_dev->subordinate, PCI_DEVFN(devn, funn), PCI_VENDOR_ID, &vid);
-
-                       if (vid != 0xFFFFFFFF) {
-                               func = shpchp_slot_find(busn, devn, funn);
-                               if (!func) {
-                                       memset(&new_func, 0, sizeof(struct pci_func));
-                                       new_func.bus = busn;
-                                       new_func.device = devn;
-                                       new_func.function = funn;
-                                       new_func.is_a_board = 1;
-                                       configure_existing_function(ctrl, &new_func);
-                                       phprm_dump_func_res(&new_func);
-                               } else {
-                                       configure_existing_function(ctrl, func);
-                                       phprm_dump_func_res(func);
-                               }
-                               dbg("aCCF:existing PCI 0x%x Func ResourceDump\n", ctrl->bus);
-                       }
-               }
-       }
-
-       return 0;
-}
-
-static void phprm_dump_ctrl_res( struct controller *ctlr)
-{
-       struct controller *ctrl = ctlr;
-
-       if (ctrl->bus_head) {
-               dbg(":    BUS Resources:\n");
-               print_pci_resource (ctrl->bus_head);
-       }
-       if (ctrl->io_head) {
-               dbg(":    IO Resources:\n");
-               print_pci_resource (ctrl->io_head);
-       }
-       if (ctrl->mem_head) {
-               dbg(":    MEM Resources:\n");
-               print_pci_resource (ctrl->mem_head);
-       }
-       if (ctrl->p_mem_head) {
-               dbg(":    PMEM Resources:\n");
-               print_pci_resource (ctrl->p_mem_head);
-       }
-}
-
-/*
- * phprm_find_available_resources
- *
- *  Finds available memory, IO, and IRQ resources for programming
- *  devices which may be added to the system
- *  this function is for hot plug ADD!
- *
- * returns 0 if success
- */
-int shpchprm_find_available_resources(struct controller *ctrl)
-{
-       struct pci_func func;
-       u32 rc;
-
-       memset(&func, 0, sizeof(struct pci_func));
-
-       func.bus = ctrl->bus;
-       func.device = ctrl->device;
-       func.function = ctrl->function;
-       func.is_a_board = 1;
-
-       /* Get resources for this PCI bridge */
-       rc = shpchp_save_used_resources (ctrl, &func, !DISABLE_CARD);
-       dbg("%s: shpchp_save_used_resources rc = %d\n", __FUNCTION__, rc);
-
-       if (func.mem_head)
-               func.mem_head->next = ctrl->mem_head;
-       ctrl->mem_head = func.mem_head;
-
-       if (func.p_mem_head)
-               func.p_mem_head->next = ctrl->p_mem_head;
-       ctrl->p_mem_head = func.p_mem_head;
-
-       if (func.io_head)
-               func.io_head->next = ctrl->io_head;
-       ctrl->io_head = func.io_head;
-
-       if(func.bus_head)
-               func.bus_head->next = ctrl->bus_head;
-       ctrl->bus_head = func.bus_head;
-       if (ctrl->bus_head)
-               phprm_delete_resource(&ctrl->bus_head, ctrl->pci_dev->subordinate->number, 1);
-
-       dbg("%s:pre-Bind PCI 0x%x Ctrl Resource Dump\n", __FUNCTION__, ctrl->bus);
-       phprm_dump_ctrl_res(ctrl);
-       bind_pci_resources_to_slots (ctrl);
-
-       dbg("%s:post-Bind PCI 0x%x Ctrl Resource Dump\n", __FUNCTION__, ctrl->bus);
-       phprm_dump_ctrl_res(ctrl);
-
-
-       /* If all of the following fail, we don't have any resources for hot plug add */
-       rc = 1;
-       rc &= shpchp_resource_sort_and_combine(&(ctrl->mem_head));
-       rc &= shpchp_resource_sort_and_combine(&(ctrl->p_mem_head));
-       rc &= shpchp_resource_sort_and_combine(&(ctrl->io_head));
-       rc &= shpchp_resource_sort_and_combine(&(ctrl->bus_head));
-
-       return (rc);
-}
-
-int shpchprm_set_hpp(
-       struct controller *ctrl,
-       struct pci_func *func,
-       u8      card_type)
-{
-       u32 rc;
-       u8 temp_byte;
-       struct pci_bus lpci_bus, *pci_bus;
-       unsigned int    devfn;
-       memcpy(&lpci_bus, ctrl->pci_bus, sizeof(lpci_bus));
-       pci_bus = &lpci_bus;
-       pci_bus->number = func->bus;
-       devfn = PCI_DEVFN(func->device, func->function);
-
-       temp_byte = 0x40;       /* hard coded value for LT */
-       if (card_type == PCI_HEADER_TYPE_BRIDGE) {
-               /* set subordinate Latency Timer */
-               rc = pci_bus_write_config_byte(pci_bus, devfn, PCI_SEC_LATENCY_TIMER, temp_byte);
-
-               if (rc) {
-                       dbg("%s: set secondary LT error. b:d:f(%02x:%02x:%02x)\n", __FUNCTION__, func->bus, 
-                               func->device, func->function);
-                       return rc;
-               }
-       }
-
-       /* set base Latency Timer */
-       rc = pci_bus_write_config_byte(pci_bus, devfn, PCI_LATENCY_TIMER, temp_byte);
-
-       if (rc) {
-               dbg("%s: set LT error. b:d:f(%02x:%02x:%02x)\n", __FUNCTION__, func->bus, func->device, func->function);
-               return rc;
-       }
-
-       /* set Cache Line size */
-       temp_byte = 0x08;       /* hard coded value for CLS */
-
-       rc = pci_bus_write_config_byte(pci_bus, devfn, PCI_CACHE_LINE_SIZE, temp_byte);
-
-       if (rc) {
-               dbg("%s: set CLS error. b:d:f(%02x:%02x:%02x)\n", __FUNCTION__, func->bus, func->device, func->function);
-       }
-
-       /* set enable_perr */
-       /* set enable_serr */
-
-       return rc;
-}
-
-void shpchprm_enable_card(
-       struct controller *ctrl,
-       struct pci_func *func,
-       u8 card_type)
-{
-       u16 command, bcommand;
-       struct pci_bus lpci_bus, *pci_bus;
-       unsigned int devfn;
-       int rc;
-
-       memcpy(&lpci_bus, ctrl->pci_bus, sizeof(lpci_bus));
-       pci_bus = &lpci_bus;
-       pci_bus->number = func->bus;
-       devfn = PCI_DEVFN(func->device, func->function);
-
-       rc = pci_bus_read_config_word(pci_bus, devfn, PCI_COMMAND, &command);
-
-       command |= PCI_COMMAND_PARITY | PCI_COMMAND_SERR
-               | PCI_COMMAND_MASTER | PCI_COMMAND_INVALIDATE
-               | PCI_COMMAND_IO | PCI_COMMAND_MEMORY;
-
-       rc = pci_bus_write_config_word(pci_bus, devfn, PCI_COMMAND, command);
-
-       if (card_type == PCI_HEADER_TYPE_BRIDGE) {
-
-               rc = pci_bus_read_config_word(pci_bus, devfn, PCI_BRIDGE_CONTROL, &bcommand);
-
-               bcommand |= PCI_BRIDGE_CTL_PARITY | PCI_BRIDGE_CTL_SERR
-                       | PCI_BRIDGE_CTL_NO_ISA;
-
-               rc = pci_bus_write_config_word(pci_bus, devfn, PCI_BRIDGE_CONTROL, bcommand);
-       }
-}
-
-static int legacy_shpchprm_init_pci(void)
-{
-       return 0;
+       return;
 }
 
-int shpchprm_init(enum php_ctlr_type ctrl_type)
+void get_hp_hw_control_from_firmware(struct pci_dev *dev)
 {
-       int retval;
-
-       switch (ctrl_type) {
-       case PCI:
-               retval = legacy_shpchprm_init_pci();
-               break;
-       default:
-               retval = -ENODEV;
-               break;
-       }
-
-       return retval;
+       return;
 }
diff --git a/drivers/pci/hotplug/shpchprm_nonacpi.h b/drivers/pci/hotplug/shpchprm_nonacpi.h
deleted file mode 100644 (file)
index cddaaa5..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * SHPCHPRM NONACPI: PHP Resource Manager for Non-ACPI/Legacy platform
- *
- * Copyright (C) 1995,2001 Compaq Computer Corporation
- * Copyright (C) 2001 Greg Kroah-Hartman (greg@kroah.com)
- * Copyright (C) 2001 IBM Corp.
- * Copyright (C) 2003-2004 Intel Corporation
- *
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or (at
- * your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
- * NON INFRINGEMENT.  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.
- *
- * Send feedback to <greg@kroah.com>, <kristen.c.accardi@intel.com>
- *
- */
-
-#ifndef _SHPCHPRM_NONACPI_H_
-#define _SHPCHPRM_NONACPI_H_
-
-struct irq_info {
-       u8 bus, devfn;          /* bus, device and function */
-       struct {
-               u8 link;        /* IRQ line ID, chipset dependent, 0=not routed */
-               u16 bitmap;     /* Available IRQs */
-       } __attribute__ ((packed)) irq[4];
-       u8 slot;                /* slot number, 0=onboard */
-       u8 rfu;
-} __attribute__ ((packed));
-
-struct irq_routing_table {
-       u32 signature;          /* PIRQ_SIGNATURE should be here */
-       u16 version;            /* PIRQ_VERSION */
-       u16 size;                       /* Table size in bytes */
-       u8 rtr_bus, rtr_devfn;  /* Where the interrupt router lies */
-       u16 exclusive_irqs;     /* IRQs devoted exclusively to PCI usage */
-       u16 rtr_vendor, rtr_device;     /* Vendor and device ID of interrupt router */
-       u32 miniport_data;      /* Crap */
-       u8 rfu[11];
-       u8 checksum;            /* Modulo 256 checksum must give zero */
-       struct irq_info slots[0];
-} __attribute__ ((packed));
-
-#endif                         /* _SHPCHPRM_NONACPI_H_ */
index ee8677b..a203355 100644 (file)
@@ -575,6 +575,8 @@ static int msi_capability_init(struct pci_dev *dev)
 /**
  * msix_capability_init - configure device's MSI-X capability
  * @dev: pointer to the pci_dev data structure of MSI-X device function
+ * @entries: pointer to an array of struct msix_entry entries
+ * @nvec: number of @entries
  *
  * Setup the MSI-X capability structure of device function with a
  * single MSI-X vector. A return of zero indicates the successful setup of
index 0d0d533..8972e6a 100644 (file)
@@ -26,7 +26,10 @@ struct pci_dynid {
 #ifdef CONFIG_HOTPLUG
 
 /**
- * store_new_id
+ * store_new_id - add a new PCI device ID to this driver and re-probe devices
+ * @driver: target device driver
+ * @buf: buffer for scanning device ID data
+ * @count: input size
  *
  * Adds a new dynamic pci device ID to this driver,
  * and causes the driver to probe for all devices again.
@@ -194,8 +197,10 @@ static int pci_call_probe(struct pci_driver *drv, struct pci_dev *dev,
 
 /**
  * __pci_device_probe()
+ * @drv: driver to call to check if it wants the PCI device
+ * @pci_dev: PCI device being probed
  * 
- * returns 0  on success, else error.
+ * returns 0 on success, else error.
  * side-effect: pci_dev->driver is set to drv when drv claims pci_dev.
  */
 static int
@@ -377,6 +382,10 @@ int pci_register_driver(struct pci_driver *drv)
         * the pci shutdown function, this test can go away. */
        if (!drv->driver.shutdown)
                drv->driver.shutdown = pci_device_shutdown;
+       else
+               printk(KERN_WARNING "Warning: PCI driver %s has a struct "
+                       "device_driver shutdown method, please update!\n",
+                       drv->name);
        drv->driver.owner = drv->owner;
        drv->driver.kobj.ktype = &pci_driver_kobj_type;
 
@@ -436,11 +445,11 @@ pci_dev_driver(const struct pci_dev *dev)
 
 /**
  * pci_bus_match - Tell if a PCI device structure has a matching PCI device id structure
- * @ids: array of PCI device id structures to search in
  * @dev: the PCI device structure to match against
+ * @drv: the device driver to search for matching PCI device id structures
  * 
  * Used by a driver to check whether a PCI device present in the
- * system is in its list of supported devices.Returns the matching
+ * system is in its list of supported devices. Returns the matching
  * pci_device_id structure or %NULL if there is no match.
  */
 static int pci_bus_match(struct device *dev, struct device_driver *drv)
index 2898830..965a593 100644 (file)
@@ -130,7 +130,7 @@ pci_read_config(struct kobject *kobj, char *buf, loff_t off, size_t count)
 
        if ((off & 1) && size) {
                u8 val;
-               pci_read_config_byte(dev, off, &val);
+               pci_user_read_config_byte(dev, off, &val);
                data[off - init_off] = val;
                off++;
                size--;
@@ -138,7 +138,7 @@ pci_read_config(struct kobject *kobj, char *buf, loff_t off, size_t count)
 
        if ((off & 3) && size > 2) {
                u16 val;
-               pci_read_config_word(dev, off, &val);
+               pci_user_read_config_word(dev, off, &val);
                data[off - init_off] = val & 0xff;
                data[off - init_off + 1] = (val >> 8) & 0xff;
                off += 2;
@@ -147,7 +147,7 @@ pci_read_config(struct kobject *kobj, char *buf, loff_t off, size_t count)
 
        while (size > 3) {
                u32 val;
-               pci_read_config_dword(dev, off, &val);
+               pci_user_read_config_dword(dev, off, &val);
                data[off - init_off] = val & 0xff;
                data[off - init_off + 1] = (val >> 8) & 0xff;
                data[off - init_off + 2] = (val >> 16) & 0xff;
@@ -158,7 +158,7 @@ pci_read_config(struct kobject *kobj, char *buf, loff_t off, size_t count)
 
        if (size >= 2) {
                u16 val;
-               pci_read_config_word(dev, off, &val);
+               pci_user_read_config_word(dev, off, &val);
                data[off - init_off] = val & 0xff;
                data[off - init_off + 1] = (val >> 8) & 0xff;
                off += 2;
@@ -167,7 +167,7 @@ pci_read_config(struct kobject *kobj, char *buf, loff_t off, size_t count)
 
        if (size > 0) {
                u8 val;
-               pci_read_config_byte(dev, off, &val);
+               pci_user_read_config_byte(dev, off, &val);
                data[off - init_off] = val;
                off++;
                --size;
@@ -192,7 +192,7 @@ pci_write_config(struct kobject *kobj, char *buf, loff_t off, size_t count)
        }
        
        if ((off & 1) && size) {
-               pci_write_config_byte(dev, off, data[off - init_off]);
+               pci_user_write_config_byte(dev, off, data[off - init_off]);
                off++;
                size--;
        }
@@ -200,7 +200,7 @@ pci_write_config(struct kobject *kobj, char *buf, loff_t off, size_t count)
        if ((off & 3) && size > 2) {
                u16 val = data[off - init_off];
                val |= (u16) data[off - init_off + 1] << 8;
-                pci_write_config_word(dev, off, val);
+                pci_user_write_config_word(dev, off, val);
                 off += 2;
                 size -= 2;
         }
@@ -210,7 +210,7 @@ pci_write_config(struct kobject *kobj, char *buf, loff_t off, size_t count)
                val |= (u32) data[off - init_off + 1] << 8;
                val |= (u32) data[off - init_off + 2] << 16;
                val |= (u32) data[off - init_off + 3] << 24;
-               pci_write_config_dword(dev, off, val);
+               pci_user_write_config_dword(dev, off, val);
                off += 4;
                size -= 4;
        }
@@ -218,13 +218,13 @@ pci_write_config(struct kobject *kobj, char *buf, loff_t off, size_t count)
        if (size >= 2) {
                u16 val = data[off - init_off];
                val |= (u16) data[off - init_off + 1] << 8;
-               pci_write_config_word(dev, off, val);
+               pci_user_write_config_word(dev, off, val);
                off += 2;
                size -= 2;
        }
 
        if (size) {
-               pci_write_config_byte(dev, off, data[off - init_off]);
+               pci_user_write_config_byte(dev, off, data[off - init_off]);
                off++;
                --size;
        }
index 259d247..61b855c 100644 (file)
@@ -252,6 +252,8 @@ pci_restore_bars(struct pci_dev *dev)
                pci_update_resource(dev, &dev->resource[i], i);
 }
 
+int (*platform_pci_set_power_state)(struct pci_dev *dev, pci_power_t t);
+
 /**
  * pci_set_power_state - Set the power state of a PCI device
  * @dev: PCI device to be suspended
@@ -266,7 +268,6 @@ pci_restore_bars(struct pci_dev *dev)
  * -EIO if device does not support PCI PM.
  * 0 if we can successfully change the power state.
  */
-int (*platform_pci_set_power_state)(struct pci_dev *dev, pci_power_t t);
 int
 pci_set_power_state(struct pci_dev *dev, pci_power_t state)
 {
@@ -314,19 +315,19 @@ pci_set_power_state(struct pci_dev *dev, pci_power_t state)
         * sets PowerState to 0.
         */
        switch (dev->current_state) {
+       case PCI_D0:
+       case PCI_D1:
+       case PCI_D2:
+               pmcsr &= ~PCI_PM_CTRL_STATE_MASK;
+               pmcsr |= state;
+               break;
        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;
-               break;
        default:
-               pmcsr &= ~PCI_PM_CTRL_STATE_MASK;
-               pmcsr |= state;
+               pmcsr = 0;
                break;
        }
 
@@ -808,8 +809,8 @@ pci_clear_mwi(struct pci_dev *dev)
 
 /**
  * pci_intx - enables/disables PCI INTx for device dev
- * @dev: the PCI device to operate on
- * @enable: boolean
+ * @pdev: the PCI device to operate on
+ * @enable: boolean: whether to enable or disable PCI INTx
  *
  * Enables/disables PCI INTx for device dev
  */
index d3f3dd4..6527b36 100644 (file)
@@ -15,6 +15,13 @@ extern int pci_bus_alloc_resource(struct pci_bus *bus, struct resource *res,
 extern int (*platform_pci_choose_state)(struct pci_dev *dev, pm_message_t state);
 extern int (*platform_pci_set_power_state)(struct pci_dev *dev, pci_power_t state);
 
+extern int pci_user_read_config_byte(struct pci_dev *dev, int where, u8 *val);
+extern int pci_user_read_config_word(struct pci_dev *dev, int where, u16 *val);
+extern int pci_user_read_config_dword(struct pci_dev *dev, int where, u32 *val);
+extern int pci_user_write_config_byte(struct pci_dev *dev, int where, u8 val);
+extern int pci_user_write_config_word(struct pci_dev *dev, int where, u16 val);
+extern int pci_user_write_config_dword(struct pci_dev *dev, int where, u32 val);
+
 /* PCI /proc functions */
 #ifdef CONFIG_PROC_FS
 extern int pci_proc_attach_device(struct pci_dev *dev);
index 0057864..fce2cb2 100644 (file)
@@ -669,6 +669,7 @@ static void pci_release_dev(struct device *dev)
 
 /**
  * pci_cfg_space_size - get the configuration space size of the PCI device.
+ * @dev: PCI device
  *
  * Regular PCI devices have 256 bytes, but PCI-X 2 and PCI Express devices
  * have 4096 bytes.  Even if the device is capable, that doesn't mean we can
index 9613f66..9eb4657 100644 (file)
@@ -80,7 +80,7 @@ proc_bus_pci_read(struct file *file, char __user *buf, size_t nbytes, loff_t *pp
 
        if ((pos & 1) && cnt) {
                unsigned char val;
-               pci_read_config_byte(dev, pos, &val);
+               pci_user_read_config_byte(dev, pos, &val);
                __put_user(val, buf);
                buf++;
                pos++;
@@ -89,7 +89,7 @@ proc_bus_pci_read(struct file *file, char __user *buf, size_t nbytes, loff_t *pp
 
        if ((pos & 3) && cnt > 2) {
                unsigned short val;
-               pci_read_config_word(dev, pos, &val);
+               pci_user_read_config_word(dev, pos, &val);
                __put_user(cpu_to_le16(val), (unsigned short __user *) buf);
                buf += 2;
                pos += 2;
@@ -98,7 +98,7 @@ proc_bus_pci_read(struct file *file, char __user *buf, size_t nbytes, loff_t *pp
 
        while (cnt >= 4) {
                unsigned int val;
-               pci_read_config_dword(dev, pos, &val);
+               pci_user_read_config_dword(dev, pos, &val);
                __put_user(cpu_to_le32(val), (unsigned int __user *) buf);
                buf += 4;
                pos += 4;
@@ -107,7 +107,7 @@ proc_bus_pci_read(struct file *file, char __user *buf, size_t nbytes, loff_t *pp
 
        if (cnt >= 2) {
                unsigned short val;
-               pci_read_config_word(dev, pos, &val);
+               pci_user_read_config_word(dev, pos, &val);
                __put_user(cpu_to_le16(val), (unsigned short __user *) buf);
                buf += 2;
                pos += 2;
@@ -116,7 +116,7 @@ proc_bus_pci_read(struct file *file, char __user *buf, size_t nbytes, loff_t *pp
 
        if (cnt) {
                unsigned char val;
-               pci_read_config_byte(dev, pos, &val);
+               pci_user_read_config_byte(dev, pos, &val);
                __put_user(val, buf);
                buf++;
                pos++;
@@ -151,7 +151,7 @@ proc_bus_pci_write(struct file *file, const char __user *buf, size_t nbytes, lof
        if ((pos & 1) && cnt) {
                unsigned char val;
                __get_user(val, buf);
-               pci_write_config_byte(dev, pos, val);
+               pci_user_write_config_byte(dev, pos, val);
                buf++;
                pos++;
                cnt--;
@@ -160,7 +160,7 @@ proc_bus_pci_write(struct file *file, const char __user *buf, size_t nbytes, lof
        if ((pos & 3) && cnt > 2) {
                unsigned short val;
                __get_user(val, (unsigned short __user *) buf);
-               pci_write_config_word(dev, pos, le16_to_cpu(val));
+               pci_user_write_config_word(dev, pos, le16_to_cpu(val));
                buf += 2;
                pos += 2;
                cnt -= 2;
@@ -169,7 +169,7 @@ proc_bus_pci_write(struct file *file, const char __user *buf, size_t nbytes, lof
        while (cnt >= 4) {
                unsigned int val;
                __get_user(val, (unsigned int __user *) buf);
-               pci_write_config_dword(dev, pos, le32_to_cpu(val));
+               pci_user_write_config_dword(dev, pos, le32_to_cpu(val));
                buf += 4;
                pos += 4;
                cnt -= 4;
@@ -178,7 +178,7 @@ proc_bus_pci_write(struct file *file, const char __user *buf, size_t nbytes, lof
        if (cnt >= 2) {
                unsigned short val;
                __get_user(val, (unsigned short __user *) buf);
-               pci_write_config_word(dev, pos, le16_to_cpu(val));
+               pci_user_write_config_word(dev, pos, le16_to_cpu(val));
                buf += 2;
                pos += 2;
                cnt -= 2;
@@ -187,7 +187,7 @@ proc_bus_pci_write(struct file *file, const char __user *buf, size_t nbytes, lof
        if (cnt) {
                unsigned char val;
                __get_user(val, buf);
-               pci_write_config_byte(dev, pos, val);
+               pci_user_write_config_byte(dev, pos, val);
                buf++;
                pos++;
                cnt--;
@@ -484,10 +484,10 @@ static int show_dev_config(struct seq_file *m, void *v)
 
        drv = pci_dev_driver(dev);
 
-       pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev);
-       pci_read_config_byte (dev, PCI_LATENCY_TIMER, &latency);
-       pci_read_config_byte (dev, PCI_MIN_GNT, &min_gnt);
-       pci_read_config_byte (dev, PCI_MAX_LAT, &max_lat);
+       pci_user_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev);
+       pci_user_read_config_byte (dev, PCI_LATENCY_TIMER, &latency);
+       pci_user_read_config_byte (dev, PCI_MIN_GNT, &min_gnt);
+       pci_user_read_config_byte (dev, PCI_MAX_LAT, &max_lat);
        seq_printf(m, "  Bus %2d, device %3d, function %2d:\n",
               dev->bus->number, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn));
        seq_printf(m, "    Class %04x", class_rev >> 16);
index 7992bc8..bbd9c23 100644 (file)
@@ -7,6 +7,9 @@
  *
  *  Copyright (c) 1999 Martin Mares <mj@ucw.cz>
  *
+ *  Init/reset quirks for USB host controllers should be in the
+ *  USB quirks file, where their drivers can access reuse it.
+ *
  *  The bridge optimization stuff has been removed. If you really
  *  have a silly BIOS which is unable to set your host bridge right,
  *  use the PowerTweak utility (see http://powertweak.sourceforge.net).
@@ -414,6 +417,18 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,    PCI_DEVICE_ID_INTEL_82801DB_12,
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,    PCI_DEVICE_ID_INTEL_82801EB_0,                quirk_ich4_lpc_acpi );
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,    PCI_DEVICE_ID_INTEL_ESB_1,            quirk_ich4_lpc_acpi );
 
+static void __devinit quirk_ich6_lpc_acpi(struct pci_dev *dev)
+{
+       u32 region;
+
+       pci_read_config_dword(dev, 0x40, &region);
+       quirk_io_region(dev, region, 128, PCI_BRIDGE_RESOURCES, "ICH6 ACPI/GPIO/TCO");
+
+       pci_read_config_dword(dev, 0x48, &region);
+       quirk_io_region(dev, region, 64, PCI_BRIDGE_RESOURCES+1, "ICH6 GPIO");
+}
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,  PCI_DEVICE_ID_INTEL_ICH6_1, quirk_ich6_lpc_acpi );
+
 /*
  * VIA ACPI: One IO region pointed to by longword at
  *     0x48 or 0x20 (256 bytes of ACPI registers)
@@ -632,28 +647,6 @@ static void quirk_via_irq(struct pci_dev *dev)
 }
 DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_VIA, PCI_ANY_ID, quirk_via_irq);
 
-/*
- * PIIX3 USB: We have to disable USB interrupts that are
- * hardwired to PIRQD# and may be shared with an
- * external device.
- *
- * Legacy Support Register (LEGSUP):
- *     bit13:  USB PIRQ Enable (USBPIRQDEN),
- *     bit4:   Trap/SMI On IRQ Enable (USBSMIEN).
- *
- * We mask out all r/wc bits, too.
- */
-static void __devinit quirk_piix3_usb(struct pci_dev *dev)
-{
-       u16 legsup;
-
-       pci_read_config_word(dev, 0xc0, &legsup);
-       legsup &= 0x50ef;
-       pci_write_config_word(dev, 0xc0, legsup);
-}
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,  PCI_DEVICE_ID_INTEL_82371SB_2,  quirk_piix3_usb );
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,  PCI_DEVICE_ID_INTEL_82371AB_2,  quirk_piix3_usb );
-
 /*
  * VIA VT82C598 has its device ID settable and many BIOSes
  * set it to the ID of VT82C597 for backward compatibility.
@@ -922,6 +915,12 @@ static void __init asus_hides_smbus_hostbridge(struct pci_dev *dev)
                        case 0x186a: /* M6Ne notebook */
                                asus_hides_smbus = 1;
                        }
+               if (dev->device == PCI_DEVICE_ID_INTEL_82915GM_HB) {
+                       switch (dev->subsystem_device) {
+                       case 0x1882: /* M6V notebook */
+                               asus_hides_smbus = 1;
+                       }
+               }
        } else if (unlikely(dev->subsystem_vendor == PCI_VENDOR_ID_HP)) {
                if (dev->device ==  PCI_DEVICE_ID_INTEL_82855PM_HB)
                        switch(dev->subsystem_device) {
@@ -932,6 +931,7 @@ static void __init asus_hides_smbus_hostbridge(struct pci_dev *dev)
                if (dev->device == PCI_DEVICE_ID_INTEL_82865_HB)
                        switch (dev->subsystem_device) {
                        case 0x12bc: /* HP D330L */
+                       case 0x12bd: /* HP D530 */
                                asus_hides_smbus = 1;
                        }
        } else if (unlikely(dev->subsystem_vendor == PCI_VENDOR_ID_TOSHIBA)) {
@@ -966,6 +966,7 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,       PCI_DEVICE_ID_INTEL_82865_HB,   asus
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,  PCI_DEVICE_ID_INTEL_7205_0,     asus_hides_smbus_hostbridge );
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,  PCI_DEVICE_ID_INTEL_82855PM_HB, asus_hides_smbus_hostbridge );
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,  PCI_DEVICE_ID_INTEL_82855GM_HB, asus_hides_smbus_hostbridge );
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,  PCI_DEVICE_ID_INTEL_82915GM_HB, asus_hides_smbus_hostbridge );
 
 static void __init asus_hides_smbus_lpc(struct pci_dev *dev)
 {
@@ -990,6 +991,23 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,      PCI_DEVICE_ID_INTEL_82801CA_12, as
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,  PCI_DEVICE_ID_INTEL_82801DB_12, asus_hides_smbus_lpc );
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,  PCI_DEVICE_ID_INTEL_82801EB_0,  asus_hides_smbus_lpc );
 
+static void __init asus_hides_smbus_lpc_ich6(struct pci_dev *dev)
+{
+       u32 val, rcba;
+       void __iomem *base;
+
+       if (likely(!asus_hides_smbus))
+               return;
+       pci_read_config_dword(dev, 0xF0, &rcba);
+       base = ioremap_nocache(rcba & 0xFFFFC000, 0x4000); /* use bits 31:14, 16 kB aligned */
+       if (base == NULL) return;
+       val=readl(base + 0x3418); /* read the Function Disable register, dword mode only */
+       writel(val & 0xFFFFFFF7, base + 0x3418); /* enable the SMBus device */
+       iounmap(base);
+       printk(KERN_INFO "PCI: Enabled ICH6/i801 SMBus device\n");
+}
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,  PCI_DEVICE_ID_INTEL_ICH6_1,     asus_hides_smbus_lpc_ich6 );
+
 /*
  * SiS 96x south bridge: BIOS typically hides SMBus device...
  */
@@ -1002,234 +1020,6 @@ static void __init quirk_sis_96x_smbus(struct pci_dev *dev)
        pci_read_config_byte(dev, 0x77, &val);
 }
 
-
-#define UHCI_USBLEGSUP         0xc0            /* legacy support */
-#define UHCI_USBCMD            0               /* command register */
-#define UHCI_USBSTS            2               /* status register */
-#define UHCI_USBINTR           4               /* interrupt register */
-#define UHCI_USBLEGSUP_DEFAULT 0x2000          /* only PIRQ enable set */
-#define UHCI_USBCMD_RUN                (1 << 0)        /* RUN/STOP bit */
-#define UHCI_USBCMD_GRESET     (1 << 2)        /* Global reset */
-#define UHCI_USBCMD_CONFIGURE  (1 << 6)        /* config semaphore */
-#define UHCI_USBSTS_HALTED     (1 << 5)        /* HCHalted bit */
-
-#define OHCI_CONTROL           0x04
-#define OHCI_CMDSTATUS         0x08
-#define OHCI_INTRSTATUS                0x0c
-#define OHCI_INTRENABLE                0x10
-#define OHCI_INTRDISABLE       0x14
-#define OHCI_OCR               (1 << 3)        /* ownership change request */
-#define OHCI_CTRL_IR           (1 << 8)        /* interrupt routing */
-#define OHCI_INTR_OC           (1 << 30)       /* ownership change */
-
-#define EHCI_HCC_PARAMS                0x08            /* extended capabilities */
-#define EHCI_USBCMD            0               /* command register */
-#define EHCI_USBCMD_RUN                (1 << 0)        /* RUN/STOP bit */
-#define EHCI_USBSTS            4               /* status register */
-#define EHCI_USBSTS_HALTED     (1 << 12)       /* HCHalted bit */
-#define EHCI_USBINTR           8               /* interrupt register */
-#define EHCI_USBLEGSUP         0               /* legacy support register */
-#define EHCI_USBLEGSUP_BIOS    (1 << 16)       /* BIOS semaphore */
-#define EHCI_USBLEGSUP_OS      (1 << 24)       /* OS semaphore */
-#define EHCI_USBLEGCTLSTS      4               /* legacy control/status */
-#define EHCI_USBLEGCTLSTS_SOOE (1 << 13)       /* SMI on ownership change */
-
-int usb_early_handoff __devinitdata = 0;
-static int __init usb_handoff_early(char *str)
-{
-       usb_early_handoff = 1;
-       return 0;
-}
-__setup("usb-handoff", usb_handoff_early);
-
-static void __devinit quirk_usb_handoff_uhci(struct pci_dev *pdev)
-{
-       unsigned long base = 0;
-       int wait_time, delta;
-       u16 val, sts;
-       int i;
-
-       for (i = 0; i < PCI_ROM_RESOURCE; i++)
-               if ((pci_resource_flags(pdev, i) & IORESOURCE_IO)) {
-                       base = pci_resource_start(pdev, i);
-                       break;
-               }
-
-       if (!base)
-               return;
-
-       /*
-        * stop controller
-        */
-       sts = inw(base + UHCI_USBSTS);
-       val = inw(base + UHCI_USBCMD);
-       val &= ~(u16)(UHCI_USBCMD_RUN | UHCI_USBCMD_CONFIGURE);
-       outw(val, base + UHCI_USBCMD);
-
-       /*
-        * wait while it stops if it was running
-        */
-       if ((sts & UHCI_USBSTS_HALTED) == 0)
-       {
-               wait_time = 1000;
-               delta = 100;
-
-               do {
-                       outw(0x1f, base + UHCI_USBSTS);
-                       udelay(delta);
-                       wait_time -= delta;
-                       val = inw(base + UHCI_USBSTS);
-                       if (val & UHCI_USBSTS_HALTED)
-                               break;
-               } while (wait_time > 0);
-       }
-
-       /*
-        * disable interrupts & legacy support
-        */
-       outw(0, base + UHCI_USBINTR);
-       outw(0x1f, base + UHCI_USBSTS);
-       pci_read_config_word(pdev, UHCI_USBLEGSUP, &val);
-       if (val & 0xbf) 
-               pci_write_config_word(pdev, UHCI_USBLEGSUP, UHCI_USBLEGSUP_DEFAULT);
-               
-}
-
-static void __devinit quirk_usb_handoff_ohci(struct pci_dev *pdev)
-{
-       void __iomem *base;
-       int wait_time;
-
-       base = ioremap_nocache(pci_resource_start(pdev, 0),
-                                    pci_resource_len(pdev, 0));
-       if (base == NULL) return;
-
-       if (readl(base + OHCI_CONTROL) & OHCI_CTRL_IR) {
-               wait_time = 500; /* 0.5 seconds */
-               writel(OHCI_INTR_OC, base + OHCI_INTRENABLE);
-               writel(OHCI_OCR, base + OHCI_CMDSTATUS);
-               while (wait_time > 0 && 
-                               readl(base + OHCI_CONTROL) & OHCI_CTRL_IR) {
-                       wait_time -= 10;
-                       msleep(10);
-               }
-       }
-
-       /*
-        * disable interrupts
-        */
-       writel(~(u32)0, base + OHCI_INTRDISABLE);
-       writel(~(u32)0, base + OHCI_INTRSTATUS);
-
-       iounmap(base);
-}
-
-static void __devinit quirk_usb_disable_ehci(struct pci_dev *pdev)
-{
-       int wait_time, delta;
-       void __iomem *base, *op_reg_base;
-       u32 hcc_params, val, temp;
-       u8 cap_length;
-
-       base = ioremap_nocache(pci_resource_start(pdev, 0),
-                               pci_resource_len(pdev, 0));
-       if (base == NULL) return;
-
-       cap_length = readb(base);
-       op_reg_base = base + cap_length;
-       hcc_params = readl(base + EHCI_HCC_PARAMS);
-       hcc_params = (hcc_params >> 8) & 0xff;
-       if (hcc_params) {
-               pci_read_config_dword(pdev, 
-                                       hcc_params + EHCI_USBLEGSUP,
-                                       &val);
-               if (((val & 0xff) == 1) && (val & EHCI_USBLEGSUP_BIOS)) {
-                       /*
-                        * Ok, BIOS is in smm mode, try to hand off...
-                        */
-                       pci_read_config_dword(pdev,
-                                               hcc_params + EHCI_USBLEGCTLSTS,
-                                               &temp);
-                       pci_write_config_dword(pdev,
-                                               hcc_params + EHCI_USBLEGCTLSTS,
-                                               temp | EHCI_USBLEGCTLSTS_SOOE);
-                       val |= EHCI_USBLEGSUP_OS;
-                       pci_write_config_dword(pdev, 
-                                               hcc_params + EHCI_USBLEGSUP, 
-                                               val);
-
-                       wait_time = 500;
-                       do {
-                               msleep(10);
-                               wait_time -= 10;
-                               pci_read_config_dword(pdev,
-                                               hcc_params + EHCI_USBLEGSUP,
-                                               &val);
-                       } while (wait_time && (val & EHCI_USBLEGSUP_BIOS));
-                       if (!wait_time) {
-                               /*
-                                * well, possibly buggy BIOS...
-                                */
-                               printk(KERN_WARNING "EHCI early BIOS handoff "
-                                               "failed (BIOS bug ?)\n");
-                               pci_write_config_dword(pdev,
-                                               hcc_params + EHCI_USBLEGSUP,
-                                               EHCI_USBLEGSUP_OS);
-                               pci_write_config_dword(pdev,
-                                               hcc_params + EHCI_USBLEGCTLSTS,
-                                               0);
-                       }
-               }
-       }
-
-       /*
-        * halt EHCI & disable its interrupts in any case
-        */
-       val = readl(op_reg_base + EHCI_USBSTS);
-       if ((val & EHCI_USBSTS_HALTED) == 0) {
-               val = readl(op_reg_base + EHCI_USBCMD);
-               val &= ~EHCI_USBCMD_RUN;
-               writel(val, op_reg_base + EHCI_USBCMD);
-
-               wait_time = 2000;
-               delta = 100;
-               do {
-                       writel(0x3f, op_reg_base + EHCI_USBSTS);
-                       udelay(delta);
-                       wait_time -= delta;
-                       val = readl(op_reg_base + EHCI_USBSTS);
-                       if ((val == ~(u32)0) || (val & EHCI_USBSTS_HALTED)) {
-                               break;
-                       }
-               } while (wait_time > 0);
-       }
-       writel(0, op_reg_base + EHCI_USBINTR);
-       writel(0x3f, op_reg_base + EHCI_USBSTS);
-
-       iounmap(base);
-
-       return;
-}
-
-
-
-static void __devinit quirk_usb_early_handoff(struct pci_dev *pdev)
-{
-       if (!usb_early_handoff)
-               return;
-
-       if (pdev->class == ((PCI_CLASS_SERIAL_USB << 8) | 0x00)) { /* UHCI */
-               quirk_usb_handoff_uhci(pdev);
-       } else if (pdev->class == ((PCI_CLASS_SERIAL_USB << 8) | 0x10)) { /* OHCI */
-               quirk_usb_handoff_ohci(pdev);
-       } else if (pdev->class == ((PCI_CLASS_SERIAL_USB << 8) | 0x20)) { /* EHCI */
-               quirk_usb_disable_ehci(pdev);
-       }
-
-       return;
-}
-DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, quirk_usb_early_handoff);
-
 /*
  * ... This is further complicated by the fact that some SiS96x south
  * bridges pretend to be 85C503/5513 instead.  In that case see if we
index c071790..87fafc0 100644 (file)
@@ -13,7 +13,7 @@
 #include <linux/smp_lock.h>
 #include <linux/syscalls.h>
 #include <asm/uaccess.h>
-
+#include "pci.h"
 
 asmlinkage long
 sys_pciconfig_read(unsigned long bus, unsigned long dfn,
@@ -38,13 +38,13 @@ sys_pciconfig_read(unsigned long bus, unsigned long dfn,
        lock_kernel();
        switch (len) {
        case 1:
-               cfg_ret = pci_read_config_byte(dev, off, &byte);
+               cfg_ret = pci_user_read_config_byte(dev, off, &byte);
                break;
        case 2:
-               cfg_ret = pci_read_config_word(dev, off, &word);
+               cfg_ret = pci_user_read_config_word(dev, off, &word);
                break;
        case 4:
-               cfg_ret = pci_read_config_dword(dev, off, &dword);
+               cfg_ret = pci_user_read_config_dword(dev, off, &dword);
                break;
        default:
                err = -EINVAL;
@@ -112,7 +112,7 @@ sys_pciconfig_write(unsigned long bus, unsigned long dfn,
                err = get_user(byte, (u8 __user *)buf);
                if (err)
                        break;
-               err = pci_write_config_byte(dev, off, byte);
+               err = pci_user_write_config_byte(dev, off, byte);
                if (err != PCIBIOS_SUCCESSFUL)
                        err = -EIO;
                break;
@@ -121,7 +121,7 @@ sys_pciconfig_write(unsigned long bus, unsigned long dfn,
                err = get_user(word, (u16 __user *)buf);
                if (err)
                        break;
-               err = pci_write_config_word(dev, off, word);
+               err = pci_user_write_config_word(dev, off, word);
                if (err != PCIBIOS_SUCCESSFUL)
                        err = -EIO;
                break;
@@ -130,7 +130,7 @@ sys_pciconfig_write(unsigned long bus, unsigned long dfn,
                err = get_user(dword, (u32 __user *)buf);
                if (err)
                        break;
-               err = pci_write_config_dword(dev, off, dword);
+               err = pci_user_write_config_dword(dev, off, dword);
                if (err != PCIBIOS_SUCCESSFUL)
                        err = -EIO;
                break;
index a107fec..b2d75de 100644 (file)
@@ -787,8 +787,8 @@ vmlogrdr_register_device(struct vmlogrdr_priv_t *priv) {
                return ret;
        }
        priv->class_device = class_device_create(
-                               NULL,
                                vmlogrdr_class,
+                               NULL,
                                MKDEV(vmlogrdr_major, priv->minor_num),
                                dev,
                                "%s", dev->bus_id );
index babd483..e0039df 100644 (file)
@@ -4944,6 +4944,7 @@ static int ipr_reset_restore_cfg_space(struct ipr_cmnd *ipr_cmd)
        int rc;
 
        ENTER;
+       pci_unblock_user_cfg_access(ioa_cfg->pdev);
        rc = pci_restore_state(ioa_cfg->pdev);
 
        if (rc != PCIBIOS_SUCCESSFUL) {
@@ -4998,6 +4999,7 @@ static int ipr_reset_start_bist(struct ipr_cmnd *ipr_cmd)
        int rc;
 
        ENTER;
+       pci_block_user_cfg_access(ioa_cfg->pdev);
        rc = pci_write_config_byte(ioa_cfg->pdev, PCI_BIST, PCI_BIST_START);
 
        if (rc != PCIBIOS_SUCCESSFUL) {
index d47be8e..c9e743b 100644 (file)
@@ -76,7 +76,7 @@ static void megaraid_exit(void);
 
 static int megaraid_probe_one(struct pci_dev*, const struct pci_device_id *);
 static void megaraid_detach_one(struct pci_dev *);
-static void megaraid_mbox_shutdown(struct device *);
+static void megaraid_mbox_shutdown(struct pci_dev *);
 
 static int megaraid_io_attach(adapter_t *);
 static void megaraid_io_detach(adapter_t *);
@@ -369,9 +369,7 @@ static struct pci_driver megaraid_pci_driver_g = {
        .id_table       = pci_id_table_g,
        .probe          = megaraid_probe_one,
        .remove         = __devexit_p(megaraid_detach_one),
-       .driver         = {
-               .shutdown       = megaraid_mbox_shutdown,
-       }
+       .shutdown       = megaraid_mbox_shutdown,
 };
 
 
@@ -673,9 +671,9 @@ megaraid_detach_one(struct pci_dev *pdev)
  * Shutdown notification, perform flush cache
  */
 static void
-megaraid_mbox_shutdown(struct device *device)
+megaraid_mbox_shutdown(struct pci_dev *pdev)
 {
-       adapter_t               *adapter = pci_get_drvdata(to_pci_dev(device));
+       adapter_t               *adapter = pci_get_drvdata(pdev);
        static int              counter;
 
        if (!adapter) {
index 32d730b..51855d3 100644 (file)
@@ -220,8 +220,8 @@ struct sil24_port_priv {
 
 /* ap->host_set->private_data */
 struct sil24_host_priv {
-       void *host_base;        /* global controller control (128 bytes @BAR0) */
-       void *port_base;        /* port registers (4 * 8192 bytes @BAR2) */
+       void __iomem *host_base;        /* global controller control (128 bytes @BAR0) */
+       void __iomem *port_base;        /* port registers (4 * 8192 bytes @BAR2) */
 };
 
 static u8 sil24_check_status(struct ata_port *ap);
@@ -349,10 +349,12 @@ static struct ata_port_info sil24_port_info[] = {
 static inline void sil24_update_tf(struct ata_port *ap)
 {
        struct sil24_port_priv *pp = ap->private_data;
-       void *port = (void *)ap->ioaddr.cmd_addr;
-       struct sil24_prb *prb = port;
+       void __iomem *port = (void __iomem *)ap->ioaddr.cmd_addr;
+       struct sil24_prb __iomem *prb = port;
+       u8 fis[6 * 4];
 
-       ata_tf_from_fis(prb->fis, &pp->tf);
+       memcpy_fromio(fis, prb->fis, 6 * 4);
+       ata_tf_from_fis(fis, &pp->tf);
 }
 
 static u8 sil24_check_status(struct ata_port *ap)
@@ -376,9 +378,9 @@ static int sil24_scr_map[] = {
 
 static u32 sil24_scr_read(struct ata_port *ap, unsigned sc_reg)
 {
-       void *scr_addr = (void *)ap->ioaddr.scr_addr;
+       void __iomem *scr_addr = (void __iomem *)ap->ioaddr.scr_addr;
        if (sc_reg < ARRAY_SIZE(sil24_scr_map)) {
-               void *addr;
+               void __iomem *addr;
                addr = scr_addr + sil24_scr_map[sc_reg] * 4;
                return readl(scr_addr + sil24_scr_map[sc_reg] * 4);
        }
@@ -387,9 +389,9 @@ static u32 sil24_scr_read(struct ata_port *ap, unsigned sc_reg)
 
 static void sil24_scr_write(struct ata_port *ap, unsigned sc_reg, u32 val)
 {
-       void *scr_addr = (void *)ap->ioaddr.scr_addr;
+       void __iomem *scr_addr = (void __iomem *)ap->ioaddr.scr_addr;
        if (sc_reg < ARRAY_SIZE(sil24_scr_map)) {
-               void *addr;
+               void __iomem *addr;
                addr = scr_addr + sil24_scr_map[sc_reg] * 4;
                writel(val, scr_addr + sil24_scr_map[sc_reg] * 4);
        }
@@ -454,7 +456,7 @@ static void sil24_qc_prep(struct ata_queued_cmd *qc)
 static int sil24_qc_issue(struct ata_queued_cmd *qc)
 {
        struct ata_port *ap = qc->ap;
-       void *port = (void *)ap->ioaddr.cmd_addr;
+       void __iomem *port = (void __iomem *)ap->ioaddr.cmd_addr;
        struct sil24_port_priv *pp = ap->private_data;
        dma_addr_t paddr = pp->cmd_block_dma + qc->tag * sizeof(*pp->cmd_block);
 
@@ -467,7 +469,7 @@ static void sil24_irq_clear(struct ata_port *ap)
        /* unused */
 }
 
-static int __sil24_reset_controller(void *port)
+static int __sil24_reset_controller(void __iomem *port)
 {
        int cnt;
        u32 tmp;
@@ -493,7 +495,7 @@ static void sil24_reset_controller(struct ata_port *ap)
 {
        printk(KERN_NOTICE DRV_NAME
               " ata%u: resetting controller...\n", ap->id);
-       if (__sil24_reset_controller((void *)ap->ioaddr.cmd_addr))
+       if (__sil24_reset_controller((void __iomem *)ap->ioaddr.cmd_addr))
                 printk(KERN_ERR DRV_NAME
                        " ata%u: failed to reset controller\n", ap->id);
 }
@@ -527,7 +529,7 @@ static void sil24_error_intr(struct ata_port *ap, u32 slot_stat)
 {
        struct ata_queued_cmd *qc = ata_qc_from_tag(ap, ap->active_tag);
        struct sil24_port_priv *pp = ap->private_data;
-       void *port = (void *)ap->ioaddr.cmd_addr;
+       void __iomem *port = (void __iomem *)ap->ioaddr.cmd_addr;
        u32 irq_stat, cmd_err, sstatus, serror;
 
        irq_stat = readl(port + PORT_IRQ_STAT);
@@ -574,7 +576,7 @@ static void sil24_error_intr(struct ata_port *ap, u32 slot_stat)
 static inline void sil24_host_intr(struct ata_port *ap)
 {
        struct ata_queued_cmd *qc = ata_qc_from_tag(ap, ap->active_tag);
-       void *port = (void *)ap->ioaddr.cmd_addr;
+       void __iomem *port = (void __iomem *)ap->ioaddr.cmd_addr;
        u32 slot_stat;
 
        slot_stat = readl(port + PORT_SLOT_STAT);
@@ -689,7 +691,8 @@ static int sil24_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
        struct ata_port_info *pinfo = &sil24_port_info[board_id];
        struct ata_probe_ent *probe_ent = NULL;
        struct sil24_host_priv *hpriv = NULL;
-       void *host_base = NULL, *port_base = NULL;
+       void __iomem *host_base = NULL;
+       void __iomem *port_base = NULL;
        int i, rc;
 
        if (!printed_version++)
@@ -771,7 +774,7 @@ static int sil24_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
        writel(0, host_base + HOST_CTRL);
 
        for (i = 0; i < probe_ent->n_ports; i++) {
-               void *port = port_base + i * PORT_REGS_SIZE;
+               void __iomem *port = port_base + i * PORT_REGS_SIZE;
                unsigned long portu = (unsigned long)port;
                u32 tmp;
                int cnt;
index df014c2..a50c2bc 100644 (file)
@@ -8,6 +8,7 @@ obj-$(CONFIG_USB)               += core/
 
 obj-$(CONFIG_USB_MON)          += mon/
 
+obj-$(CONFIG_PCI)              += host/
 obj-$(CONFIG_USB_EHCI_HCD)     += host/
 obj-$(CONFIG_USB_ISP116X_HCD)  += host/
 obj-$(CONFIG_USB_OHCI_HCD)     += host/
@@ -17,7 +18,6 @@ obj-$(CONFIG_ETRAX_USB_HOST)  += host/
 
 obj-$(CONFIG_USB_ACM)          += class/
 obj-$(CONFIG_USB_AUDIO)                += class/
-obj-$(CONFIG_USB_BLUETOOTH_TTY)        += class/
 obj-$(CONFIG_USB_MIDI)         += class/
 obj-$(CONFIG_USB_PRINTER)      += class/
 
index 333e39b..ef105a9 100644 (file)
@@ -28,29 +28,6 @@ config USB_AUDIO
          To compile this driver as a module, choose M here: the
          module will be called audio.
 
-comment "USB Bluetooth TTY can only be used with disabled Bluetooth subsystem"
-       depends on USB && BT
-
-config USB_BLUETOOTH_TTY
-       tristate "USB Bluetooth TTY support"
-       depends on USB && BT=n
-       ---help---
-         This driver implements a nonstandard tty interface to a Bluetooth
-         device that can be used only by specialized Bluetooth HCI software.
-
-         Say Y here if you want to use OpenBT Bluetooth stack (available
-         at <http://developer.axis.com/software>), or other TTY based
-         Bluetooth stacks, and want to connect a USB Bluetooth device
-         to your computer's USB port.
-
-         Do *not* enable this driver if you want to use generic Linux
-         Bluetooth support.
-
-         If in doubt, say N here.
-
-         To compile this driver as a module, choose M here: the
-         module will be called bluetty.
-
 config USB_MIDI
        tristate "USB MIDI support"
        depends on USB && SOUND && OBSOLETE_OSS_USB_DRIVER
index 971e549..2294712 100644 (file)
@@ -5,6 +5,5 @@
 
 obj-$(CONFIG_USB_ACM)          += cdc-acm.o
 obj-$(CONFIG_USB_AUDIO)                += audio.o
-obj-$(CONFIG_USB_BLUETOOTH_TTY)        += bluetty.o
 obj-$(CONFIG_USB_MIDI)         += usb-midi.o
 obj-$(CONFIG_USB_PRINTER)      += usblp.o
diff --git a/drivers/usb/class/bluetty.c b/drivers/usb/class/bluetty.c
deleted file mode 100644 (file)
index 5240233..0000000
+++ /dev/null
@@ -1,1279 +0,0 @@
-/*
- * bluetty.c   Version 0.13
- *
- * Copyright (C) 2000, 2001 Greg Kroah-Hartman <greg@kroah.com>
- * Copyright (C) 2000 Mark Douglas Corner      <mcorner@umich.edu>
- *
- * USB Bluetooth TTY driver, based on the Bluetooth Spec version 1.0B
- * 
- * (2001/11/30) Version 0.13 gkh
- *     - added locking patch from Masoodur Rahman <rmasoodu@in.ibm.com>
- *     - removed active variable, as open_count will do.
- *
- * (2001/07/09) Version 0.12 gkh
- *     - removed in_interrupt() call, as it doesn't make sense to do 
- *       that anymore.
- *
- * (2001/06/05) Version 0.11 gkh
- *     - Fixed problem with read urb status saying that we have shutdown,
- *       and that we shouldn't resubmit the urb.  Patch from unknown.
- *
- * (2001/05/28) Version 0.10 gkh
- *     - Fixed problem with using data from userspace in the bluetooth_write
- *       function as found by the CHECKER project.
- *     - Added a buffer to the write_urb_pool which reduces the number of
- *       buffers being created and destroyed for ever write.  Also cleans
- *       up the logic a bit.
- *     - Added a buffer to the control_urb_pool which fixes a memory leak
- *       when the device is removed from the system.
- *
- * (2001/05/28) Version 0.9 gkh
- *     Fixed problem with bluetooth==NULL for bluetooth_read_bulk_callback
- *     which was found by both the CHECKER project and Mikko Rahkonen.
- *
- * (08/04/2001) gb
- *     Identify version on module load.
- *
- * (2001/03/10) Version 0.8 gkh
- *     Fixed problem with not unlinking interrupt urb on device close
- *     and resubmitting the read urb on error with bluetooth struct.
- *     Thanks to Narayan Mohanram <narayan@RovingNetworks.com> for the
- *     fixes.
- *
- * (11/29/2000) Version 0.7 gkh
- *     Fixed problem with overrunning the tty flip buffer.
- *     Removed unneeded NULL pointer initialization.
- *
- * (10/05/2000) Version 0.6 gkh
- *     Fixed bug with urb->dev not being set properly, now that the usb
- *     core needs it.
- *     Got a real major id number and name.
- *
- * (08/06/2000) Version 0.5 gkh
- *     Fixed problem of not resubmitting the bulk read urb if there is
- *     an error in the callback.  Ericsson devices seem to need this.
- *
- * (07/11/2000) Version 0.4 gkh
- *     Fixed bug in disconnect for when we call tty_hangup
- *     Fixed bug in bluetooth_ctrl_msg where the bluetooth struct was not
- *     getting attached to the control urb properly.
- *     Fixed bug in bluetooth_write where we pay attention to the result
- *     of bluetooth_ctrl_msg.
- *
- * (08/03/2000) Version 0.3 gkh mdc
- *     Merged in Mark's changes to make the driver play nice with the Axis
- *     stack.
- *     Made the write bulk use an urb pool to enable larger transfers with
- *     fewer calls to the driver.
- *     Fixed off by one bug in acl pkt receive
- *     Made packet counters specific to each bluetooth device 
- *     Added checks for zero length callbacks
- *     Added buffers for int and bulk packets.  Had to do this otherwise 
- *     packet types could intermingle.
- *     Made a control urb pool for the control messages.
- *
- * (07/11/2000) Version 0.2 gkh
- *     Fixed a small bug found by Nils Faerber in the usb_bluetooth_probe 
- *     function.
- *
- * (07/09/2000) Version 0.1 gkh
- *     Initial release. Has support for sending ACL data (which is really just
- *     a HCI frame.) Raw HCI commands and HCI events are not supported.
- *     A ioctl will probably be needed for the HCI commands and events in the
- *     future. All isoch endpoints are ignored at this time also.
- *     This driver should work for all currently shipping USB Bluetooth 
- *     devices at this time :)
- * 
- */
-
-/*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/tty.h>
-#include <linux/tty_driver.h>
-#include <linux/tty_flip.h>
-#include <linux/module.h>
-#include <asm/uaccess.h>
-
-#define DEBUG
-#include <linux/usb.h>
-
-/*
- * Version Information
- */
-#define DRIVER_VERSION "v0.13"
-#define DRIVER_AUTHOR "Greg Kroah-Hartman, Mark Douglas Corner"
-#define DRIVER_DESC "USB Bluetooth tty driver"
-
-/* define this if you have hardware that is not good */
-/*#define      BTBUGGYHARDWARE */
-
-/* Class, SubClass, and Protocol codes that describe a Bluetooth device */
-#define WIRELESS_CLASS_CODE                    0xe0
-#define RF_SUBCLASS_CODE                       0x01
-#define BLUETOOTH_PROGRAMMING_PROTOCOL_CODE    0x01
-
-
-#define BLUETOOTH_TTY_MAJOR    216     /* real device node major id */
-#define BLUETOOTH_TTY_MINORS   256     /* whole lotta bluetooth devices */
-
-#define USB_BLUETOOTH_MAGIC    0x6d02  /* magic number for bluetooth struct */
-
-#define BLUETOOTH_CONTROL_REQUEST_TYPE 0x20
-
-/* Bluetooth packet types */
-#define CMD_PKT                        0x01
-#define ACL_PKT                        0x02
-#define SCO_PKT                        0x03
-#define EVENT_PKT              0x04
-#define ERROR_PKT              0x05
-#define NEG_PKT                        0x06
-
-/* Message sizes */
-#define MAX_EVENT_SIZE         0xFF
-#define EVENT_HDR_SIZE         3       /* 2 for the header + 1 for the type indicator */
-#define EVENT_BUFFER_SIZE      (MAX_EVENT_SIZE + EVENT_HDR_SIZE)
-
-#define MAX_ACL_SIZE           0xFFFF
-#define ACL_HDR_SIZE           5       /* 4 for the header + 1 for the type indicator */
-#define ACL_BUFFER_SIZE                (MAX_ACL_SIZE + ACL_HDR_SIZE)
-
-/* parity check flag */
-#define RELEVANT_IFLAG(iflag)  (iflag & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK))
-
-#define CHAR2INT16(c1,c0)      (((u32)((c1) & 0xff) << 8) + (u32)((c0) & 0xff))
-
-#define NUM_BULK_URBS          24
-#define NUM_CONTROL_URBS       16
-
-struct usb_bluetooth {
-       int                     magic;
-       struct usb_device *     dev;
-       struct tty_driver *     tty_driver;     /* the tty_driver for this device */
-       struct tty_struct *     tty;            /* the corresponding tty for this port */
-
-       unsigned char           minor;          /* the starting minor number for this device */
-       int                     throttle;       /* throttled by tty layer */
-       int                     open_count;
-       
-       __u8                    control_out_bInterfaceNum;
-       struct urb *            control_urb_pool[NUM_CONTROL_URBS];
-       struct usb_ctrlrequest  dr[NUM_CONTROL_URBS];
-
-       unsigned char *         interrupt_in_buffer;
-       struct urb *            interrupt_in_urb;
-       __u8                    interrupt_in_endpointAddress;
-       __u8                    interrupt_in_interval;
-       int                     interrupt_in_buffer_size;
-
-       unsigned char *         bulk_in_buffer;
-       struct urb *            read_urb;
-       __u8                    bulk_in_endpointAddress;
-       int                     bulk_in_buffer_size;
-
-       int                     bulk_out_buffer_size;
-       __u8                    bulk_out_endpointAddress;
-
-       wait_queue_head_t       write_wait;
-
-       struct work_struct                      work;   /* work queue entry for line discipline waking up */
-       
-       unsigned int            int_packet_pos;
-       unsigned char           int_buffer[EVENT_BUFFER_SIZE];
-       unsigned int            bulk_packet_pos;
-       unsigned char           bulk_buffer[ACL_BUFFER_SIZE];   /* 64k preallocated, fix? */
-       struct semaphore        lock;
-};
-
-
-/* local function prototypes */
-static int  bluetooth_open             (struct tty_struct *tty, struct file *filp);
-static void bluetooth_close            (struct tty_struct *tty, struct file *filp);
-static int  bluetooth_write            (struct tty_struct *tty, const unsigned char *buf, int count);
-static int  bluetooth_write_room       (struct tty_struct *tty);
-static int  bluetooth_chars_in_buffer  (struct tty_struct *tty);
-static void bluetooth_throttle         (struct tty_struct *tty);
-static void bluetooth_unthrottle       (struct tty_struct *tty);
-static int  bluetooth_ioctl            (struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg);
-static void bluetooth_set_termios      (struct tty_struct *tty, struct termios *old);
-
-static void bluetooth_int_callback             (struct urb *urb, struct pt_regs *regs);
-static void bluetooth_ctrl_callback            (struct urb *urb, struct pt_regs *regs);
-static void bluetooth_read_bulk_callback       (struct urb *urb, struct pt_regs *regs);
-static void bluetooth_write_bulk_callback      (struct urb *urb, struct pt_regs *regs);
-
-static int usb_bluetooth_probe (struct usb_interface *intf, 
-                               const struct usb_device_id *id);
-static void usb_bluetooth_disconnect   (struct usb_interface *intf);
-
-
-static struct usb_device_id usb_bluetooth_ids [] = {
-       { USB_DEVICE_INFO(WIRELESS_CLASS_CODE, RF_SUBCLASS_CODE, BLUETOOTH_PROGRAMMING_PROTOCOL_CODE) },
-       { }                                             /* Terminating entry */
-};
-
-MODULE_DEVICE_TABLE (usb, usb_bluetooth_ids);
-
-static struct usb_driver usb_bluetooth_driver = {
-       .owner =        THIS_MODULE,
-       .name =         "bluetty",
-       .probe =        usb_bluetooth_probe,
-       .disconnect =   usb_bluetooth_disconnect,
-       .id_table =     usb_bluetooth_ids,
-};
-
-static struct tty_driver       *bluetooth_tty_driver;
-static struct usb_bluetooth    *bluetooth_table[BLUETOOTH_TTY_MINORS];
-
-
-static inline int bluetooth_paranoia_check (struct usb_bluetooth *bluetooth, const char *function)
-{
-       if (!bluetooth) {
-               dbg("%s - bluetooth == NULL", function);
-               return -1;
-       }
-       if (bluetooth->magic != USB_BLUETOOTH_MAGIC) {
-               dbg("%s - bad magic number for bluetooth", function);
-               return -1;
-       }
-
-       return 0;
-}
-
-
-static inline struct usb_bluetooth* get_usb_bluetooth (struct usb_bluetooth *bluetooth, const char *function)
-{
-       if (!bluetooth || 
-           bluetooth_paranoia_check (bluetooth, function)) { 
-               /* then say that we don't have a valid usb_bluetooth thing, which will
-                * end up generating -ENODEV return values */
-               return NULL;
-       }
-
-       return bluetooth;
-}
-
-
-static inline struct usb_bluetooth *get_bluetooth_by_index (int index)
-{
-       return bluetooth_table[index];
-}
-
-
-static int bluetooth_ctrl_msg (struct usb_bluetooth *bluetooth, int request, int value, const unsigned char *buf, int len)
-{
-       struct urb *urb = NULL;
-       struct usb_ctrlrequest *dr = NULL;
-       int i;
-       int status;
-
-       dbg ("%s", __FUNCTION__);
-
-       /* try to find a free urb in our list */
-       for (i = 0; i < NUM_CONTROL_URBS; ++i) {
-               if (bluetooth->control_urb_pool[i]->status != -EINPROGRESS) {
-                       urb = bluetooth->control_urb_pool[i];
-                       dr = &bluetooth->dr[i];
-                       break;
-               }
-       }
-       if (urb == NULL) {
-               dbg ("%s - no free urbs", __FUNCTION__);
-               return -ENOMEM;
-       }
-
-       /* keep increasing the urb transfer buffer to fit the size of the message */
-       if (urb->transfer_buffer == NULL) {
-               urb->transfer_buffer = kmalloc (len, GFP_KERNEL);
-               if (urb->transfer_buffer == NULL) {
-                       err ("%s - out of memory", __FUNCTION__);
-                       return -ENOMEM;
-               }
-       }
-       if (urb->transfer_buffer_length < len) {
-               kfree(urb->transfer_buffer);
-               urb->transfer_buffer = kmalloc (len, GFP_KERNEL);
-               if (urb->transfer_buffer == NULL) {
-                       err ("%s - out of memory", __FUNCTION__);
-                       return -ENOMEM;
-               }
-       }
-       memcpy (urb->transfer_buffer, buf, len);
-
-       dr->bRequestType= BLUETOOTH_CONTROL_REQUEST_TYPE;
-       dr->bRequest = request;
-       dr->wValue = cpu_to_le16((u16) value);
-       dr->wIndex = cpu_to_le16((u16) bluetooth->control_out_bInterfaceNum);
-       dr->wLength = cpu_to_le16((u16) len);
-       
-       usb_fill_control_urb (urb, bluetooth->dev, usb_sndctrlpipe(bluetooth->dev, 0),
-                         (unsigned char*)dr, urb->transfer_buffer, len, bluetooth_ctrl_callback, bluetooth);
-
-       /* send it down the pipe */
-       status = usb_submit_urb(urb, GFP_KERNEL);
-       if (status)
-               dbg("%s - usb_submit_urb(control) failed with status = %d", __FUNCTION__, status);
-       
-       return status;
-}
-
-
-
-
-
-/*****************************************************************************
- * Driver tty interface functions
- *****************************************************************************/
-static int bluetooth_open (struct tty_struct *tty, struct file * filp)
-{
-       struct usb_bluetooth *bluetooth;
-       int result;
-
-       dbg("%s", __FUNCTION__);
-
-       /* initialize the pointer incase something fails */
-       tty->driver_data = NULL;
-
-       /* get the bluetooth object associated with this tty pointer */
-       bluetooth = get_bluetooth_by_index (tty->index);
-
-       if (bluetooth_paranoia_check (bluetooth, __FUNCTION__)) {
-               return -ENODEV;
-       }
-
-       down (&bluetooth->lock);
-       ++bluetooth->open_count;
-       if (bluetooth->open_count == 1) {
-               /* set up our structure making the tty driver remember our object, and us it */
-               tty->driver_data = bluetooth;
-               bluetooth->tty = tty;
-
-               /* force low_latency on so that our tty_push actually forces the data through, 
-               * otherwise it is scheduled, and with high data rates (like with OHCI) data
-               * can get lost. */
-               bluetooth->tty->low_latency = 1;
-       
-               /* Reset the packet position counters */
-               bluetooth->int_packet_pos = 0;
-               bluetooth->bulk_packet_pos = 0;
-
-#ifndef BTBUGGYHARDWARE
-               /* Start reading from the device */
-               usb_fill_bulk_urb (bluetooth->read_urb, bluetooth->dev, 
-                              usb_rcvbulkpipe(bluetooth->dev, bluetooth->bulk_in_endpointAddress),
-                              bluetooth->bulk_in_buffer,
-                              bluetooth->bulk_in_buffer_size,
-                              bluetooth_read_bulk_callback, bluetooth);
-               result = usb_submit_urb(bluetooth->read_urb, GFP_KERNEL);
-               if (result)
-                       dbg("%s - usb_submit_urb(read bulk) failed with status %d", __FUNCTION__, result);
-#endif
-               usb_fill_int_urb (bluetooth->interrupt_in_urb, bluetooth->dev,
-                             usb_rcvintpipe(bluetooth->dev, bluetooth->interrupt_in_endpointAddress),
-                             bluetooth->interrupt_in_buffer,
-                             bluetooth->interrupt_in_buffer_size,
-                             bluetooth_int_callback, bluetooth,
-                             bluetooth->interrupt_in_interval);
-               result = usb_submit_urb(bluetooth->interrupt_in_urb, GFP_KERNEL);
-               if (result)
-                       dbg("%s - usb_submit_urb(interrupt in) failed with status %d", __FUNCTION__, result);
-       }
-       
-       up(&bluetooth->lock);
-
-       return 0;
-}
-
-
-static void bluetooth_close (struct tty_struct *tty, struct file * filp)
-{
-       struct usb_bluetooth *bluetooth = get_usb_bluetooth ((struct usb_bluetooth *)tty->driver_data, __FUNCTION__);
-
-       if (!bluetooth) {
-               return;
-       }
-
-       dbg("%s", __FUNCTION__);
-
-       if (!bluetooth->open_count) {
-               dbg ("%s - device not opened", __FUNCTION__);
-               return;
-       }
-
-       down (&bluetooth->lock);
-       --bluetooth->open_count;
-       if (bluetooth->open_count <= 0) {
-               bluetooth->open_count = 0;
-
-               /* shutdown any in-flight urbs that we know about */
-               usb_kill_urb (bluetooth->read_urb);
-               usb_kill_urb (bluetooth->interrupt_in_urb);
-       }
-       up(&bluetooth->lock);
-}
-
-
-static int bluetooth_write (struct tty_struct * tty, const unsigned char *buf, int count)
-{
-       struct usb_bluetooth *bluetooth = get_usb_bluetooth ((struct usb_bluetooth *)tty->driver_data, __FUNCTION__);
-       struct urb *urb = NULL;
-       unsigned char *temp_buffer = NULL;
-       const unsigned char *current_buffer;
-       unsigned char *urb_buffer;
-       int i;
-       int retval = 0;
-
-       if (!bluetooth) {
-               return -ENODEV;
-       }
-
-       dbg("%s - %d byte(s)", __FUNCTION__, count);
-
-       if (!bluetooth->open_count) {
-               dbg ("%s - device not opened", __FUNCTION__);
-               return -EINVAL;
-       }
-
-       if (count == 0) {
-               dbg("%s - write request of 0 bytes", __FUNCTION__);
-               return 0;
-       }
-       if (count == 1) {
-               dbg("%s - write request only included type %d", __FUNCTION__, buf[0]);
-               return 1;
-       }
-
-#ifdef DEBUG
-       printk (KERN_DEBUG __FILE__ ": %s - length = %d, data = ", __FUNCTION__, count);
-       for (i = 0; i < count; ++i) {
-               printk ("%.2x ", buf[i]);
-       }
-       printk ("\n");
-#endif
-
-       current_buffer = buf;
-
-       switch (*current_buffer) {
-               /* First byte indicates the type of packet */
-               case CMD_PKT:
-                       /* dbg("%s- Send cmd_pkt len:%d", __FUNCTION__, count);*/
-
-                       retval = bluetooth_ctrl_msg (bluetooth, 0x00, 0x00, &current_buffer[1], count-1);
-                       if (retval) {
-                               goto exit;
-                       }
-                       retval = count;
-                       break;
-
-               case ACL_PKT:
-                       ++current_buffer;
-                       --count;
-
-                       urb_buffer = kmalloc (count, GFP_ATOMIC);
-                       if (!urb_buffer) {
-                               dev_err(&bluetooth->dev->dev, "out of memory\n");
-                               retval = -ENOMEM;
-                               goto exit;
-                       }
-
-                       urb = usb_alloc_urb(0, GFP_ATOMIC);
-                       if (!urb) {
-                               dev_err(&bluetooth->dev->dev, "no more free urbs\n");
-                               kfree(urb_buffer);
-                               retval = -ENOMEM;
-                               goto exit;
-                       }
-                       memcpy (urb_buffer, current_buffer, count);
-
-                       /* build up our urb */
-                       usb_fill_bulk_urb(urb, bluetooth->dev, 
-                                         usb_sndbulkpipe(bluetooth->dev,
-                                                         bluetooth->bulk_out_endpointAddress),
-                                         urb_buffer,
-                                         count,
-                                         bluetooth_write_bulk_callback,
-                                         bluetooth);
-
-
-                       /* send it down the pipe */
-                       retval = usb_submit_urb(urb, GFP_KERNEL);
-                       if (retval) {
-                               dbg("%s - usb_submit_urb(write bulk) failed with error = %d", __FUNCTION__, retval);
-                               goto exit;
-                       }
-
-                       /* we are done with this urb, so let the host driver
-                        * really free it when it is finished with it */
-                       usb_free_urb (urb);
-                       retval = count + 1;
-                       break;
-               
-               default :
-                       dbg("%s - unsupported (at this time) write type", __FUNCTION__);
-                       retval = -EINVAL;
-                       break;
-       }
-
-exit:
-       kfree(temp_buffer);
-
-       return retval;
-} 
-
-
-static int bluetooth_write_room (struct tty_struct *tty) 
-{
-       dbg("%s", __FUNCTION__);
-
-       /*
-        * We really can take anything the user throws at us
-        * but let's pick a nice big number to tell the tty
-        * layer that we have lots of free space
-        */
-       return 2048;
-}
-
-
-static int bluetooth_chars_in_buffer (struct tty_struct *tty) 
-{
-       dbg("%s", __FUNCTION__);
-
-       /* 
-        * We can't really account for how much data we
-        * have sent out, but hasn't made it through to the
-        * device, so just tell the tty layer that everything
-        * is flushed.
-        */
-       return 0;
-}
-
-
-static void bluetooth_throttle (struct tty_struct * tty)
-{
-       struct usb_bluetooth *bluetooth = get_usb_bluetooth ((struct usb_bluetooth *)tty->driver_data, __FUNCTION__);
-
-       if (!bluetooth) {
-               return;
-       }
-
-       dbg("%s", __FUNCTION__);
-
-       if (!bluetooth->open_count) {
-               dbg ("%s - device not open", __FUNCTION__);
-               return;
-       }
-       
-       dbg("%s unsupported (at this time)", __FUNCTION__);
-
-       return;
-}
-
-
-static void bluetooth_unthrottle (struct tty_struct * tty)
-{
-       struct usb_bluetooth *bluetooth = get_usb_bluetooth ((struct usb_bluetooth *)tty->driver_data, __FUNCTION__);
-
-       if (!bluetooth) {
-               return;
-       }
-
-       dbg("%s", __FUNCTION__);
-
-       if (!bluetooth->open_count) {
-               dbg ("%s - device not open", __FUNCTION__);
-               return;
-       }
-
-       dbg("%s unsupported (at this time)", __FUNCTION__);
-}
-
-
-static int bluetooth_ioctl (struct tty_struct *tty, struct file * file, unsigned int cmd, unsigned long arg)
-{
-       struct usb_bluetooth *bluetooth = get_usb_bluetooth ((struct usb_bluetooth *)tty->driver_data, __FUNCTION__);
-
-       if (!bluetooth) {
-               return -ENODEV;
-       }
-
-       dbg("%s - cmd 0x%.4x", __FUNCTION__, cmd);
-
-       if (!bluetooth->open_count) {
-               dbg ("%s - device not open", __FUNCTION__);
-               return -ENODEV;
-       }
-
-       /* FIXME!!! */
-       return -ENOIOCTLCMD;
-}
-
-
-static void bluetooth_set_termios (struct tty_struct *tty, struct termios * old)
-{
-       struct usb_bluetooth *bluetooth = get_usb_bluetooth ((struct usb_bluetooth *)tty->driver_data, __FUNCTION__);
-
-       if (!bluetooth) {
-               return;
-       }
-
-       dbg("%s", __FUNCTION__);
-
-       if (!bluetooth->open_count) {
-               dbg ("%s - device not open", __FUNCTION__);
-               return;
-       }
-
-       /* FIXME!!! */
-
-       return;
-}
-
-
-#ifdef BTBUGGYHARDWARE
-void btusb_enable_bulk_read(struct tty_struct *tty){
-       struct usb_bluetooth *bluetooth = get_usb_bluetooth ((struct usb_bluetooth *)tty->driver_data, __FUNCTION__);
-       int result;
-
-       if (!bluetooth) {
-               return;
-       }
-
-       dbg("%s", __FUNCTION__);
-
-       if (!bluetooth->open_count) {
-               dbg ("%s - device not open", __FUNCTION__);
-               return;
-       }
-
-       if (bluetooth->read_urb) {
-               usb_fill_bulk_urb(bluetooth->read_urb, bluetooth->dev, 
-                             usb_rcvbulkpipe(bluetooth->dev, bluetooth->bulk_in_endpointAddress),
-                             bluetooth->bulk_in_buffer, bluetooth->bulk_in_buffer_size, 
-                             bluetooth_read_bulk_callback, bluetooth);
-               result = usb_submit_urb(bluetooth->read_urb, GFP_KERNEL);
-               if (result)
-                       err ("%s - failed submitting read urb, error %d", __FUNCTION__, result);
-       }
-}
-
-void btusb_disable_bulk_read(struct tty_struct *tty){
-       struct usb_bluetooth *bluetooth = get_usb_bluetooth ((struct usb_bluetooth *)tty->driver_data, __FUNCTION__);
-
-       if (!bluetooth) {
-               return;
-       }
-
-       dbg("%s", __FUNCTION__);
-
-       if (!bluetooth->open_count) {
-               dbg ("%s - device not open", __FUNCTION__);
-               return;
-       }
-
-       if ((bluetooth->read_urb) && (bluetooth->read_urb->actual_length))
-               usb_kill_urb(bluetooth->read_urb);
-}
-#endif
-
-
-/*****************************************************************************
- * urb callback functions
- *****************************************************************************/
-
-
-static void bluetooth_int_callback (struct urb *urb, struct pt_regs *regs)
-{
-       struct usb_bluetooth *bluetooth = get_usb_bluetooth ((struct usb_bluetooth *)urb->context, __FUNCTION__);
-       unsigned char *data = urb->transfer_buffer;
-       unsigned int i;
-       unsigned int count = urb->actual_length;
-       unsigned int packet_size;
-       int status;
-
-       dbg("%s", __FUNCTION__);
-
-       if (!bluetooth) {
-               dbg("%s - bad bluetooth pointer, exiting", __FUNCTION__);
-               return;
-       }
-
-       switch (urb->status) {
-       case 0:
-               /* success */
-               break;
-       case -ECONNRESET:
-       case -ENOENT:
-       case -ESHUTDOWN:
-               /* this urb is terminated, clean up */
-               dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status);
-               return;
-       default:
-               dbg("%s - nonzero urb status received: %d", __FUNCTION__, urb->status);
-               goto exit;
-       }
-
-       if (!count) {
-               dbg("%s - zero length int", __FUNCTION__);
-               goto exit;
-       }
-
-
-#ifdef DEBUG
-       if (count) {
-               printk (KERN_DEBUG __FILE__ ": %s- length = %d, data = ", __FUNCTION__, count);
-               for (i = 0; i < count; ++i) {
-                       printk ("%.2x ", data[i]);
-               }
-               printk ("\n");
-       }
-#endif
-
-#ifdef BTBUGGYHARDWARE
-       if ((count >= 2) && (data[0] == 0xFF) && (data[1] == 0x00)) {
-               data += 2;
-               count -= 2;
-       }
-       if (count == 0) {
-               urb->actual_length = 0;
-               goto exit;
-       }
-#endif
-       /* We add  a packet type identifier to the beginning of each
-          HCI frame.  This makes the data in the tty look like a
-          serial USB devices.  Each HCI frame can be broken across
-          multiple URBs so we buffer them until we have a full hci
-          packet */
-
-       if (!bluetooth->int_packet_pos) {
-               bluetooth->int_buffer[0] = EVENT_PKT;
-               bluetooth->int_packet_pos++;
-       }
-       
-       if (bluetooth->int_packet_pos + count > EVENT_BUFFER_SIZE) {
-               err("%s - exceeded EVENT_BUFFER_SIZE", __FUNCTION__);
-               bluetooth->int_packet_pos = 0;
-               goto exit;
-       }
-
-       memcpy (&bluetooth->int_buffer[bluetooth->int_packet_pos],
-               urb->transfer_buffer, count);
-       bluetooth->int_packet_pos += count;
-       urb->actual_length = 0;
-
-       if (bluetooth->int_packet_pos >= EVENT_HDR_SIZE)
-               packet_size = bluetooth->int_buffer[2];
-       else
-               goto exit;
-
-       if (packet_size + EVENT_HDR_SIZE < bluetooth->int_packet_pos) {
-               err("%s - packet was too long", __FUNCTION__);
-               bluetooth->int_packet_pos = 0;
-               goto exit;
-       }
-
-       if (packet_size + EVENT_HDR_SIZE == bluetooth->int_packet_pos) {
-               for (i = 0; i < bluetooth->int_packet_pos; ++i) {
-                       /* if we insert more than TTY_FLIPBUF_SIZE characters, we drop them */
-                       if (bluetooth->tty->flip.count >= TTY_FLIPBUF_SIZE) {
-                               tty_flip_buffer_push(bluetooth->tty);
-                       }
-                       tty_insert_flip_char(bluetooth->tty, bluetooth->int_buffer[i], 0);
-               }
-               tty_flip_buffer_push(bluetooth->tty);
-
-               bluetooth->int_packet_pos = 0;
-       }
-
-exit:
-       status = usb_submit_urb (urb, GFP_ATOMIC);
-       if (status)
-               err ("%s - usb_submit_urb failed with result %d",
-                    __FUNCTION__, status);
-}
-
-
-static void bluetooth_ctrl_callback (struct urb *urb, struct pt_regs *regs)
-{
-       struct usb_bluetooth *bluetooth = get_usb_bluetooth ((struct usb_bluetooth *)urb->context, __FUNCTION__);
-
-       dbg("%s", __FUNCTION__);
-
-       if (!bluetooth) {
-               dbg("%s - bad bluetooth pointer, exiting", __FUNCTION__);
-               return;
-       }
-
-       if (urb->status) {
-               dbg("%s - nonzero read bulk status received: %d", __FUNCTION__, urb->status);
-               return;
-       }
-}
-
-
-static void bluetooth_read_bulk_callback (struct urb *urb, struct pt_regs *regs)
-{
-       struct usb_bluetooth *bluetooth = get_usb_bluetooth ((struct usb_bluetooth *)urb->context, __FUNCTION__);
-       unsigned char *data = urb->transfer_buffer;
-       unsigned int count = urb->actual_length;
-       unsigned int i;
-       unsigned int packet_size;
-       int result;
-
-
-       dbg("%s", __FUNCTION__);
-
-       if (!bluetooth) {
-               dbg("%s - bad bluetooth pointer, exiting", __FUNCTION__);
-               return;
-       }
-
-       if (urb->status) {
-               dbg("%s - nonzero read bulk status received: %d", __FUNCTION__, urb->status);
-               if (urb->status == -ENOENT) {                   
-                       dbg("%s - URB canceled, won't reschedule", __FUNCTION__);
-                       return;
-               }
-               goto exit;
-       }
-
-       if (!count) {
-               dbg("%s - zero length read bulk", __FUNCTION__);
-               goto exit;
-       }
-
-#ifdef DEBUG
-       if (count) {
-               printk (KERN_DEBUG __FILE__ ": %s- length = %d, data = ", __FUNCTION__, count);
-               for (i = 0; i < count; ++i) {
-                       printk ("%.2x ", data[i]);
-               }
-               printk ("\n");
-       }
-#endif
-#ifdef BTBUGGYHARDWARE
-       if ((count == 4) && (data[0] == 0x00) && (data[1] == 0x00)
-           && (data[2] == 0x00) && (data[3] == 0x00)) {
-               urb->actual_length = 0;
-               usb_fill_bulk_urb(bluetooth->read_urb, bluetooth->dev, 
-                             usb_rcvbulkpipe(bluetooth->dev, bluetooth->bulk_in_endpointAddress),
-                             bluetooth->bulk_in_buffer, bluetooth->bulk_in_buffer_size, 
-                             bluetooth_read_bulk_callback, bluetooth);
-               result = usb_submit_urb(bluetooth->read_urb, GFP_KERNEL);
-               if (result)
-                       err ("%s - failed resubmitting read urb, error %d", __FUNCTION__, result);
-
-               return;
-       }
-#endif
-       /* We add  a packet type identifier to the beginning of each
-          HCI frame.  This makes the data in the tty look like a
-          serial USB devices.  Each HCI frame can be broken across
-          multiple URBs so we buffer them until we have a full hci
-          packet */
-       
-       if (!bluetooth->bulk_packet_pos) {
-               bluetooth->bulk_buffer[0] = ACL_PKT;
-               bluetooth->bulk_packet_pos++;
-       }
-
-       if (bluetooth->bulk_packet_pos + count > ACL_BUFFER_SIZE) {
-               err("%s - exceeded ACL_BUFFER_SIZE", __FUNCTION__);
-               bluetooth->bulk_packet_pos = 0;
-               goto exit;
-       }
-
-       memcpy (&bluetooth->bulk_buffer[bluetooth->bulk_packet_pos],
-               urb->transfer_buffer, count);
-       bluetooth->bulk_packet_pos += count;
-       urb->actual_length = 0;
-
-       if (bluetooth->bulk_packet_pos >= ACL_HDR_SIZE) {
-               packet_size = CHAR2INT16(bluetooth->bulk_buffer[4],bluetooth->bulk_buffer[3]);
-       } else {
-               goto exit;
-       }
-
-       if (packet_size + ACL_HDR_SIZE < bluetooth->bulk_packet_pos) {
-               err("%s - packet was too long", __FUNCTION__);
-               bluetooth->bulk_packet_pos = 0;
-               goto exit;
-       }
-
-       if (packet_size + ACL_HDR_SIZE == bluetooth->bulk_packet_pos) {
-               for (i = 0; i < bluetooth->bulk_packet_pos; ++i) {
-                       /* if we insert more than TTY_FLIPBUF_SIZE characters, we drop them. */
-                       if (bluetooth->tty->flip.count >= TTY_FLIPBUF_SIZE) {
-                               tty_flip_buffer_push(bluetooth->tty);
-                       }
-                       tty_insert_flip_char(bluetooth->tty, bluetooth->bulk_buffer[i], 0);
-               }
-               tty_flip_buffer_push(bluetooth->tty);
-               bluetooth->bulk_packet_pos = 0;
-       }       
-
-exit:
-       if (!bluetooth || !bluetooth->open_count)
-               return;
-
-       usb_fill_bulk_urb(bluetooth->read_urb, bluetooth->dev, 
-                     usb_rcvbulkpipe(bluetooth->dev, bluetooth->bulk_in_endpointAddress),
-                     bluetooth->bulk_in_buffer, bluetooth->bulk_in_buffer_size, 
-                     bluetooth_read_bulk_callback, bluetooth);
-       result = usb_submit_urb(bluetooth->read_urb, GFP_KERNEL);
-       if (result)
-               err ("%s - failed resubmitting read urb, error %d", __FUNCTION__, result);
-
-       return;
-}
-
-
-static void bluetooth_write_bulk_callback (struct urb *urb, struct pt_regs *regs)
-{
-       struct usb_bluetooth *bluetooth = get_usb_bluetooth ((struct usb_bluetooth *)urb->context, __FUNCTION__);
-
-       dbg("%s", __FUNCTION__);
-
-       /* free up the transfer buffer, as usb_free_urb() does not do this */
-       kfree(urb->transfer_buffer);
-
-       if (!bluetooth) {
-               dbg("%s - bad bluetooth pointer, exiting", __FUNCTION__);
-               return;
-       }
-
-       if (urb->status) {
-               dbg("%s - nonzero write bulk status received: %d", __FUNCTION__, urb->status);
-               return;
-       }
-
-       /* wake up our little function to let the tty layer know that something happened */
-       schedule_work(&bluetooth->work);
-}
-
-
-static void bluetooth_softint(void *private)
-{
-       struct usb_bluetooth *bluetooth = get_usb_bluetooth ((struct usb_bluetooth *)private, __FUNCTION__);
-
-       dbg("%s", __FUNCTION__);
-
-       if (!bluetooth)
-               return;
-
-       tty_wakeup(bluetooth->tty);
-}
-
-
-static int usb_bluetooth_probe (struct usb_interface *intf, 
-                               const struct usb_device_id *id)
-{
-       struct usb_device *dev = interface_to_usbdev (intf);
-       struct usb_bluetooth *bluetooth = NULL;
-       struct usb_host_interface *interface;
-       struct usb_endpoint_descriptor *endpoint;
-       struct usb_endpoint_descriptor *interrupt_in_endpoint[8];
-       struct usb_endpoint_descriptor *bulk_in_endpoint[8];
-       struct usb_endpoint_descriptor *bulk_out_endpoint[8];
-       int control_out_endpoint;
-
-       int minor;
-       int buffer_size;
-       int i;
-       int num_interrupt_in = 0;
-       int num_bulk_in = 0;
-       int num_bulk_out = 0;
-
-       interface = intf->cur_altsetting;
-       control_out_endpoint = interface->desc.bInterfaceNumber;
-
-       /* find the endpoints that we need */
-       for (i = 0; i < interface->desc.bNumEndpoints; ++i) {
-               endpoint = &interface->endpoint[i].desc;
-
-               if ((endpoint->bEndpointAddress & 0x80) &&
-                   ((endpoint->bmAttributes & 3) == 0x02)) {
-                       /* we found a bulk in endpoint */
-                       dbg("found bulk in");
-                       bulk_in_endpoint[num_bulk_in] = endpoint;
-                       ++num_bulk_in;
-               }
-
-               if (((endpoint->bEndpointAddress & 0x80) == 0x00) &&
-                   ((endpoint->bmAttributes & 3) == 0x02)) {
-                       /* we found a bulk out endpoint */
-                       dbg("found bulk out");
-                       bulk_out_endpoint[num_bulk_out] = endpoint;
-                       ++num_bulk_out;
-               }
-
-               if ((endpoint->bEndpointAddress & 0x80) &&
-                   ((endpoint->bmAttributes & 3) == 0x03)) {
-                       /* we found a interrupt in endpoint */
-                       dbg("found interrupt in");
-                       interrupt_in_endpoint[num_interrupt_in] = endpoint;
-                       ++num_interrupt_in;
-               }
-       }
-
-       /* according to the spec, we can only have 1 bulk_in, 1 bulk_out, and 1 interrupt_in endpoints */
-       if ((num_bulk_in != 1) ||
-           (num_bulk_out != 1) ||
-           (num_interrupt_in != 1)) {
-               dbg ("%s - improper number of endpoints. Bluetooth driver not bound.", __FUNCTION__);
-               return -EIO;
-       }
-
-       info("USB Bluetooth converter detected");
-
-       for (minor = 0; minor < BLUETOOTH_TTY_MINORS && bluetooth_table[minor]; ++minor)
-               ;
-       if (bluetooth_table[minor]) {
-               err("No more free Bluetooth devices");
-               return -ENODEV;
-       }
-
-       if (!(bluetooth = kmalloc(sizeof(struct usb_bluetooth), GFP_KERNEL))) {
-               err("Out of memory");
-               return -ENOMEM;
-       }
-
-       memset(bluetooth, 0, sizeof(struct usb_bluetooth));
-
-       bluetooth->magic = USB_BLUETOOTH_MAGIC;
-       bluetooth->dev = dev;
-       bluetooth->minor = minor;
-       INIT_WORK(&bluetooth->work, bluetooth_softint, bluetooth);
-       init_MUTEX(&bluetooth->lock);
-
-       /* record the interface number for the control out */
-       bluetooth->control_out_bInterfaceNum = control_out_endpoint;
-       
-       /* create our control out urb pool */ 
-       for (i = 0; i < NUM_CONTROL_URBS; ++i) {
-               struct urb  *urb = usb_alloc_urb(0, GFP_KERNEL);
-               if (urb == NULL) {
-                       err("No free urbs available");
-                       goto probe_error;
-               }
-               urb->transfer_buffer = NULL;
-               bluetooth->control_urb_pool[i] = urb;
-       }
-
-       /* set up the endpoint information */
-       endpoint = bulk_in_endpoint[0];
-       bluetooth->read_urb = usb_alloc_urb (0, GFP_KERNEL);
-       if (!bluetooth->read_urb) {
-               err("No free urbs available");
-               goto probe_error;
-       }
-       bluetooth->bulk_in_buffer_size = buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
-       bluetooth->bulk_in_endpointAddress = endpoint->bEndpointAddress;
-       bluetooth->bulk_in_buffer = kmalloc (buffer_size, GFP_KERNEL);
-       if (!bluetooth->bulk_in_buffer) {
-               err("Couldn't allocate bulk_in_buffer");
-               goto probe_error;
-       }
-       usb_fill_bulk_urb(bluetooth->read_urb, dev, usb_rcvbulkpipe(dev, endpoint->bEndpointAddress),
-                     bluetooth->bulk_in_buffer, buffer_size, bluetooth_read_bulk_callback, bluetooth);
-
-       endpoint = bulk_out_endpoint[0];
-       bluetooth->bulk_out_endpointAddress = endpoint->bEndpointAddress;
-       bluetooth->bulk_out_buffer_size = le16_to_cpu(endpoint->wMaxPacketSize) * 2;
-
-       endpoint = interrupt_in_endpoint[0];
-       bluetooth->interrupt_in_urb = usb_alloc_urb(0, GFP_KERNEL);
-       if (!bluetooth->interrupt_in_urb) {
-               err("No free urbs available");
-               goto probe_error;
-       }
-       bluetooth->interrupt_in_buffer_size = buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
-       bluetooth->interrupt_in_endpointAddress = endpoint->bEndpointAddress;
-       bluetooth->interrupt_in_interval = endpoint->bInterval;
-       bluetooth->interrupt_in_buffer = kmalloc (buffer_size, GFP_KERNEL);
-       if (!bluetooth->interrupt_in_buffer) {
-               err("Couldn't allocate interrupt_in_buffer");
-               goto probe_error;
-       }
-       usb_fill_int_urb(bluetooth->interrupt_in_urb, dev, usb_rcvintpipe(dev, endpoint->bEndpointAddress),
-                    bluetooth->interrupt_in_buffer, buffer_size, bluetooth_int_callback,
-                    bluetooth, endpoint->bInterval);
-
-       /* initialize the devfs nodes for this device and let the user know what bluetooths we are bound to */
-       tty_register_device (bluetooth_tty_driver, minor, &intf->dev);
-       info("Bluetooth converter now attached to ttyUB%d (or usb/ttub/%d for devfs)", minor, minor);
-
-       bluetooth_table[minor] = bluetooth;
-
-       /* success */
-       usb_set_intfdata (intf, bluetooth);
-       return 0;
-
-probe_error:
-       if (bluetooth->read_urb)
-               usb_free_urb (bluetooth->read_urb);
-       if (bluetooth->bulk_in_buffer)
-               kfree (bluetooth->bulk_in_buffer);
-       if (bluetooth->interrupt_in_urb)
-               usb_free_urb (bluetooth->interrupt_in_urb);
-       if (bluetooth->interrupt_in_buffer)
-               kfree (bluetooth->interrupt_in_buffer);
-       for (i = 0; i < NUM_CONTROL_URBS; ++i) 
-               if (bluetooth->control_urb_pool[i]) {
-                       if (bluetooth->control_urb_pool[i]->transfer_buffer)
-                               kfree (bluetooth->control_urb_pool[i]->transfer_buffer);
-                       usb_free_urb (bluetooth->control_urb_pool[i]);
-               }
-
-       bluetooth_table[minor] = NULL;
-
-       /* free up any memory that we allocated */
-       kfree (bluetooth);
-       return -EIO;
-}
-
-
-static void usb_bluetooth_disconnect(struct usb_interface *intf)
-{
-       struct usb_bluetooth *bluetooth = usb_get_intfdata (intf);
-       int i;
-
-       usb_set_intfdata (intf, NULL);
-       if (bluetooth) {
-               if ((bluetooth->open_count) && (bluetooth->tty))
-                       tty_hangup(bluetooth->tty);
-
-               bluetooth->open_count = 0;
-
-               if (bluetooth->read_urb) {
-                       usb_kill_urb (bluetooth->read_urb);
-                       usb_free_urb (bluetooth->read_urb);
-               }
-               if (bluetooth->bulk_in_buffer)
-                       kfree (bluetooth->bulk_in_buffer);
-
-               if (bluetooth->interrupt_in_urb) {
-                       usb_kill_urb (bluetooth->interrupt_in_urb);
-                       usb_free_urb (bluetooth->interrupt_in_urb);
-               }
-               if (bluetooth->interrupt_in_buffer)
-                       kfree (bluetooth->interrupt_in_buffer);
-
-               tty_unregister_device (bluetooth_tty_driver, bluetooth->minor);
-
-               for (i = 0; i < NUM_CONTROL_URBS; ++i) {
-                       if (bluetooth->control_urb_pool[i]) {
-                               usb_kill_urb (bluetooth->control_urb_pool[i]);
-                               if (bluetooth->control_urb_pool[i]->transfer_buffer)
-                                       kfree (bluetooth->control_urb_pool[i]->transfer_buffer);
-                               usb_free_urb (bluetooth->control_urb_pool[i]);
-                       }
-               }
-               
-               info("Bluetooth converter now disconnected from ttyUB%d", bluetooth->minor);
-
-               bluetooth_table[bluetooth->minor] = NULL;
-
-               /* free up any memory that we allocated */
-               kfree (bluetooth);
-       } else {
-               info("device disconnected");
-       }
-}
-
-static struct tty_operations bluetooth_ops = {
-       .open =                 bluetooth_open,
-       .close =                bluetooth_close,
-       .write =                bluetooth_write,
-       .write_room =           bluetooth_write_room,
-       .ioctl =                bluetooth_ioctl,
-       .set_termios =          bluetooth_set_termios,
-       .throttle =             bluetooth_throttle,
-       .unthrottle =           bluetooth_unthrottle,
-       .chars_in_buffer =      bluetooth_chars_in_buffer,
-};
-
-static int usb_bluetooth_init(void)
-{
-       int i;
-       int result;
-
-       /* Initialize our global data */
-       for (i = 0; i < BLUETOOTH_TTY_MINORS; ++i) {
-               bluetooth_table[i] = NULL;
-       }
-
-       info ("USB Bluetooth support registered");
-
-       bluetooth_tty_driver = alloc_tty_driver(BLUETOOTH_TTY_MINORS);
-       if (!bluetooth_tty_driver)
-               return -ENOMEM;
-
-       bluetooth_tty_driver->owner = THIS_MODULE;
-       bluetooth_tty_driver->driver_name = "usb-bluetooth";
-       bluetooth_tty_driver->name = "ttyUB";
-       bluetooth_tty_driver->devfs_name = "usb/ttub/";
-       bluetooth_tty_driver->major = BLUETOOTH_TTY_MAJOR;
-       bluetooth_tty_driver->minor_start = 0;
-       bluetooth_tty_driver->type = TTY_DRIVER_TYPE_SERIAL;
-       bluetooth_tty_driver->subtype = SERIAL_TYPE_NORMAL;
-       bluetooth_tty_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_NO_DEVFS;
-       bluetooth_tty_driver->init_termios = tty_std_termios;
-       bluetooth_tty_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
-       tty_set_operations(bluetooth_tty_driver, &bluetooth_ops);
-       if (tty_register_driver (bluetooth_tty_driver)) {
-               err("%s - failed to register tty driver", __FUNCTION__);
-               put_tty_driver(bluetooth_tty_driver);
-               return -1;
-       }
-
-       /* register the USB driver */
-       result = usb_register(&usb_bluetooth_driver);
-       if (result < 0) {
-               tty_unregister_driver(bluetooth_tty_driver);
-               put_tty_driver(bluetooth_tty_driver);
-               err("usb_register failed for the USB bluetooth driver. Error number %d", result);
-               return -1;
-       }
-
-       info(DRIVER_DESC " " DRIVER_VERSION);
-
-       return 0;
-}
-
-
-static void usb_bluetooth_exit(void)
-{
-       usb_deregister(&usb_bluetooth_driver);
-       tty_unregister_driver(bluetooth_tty_driver);
-       put_tty_driver(bluetooth_tty_driver);
-}
-
-
-module_init(usb_bluetooth_init);
-module_exit(usb_bluetooth_exit);
-
-/* Module information */
-MODULE_AUTHOR( DRIVER_AUTHOR );
-MODULE_DESCRIPTION( DRIVER_DESC );
-MODULE_LICENSE("GPL");
-
index 16ecad3..1b47514 100644 (file)
@@ -827,11 +827,10 @@ skip_normal_probe:
                return -ENODEV;
        }
 
-       if (!(acm = kmalloc(sizeof(struct acm), GFP_KERNEL))) {
-               dev_dbg(&intf->dev, "out of memory (acm kmalloc)\n");
+       if (!(acm = kzalloc(sizeof(struct acm), GFP_KERNEL))) {
+               dev_dbg(&intf->dev, "out of memory (acm kzalloc)\n");
                goto alloc_fail;
        }
-       memset(acm, 0, sizeof(struct acm));
 
        ctrlsize = le16_to_cpu(epctrl->wMaxPacketSize);
        readsize = le16_to_cpu(epread->wMaxPacketSize);
index e195709..357e753 100644 (file)
@@ -844,9 +844,8 @@ static struct file_operations usblp_fops = {
 };
 
 static struct usb_class_driver usblp_class = {
-       .name =         "usb/lp%d",
+       .name =         "lp%d",
        .fops =         &usblp_fops,
-       .mode =         S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP,
        .minor_base =   USBLP_MINOR_BASE,
 };
 
index 1a9ff61..ff03184 100644 (file)
@@ -61,14 +61,17 @@ config USB_DYNAMIC_MINORS
          If you are unsure about this, say N here.
 
 config USB_SUSPEND
-       bool "USB suspend/resume (EXPERIMENTAL)"
+       bool "USB selective suspend/resume and wakeup (EXPERIMENTAL)"
        depends on USB && PM && EXPERIMENTAL
        help
          If you say Y here, you can use driver calls or the sysfs
          "power/state" file to suspend or resume individual USB
-         peripherals.  There are many related features, such as
-         remote wakeup and driver-specific suspend processing, that
-         may not yet work as expected.
+         peripherals.
+
+         Also, USB "remote wakeup" signaling is supported, whereby some
+         USB devices (like keyboards and network adapters) can wake up
+         their parent hub.  That wakeup cascades up the USB tree, and
+         could wake the system from states like suspend-to-RAM.
 
          If you are unsure about this, say N here.
 
index d5503cf..dd1c4d2 100644 (file)
@@ -3,7 +3,7 @@
 #
 
 usbcore-objs   := usb.o hub.o hcd.o urb.o message.o \
-                       config.o file.o buffer.o sysfs.o devio.o
+                       config.o file.o buffer.o sysfs.o devio.o notify.o
 
 ifeq ($(CONFIG_PCI),y)
        usbcore-objs    += hcd-pci.o
index 99595e0..9930195 100644 (file)
@@ -112,8 +112,12 @@ void usb_release_interface_cache(struct kref *ref)
        struct usb_interface_cache *intfc = ref_to_usb_interface_cache(ref);
        int j;
 
-       for (j = 0; j < intfc->num_altsetting; j++)
-               kfree(intfc->altsetting[j].endpoint);
+       for (j = 0; j < intfc->num_altsetting; j++) {
+               struct usb_host_interface *alt = &intfc->altsetting[j];
+
+               kfree(alt->endpoint);
+               kfree(alt->string);
+       }
        kfree(intfc);
 }
 
@@ -188,10 +192,9 @@ static int usb_parse_interface(struct device *ddev, int cfgno,
        }
 
        len = sizeof(struct usb_host_endpoint) * num_ep;
-       alt->endpoint = kmalloc(len, GFP_KERNEL);
+       alt->endpoint = kzalloc(len, GFP_KERNEL);
        if (!alt->endpoint)
                return -ENOMEM;
-       memset(alt->endpoint, 0, len);
 
        /* Parse all the endpoint descriptors */
        n = 0;
@@ -353,10 +356,9 @@ static int usb_parse_configuration(struct device *ddev, int cfgidx,
                }
 
                len = sizeof(*intfc) + sizeof(struct usb_host_interface) * j;
-               config->intf_cache[i] = intfc = kmalloc(len, GFP_KERNEL);
+               config->intf_cache[i] = intfc = kzalloc(len, GFP_KERNEL);
                if (!intfc)
                        return -ENOMEM;
-               memset(intfc, 0, len);
                kref_init(&intfc->ref);
        }
 
@@ -422,8 +424,6 @@ void usb_destroy_configuration(struct usb_device *dev)
                struct usb_host_config *cf = &dev->config[c];
 
                kfree(cf->string);
-               cf->string = NULL;
-
                for (i = 0; i < cf->desc.bNumInterfaces; i++) {
                        if (cf->intf_cache[i])
                                kref_put(&cf->intf_cache[i]->ref, 
@@ -459,16 +459,14 @@ int usb_get_configuration(struct usb_device *dev)
        }
 
        length = ncfg * sizeof(struct usb_host_config);
-       dev->config = kmalloc(length, GFP_KERNEL);
+       dev->config = kzalloc(length, GFP_KERNEL);
        if (!dev->config)
                goto err2;
-       memset(dev->config, 0, length);
 
        length = ncfg * sizeof(char *);
-       dev->rawdescriptors = kmalloc(length, GFP_KERNEL);
+       dev->rawdescriptors = kzalloc(length, GFP_KERNEL);
        if (!dev->rawdescriptors)
                goto err2;
-       memset(dev->rawdescriptors, 0, length);
 
        buffer = kmalloc(USB_DT_CONFIG_SIZE, GFP_KERNEL);
        if (!buffer)
index befe0c7..942cd43 100644 (file)
@@ -46,6 +46,7 @@
 #include <linux/usb.h>
 #include <linux/usbdevice_fs.h>
 #include <linux/cdev.h>
+#include <linux/notifier.h>
 #include <asm/uaccess.h>
 #include <asm/byteorder.h>
 #include <linux/moduleparam.h>
@@ -209,10 +210,10 @@ err:
 static struct async *alloc_async(unsigned int numisoframes)
 {
         unsigned int assize = sizeof(struct async) + numisoframes * sizeof(struct usb_iso_packet_descriptor);
-        struct async *as = kmalloc(assize, GFP_KERNEL);
+        struct async *as = kzalloc(assize, GFP_KERNEL);
+
         if (!as)
                 return NULL;
-        memset(as, 0, assize);
        as->urb = usb_alloc_urb(numisoframes, GFP_KERNEL);
        if (!as->urb) {
                kfree(as);
@@ -279,6 +280,28 @@ static inline struct async *async_getpending(struct dev_state *ps, void __user *
         return NULL;
 }
 
+static void snoop_urb(struct urb *urb, void __user *userurb)
+{
+       int j;
+       unsigned char *data = urb->transfer_buffer;
+
+       if (!usbfs_snoop)
+               return;
+
+       if (urb->pipe & USB_DIR_IN)
+               dev_info(&urb->dev->dev, "direction=IN\n");
+       else
+               dev_info(&urb->dev->dev, "direction=OUT\n");
+       dev_info(&urb->dev->dev, "userurb=%p\n", userurb);
+       dev_info(&urb->dev->dev, "transfer_buffer_length=%d\n",
+                urb->transfer_buffer_length);
+       dev_info(&urb->dev->dev, "actual_length=%d\n", urb->actual_length);
+       dev_info(&urb->dev->dev, "data: ");
+       for (j = 0; j < urb->transfer_buffer_length; ++j)
+               printk ("%02x ", data[j]);
+       printk("\n");
+}
+
 static void async_completed(struct urb *urb, struct pt_regs *regs)
 {
         struct async *as = (struct async *)urb->context;
@@ -296,7 +319,9 @@ static void async_completed(struct urb *urb, struct pt_regs *regs)
                kill_proc_info_as_uid(as->signr, &sinfo, as->pid, as->uid, 
                                      as->euid);
        }
-        wake_up(&ps->wait);
+       snoop(&urb->dev->dev, "urb complete\n");
+       snoop_urb(urb, as->userurb);
+       wake_up(&ps->wait);
 }
 
 static void destroy_async (struct dev_state *ps, struct list_head *list)
@@ -493,6 +518,23 @@ static int check_ctrlrecip(struct dev_state *ps, unsigned int requesttype, unsig
        return ret;
 }
 
+static struct usb_device *usbdev_lookup_minor(int minor)
+{
+       struct class_device *class_dev;
+       struct usb_device *dev = NULL;
+
+       down(&usb_device_class->sem);
+       list_for_each_entry(class_dev, &usb_device_class->children, node) {
+               if (class_dev->devt == MKDEV(USB_DEVICE_MAJOR, minor)) {
+                       dev = class_dev->class_data;
+                       break;
+               }
+       }
+       up(&usb_device_class->sem);
+
+       return dev;
+};
+
 /*
  * file operations
  */
@@ -601,7 +643,7 @@ static int proc_control(struct dev_state *ps, void __user *arg)
                        if (usbfs_snoop) {
                                dev_info(&dev->dev, "control read: data ");
                                for (j = 0; j < i; ++j)
-                                       printk ("%02x ", (unsigned char)(tbuf)[j]);
+                                       printk("%02x ", (unsigned char)(tbuf)[j]);
                                printk("\n");
                        }
                        if (copy_to_user(ctrl.data, tbuf, i)) {
@@ -624,7 +666,7 @@ static int proc_control(struct dev_state *ps, void __user *arg)
                if (usbfs_snoop) {
                        dev_info(&dev->dev, "control write: data: ");
                        for (j = 0; j < ctrl.wLength; ++j)
-                               printk ("%02x ", (unsigned char)(tbuf)[j]);
+                               printk("%02x ", (unsigned char)(tbuf)[j]);
                        printk("\n");
                }
                usb_unlock_device(dev);
@@ -649,7 +691,7 @@ static int proc_bulk(struct dev_state *ps, void __user *arg)
        unsigned int tmo, len1, pipe;
        int len2;
        unsigned char *tbuf;
-       int i, ret;
+       int i, j, ret;
 
        if (copy_from_user(&bulk, arg, sizeof(bulk)))
                return -EFAULT;
@@ -674,10 +716,18 @@ static int proc_bulk(struct dev_state *ps, void __user *arg)
                        kfree(tbuf);
                        return -EINVAL;
                }
+               snoop(&dev->dev, "bulk read: len=0x%02x timeout=%04d\n",
+                       bulk.len, bulk.timeout);
                usb_unlock_device(dev);
                i = usb_bulk_msg(dev, pipe, tbuf, len1, &len2, tmo);
                usb_lock_device(dev);
                if (!i && len2) {
+                       if (usbfs_snoop) {
+                               dev_info(&dev->dev, "bulk read: data ");
+                               for (j = 0; j < len2; ++j)
+                                       printk("%02x ", (unsigned char)(tbuf)[j]);
+                               printk("\n");
+                       }
                        if (copy_to_user(bulk.data, tbuf, len2)) {
                                kfree(tbuf);
                                return -EFAULT;
@@ -690,6 +740,14 @@ static int proc_bulk(struct dev_state *ps, void __user *arg)
                                return -EFAULT;
                        }
                }
+               snoop(&dev->dev, "bulk write: len=0x%02x timeout=%04d\n",
+                       bulk.len, bulk.timeout);
+               if (usbfs_snoop) {
+                       dev_info(&dev->dev, "bulk write: data: ");
+                       for (j = 0; j < len1; ++j)
+                               printk("%02x ", (unsigned char)(tbuf)[j]);
+                       printk("\n");
+               }
                usb_unlock_device(dev);
                i = usb_bulk_msg(dev, pipe, tbuf, len1, &len2, tmo);
                usb_lock_device(dev);
@@ -835,7 +893,6 @@ static int proc_setconfig(struct dev_state *ps, void __user *arg)
        return status;
 }
 
-
 static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
                             struct usbdevfs_iso_packet_desc __user *iso_frame_desc,
                             void __user *arg)
@@ -896,6 +953,7 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
                        kfree(dr);
                        return -EFAULT;
                }
+               snoop(&ps->dev->dev, "control urb\n");
                break;
 
        case USBDEVFS_URB_TYPE_BULK:
@@ -910,6 +968,7 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
                        return -EINVAL;
                if (!access_ok((uurb->endpoint & USB_DIR_IN) ? VERIFY_WRITE : VERIFY_READ, uurb->buffer, uurb->buffer_length))
                        return -EFAULT;
+               snoop(&ps->dev->dev, "bulk urb\n");
                break;
 
        case USBDEVFS_URB_TYPE_ISO:
@@ -939,6 +998,7 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
                        return -EINVAL;
                }
                uurb->buffer_length = totlen;
+               snoop(&ps->dev->dev, "iso urb\n");
                break;
 
        case USBDEVFS_URB_TYPE_INTERRUPT:
@@ -954,6 +1014,7 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
                        return -EINVAL;
                if (!access_ok((uurb->endpoint & USB_DIR_IN) ? VERIFY_WRITE : VERIFY_READ, uurb->buffer, uurb->buffer_length))
                        return -EFAULT;
+               snoop(&ps->dev->dev, "interrupt urb\n");
                break;
 
        default:
@@ -1003,6 +1064,8 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
                        return -EFAULT;
                }
        }
+       snoop(&as->urb->dev->dev, "submit urb\n");
+       snoop_urb(as->urb, as->userurb);
         async_newpending(as);
         if ((ret = usb_submit_urb(as->urb, GFP_KERNEL))) {
                dev_printk(KERN_DEBUG, &ps->dev->dev, "usbfs: usb_submit_urb returned %d\n", ret);
@@ -1238,23 +1301,20 @@ static int proc_releaseinterface(struct dev_state *ps, void __user *arg)
        return 0;
 }
 
-static int proc_ioctl (struct dev_state *ps, void __user *arg)
+static int proc_ioctl(struct dev_state *ps, struct usbdevfs_ioctl *ctl)
 {
-       struct usbdevfs_ioctl   ctrl;
        int                     size;
        void                    *buf = NULL;
        int                     retval = 0;
        struct usb_interface    *intf = NULL;
        struct usb_driver       *driver = NULL;
 
-       /* get input parameters and alloc buffer */
-       if (copy_from_user(&ctrl, arg, sizeof (ctrl)))
-               return -EFAULT;
-       if ((size = _IOC_SIZE (ctrl.ioctl_code)) > 0) {
+       /* alloc buffer */
+       if ((size = _IOC_SIZE (ctl->ioctl_code)) > 0) {
                if ((buf = kmalloc (size, GFP_KERNEL)) == NULL)
                        return -ENOMEM;
-               if ((_IOC_DIR(ctrl.ioctl_code) & _IOC_WRITE)) {
-                       if (copy_from_user (buf, ctrl.data, size)) {
+               if ((_IOC_DIR(ctl->ioctl_code) & _IOC_WRITE)) {
+                       if (copy_from_user (buf, ctl->data, size)) {
                                kfree(buf);
                                return -EFAULT;
                        }
@@ -1270,9 +1330,9 @@ static int proc_ioctl (struct dev_state *ps, void __user *arg)
 
        if (ps->dev->state != USB_STATE_CONFIGURED)
                retval = -EHOSTUNREACH;
-       else if (!(intf = usb_ifnum_to_if (ps->dev, ctrl.ifno)))
+       else if (!(intf = usb_ifnum_to_if (ps->dev, ctl->ifno)))
                retval = -EINVAL;
-       else switch (ctrl.ioctl_code) {
+       else switch (ctl->ioctl_code) {
 
        /* disconnect kernel driver from interface */
        case USBDEVFS_DISCONNECT:
@@ -1304,7 +1364,7 @@ static int proc_ioctl (struct dev_state *ps, void __user *arg)
                if (driver == NULL || driver->ioctl == NULL) {
                        retval = -ENOTTY;
                } else {
-                       retval = driver->ioctl (intf, ctrl.ioctl_code, buf);
+                       retval = driver->ioctl (intf, ctl->ioctl_code, buf);
                        if (retval == -ENOIOCTLCMD)
                                retval = -ENOTTY;
                }
@@ -1313,15 +1373,42 @@ static int proc_ioctl (struct dev_state *ps, void __user *arg)
 
        /* cleanup and return */
        if (retval >= 0
-                       && (_IOC_DIR (ctrl.ioctl_code) & _IOC_READ) != 0
+                       && (_IOC_DIR (ctl->ioctl_code) & _IOC_READ) != 0
                        && size > 0
-                       && copy_to_user (ctrl.data, buf, size) != 0)
+                       && copy_to_user (ctl->data, buf, size) != 0)
                retval = -EFAULT;
 
        kfree(buf);
        return retval;
 }
 
+static int proc_ioctl_default(struct dev_state *ps, void __user *arg)
+{
+       struct usbdevfs_ioctl   ctrl;
+
+       if (copy_from_user(&ctrl, arg, sizeof (ctrl)))
+               return -EFAULT;
+       return proc_ioctl(ps, &ctrl);
+}
+
+#ifdef CONFIG_COMPAT
+static int proc_ioctl_compat(struct dev_state *ps, void __user *arg)
+{
+       struct usbdevfs_ioctl32 __user *uioc;
+       struct usbdevfs_ioctl ctrl;
+       u32 udata;
+
+       uioc = compat_ptr(arg);
+       if (get_user(ctrl.ifno, &uioc->ifno) ||
+           get_user(ctrl.ioctl_code, &uioc->ioctl_code) ||
+           __get_user(udata, &uioc->data))
+               return -EFAULT;
+       ctrl.data = compat_ptr(udata);
+
+       return proc_ioctl(ps, &ctrl);
+}
+#endif
+
 /*
  * NOTE:  All requests here that have interface numbers as parameters
  * are assuming that somehow the configuration has been prevented from
@@ -1422,6 +1509,10 @@ static int usbdev_ioctl(struct inode *inode, struct file *file, unsigned int cmd
                ret = proc_reapurbnonblock_compat(ps, p);
                break;
 
+       case USBDEVFS_IOCTL32:
+               snoop(&dev->dev, "%s: IOCTL\n", __FUNCTION__);
+               ret = proc_ioctl_compat(ps, p);
+               break;
 #endif
 
        case USBDEVFS_DISCARDURB:
@@ -1456,7 +1547,7 @@ static int usbdev_ioctl(struct inode *inode, struct file *file, unsigned int cmd
 
        case USBDEVFS_IOCTL:
                snoop(&dev->dev, "%s: IOCTL\n", __FUNCTION__);
-               ret = proc_ioctl(ps, p);
+               ret = proc_ioctl_default(ps, p);
                break;
        }
        usb_unlock_device(dev);
@@ -1488,24 +1579,7 @@ struct file_operations usbfs_device_file_operations = {
        .release =      usbdev_release,
 };
 
-struct usb_device *usbdev_lookup_minor(int minor)
-{
-       struct class_device *class_dev;
-       struct usb_device *dev = NULL;
-
-       down(&usb_device_class->sem);
-       list_for_each_entry(class_dev, &usb_device_class->children, node) {
-               if (class_dev->devt == MKDEV(USB_DEVICE_MAJOR, minor)) {
-                       dev = class_dev->class_data;
-                       break;
-               }
-       }
-       up(&usb_device_class->sem);
-
-       return dev;
-};
-
-void usbdev_add(struct usb_device *dev)
+static void usbdev_add(struct usb_device *dev)
 {
        int minor = ((dev->bus->busnum-1) * 128) + (dev->devnum-1);
 
@@ -1516,11 +1590,29 @@ void usbdev_add(struct usb_device *dev)
        dev->class_dev->class_data = dev;
 }
 
-void usbdev_remove(struct usb_device *dev)
+static void usbdev_remove(struct usb_device *dev)
 {
        class_device_unregister(dev->class_dev);
 }
 
+static int usbdev_notify(struct notifier_block *self, unsigned long action,
+                        void *dev)
+{
+       switch (action) {
+       case USB_DEVICE_ADD:
+               usbdev_add(dev);
+               break;
+       case USB_DEVICE_REMOVE:
+               usbdev_remove(dev);
+               break;
+       }
+       return NOTIFY_OK;
+}
+
+static struct notifier_block usbdev_nb = {
+       .notifier_call =        usbdev_notify,
+};
+
 static struct cdev usb_device_cdev = {
        .kobj   = {.name = "usb_device", },
        .owner  = THIS_MODULE,
@@ -1540,24 +1632,32 @@ int __init usbdev_init(void)
        retval = cdev_add(&usb_device_cdev, USB_DEVICE_DEV, USB_DEVICE_MAX);
        if (retval) {
                err("unable to get usb_device major %d", USB_DEVICE_MAJOR);
-               unregister_chrdev_region(USB_DEVICE_DEV, USB_DEVICE_MAX);
-               goto out;
+               goto error_cdev;
        }
        usb_device_class = class_create(THIS_MODULE, "usb_device");
        if (IS_ERR(usb_device_class)) {
                err("unable to register usb_device class");
                retval = PTR_ERR(usb_device_class);
-               usb_device_class = NULL;
-               cdev_del(&usb_device_cdev);
-               unregister_chrdev_region(USB_DEVICE_DEV, USB_DEVICE_MAX);
+               goto error_class;
        }
 
+       usb_register_notify(&usbdev_nb);
+
 out:
        return retval;
+
+error_class:
+       usb_device_class = NULL;
+       cdev_del(&usb_device_cdev);
+
+error_cdev:
+       unregister_chrdev_region(USB_DEVICE_DEV, USB_DEVICE_MAX);
+       goto out;
 }
 
 void usbdev_cleanup(void)
 {
+       usb_unregister_notify(&usbdev_nb);
        class_destroy(usb_device_class);
        cdev_del(&usb_device_cdev);
        unregister_chrdev_region(USB_DEVICE_DEV, USB_DEVICE_MAX);
index 78cb4be..e695308 100644 (file)
@@ -17,7 +17,6 @@
 
 #include <linux/config.h>
 #include <linux/module.h>
-#include <linux/devfs_fs_kernel.h>
 #include <linux/spinlock.h>
 #include <linux/errno.h>
 
@@ -88,8 +87,6 @@ int usb_major_init(void)
                goto out;
        }
 
-       devfs_mk_dir("usb");
-
 out:
        return error;
 }
@@ -97,7 +94,6 @@ out:
 void usb_major_cleanup(void)
 {
        class_destroy(usb_class);
-       devfs_remove("usb");
        unregister_chrdev(USB_MAJOR, "usb");
 }
 
@@ -112,8 +108,7 @@ void usb_major_cleanup(void)
  * enabled, the minor number will be based on the next available free minor,
  * starting at the class_driver->minor_base.
  *
- * This function also creates the devfs file for the usb device, if devfs
- * is enabled, and creates a usb class device in the sysfs tree.
+ * This function also creates a usb class device in the sysfs tree.
  *
  * usb_deregister_dev() must be called when the driver is done with
  * the minor numbers given out by this function.
@@ -162,11 +157,8 @@ int usb_register_dev(struct usb_interface *intf,
 
        intf->minor = minor;
 
-       /* handle the devfs registration */
-       snprintf(name, BUS_ID_SIZE, class_driver->name, minor - minor_base);
-       devfs_mk_cdev(MKDEV(USB_MAJOR, minor), class_driver->mode, name);
-
        /* create a usb class device for this usb interface */
+       snprintf(name, BUS_ID_SIZE, class_driver->name, minor - minor_base);
        temp = strrchr(name, '/');
        if (temp && (temp[1] != 0x00))
                ++temp;
@@ -179,7 +171,6 @@ int usb_register_dev(struct usb_interface *intf,
                spin_lock (&minor_lock);
                usb_minors[intf->minor] = NULL;
                spin_unlock (&minor_lock);
-               devfs_remove (name);
                retval = PTR_ERR(intf->class_dev);
        }
 exit:
@@ -197,9 +188,8 @@ EXPORT_SYMBOL(usb_register_dev);
  * call to usb_register_dev() (usually when the device is disconnected
  * from the system.)
  *
- * This function also cleans up the devfs file for the usb device, if devfs
- * is enabled, and removes the usb class device from the sysfs tree.
- * 
+ * This function also removes the usb class device from the sysfs tree.
+ *
  * This should be called by all drivers that use the USB major number.
  */
 void usb_deregister_dev(struct usb_interface *intf,
@@ -222,7 +212,6 @@ void usb_deregister_dev(struct usb_interface *intf,
        spin_unlock (&minor_lock);
 
        snprintf(name, BUS_ID_SIZE, class_driver->name, intf->minor - minor_base);
-       devfs_remove (name);
        class_device_destroy(usb_class, MKDEV(USB_MAJOR, intf->minor));
        intf->class_dev = NULL;
        intf->minor = -1;
index 6385d1a..84d9e69 100644 (file)
@@ -30,6 +30,8 @@
 #include <asm/io.h>
 #include <asm/irq.h>
 #include <linux/usb.h>
+
+#include "usb.h"
 #include "hcd.h"
 
 
@@ -197,6 +199,26 @@ int usb_hcd_pci_suspend (struct pci_dev *dev, pm_message_t message)
 
        hcd = pci_get_drvdata(dev);
 
+       /* Root hub suspend should have stopped all downstream traffic,
+        * and all bus master traffic.  And done so for both the interface
+        * and the stub usb_device (which we check here).  But maybe it
+        * didn't; writing sysfs power/state files ignores such rules...
+        *
+        * We must ignore the FREEZE vs SUSPEND distinction here, because
+        * otherwise the swsusp will save (and restore) garbage state.
+        */
+       if (hcd->self.root_hub->dev.power.power_state.event == PM_EVENT_ON)
+               return -EBUSY;
+
+       if (hcd->driver->suspend) {
+               retval = hcd->driver->suspend(hcd, message);
+               if (retval) {
+                       dev_dbg (&dev->dev, "PCI pre-suspend fail, %d\n",
+                               retval);
+                       goto done;
+               }
+       }
+
        /* FIXME until the generic PM interfaces change a lot more, this
         * can't use PCI D1 and D2 states.  For example, the confusion
         * between messages and states will need to vanish, and messages
@@ -215,31 +237,13 @@ int usb_hcd_pci_suspend (struct pci_dev *dev, pm_message_t message)
         */
        has_pci_pm = pci_find_capability(dev, PCI_CAP_ID_PM);
 
-       switch (hcd->state) {
-
-       /* entry if root hub wasn't yet suspended ... from sysfs,
-        * without autosuspend, or if USB_SUSPEND isn't configured.
+       /* Downstream ports from this root hub should already be quiesced, so
+        * there will be no DMA activity.  Now we can shut down the upstream
+        * link (except maybe for PME# resume signaling) and enter some PCI
+        * low power state, if the hardware allows.
         */
-       case HC_STATE_RUNNING:
-               hcd->state = HC_STATE_QUIESCING;
-               retval = hcd->driver->suspend (hcd, message);
-               if (retval) {
-                       dev_dbg (hcd->self.controller, 
-                                       "suspend fail, retval %d\n",
-                                       retval);
-                       break;
-               }
-               hcd->state = HC_STATE_SUSPENDED;
-               /* FALLTHROUGH */
+       if (hcd->state == HC_STATE_SUSPENDED) {
 
-       /* entry with CONFIG_USB_SUSPEND, or hcds that autosuspend: the
-        * controller and/or root hub will already have been suspended,
-        * but it won't be ready for a PCI resume call.
-        *
-        * FIXME only CONFIG_USB_SUSPEND guarantees hub_suspend() will
-        * have been called, otherwise root hub timers still run ...
-        */
-       case HC_STATE_SUSPENDED:
                /* no DMA or IRQs except when HC is active */
                if (dev->current_state == PCI_D0) {
                        pci_save_state (dev);
@@ -248,7 +252,7 @@ int usb_hcd_pci_suspend (struct pci_dev *dev, pm_message_t message)
 
                if (!has_pci_pm) {
                        dev_dbg (hcd->self.controller, "--> PCI D0/legacy\n");
-                       break;
+                       goto done;
                }
 
                /* NOTE:  dev->current_state becomes nonzero only here, and
@@ -259,28 +263,29 @@ int usb_hcd_pci_suspend (struct pci_dev *dev, pm_message_t message)
                retval = pci_set_power_state (dev, PCI_D3hot);
                if (retval == 0) {
                        dev_dbg (hcd->self.controller, "--> PCI D3\n");
-                       retval = pci_enable_wake (dev, PCI_D3hot, hcd->remote_wakeup);
-                       if (retval)
-                               break;
-                       retval = pci_enable_wake (dev, PCI_D3cold, hcd->remote_wakeup);
-               } else if (retval < 0) {
+
+                       /* Ignore these return values.  We rely on pci code to
+                        * reject requests the hardware can't implement, rather
+                        * than coding the same thing.
+                        */
+                       (void) pci_enable_wake (dev, PCI_D3hot, hcd->remote_wakeup);
+                       (void) pci_enable_wake (dev, PCI_D3cold, hcd->remote_wakeup);
+               } else {
                        dev_dbg (&dev->dev, "PCI D3 suspend fail, %d\n",
                                        retval);
                        (void) usb_hcd_pci_resume (dev);
-                       break;
                }
-               break;
-       default:
+
+       } else {
                dev_dbg (hcd->self.controller, "hcd state %d; not suspended\n",
                        hcd->state);
                WARN_ON(1);
                retval = -EINVAL;
-               break;
        }
 
-       /* update power_state **ONLY** to make sysfs happier */
+done:
        if (retval == 0)
-               dev->dev.power.power_state = message;
+               dev->dev.power.power_state = PMSG_SUSPEND;
        return retval;
 }
 EXPORT_SYMBOL (usb_hcd_pci_suspend);
@@ -336,20 +341,9 @@ int usb_hcd_pci_resume (struct pci_dev *dev)
                                dev->current_state);
                }
 #endif
-               retval = pci_enable_wake (dev, dev->current_state, 0);
-               if (retval) {
-                       dev_err(hcd->self.controller,
-                               "can't enable_wake to %d, %d!\n",
-                               dev->current_state, retval);
-                       return retval;
-               }
-               retval = pci_enable_wake (dev, PCI_D3cold, 0);
-               if (retval) {
-                       dev_err(hcd->self.controller,
-                               "can't enable_wake to %d, %d!\n",
-                               PCI_D3cold, retval);
-                       return retval;
-               }
+               /* yes, ignore these results too... */
+               (void) pci_enable_wake (dev, dev->current_state, 0);
+               (void) pci_enable_wake (dev, PCI_D3cold, 0);
        } else {
                /* Same basic cases: clean (powered/not), dirty */
                dev_dbg(hcd->self.controller, "PCI legacy resume\n");
@@ -371,17 +365,17 @@ int usb_hcd_pci_resume (struct pci_dev *dev)
 
        dev->dev.power.power_state = PMSG_ON;
 
-       hcd->state = HC_STATE_RESUMING;
        hcd->saw_irq = 0;
 
-       retval = hcd->driver->resume (hcd);
-       if (!HC_IS_RUNNING (hcd->state)) {
-               dev_dbg (hcd->self.controller, 
-                               "resume fail, retval %d\n", retval);
-               usb_hc_died (hcd);
+       if (hcd->driver->resume) {
+               retval = hcd->driver->resume(hcd);
+               if (retval) {
+                       dev_err (hcd->self.controller,
+                               "PCI post-resume error %d!\n", retval);
+                       usb_hc_died (hcd);
+               }
        }
 
-       retval = pci_enable_device(dev);
        return retval;
 }
 EXPORT_SYMBOL (usb_hcd_pci_resume);
index 14c47a1..6c7ca5b 100644 (file)
@@ -130,7 +130,7 @@ static const u8 usb2_rh_dev_descriptor [18] = {
        0x09,       /*  __u8  bDeviceClass; HUB_CLASSCODE */
        0x00,       /*  __u8  bDeviceSubClass; */
        0x01,       /*  __u8  bDeviceProtocol; [ usb 2.0 single TT ]*/
-       0x08,       /*  __u8  bMaxPacketSize0; 8 Bytes */
+       0x40,       /*  __u8  bMaxPacketSize0; 64 Bytes */
 
        0x00, 0x00, /*  __le16 idVendor; */
        0x00, 0x00, /*  __le16 idProduct; */
@@ -153,7 +153,7 @@ static const u8 usb11_rh_dev_descriptor [18] = {
        0x09,       /*  __u8  bDeviceClass; HUB_CLASSCODE */
        0x00,       /*  __u8  bDeviceSubClass; */
        0x00,       /*  __u8  bDeviceProtocol; [ low/full speeds only ] */
-       0x08,       /*  __u8  bMaxPacketSize0; 8 Bytes */
+       0x40,       /*  __u8  bMaxPacketSize0; 64 Bytes */
 
        0x00, 0x00, /*  __le16 idVendor; */
        0x00, 0x00, /*  __le16 idProduct; */
@@ -458,22 +458,18 @@ static int rh_call_control (struct usb_hcd *hcd, struct urb *urb)
 
        default:
                /* non-generic request */
-               if (HC_IS_SUSPENDED (hcd->state))
-                       status = -EAGAIN;
-               else {
-                       switch (typeReq) {
-                       case GetHubStatus:
-                       case GetPortStatus:
-                               len = 4;
-                               break;
-                       case GetHubDescriptor:
-                               len = sizeof (struct usb_hub_descriptor);
-                               break;
-                       }
-                       status = hcd->driver->hub_control (hcd,
-                               typeReq, wValue, wIndex,
-                               tbuf, wLength);
+               switch (typeReq) {
+               case GetHubStatus:
+               case GetPortStatus:
+                       len = 4;
+                       break;
+               case GetHubDescriptor:
+                       len = sizeof (struct usb_hub_descriptor);
+                       break;
                }
+               status = hcd->driver->hub_control (hcd,
+                       typeReq, wValue, wIndex,
+                       tbuf, wLength);
                break;
 error:
                /* "protocol stall" on error */
@@ -487,7 +483,7 @@ error:
                                "CTRL: TypeReq=0x%x val=0x%x "
                                "idx=0x%x len=%d ==> %d\n",
                                typeReq, wValue, wIndex,
-                               wLength, urb->status);
+                               wLength, status);
                }
        }
        if (len) {
@@ -748,10 +744,9 @@ struct usb_bus *usb_alloc_bus (struct usb_operations *op)
 {
        struct usb_bus *bus;
 
-       bus = kmalloc (sizeof *bus, GFP_KERNEL);
+       bus = kzalloc (sizeof *bus, GFP_KERNEL);
        if (!bus)
                return NULL;
-       memset(bus, 0, sizeof(struct usb_bus));
        usb_bus_init (bus);
        bus->op = op;
        return bus;
@@ -796,8 +791,7 @@ static int usb_register_bus(struct usb_bus *bus)
        list_add (&bus->bus_list, &usb_bus_list);
        up (&usb_bus_list_lock);
 
-       usbfs_add_bus (bus);
-       usbmon_notify_bus_add (bus);
+       usb_notify_add_bus(bus);
 
        dev_info (bus->controller, "new USB bus registered, assigned bus number %d\n", bus->busnum);
        return 0;
@@ -824,8 +818,7 @@ static void usb_deregister_bus (struct usb_bus *bus)
        list_del (&bus->bus_list);
        up (&usb_bus_list_lock);
 
-       usbmon_notify_bus_remove (bus);
-       usbfs_remove_bus (bus);
+       usb_notify_remove_bus(bus);
 
        clear_bit (bus->busnum, busmap.busmap);
 
@@ -1143,10 +1136,20 @@ static int hcd_submit_urb (struct urb *urb, gfp_t mem_flags)
        else switch (hcd->state) {
        case HC_STATE_RUNNING:
        case HC_STATE_RESUMING:
+doit:
                usb_get_dev (urb->dev);
                list_add_tail (&urb->urb_list, &ep->urb_list);
                status = 0;
                break;
+       case HC_STATE_SUSPENDED:
+               /* HC upstream links (register access, wakeup signaling) can work
+                * even when the downstream links (and DMA etc) are quiesced; let
+                * usbcore talk to the root hub.
+                */
+               if (hcd->self.controller->power.power_state.event == PM_EVENT_ON
+                               && urb->dev->parent == NULL)
+                       goto doit;
+               /* FALL THROUGH */
        default:
                status = -ESHUTDOWN;
                break;
@@ -1294,12 +1297,6 @@ static int hcd_unlink_urb (struct urb *urb, int status)
                goto done;
        }
 
-       /* running ~= hc unlink handshake works (irq, timer, etc)
-        * halted ~= no unlink handshake is needed
-        * suspended, resuming == should never happen
-        */
-       WARN_ON (!HC_IS_RUNNING (hcd->state) && hcd->state != HC_STATE_HALT);
-
        /* insist the urb is still queued */
        list_for_each(tmp, &ep->urb_list) {
                if (tmp == &urb->urb_list)
@@ -1431,28 +1428,92 @@ rescan:
 
 /*-------------------------------------------------------------------------*/
 
-#ifdef CONFIG_USB_SUSPEND
+#ifdef CONFIG_PM
 
-static int hcd_hub_suspend (struct usb_bus *bus)
+int hcd_bus_suspend (struct usb_bus *bus)
 {
        struct usb_hcd          *hcd;
+       int                     status;
 
        hcd = container_of (bus, struct usb_hcd, self);
-       if (hcd->driver->hub_suspend)
-               return hcd->driver->hub_suspend (hcd);
-       return 0;
+       if (!hcd->driver->bus_suspend)
+               return -ENOENT;
+       hcd->state = HC_STATE_QUIESCING;
+       status = hcd->driver->bus_suspend (hcd);
+       if (status == 0)
+               hcd->state = HC_STATE_SUSPENDED;
+       else
+               dev_dbg(&bus->root_hub->dev, "%s fail, err %d\n",
+                               "suspend", status);
+       return status;
 }
 
-static int hcd_hub_resume (struct usb_bus *bus)
+int hcd_bus_resume (struct usb_bus *bus)
 {
        struct usb_hcd          *hcd;
+       int                     status;
 
        hcd = container_of (bus, struct usb_hcd, self);
-       if (hcd->driver->hub_resume)
-               return hcd->driver->hub_resume (hcd);
-       return 0;
+       if (!hcd->driver->bus_resume)
+               return -ENOENT;
+       if (hcd->state == HC_STATE_RUNNING)
+               return 0;
+       hcd->state = HC_STATE_RESUMING;
+       status = hcd->driver->bus_resume (hcd);
+       if (status == 0)
+               hcd->state = HC_STATE_RUNNING;
+       else {
+               dev_dbg(&bus->root_hub->dev, "%s fail, err %d\n",
+                               "resume", status);
+               usb_hc_died(hcd);
+       }
+       return status;
 }
 
+/*
+ * usb_hcd_suspend_root_hub - HCD autosuspends downstream ports
+ * @hcd: host controller for this root hub
+ *
+ * This call arranges that usb_hcd_resume_root_hub() is safe to call later;
+ * that the HCD's root hub polling is deactivated; and that the root's hub
+ * driver is suspended.  HCDs may call this to autosuspend when their root
+ * hub's downstream ports are all inactive:  unpowered, disconnected,
+ * disabled, or suspended.
+ *
+ * The HCD will autoresume on device connect change detection (using SRP
+ * or a D+/D- pullup).  The HCD also autoresumes on remote wakeup signaling
+ * from any ports that are suspended (if that is enabled).  In most cases,
+ * overcurrent signaling (on powered ports) will also start autoresume.
+ *
+ * Always called with IRQs blocked.
+ */
+void usb_hcd_suspend_root_hub (struct usb_hcd *hcd)
+{
+       struct urb      *urb;
+
+       spin_lock (&hcd_root_hub_lock);
+       usb_suspend_root_hub (hcd->self.root_hub);
+
+       /* force status urb to complete/unlink while suspended */
+       if (hcd->status_urb) {
+               urb = hcd->status_urb;
+               urb->status = -ECONNRESET;
+               urb->hcpriv = NULL;
+               urb->actual_length = 0;
+
+               del_timer (&hcd->rh_timer);
+               hcd->poll_pending = 0;
+               hcd->status_urb = NULL;
+       } else
+               urb = NULL;
+       spin_unlock (&hcd_root_hub_lock);
+       hcd->state = HC_STATE_SUSPENDED;
+
+       if (urb)
+               usb_hcd_giveback_urb (hcd, urb, NULL);
+}
+EXPORT_SYMBOL_GPL(usb_hcd_suspend_root_hub);
+
 /**
  * usb_hcd_resume_root_hub - called by HCD to resume its root hub 
  * @hcd: host controller for this root hub
@@ -1460,7 +1521,7 @@ static int hcd_hub_resume (struct usb_bus *bus)
  * The USB host controller calls this function when its root hub is
  * suspended (with the remote wakeup feature enabled) and a remote
  * wakeup request is received.  It queues a request for khubd to
- * resume the root hub.
+ * resume the root hub (that is, manage its downstream ports again).
  */
 void usb_hcd_resume_root_hub (struct usb_hcd *hcd)
 {
@@ -1471,13 +1532,9 @@ void usb_hcd_resume_root_hub (struct usb_hcd *hcd)
                usb_resume_root_hub (hcd->self.root_hub);
        spin_unlock_irqrestore (&hcd_root_hub_lock, flags);
 }
+EXPORT_SYMBOL_GPL(usb_hcd_resume_root_hub);
 
-#else
-void usb_hcd_resume_root_hub (struct usb_hcd *hcd)
-{
-}
 #endif
-EXPORT_SYMBOL_GPL(usb_hcd_resume_root_hub);
 
 /*-------------------------------------------------------------------------*/
 
@@ -1530,10 +1587,6 @@ static struct usb_operations usb_hcd_operations = {
        .buffer_alloc =         hcd_buffer_alloc,
        .buffer_free =          hcd_buffer_free,
        .disable =              hcd_endpoint_disable,
-#ifdef CONFIG_USB_SUSPEND
-       .hub_suspend =          hcd_hub_suspend,
-       .hub_resume =           hcd_hub_resume,
-#endif
 };
 
 /*-------------------------------------------------------------------------*/
index 1f1ed62..24a62a2 100644 (file)
@@ -154,10 +154,6 @@ struct usb_operations {
 
        void (*disable)(struct usb_device *udev,
                        struct usb_host_endpoint *ep);
-
-       /* global suspend/resume of bus */
-       int (*hub_suspend)(struct usb_bus *);
-       int (*hub_resume)(struct usb_bus *);
 };
 
 /* each driver provides one of these, and hardware init support */
@@ -182,12 +178,12 @@ struct hc_driver {
        int     (*start) (struct usb_hcd *hcd);
 
        /* NOTE:  these suspend/resume calls relate to the HC as
-        * a whole, not just the root hub; they're for bus glue.
+        * a whole, not just the root hub; they're for PCI bus glue.
         */
-       /* called after all devices were suspended */
+       /* called after suspending the hub, before entering D3 etc */
        int     (*suspend) (struct usb_hcd *hcd, pm_message_t message);
 
-       /* called before any devices get resumed */
+       /* called after entering D0 (etc), before resuming the hub */
        int     (*resume) (struct usb_hcd *hcd);
 
        /* cleanly make HCD stop writing memory and doing I/O */
@@ -212,8 +208,8 @@ struct hc_driver {
        int             (*hub_control) (struct usb_hcd *hcd,
                                u16 typeReq, u16 wValue, u16 wIndex,
                                char *buf, u16 wLength);
-       int             (*hub_suspend)(struct usb_hcd *);
-       int             (*hub_resume)(struct usb_hcd *);
+       int             (*bus_suspend)(struct usb_hcd *);
+       int             (*bus_resume)(struct usb_hcd *);
        int             (*start_port_reset)(struct usb_hcd *, unsigned port_num);
        void            (*hub_irq_enable)(struct usb_hcd *);
                /* Needed only if port-change IRQs are level-triggered */
@@ -355,8 +351,6 @@ extern long usb_calc_bus_time (int speed, int is_input,
 
 extern struct usb_bus *usb_alloc_bus (struct usb_operations *);
 
-extern void usb_hcd_resume_root_hub (struct usb_hcd *hcd);
-
 extern void usb_set_device_state(struct usb_device *udev,
                enum usb_device_state new_state);
 
@@ -378,6 +372,33 @@ extern int usb_find_interface_driver (struct usb_device *dev,
 
 #define usb_endpoint_out(ep_dir)       (!((ep_dir) & USB_DIR_IN))
 
+#ifdef CONFIG_PM
+extern void usb_hcd_suspend_root_hub (struct usb_hcd *hcd);
+extern void usb_hcd_resume_root_hub (struct usb_hcd *hcd);
+extern int hcd_bus_suspend (struct usb_bus *bus);
+extern int hcd_bus_resume (struct usb_bus *bus);
+#else
+static inline void usb_hcd_suspend_root_hub(struct usb_hcd *hcd)
+{
+       return;
+}
+
+static inline void usb_hcd_resume_root_hub(struct usb_hcd *hcd)
+{
+       return;
+}
+
+static inline int hcd_bus_suspend(struct usb_bus *bus)
+{
+       return 0;
+}
+
+static inline int hcd_bus_resume (struct usb_bus *bus)
+{
+       return 0;
+}
+#endif /* CONFIG_PM */
+
 /*
  * USB device fs stuff
  */
@@ -388,23 +409,13 @@ extern int usb_find_interface_driver (struct usb_device *dev,
  * these are expected to be called from the USB core/hub thread
  * with the kernel lock held
  */
-extern void usbfs_add_bus(struct usb_bus *bus);
-extern void usbfs_remove_bus(struct usb_bus *bus);
-extern void usbfs_add_device(struct usb_device *dev);
-extern void usbfs_remove_device(struct usb_device *dev);
 extern void usbfs_update_special (void);
-
 extern int usbfs_init(void);
 extern void usbfs_cleanup(void);
 
 #else /* CONFIG_USB_DEVICEFS */
 
-static inline void usbfs_add_bus(struct usb_bus *bus) {}
-static inline void usbfs_remove_bus(struct usb_bus *bus) {}
-static inline void usbfs_add_device(struct usb_device *dev) {}
-static inline void usbfs_remove_device(struct usb_device *dev) {}
 static inline void usbfs_update_special (void) {}
-
 static inline int usbfs_init(void) { return 0; }
 static inline void usbfs_cleanup(void) { }
 
@@ -419,8 +430,6 @@ struct usb_mon_operations {
        void (*urb_submit_error)(struct usb_bus *bus, struct urb *urb, int err);
        void (*urb_complete)(struct usb_bus *bus, struct urb *urb);
        /* void (*urb_unlink)(struct usb_bus *bus, struct urb *urb); */
-       void (*bus_add)(struct usb_bus *bus);
-       void (*bus_remove)(struct usb_bus *bus);
 };
 
 extern struct usb_mon_operations *mon_ops;
@@ -443,18 +452,6 @@ static inline void usbmon_urb_complete(struct usb_bus *bus, struct urb *urb)
        if (bus->monitored)
                (*mon_ops->urb_complete)(bus, urb);
 }
-static inline void usbmon_notify_bus_add(struct usb_bus *bus)
-{
-       if (mon_ops)
-               (*mon_ops->bus_add)(bus);
-}
-
-static inline void usbmon_notify_bus_remove(struct usb_bus *bus)
-{
-       if (mon_ops)
-               (*mon_ops->bus_remove)(bus);
-}
 
 int usb_mon_register(struct usb_mon_operations *ops);
 void usb_mon_deregister(void);
@@ -465,8 +462,6 @@ static inline void usbmon_urb_submit(struct usb_bus *bus, struct urb *urb) {}
 static inline void usbmon_urb_submit_error(struct usb_bus *bus, struct urb *urb,
     int error) {}
 static inline void usbmon_urb_complete(struct usb_bus *bus, struct urb *urb) {}
-static inline void usbmon_notify_bus_add(struct usb_bus *bus) {}
-static inline void usbmon_notify_bus_remove(struct usb_bus *bus) {}
 
 #endif /* CONFIG_USB_MON */
 
index c3e2024..256d9f6 100644 (file)
@@ -436,9 +436,10 @@ static void hub_power_on(struct usb_hub *hub)
 {
        int port1;
        unsigned pgood_delay = hub->descriptor->bPwrOn2PwrGood * 2;
+       u16 wHubCharacteristics = le16_to_cpu(hub->descriptor->wHubCharacteristics);
 
        /* if hub supports power switching, enable power on each port */
-       if ((hub->descriptor->wHubCharacteristics & HUB_CHAR_LPSM) < 2) {
+       if ((wHubCharacteristics & HUB_CHAR_LPSM) < 2) {
                dev_dbg(hub->intfdev, "enabling power on all ports\n");
                for (port1 = 1; port1 <= hub->descriptor->bNbrPorts; port1++)
                        set_port_feature(hub->hdev, port1,
@@ -449,10 +450,18 @@ static void hub_power_on(struct usb_hub *hub)
        msleep(max(pgood_delay, (unsigned) 100));
 }
 
-static void hub_quiesce(struct usb_hub *hub)
+static inline void __hub_quiesce(struct usb_hub *hub)
 {
-       /* stop khubd and related activity */
+       /* (nonblocking) khubd and related activity won't re-trigger */
        hub->quiescing = 1;
+       hub->activating = 0;
+       hub->resume_root_hub = 0;
+}
+
+static void hub_quiesce(struct usb_hub *hub)
+{
+       /* (blocking) stop khubd and related activity */
+       __hub_quiesce(hub);
        usb_kill_urb(hub->urb);
        if (hub->has_indicators)
                cancel_delayed_work(&hub->leds);
@@ -466,6 +475,7 @@ static void hub_activate(struct usb_hub *hub)
 
        hub->quiescing = 0;
        hub->activating = 1;
+       hub->resume_root_hub = 0;
        status = usb_submit_urb(hub->urb, GFP_NOIO);
        if (status < 0)
                dev_err(hub->intfdev, "activate --> %d\n", status);
@@ -516,6 +526,7 @@ static int hub_configure(struct usb_hub *hub,
        struct usb_device *hdev = hub->hdev;
        struct device *hub_dev = hub->intfdev;
        u16 hubstatus, hubchange;
+       u16 wHubCharacteristics;
        unsigned int pipe;
        int maxp, ret;
        char *message;
@@ -561,9 +572,9 @@ static int hub_configure(struct usb_hub *hub,
        dev_info (hub_dev, "%d port%s detected\n", hdev->maxchild,
                (hdev->maxchild == 1) ? "" : "s");
 
-       le16_to_cpus(&hub->descriptor->wHubCharacteristics);
+       wHubCharacteristics = le16_to_cpu(hub->descriptor->wHubCharacteristics);
 
-       if (hub->descriptor->wHubCharacteristics & HUB_CHAR_COMPOUND) {
+       if (wHubCharacteristics & HUB_CHAR_COMPOUND) {
                int     i;
                char    portstr [USB_MAXCHILDREN + 1];
 
@@ -576,7 +587,7 @@ static int hub_configure(struct usb_hub *hub,
        } else
                dev_dbg(hub_dev, "standalone hub\n");
 
-       switch (hub->descriptor->wHubCharacteristics & HUB_CHAR_LPSM) {
+       switch (wHubCharacteristics & HUB_CHAR_LPSM) {
                case 0x00:
                        dev_dbg(hub_dev, "ganged power switching\n");
                        break;
@@ -589,7 +600,7 @@ static int hub_configure(struct usb_hub *hub,
                        break;
        }
 
-       switch (hub->descriptor->wHubCharacteristics & HUB_CHAR_OCPM) {
+       switch (wHubCharacteristics & HUB_CHAR_OCPM) {
                case 0x00:
                        dev_dbg(hub_dev, "global over-current protection\n");
                        break;
@@ -629,7 +640,7 @@ static int hub_configure(struct usb_hub *hub,
        }
 
        /* Note 8 FS bit times == (8 bits / 12000000 bps) ~= 666ns */
-       switch (hub->descriptor->wHubCharacteristics & HUB_CHAR_TTTT) {
+       switch (wHubCharacteristics & HUB_CHAR_TTTT) {
                case HUB_TTTT_8_BITS:
                        if (hdev->descriptor.bDeviceProtocol != 0) {
                                hub->tt.think_time = 666;
@@ -659,7 +670,7 @@ static int hub_configure(struct usb_hub *hub,
        }
 
        /* probe() zeroes hub->indicator[] */
-       if (hub->descriptor->wHubCharacteristics & HUB_CHAR_PORTIND) {
+       if (wHubCharacteristics & HUB_CHAR_PORTIND) {
                hub->has_indicators = 1;
                dev_dbg(hub_dev, "Port indicators are supported\n");
        }
@@ -704,7 +715,7 @@ static int hub_configure(struct usb_hub *hub,
                        (hubstatus & HUB_STATUS_LOCAL_POWER)
                        ? "lost (inactive)" : "good");
 
-       if ((hub->descriptor->wHubCharacteristics & HUB_CHAR_OCPM) == 0)
+       if ((wHubCharacteristics & HUB_CHAR_OCPM) == 0)
                dev_dbg(hub_dev, "%sover-current condition exists\n",
                        (hubstatus & HUB_STATUS_OVERCURRENT) ? "" : "no ");
 
@@ -854,14 +865,12 @@ descriptor_error:
        /* We found a hub */
        dev_info (&intf->dev, "USB hub found\n");
 
-       hub = kmalloc(sizeof(*hub), GFP_KERNEL);
+       hub = kzalloc(sizeof(*hub), GFP_KERNEL);
        if (!hub) {
                dev_dbg (&intf->dev, "couldn't kmalloc hub struct\n");
                return -ENOMEM;
        }
 
-       memset(hub, 0, sizeof(*hub));
-
        INIT_LIST_HEAD(&hub->event_list);
        hub->intfdev = &intf->dev;
        hub->hdev = hdev;
@@ -1117,14 +1126,14 @@ void usb_disconnect(struct usb_device **pdev)
         */
        usb_disable_device(udev, 0);
 
+       usb_notify_remove_device(udev);
+
        /* Free the device number, remove the /proc/bus/usb entry and
         * the sysfs attributes, and delete the parent's children[]
         * (or root_hub) pointer.
         */
        dev_dbg (&udev->dev, "unregistering device\n");
        release_address(udev);
-       usbfs_remove_device(udev);
-       usbdev_remove(udev);
        usb_remove_sysfs_dev_files(udev);
 
        /* Avoid races with recursively_mark_NOTATTACHED() */
@@ -1195,21 +1204,6 @@ static inline void show_string(struct usb_device *udev, char *id, char *string)
 {}
 #endif
 
-static void get_string(struct usb_device *udev, char **string, int index)
-{
-       char *buf;
-
-       if (!index)
-               return;
-       buf = kmalloc(256, GFP_KERNEL);
-       if (!buf)
-               return;
-       if (usb_string(udev, index, buf, 256) > 0)
-               *string = buf;
-       else
-               kfree(buf);
-}
-
 
 #ifdef CONFIG_USB_OTG
 #include "otg_whitelist.h"
@@ -1248,9 +1242,10 @@ int usb_new_device(struct usb_device *udev)
        }
 
        /* read the standard strings and cache them if present */
-       get_string(udev, &udev->product, udev->descriptor.iProduct);
-       get_string(udev, &udev->manufacturer, udev->descriptor.iManufacturer);
-       get_string(udev, &udev->serial, udev->descriptor.iSerialNumber);
+       udev->product = usb_cache_string(udev, udev->descriptor.iProduct);
+       udev->manufacturer = usb_cache_string(udev,
+                       udev->descriptor.iManufacturer);
+       udev->serial = usb_cache_string(udev, udev->descriptor.iSerialNumber);
 
        /* Tell the world! */
        dev_dbg(&udev->dev, "new device strings: Mfr=%d, Product=%d, "
@@ -1322,11 +1317,9 @@ int usb_new_device(struct usb_device *udev)
                 * (Includes HNP test device.)
                 */
                if (udev->bus->b_hnp_enable || udev->bus->is_b_host) {
-                       static int __usb_suspend_device (struct usb_device *,
-                                               int port1, pm_message_t state);
-                       err = __usb_suspend_device(udev,
-                                       udev->bus->otg_port,
-                                       PMSG_SUSPEND);
+                       static int __usb_suspend_device(struct usb_device *,
+                                               int port1);
+                       err = __usb_suspend_device(udev, udev->bus->otg_port);
                        if (err < 0)
                                dev_dbg(&udev->dev, "HNP fail, %d\n", err);
                }
@@ -1362,10 +1355,8 @@ int usb_new_device(struct usb_device *udev)
        }
 
        /* USB device state == configured ... usable */
+       usb_notify_add_device(udev);
 
-       /* add a /proc/bus/usb entry */
-       usbdev_add(udev);
-       usbfs_add_device(udev);
        return 0;
 
 fail:
@@ -1516,7 +1507,7 @@ static void hub_port_logical_disconnect(struct usb_hub *hub, int port1)
        /* FIXME let caller ask to power down the port:
         *  - some devices won't enumerate without a VBUS power cycle
         *  - SRP saves power that way
-        *  - usb_suspend_device(dev, PMSG_SUSPEND)
+        *  - ... new call, TBD ...
         * That's easy if this hub can switch power per-port, and
         * khubd reactivates the port later (timer, SRP, etc).
         * Powerdown must be optional, because of reset/DFU.
@@ -1598,11 +1589,14 @@ static int hub_port_suspend(struct usb_hub *hub, int port1,
  * Other than re-initializing the hub (plug/unplug, except for root hubs),
  * Linux (2.6) currently has NO mechanisms to initiate that:  no khubd
  * timer, no SRP, no requests through sysfs.
+ *
+ * If CONFIG_USB_SUSPEND isn't enabled, devices only really suspend when
+ * the root hub for their bus goes into global suspend ... so we don't
+ * (falsely) update the device power state to say it suspended.
  */
-static int __usb_suspend_device (struct usb_device *udev, int port1,
-                                pm_message_t state)
+static int __usb_suspend_device (struct usb_device *udev, int port1)
 {
-       int     status;
+       int     status = 0;
 
        /* caller owns the udev device lock */
        if (port1 < 0)
@@ -1613,95 +1607,39 @@ static int __usb_suspend_device (struct usb_device *udev, int port1,
                return 0;
        }
 
-       /* suspend interface drivers; if this is a hub, it
-        * suspends the child devices
-        */
+       /* all interfaces must already be suspended */
        if (udev->actconfig) {
                int     i;
 
                for (i = 0; i < udev->actconfig->desc.bNumInterfaces; i++) {
                        struct usb_interface    *intf;
-                       struct usb_driver       *driver;
 
                        intf = udev->actconfig->interface[i];
-                       if (state.event <= intf->dev.power.power_state.event)
-                               continue;
-                       if (!intf->dev.driver)
-                               continue;
-                       driver = to_usb_driver(intf->dev.driver);
-
-                       if (driver->suspend) {
-                               status = driver->suspend(intf, state);
-                               if (intf->dev.power.power_state.event != state.event
-                                               || status)
-                                       dev_err(&intf->dev,
-                                               "suspend %d fail, code %d\n",
-                                               state.event, status);
-                       }
-
-                       /* only drivers with suspend() can ever resume();
-                        * and after power loss, even they won't.
-                        * bus_rescan_devices() can rebind drivers later.
-                        *
-                        * FIXME the PM core self-deadlocks when unbinding
-                        * drivers during suspend/resume ... everything grabs
-                        * dpm_sem (not a spinlock, ugh).  we want to unbind,
-                        * since we know every driver's probe/disconnect works
-                        * even for drivers that can't suspend.
-                        */
-                       if (!driver->suspend || state.event > PM_EVENT_FREEZE) {
-#if 1
-                               dev_warn(&intf->dev, "resume is unsafe!\n");
-#else
-                               down_write(&usb_bus_type.rwsem);
-                               device_release_driver(&intf->dev);
-                               up_write(&usb_bus_type.rwsem);
-#endif
+                       if (is_active(intf)) {
+                               dev_dbg(&intf->dev, "nyet suspended\n");
+                               return -EBUSY;
                        }
                }
        }
 
-       /*
-        * FIXME this needs port power off call paths too, to help force
-        * USB into the "generic" PM model.  At least for devices on
-        * ports that aren't using ganged switching (usually root hubs).
-        *
-        * NOTE: SRP-capable links should adopt more aggressive poweroff
-        * policies (when HNP doesn't apply) once we have mechanisms to
-        * turn power back on!  (Likely not before 2.7...)
+       /* we only change a device's upstream USB link.
+        * root hubs have no upstream USB link.
         */
-       if (state.event > PM_EVENT_FREEZE) {
-               dev_warn(&udev->dev, "no poweroff yet, suspending instead\n");
-       }
-
-       /* "global suspend" of the HC-to-USB interface (root hub), or
-        * "selective suspend" of just one hub-device link.
-        */
-       if (!udev->parent) {
-               struct usb_bus  *bus = udev->bus;
-               if (bus && bus->op->hub_suspend) {
-                       status = bus->op->hub_suspend (bus);
-                       if (status == 0) {
-                               dev_dbg(&udev->dev, "usb suspend\n");
-                               usb_set_device_state(udev,
-                                               USB_STATE_SUSPENDED);
-                       }
-               } else
-                       status = -EOPNOTSUPP;
-       } else
+       if (udev->parent)
                status = hub_port_suspend(hdev_to_hub(udev->parent), port1,
                                udev);
 
        if (status == 0)
-               udev->dev.power.power_state = state;
+               udev->dev.power.power_state = PMSG_SUSPEND;
        return status;
 }
 
-/**
+#endif
+
+/*
  * usb_suspend_device - suspend a usb device
  * @udev: device that's no longer in active use
- * @state: PMSG_SUSPEND to suspend
- * Context: must be able to sleep; device not locked
+ * Context: must be able to sleep; device not locked; pm locks held
  *
  * Suspends a USB device that isn't in active use, conserving power.
  * Devices may wake out of a suspend, if anything important happens,
@@ -1709,37 +1647,50 @@ static int __usb_suspend_device (struct usb_device *udev, int port1,
  * suspend by the host, using usb_resume_device().  It's also routine
  * to disconnect devices while they are suspended.
  *
+ * This only affects the USB hardware for a device; its interfaces
+ * (and, for hubs, child devices) must already have been suspended.
+ *
  * Suspending OTG devices may trigger HNP, if that's been enabled
  * between a pair of dual-role devices.  That will change roles, such
  * as from A-Host to A-Peripheral or from B-Host back to B-Peripheral.
  *
  * Returns 0 on success, else negative errno.
  */
-int usb_suspend_device(struct usb_device *udev, pm_message_t state)
+int usb_suspend_device(struct usb_device *udev)
 {
+#ifdef CONFIG_USB_SUSPEND
        int     port1, status;
 
        port1 = locktree(udev);
        if (port1 < 0)
                return port1;
 
-       status = __usb_suspend_device(udev, port1, state);
+       status = __usb_suspend_device(udev, port1);
        usb_unlock_device(udev);
        return status;
+#else
+       /* NOTE:  udev->state unchanged, it's not lying ... */
+       udev->dev.power.power_state = PMSG_SUSPEND;
+       return 0;
+#endif
 }
+EXPORT_SYMBOL_GPL(usb_suspend_device);
 
 /*
+ * If the USB "suspend" state is in use (rather than "global suspend"),
+ * many devices will be individually taken out of suspend state using
+ * special" resume" signaling.  These routines kick in shortly after
  * hardware resume signaling is finished, either because of selective
  * resume (by host) or remote wakeup (by device) ... now see what changed
  * in the tree that's rooted at this device.
  */
-static int finish_port_resume(struct usb_device *udev)
+static int finish_device_resume(struct usb_device *udev)
 {
        int     status;
        u16     devstatus;
 
        /* caller owns the udev device lock */
-       dev_dbg(&udev->dev, "usb resume\n");
+       dev_dbg(&udev->dev, "finish resume\n");
 
        /* usb ch9 identifies four variants of SUSPENDED, based on what
         * state the device resumes to.  Linux currently won't see the
@@ -1749,7 +1700,6 @@ static int finish_port_resume(struct usb_device *udev)
        usb_set_device_state(udev, udev->actconfig
                        ? USB_STATE_CONFIGURED
                        : USB_STATE_ADDRESS);
-       udev->dev.power.power_state = PMSG_ON;
 
        /* 10.5.4.5 says be sure devices in the tree are still there.
         * For now let's assume the device didn't go crazy on resume,
@@ -1762,9 +1712,11 @@ static int finish_port_resume(struct usb_device *udev)
                        status);
        else if (udev->actconfig) {
                unsigned        i;
+               int             (*resume)(struct device *);
 
                le16_to_cpus(&devstatus);
-               if (devstatus & (1 << USB_DEVICE_REMOTE_WAKEUP)) {
+               if (devstatus & (1 << USB_DEVICE_REMOTE_WAKEUP)
+                               && udev->parent) {
                        status = usb_control_msg(udev,
                                        usb_sndctrlpipe(udev, 0),
                                        USB_REQ_CLEAR_FEATURE,
@@ -1780,33 +1732,11 @@ static int finish_port_resume(struct usb_device *udev)
                }
 
                /* resume interface drivers; if this is a hub, it
-                * resumes the child devices
+                * may have a child resume event to deal with soon
                 */
-               for (i = 0; i < udev->actconfig->desc.bNumInterfaces; i++) {
-                       struct usb_interface    *intf;
-                       struct usb_driver       *driver;
-
-                       intf = udev->actconfig->interface[i];
-                       if (intf->dev.power.power_state.event == PM_EVENT_ON)
-                               continue;
-                       if (!intf->dev.driver) {
-                               /* FIXME maybe force to alt 0 */
-                               continue;
-                       }
-                       driver = to_usb_driver(intf->dev.driver);
-
-                       /* bus_rescan_devices() may rebind drivers */
-                       if (!driver->resume)
-                               continue;
-
-                       /* can we do better than just logging errors? */
-                       status = driver->resume(intf);
-                       if (intf->dev.power.power_state.event != PM_EVENT_ON
-                                       || status)
-                               dev_dbg(&intf->dev,
-                                       "resume fail, state %d code %d\n",
-                                       intf->dev.power.power_state.event, status);
-               }
+               resume = udev->dev.bus->resume;
+               for (i = 0; i < udev->actconfig->desc.bNumInterfaces; i++)
+                       (void) resume(&udev->actconfig->interface[i]->dev);
                status = 0;
 
        } else if (udev->devnum <= 0) {
@@ -1816,6 +1746,8 @@ static int finish_port_resume(struct usb_device *udev)
        return status;
 }
 
+#ifdef CONFIG_USB_SUSPEND
+
 static int
 hub_port_resume(struct usb_hub *hub, int port1, struct usb_device *udev)
 {
@@ -1861,7 +1793,7 @@ hub_port_resume(struct usb_hub *hub, int port1, struct usb_device *udev)
                        /* TRSMRCY = 10 msec */
                        msleep(10);
                        if (udev)
-                               status = finish_port_resume(udev);
+                               status = finish_device_resume(udev);
                }
        }
        if (status < 0)
@@ -1870,12 +1802,12 @@ hub_port_resume(struct usb_hub *hub, int port1, struct usb_device *udev)
        return status;
 }
 
-static int hub_resume (struct usb_interface *intf);
+#endif
 
-/**
+/*
  * usb_resume_device - re-activate a suspended usb device
  * @udev: device to re-activate
- * Context: must be able to sleep; device not locked
+ * Context: must be able to sleep; device not locked; pm locks held
  *
  * This will re-activate the suspended device, increasing power usage
  * while letting drivers communicate again with its endpoints.
@@ -1893,35 +1825,22 @@ int usb_resume_device(struct usb_device *udev)
        if (port1 < 0)
                return port1;
 
-       /* "global resume" of the HC-to-USB interface (root hub), or
-        * selective resume of one hub-to-device port
-        */
-       if (!udev->parent) {
-               struct usb_bus  *bus = udev->bus;
-               if (bus && bus->op->hub_resume) {
-                       status = bus->op->hub_resume (bus);
+#ifdef CONFIG_USB_SUSPEND
+       /* selective resume of one downstream hub-to-device port */
+       if (udev->parent) {
+               if (udev->state == USB_STATE_SUSPENDED) {
+                       // NOTE swsusp may bork us, device state being wrong...
+                       // NOTE this fails if parent is also suspended...
+                       status = hub_port_resume(hdev_to_hub(udev->parent),
+                                       port1, udev);
                } else
-                       status = -EOPNOTSUPP;
-               if (status == 0) {
-                       dev_dbg(&udev->dev, "usb resume\n");
-                       /* TRSMRCY = 10 msec */
-                       msleep(10);
-                       usb_set_device_state (udev, USB_STATE_CONFIGURED);
-                       udev->dev.power.power_state = PMSG_ON;
-                       status = hub_resume (udev
-                                       ->actconfig->interface[0]);
-               }
-       } else if (udev->state == USB_STATE_SUSPENDED) {
-               // NOTE this fails if parent is also suspended...
-               status = hub_port_resume(hdev_to_hub(udev->parent),
-                               port1, udev);
-       } else {
-               status = 0;
-       }
-       if (status < 0) {
+                       status = 0;
+       } else
+#endif
+               status = finish_device_resume(udev);
+       if (status < 0)
                dev_dbg(&udev->dev, "can't resume, status %d\n",
                        status);
-       }
 
        usb_unlock_device(udev);
 
@@ -1938,6 +1857,8 @@ static int remote_wakeup(struct usb_device *udev)
 {
        int     status = 0;
 
+#ifdef CONFIG_USB_SUSPEND
+
        /* don't repeat RESUME sequence if this device
         * was already woken up by some other task
         */
@@ -1946,38 +1867,52 @@ static int remote_wakeup(struct usb_device *udev)
                dev_dbg(&udev->dev, "RESUME (wakeup)\n");
                /* TRSMRCY = 10 msec */
                msleep(10);
-               status = finish_port_resume(udev);
+               status = finish_device_resume(udev);
        }
        up(&udev->serialize);
+#endif
        return status;
 }
 
-static int hub_suspend(struct usb_interface *intf, pm_message_t state)
+static int hub_suspend(struct usb_interface *intf, pm_message_t msg)
 {
        struct usb_hub          *hub = usb_get_intfdata (intf);
        struct usb_device       *hdev = hub->hdev;
        unsigned                port1;
-       int                     status;
-
-       /* stop khubd and related activity */
-       hub_quiesce(hub);
 
-       /* then suspend every port */
+       /* fail if children aren't already suspended */
        for (port1 = 1; port1 <= hdev->maxchild; port1++) {
                struct usb_device       *udev;
 
                udev = hdev->children [port1-1];
-               if (!udev)
-                       continue;
-               down(&udev->serialize);
-               status = __usb_suspend_device(udev, port1, state);
-               up(&udev->serialize);
-               if (status < 0)
-                       dev_dbg(&intf->dev, "suspend port %d --> %d\n",
-                               port1, status);
+               if (udev && (udev->dev.power.power_state.event
+                                       == PM_EVENT_ON
+#ifdef CONFIG_USB_SUSPEND
+                               || udev->state != USB_STATE_SUSPENDED
+#endif
+                               )) {
+                       dev_dbg(&intf->dev, "port %d nyet suspended\n", port1);
+                       return -EBUSY;
+               }
        }
 
-       intf->dev.power.power_state = state;
+       /* "global suspend" of the downstream HC-to-USB interface */
+       if (!hdev->parent) {
+               struct usb_bus  *bus = hdev->bus;
+               if (bus) {
+                       int     status = hcd_bus_suspend (bus);
+
+                       if (status != 0) {
+                               dev_dbg(&hdev->dev, "'global' suspend %d\n",
+                                       status);
+                               return status;
+                       }
+               } else
+                       return -EOPNOTSUPP;
+       }
+
+       /* stop khubd and related activity */
+       hub_quiesce(hub);
        return 0;
 }
 
@@ -1985,11 +1920,35 @@ static int hub_resume(struct usb_interface *intf)
 {
        struct usb_device       *hdev = interface_to_usbdev(intf);
        struct usb_hub          *hub = usb_get_intfdata (intf);
-       unsigned                port1;
        int                     status;
 
-       if (intf->dev.power.power_state.event == PM_EVENT_ON)
-               return 0;
+       /* "global resume" of the downstream HC-to-USB interface */
+       if (!hdev->parent) {
+               struct usb_bus  *bus = hdev->bus;
+               if (bus) {
+                       status = hcd_bus_resume (bus);
+                       if (status) {
+                               dev_dbg(&intf->dev, "'global' resume %d\n",
+                                       status);
+                               return status;
+                       }
+               } else
+                       return -EOPNOTSUPP;
+               if (status == 0) {
+                       /* TRSMRCY = 10 msec */
+                       msleep(10);
+               }
+       }
+
+       hub_activate(hub);
+
+       /* REVISIT:  this recursion probably shouldn't exist.  Remove
+        * this code sometime, after retesting with different root and
+        * external hubs.
+        */
+#ifdef CONFIG_USB_SUSPEND
+       {
+       unsigned                port1;
 
        for (port1 = 1; port1 <= hdev->maxchild; port1++) {
                struct usb_device       *udev;
@@ -2015,7 +1974,7 @@ static int hub_resume(struct usb_interface *intf)
                if (portstat & USB_PORT_STAT_SUSPEND)
                        status = hub_port_resume(hub, port1, udev);
                else {
-                       status = finish_port_resume(udev);
+                       status = finish_device_resume(udev);
                        if (status < 0) {
                                dev_dbg(&intf->dev, "resume port %d --> %d\n",
                                        port1, status);
@@ -2024,43 +1983,31 @@ static int hub_resume(struct usb_interface *intf)
                }
                up(&udev->serialize);
        }
-       intf->dev.power.power_state = PMSG_ON;
-
-       hub->resume_root_hub = 0;
-       hub_activate(hub);
+       }
+#endif
        return 0;
 }
 
-void usb_resume_root_hub(struct usb_device *hdev)
+void usb_suspend_root_hub(struct usb_device *hdev)
 {
        struct usb_hub *hub = hdev_to_hub(hdev);
 
-       hub->resume_root_hub = 1;
-       kick_khubd(hub);
+       /* This also makes any led blinker stop retriggering.  We're called
+        * from irq, so the blinker might still be scheduled.  Caller promises
+        * that the root hub status URB will be canceled.
+        */
+       __hub_quiesce(hub);
+       mark_quiesced(to_usb_interface(hub->intfdev));
 }
 
-#else  /* !CONFIG_USB_SUSPEND */
-
-int usb_suspend_device(struct usb_device *udev, pm_message_t state)
+void usb_resume_root_hub(struct usb_device *hdev)
 {
-       return 0;
-}
+       struct usb_hub *hub = hdev_to_hub(hdev);
 
-int usb_resume_device(struct usb_device *udev)
-{
-       return 0;
+       hub->resume_root_hub = 1;
+       kick_khubd(hub);
 }
 
-#define        hub_suspend             NULL
-#define        hub_resume              NULL
-#define        remote_wakeup(x)        0
-
-#endif /* CONFIG_USB_SUSPEND */
-
-EXPORT_SYMBOL(usb_suspend_device);
-EXPORT_SYMBOL(usb_resume_device);
-
-
 
 /* USB 2.0 spec, 7.1.7.3 / fig 7-29:
  *
@@ -2469,6 +2416,7 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,
 {
        struct usb_device *hdev = hub->hdev;
        struct device *hub_dev = hub->intfdev;
+       u16 wHubCharacteristics = le16_to_cpu(hub->descriptor->wHubCharacteristics);
        int status, i;
  
        dev_dbg (hub_dev,
@@ -2506,8 +2454,7 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,
        if (!(portstatus & USB_PORT_STAT_CONNECTION)) {
 
                /* maybe switch power back on (e.g. root hub was reset) */
-               if ((hub->descriptor->wHubCharacteristics
-                                       & HUB_CHAR_LPSM) < 2
+               if ((wHubCharacteristics & HUB_CHAR_LPSM) < 2
                                && !(portstatus & (1 << USB_PORT_FEAT_POWER)))
                        set_port_feature(hdev, port1, USB_PORT_FEAT_POWER);
  
@@ -2686,21 +2633,28 @@ static void hub_events(void)
                intf = to_usb_interface(hub->intfdev);
                hub_dev = &intf->dev;
 
-               dev_dbg(hub_dev, "state %d ports %d chg %04x evt %04x\n",
+               i = hub->resume_root_hub;
+
+               dev_dbg(hub_dev, "state %d ports %d chg %04x evt %04x%s\n",
                                hdev->state, hub->descriptor
                                        ? hub->descriptor->bNbrPorts
                                        : 0,
                                /* NOTE: expects max 15 ports... */
                                (u16) hub->change_bits[0],
-                               (u16) hub->event_bits[0]);
+                               (u16) hub->event_bits[0],
+                               i ? ", resume root" : "");
 
                usb_get_intf(intf);
-               i = hub->resume_root_hub;
                spin_unlock_irq(&hub_event_lock);
 
-               /* Is this is a root hub wanting to be resumed? */
-               if (i)
-                       usb_resume_device(hdev);
+               /* Is this is a root hub wanting to reactivate the downstream
+                * ports?  If so, be sure the interface resumes even if its
+                * stub "device" node was never suspended.
+                */
+               if (i) {
+                       dpm_runtime_resume(&hdev->dev);
+                       dpm_runtime_resume(&intf->dev);
+               }
 
                /* Lock the device, then check to see if we were
                 * disconnected while waiting for the lock to succeed. */
index e7fa9b5..bf23f89 100644 (file)
@@ -131,7 +131,7 @@ struct usb_hub_descriptor {
        __u8  bDescLength;
        __u8  bDescriptorType;
        __u8  bNbrPorts;
-       __u16 wHubCharacteristics;
+       __le16 wHubCharacteristics;
        __u8  bPwrOn2PwrGood;
        __u8  bHubContrCurrent;
                /* add 1 bit for hub status change; round to bytes */
index d07bba0..12f490f 100644 (file)
@@ -39,6 +39,7 @@
 #include <linux/usbdevice_fs.h>
 #include <linux/smp_lock.h>
 #include <linux/parser.h>
+#include <linux/notifier.h>
 #include <asm/byteorder.h>
 #include "usb.h"
 #include "hcd.h"
@@ -619,7 +620,7 @@ void usbfs_update_special (void)
        }
 }
 
-void usbfs_add_bus(struct usb_bus *bus)
+static void usbfs_add_bus(struct usb_bus *bus)
 {
        struct dentry *parent;
        char name[8];
@@ -642,12 +643,9 @@ void usbfs_add_bus(struct usb_bus *bus)
                err ("error creating usbfs bus entry");
                return;
        }
-
-       usbfs_update_special();
-       usbfs_conn_disc_event();
 }
 
-void usbfs_remove_bus(struct usb_bus *bus)
+static void usbfs_remove_bus(struct usb_bus *bus)
 {
        if (bus->usbfs_dentry) {
                fs_remove_file (bus->usbfs_dentry);
@@ -659,12 +657,9 @@ void usbfs_remove_bus(struct usb_bus *bus)
                remove_special_files();
                num_buses = 0;
        }
-
-       usbfs_update_special();
-       usbfs_conn_disc_event();
 }
 
-void usbfs_add_device(struct usb_device *dev)
+static void usbfs_add_device(struct usb_device *dev)
 {
        char name[8];
        int i;
@@ -690,12 +685,9 @@ void usbfs_add_device(struct usb_device *dev)
        }
        if (dev->usbfs_dentry->d_inode)
                dev->usbfs_dentry->d_inode->i_size = i_size;
-
-       usbfs_update_special();
-       usbfs_conn_disc_event();
 }
 
-void usbfs_remove_device(struct usb_device *dev)
+static void usbfs_remove_device(struct usb_device *dev)
 {
        struct dev_state *ds;
        struct siginfo sinfo;
@@ -716,10 +708,33 @@ void usbfs_remove_device(struct usb_device *dev)
                        kill_proc_info_as_uid(ds->discsignr, &sinfo, ds->disc_pid, ds->disc_uid, ds->disc_euid);
                }
        }
+}
+
+static int usbfs_notify(struct notifier_block *self, unsigned long action, void *dev)
+{
+       switch (action) {
+       case USB_DEVICE_ADD:
+               usbfs_add_device(dev);
+               break;
+       case USB_DEVICE_REMOVE:
+               usbfs_remove_device(dev);
+               break;
+       case USB_BUS_ADD:
+               usbfs_add_bus(dev);
+               break;
+       case USB_BUS_REMOVE:
+               usbfs_remove_bus(dev);
+       }
+
        usbfs_update_special();
        usbfs_conn_disc_event();
+       return NOTIFY_OK;
 }
 
+static struct notifier_block usbfs_nb = {
+       .notifier_call =        usbfs_notify,
+};
+
 /* --------------------------------------------------------------------- */
 
 static struct proc_dir_entry *usbdir = NULL;
@@ -732,6 +747,8 @@ int __init usbfs_init(void)
        if (retval)
                return retval;
 
+       usb_register_notify(&usbfs_nb);
+
        /* create mount point for usbfs */
        usbdir = proc_mkdir("usb", proc_bus);
 
@@ -740,6 +757,7 @@ int __init usbfs_init(void)
 
 void usbfs_cleanup(void)
 {
+       usb_unregister_notify(&usbfs_nb);
        unregister_filesystem(&usb_fs_type);
        if (usbdir)
                remove_proc_entry("usb", proc_bus);
index f9a81e8..644a3d4 100644 (file)
@@ -187,21 +187,37 @@ int usb_control_msg(struct usb_device *dev, unsigned int pipe, __u8 request, __u
  *      If a thread in your driver uses this call, make sure your disconnect()
  *      method can wait for it to complete.  Since you don't have a handle on
  *      the URB used, you can't cancel the request.
+ *
+ *     Because there is no usb_interrupt_msg() and no USBDEVFS_INTERRUPT
+ *     ioctl, users are forced to abuse this routine by using it to submit
+ *     URBs for interrupt endpoints.  We will take the liberty of creating
+ *     an interrupt URB (with the default interval) if the target is an
+ *     interrupt endpoint.
  */
 int usb_bulk_msg(struct usb_device *usb_dev, unsigned int pipe, 
                        void *data, int len, int *actual_length, int timeout)
 {
        struct urb *urb;
+       struct usb_host_endpoint *ep;
 
-       if (len < 0)
+       ep = (usb_pipein(pipe) ? usb_dev->ep_in : usb_dev->ep_out)
+                       [usb_pipeendpoint(pipe)];
+       if (!ep || len < 0)
                return -EINVAL;
 
-       urb=usb_alloc_urb(0, GFP_KERNEL);
+       urb = usb_alloc_urb(0, GFP_KERNEL);
        if (!urb)
                return -ENOMEM;
 
-       usb_fill_bulk_urb(urb, usb_dev, pipe, data, len,
-                         usb_api_blocking_completion, NULL);
+       if ((ep->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
+                       USB_ENDPOINT_XFER_INT) {
+               pipe = (pipe & ~(3 << 30)) | (PIPE_INTERRUPT << 30);
+               usb_fill_int_urb(urb, usb_dev, pipe, data, len,
+                               usb_api_blocking_completion, NULL,
+                               ep->desc.bInterval);
+       } else
+               usb_fill_bulk_urb(urb, usb_dev, pipe, data, len,
+                               usb_api_blocking_completion, NULL);
 
        return usb_start_wait_urb(urb, timeout, actual_length);
 }
@@ -771,6 +787,31 @@ int usb_string(struct usb_device *dev, int index, char *buf, size_t size)
        return err;
 }
 
+/**
+ * usb_cache_string - read a string descriptor and cache it for later use
+ * @udev: the device whose string descriptor is being read
+ * @index: the descriptor index
+ *
+ * Returns a pointer to a kmalloc'ed buffer containing the descriptor string,
+ * or NULL if the index is 0 or the string could not be read.
+ */
+char *usb_cache_string(struct usb_device *udev, int index)
+{
+       char *buf;
+       char *smallbuf = NULL;
+       int len;
+
+       if (index > 0 && (buf = kmalloc(256, GFP_KERNEL)) != NULL) {
+               if ((len = usb_string(udev, index, buf, 256)) > 0) {
+                       if ((smallbuf = kmalloc(++len, GFP_KERNEL)) == NULL)
+                               return buf;
+                       memcpy(smallbuf, buf, len);
+               }
+               kfree(buf);
+       }
+       return smallbuf;
+}
+
 /*
  * usb_get_device_descriptor - (re)reads the device descriptor (usbcore)
  * @dev: the device whose device descriptor is being updated
@@ -992,8 +1033,6 @@ void usb_disable_device(struct usb_device *dev, int skip_ep0)
                        dev_dbg (&dev->dev, "unregistering interface %s\n",
                                interface->dev.bus_id);
                        usb_remove_sysfs_intf_files(interface);
-                       kfree(interface->cur_altsetting->string);
-                       interface->cur_altsetting->string = NULL;
                        device_del (&interface->dev);
                }
 
@@ -1133,6 +1172,8 @@ int usb_set_interface(struct usb_device *dev, int interface, int alternate)
         */
 
        /* prevent submissions using previous endpoint settings */
+       if (device_is_registered(&iface->dev))
+               usb_remove_sysfs_intf_files(iface);
        usb_disable_interface(dev, iface);
 
        iface->cur_altsetting = alt;
@@ -1168,6 +1209,8 @@ int usb_set_interface(struct usb_device *dev, int interface, int alternate)
         * (Likewise, EP0 never "halts" on well designed devices.)
         */
        usb_enable_interface(dev, iface);
+       if (device_is_registered(&iface->dev))
+               usb_create_sysfs_intf_files(iface);
 
        return 0;
 }
@@ -1217,10 +1260,8 @@ int usb_reset_configuration(struct usb_device *dev)
                        USB_REQ_SET_CONFIGURATION, 0,
                        config->desc.bConfigurationValue, 0,
                        NULL, 0, USB_CTRL_SET_TIMEOUT);
-       if (retval < 0) {
-               usb_set_device_state(dev, USB_STATE_ADDRESS);
+       if (retval < 0)
                return retval;
-       }
 
        dev->toggle[0] = dev->toggle[1] = 0;
 
@@ -1229,6 +1270,8 @@ int usb_reset_configuration(struct usb_device *dev)
                struct usb_interface *intf = config->interface[i];
                struct usb_host_interface *alt;
 
+               if (device_is_registered(&intf->dev))
+                       usb_remove_sysfs_intf_files(intf);
                alt = usb_altnum_to_altsetting(intf, 0);
 
                /* No altsetting 0?  We'll assume the first altsetting.
@@ -1241,6 +1284,8 @@ int usb_reset_configuration(struct usb_device *dev)
 
                intf->cur_altsetting = alt;
                usb_enable_interface(dev, intf);
+               if (device_is_registered(&intf->dev))
+                       usb_create_sysfs_intf_files(intf);
        }
        return 0;
 }
@@ -1328,7 +1373,7 @@ int usb_set_configuration(struct usb_device *dev, int configuration)
                }
 
                for (; n < nintf; ++n) {
-                       new_interfaces[n] = kmalloc(
+                       new_interfaces[n] = kzalloc(
                                        sizeof(struct usb_interface),
                                        GFP_KERNEL);
                        if (!new_interfaces[n]) {
@@ -1369,7 +1414,6 @@ free_interfaces:
                        struct usb_host_interface *alt;
 
                        cp->interface[i] = intf = new_interfaces[i];
-                       memset(intf, 0, sizeof(*intf));
                        intfc = cp->intf_cache[i];
                        intf->altsetting = intfc->altsetting;
                        intf->num_altsetting = intfc->num_altsetting;
@@ -1393,6 +1437,7 @@ free_interfaces:
                        intf->dev.dma_mask = dev->dev.dma_mask;
                        intf->dev.release = release_interface;
                        device_initialize (&intf->dev);
+                       mark_quiesced(intf);
                        sprintf (&intf->dev.bus_id[0], "%d-%s:%d.%d",
                                 dev->bus->busnum, dev->devpath,
                                 configuration,
@@ -1400,12 +1445,9 @@ free_interfaces:
                }
                kfree(new_interfaces);
 
-               if ((cp->desc.iConfiguration) &&
-                   (cp->string == NULL)) {
-                       cp->string = kmalloc(256, GFP_KERNEL);
-                       if (cp->string)
-                               usb_string(dev, cp->desc.iConfiguration, cp->string, 256);
-               }
+               if (cp->string == NULL)
+                       cp->string = usb_cache_string(dev,
+                                       cp->desc.iConfiguration);
 
                /* Now that all the interfaces are set up, register them
                 * to trigger binding of drivers to interfaces.  probe()
@@ -1415,13 +1457,12 @@ free_interfaces:
                 */
                for (i = 0; i < nintf; ++i) {
                        struct usb_interface *intf = cp->interface[i];
-                       struct usb_interface_descriptor *desc;
+                       struct usb_host_interface *alt = intf->cur_altsetting;
 
-                       desc = &intf->altsetting [0].desc;
                        dev_dbg (&dev->dev,
                                "adding %s (config #%d, interface %d)\n",
                                intf->dev.bus_id, configuration,
-                               desc->bInterfaceNumber);
+                               alt->desc.bInterfaceNumber);
                        ret = device_add (&intf->dev);
                        if (ret != 0) {
                                dev_err(&dev->dev,
@@ -1430,13 +1471,6 @@ free_interfaces:
                                        ret);
                                continue;
                        }
-                       if ((intf->cur_altsetting->desc.iInterface) &&
-                           (intf->cur_altsetting->string == NULL)) {
-                               intf->cur_altsetting->string = kmalloc(256, GFP_KERNEL);
-                               if (intf->cur_altsetting->string)
-                                       usb_string(dev, intf->cur_altsetting->desc.iInterface,
-                                                  intf->cur_altsetting->string, 256);
-                       }
                        usb_create_sysfs_intf_files (intf);
                }
        }
diff --git a/drivers/usb/core/notify.c b/drivers/usb/core/notify.c
new file mode 100644 (file)
index 0000000..37da059
--- /dev/null
@@ -0,0 +1,120 @@
+/*
+ * All the USB notify logic
+ *
+ * (C) Copyright 2005 Greg Kroah-Hartman <gregkh@suse.de>
+ *
+ * notifier functions originally based on those in kernel/sys.c
+ * but fixed up to not be so broken.
+ *
+ */
+
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/notifier.h>
+#ifdef CONFIG_USB_DEBUG
+       #define DEBUG
+#else
+       #undef DEBUG
+#endif
+#include <linux/usb.h>
+
+#include "usb.h"
+
+
+static struct notifier_block *usb_notifier_list;
+static DECLARE_MUTEX(usb_notifier_lock);
+
+static void usb_notifier_chain_register(struct notifier_block **list,
+                                       struct notifier_block *n)
+{
+       down(&usb_notifier_lock);
+       while (*list) {
+               if (n->priority > (*list)->priority)
+                       break;
+               list = &((*list)->next);
+       }
+       n->next = *list;
+       *list = n;
+       up(&usb_notifier_lock);
+}
+
+static void usb_notifier_chain_unregister(struct notifier_block **nl,
+                                  struct notifier_block *n)
+{
+       down(&usb_notifier_lock);
+       while ((*nl)!=NULL) {
+               if ((*nl)==n) {
+                       *nl = n->next;
+                       goto exit;
+               }
+               nl=&((*nl)->next);
+       }
+exit:
+       up(&usb_notifier_lock);
+}
+
+static int usb_notifier_call_chain(struct notifier_block **n,
+                                  unsigned long val, void *v)
+{
+       int ret=NOTIFY_DONE;
+       struct notifier_block *nb = *n;
+
+       down(&usb_notifier_lock);
+       while (nb) {
+               ret = nb->notifier_call(nb,val,v);
+               if (ret&NOTIFY_STOP_MASK) {
+                       goto exit;
+               }
+               nb = nb->next;
+       }
+exit:
+       up(&usb_notifier_lock);
+       return ret;
+}
+
+/**
+ * usb_register_notify - register a notifier callback whenever a usb change happens
+ * @nb: pointer to the notifier block for the callback events.
+ *
+ * These changes are either USB devices or busses being added or removed.
+ */
+void usb_register_notify(struct notifier_block *nb)
+{
+       usb_notifier_chain_register(&usb_notifier_list, nb);
+}
+EXPORT_SYMBOL_GPL(usb_register_notify);
+
+/**
+ * usb_unregister_notify - unregister a notifier callback
+ * @nb: pointer to the notifier block for the callback events.
+ *
+ * usb_register_notifier() must have been previously called for this function
+ * to work properly.
+ */
+void usb_unregister_notify(struct notifier_block *nb)
+{
+       usb_notifier_chain_unregister(&usb_notifier_list, nb);
+}
+EXPORT_SYMBOL_GPL(usb_unregister_notify);
+
+
+void usb_notify_add_device(struct usb_device *udev)
+{
+       usb_notifier_call_chain(&usb_notifier_list, USB_DEVICE_ADD, udev);
+}
+
+void usb_notify_remove_device(struct usb_device *udev)
+{
+       usb_notifier_call_chain(&usb_notifier_list, USB_DEVICE_REMOVE, udev);
+}
+
+void usb_notify_add_bus(struct usb_bus *ubus)
+{
+       usb_notifier_call_chain(&usb_notifier_list, USB_BUS_ADD, ubus);
+}
+
+void usb_notify_remove_bus(struct usb_bus *ubus)
+{
+       usb_notifier_call_chain(&usb_notifier_list, USB_BUS_REMOVE, ubus);
+}
index 00297f1..edd83e0 100644 (file)
 
 #include "usb.h"
 
+/* endpoint stuff */
+struct ep_object {
+       struct usb_endpoint_descriptor *desc;
+       struct usb_device *udev;
+       struct kobject kobj;
+};
+#define to_ep_object(_kobj) \
+       container_of(_kobj, struct ep_object, kobj)
+
+struct ep_attribute {
+       struct attribute attr;
+       ssize_t (*show)(struct usb_device *,
+                       struct usb_endpoint_descriptor *, char *);
+};
+#define to_ep_attribute(_attr) \
+       container_of(_attr, struct ep_attribute, attr)
+
+#define EP_ATTR(_name)                                         \
+struct ep_attribute ep_##_name = {                             \
+       .attr = {.name = #_name, .owner = THIS_MODULE,          \
+                       .mode = S_IRUGO},                       \
+       .show = show_ep_##_name}
+
+#define usb_ep_attr(field, format_string)                      \
+static ssize_t show_ep_##field(struct usb_device *udev,                \
+               struct usb_endpoint_descriptor *desc,           \
+               char *buf)                                      \
+{                                                              \
+       return sprintf(buf, format_string, desc->field);        \
+}                                                              \
+static EP_ATTR(field);
+
+usb_ep_attr(bLength, "%02x\n")
+usb_ep_attr(bEndpointAddress, "%02x\n")
+usb_ep_attr(bmAttributes, "%02x\n")
+usb_ep_attr(bInterval, "%02x\n")
+
+static ssize_t show_ep_wMaxPacketSize(struct usb_device *udev,
+               struct usb_endpoint_descriptor *desc, char *buf)
+{
+       return sprintf(buf, "%04x\n",
+                       le16_to_cpu(desc->wMaxPacketSize) & 0x07ff);
+}
+static EP_ATTR(wMaxPacketSize);
+
+static ssize_t show_ep_type(struct usb_device *udev,
+               struct usb_endpoint_descriptor *desc, char *buf)
+{
+       char *type = "unknown";
+
+       switch (desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) {
+       case USB_ENDPOINT_XFER_CONTROL:
+               type = "Control";
+               break;
+       case USB_ENDPOINT_XFER_ISOC:
+               type = "Isoc";
+               break;
+       case USB_ENDPOINT_XFER_BULK:
+               type = "Bulk";
+               break;
+       case USB_ENDPOINT_XFER_INT:
+               type = "Interrupt";
+               break;
+       }
+       return sprintf(buf, "%s\n", type);
+}
+static EP_ATTR(type);
+
+static ssize_t show_ep_interval(struct usb_device *udev,
+               struct usb_endpoint_descriptor *desc, char *buf)
+{
+       char unit;
+       unsigned interval = 0;
+       unsigned in;
+
+       in = (desc->bEndpointAddress & USB_DIR_IN);
+
+       switch (desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) {
+       case USB_ENDPOINT_XFER_CONTROL:
+               if (udev->speed == USB_SPEED_HIGH)      /* uframes per NAK */
+                       interval = desc->bInterval;
+               break;
+       case USB_ENDPOINT_XFER_ISOC:
+               interval = 1 << (desc->bInterval - 1);
+               break;
+       case USB_ENDPOINT_XFER_BULK:
+               if (udev->speed == USB_SPEED_HIGH && !in) /* uframes per NAK */
+                       interval = desc->bInterval;
+               break;
+       case USB_ENDPOINT_XFER_INT:
+               if (udev->speed == USB_SPEED_HIGH)
+                       interval = 1 << (desc->bInterval - 1);
+               else
+                       interval = desc->bInterval;
+               break;
+       }
+       interval *= (udev->speed == USB_SPEED_HIGH) ? 125 : 1000;
+       if (interval % 1000)
+               unit = 'u';
+       else {
+               unit = 'm';
+               interval /= 1000;
+       }
+
+       return sprintf(buf, "%d%cs\n", interval, unit);
+}
+static EP_ATTR(interval);
+
+static ssize_t show_ep_direction(struct usb_device *udev,
+               struct usb_endpoint_descriptor *desc, char *buf)
+{
+       char *direction;
+
+       if ((desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
+                       USB_ENDPOINT_XFER_CONTROL)
+               direction = "both";
+       else if (desc->bEndpointAddress & USB_DIR_IN)
+               direction = "in";
+       else
+               direction = "out";
+       return sprintf(buf, "%s\n", direction);
+}
+static EP_ATTR(direction);
+
+static struct attribute *ep_attrs[] = {
+       &ep_bLength.attr,
+       &ep_bEndpointAddress.attr,
+       &ep_bmAttributes.attr,
+       &ep_bInterval.attr,
+       &ep_wMaxPacketSize.attr,
+       &ep_type.attr,
+       &ep_interval.attr,
+       &ep_direction.attr,
+       NULL,
+};
+
+static void ep_object_release(struct kobject *kobj)
+{
+       kfree(to_ep_object(kobj));
+}
+
+static ssize_t ep_object_show(struct kobject *kobj, struct attribute *attr,
+               char *buf)
+{
+       struct ep_object *ep_obj = to_ep_object(kobj);
+       struct ep_attribute *ep_attr = to_ep_attribute(attr);
+
+       return (ep_attr->show)(ep_obj->udev, ep_obj->desc, buf);
+}
+
+static struct sysfs_ops ep_object_sysfs_ops = {
+       .show =                 ep_object_show,
+};
+
+static struct kobj_type ep_object_ktype = {
+       .release =              ep_object_release,
+       .sysfs_ops =            &ep_object_sysfs_ops,
+       .default_attrs =        ep_attrs,
+};
+
+static void usb_create_ep_files(struct kobject *parent,
+               struct usb_host_endpoint *endpoint,
+               struct usb_device *udev)
+{
+       struct ep_object *ep_obj;
+       struct kobject *kobj;
+
+       ep_obj = kzalloc(sizeof(struct ep_object), GFP_KERNEL);
+       if (!ep_obj)
+               return;
+
+       ep_obj->desc = &endpoint->desc;
+       ep_obj->udev = udev;
+
+       kobj = &ep_obj->kobj;
+       kobject_set_name(kobj, "ep_%02x", endpoint->desc.bEndpointAddress);
+       kobj->parent = parent;
+       kobj->ktype = &ep_object_ktype;
+
+       /* Don't use kobject_register, because it generates a hotplug event */
+       kobject_init(kobj);
+       if (kobject_add(kobj) == 0)
+               endpoint->kobj = kobj;
+       else
+               kobject_put(kobj);
+}
+
+static void usb_remove_ep_files(struct usb_host_endpoint *endpoint)
+{
+
+       if (endpoint->kobj) {
+               kobject_del(endpoint->kobj);
+               kobject_put(endpoint->kobj);
+               endpoint->kobj = NULL;
+       }
+}
+
 /* Active configuration fields */
 #define usb_actconfig_show(field, multiplier, format_string)           \
-static ssize_t  show_##field (struct device *dev, struct device_attribute *attr, char *buf)            \
+static ssize_t  show_##field (struct device *dev,                      \
+               struct device_attribute *attr, char *buf)               \
 {                                                                      \
        struct usb_device *udev;                                        \
        struct usb_host_config *actconfig;                              \
@@ -46,22 +244,17 @@ usb_actconfig_attr (bNumInterfaces, 1, "%2d\n")
 usb_actconfig_attr (bmAttributes, 1, "%2x\n")
 usb_actconfig_attr (bMaxPower, 2, "%3dmA\n")
 
-static ssize_t show_configuration_string(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t show_configuration_string(struct device *dev,
+               struct device_attribute *attr, char *buf)
 {
        struct usb_device *udev;
        struct usb_host_config *actconfig;
-       int len;
 
        udev = to_usb_device (dev);
        actconfig = udev->actconfig;
        if ((!actconfig) || (!actconfig->string))
                return 0;
-       len = sprintf(buf, actconfig->string, PAGE_SIZE);
-       if (len < 0)
-               return 0;
-       buf[len] = '\n';
-       buf[len+1] = 0;
-       return len+1;
+       return sprintf(buf, "%s\n", actconfig->string);
 }
 static DEVICE_ATTR(configuration, S_IRUGO, show_configuration_string, NULL);
 
@@ -69,7 +262,8 @@ static DEVICE_ATTR(configuration, S_IRUGO, show_configuration_string, NULL);
 usb_actconfig_show(bConfigurationValue, 1, "%u\n");
 
 static ssize_t
-set_bConfigurationValue (struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+set_bConfigurationValue (struct device *dev, struct device_attribute *attr,
+               const char *buf, size_t count)
 {
        struct usb_device       *udev = udev = to_usb_device (dev);
        int                     config, value;
@@ -87,18 +281,13 @@ static DEVICE_ATTR(bConfigurationValue, S_IRUGO | S_IWUSR,
 
 /* String fields */
 #define usb_string_attr(name)                                          \
-static ssize_t  show_##name(struct device *dev, struct device_attribute *attr, char *buf)              \
+static ssize_t  show_##name(struct device *dev,                                \
+               struct device_attribute *attr, char *buf)               \
 {                                                                      \
        struct usb_device *udev;                                        \
-       int len;                                                        \
                                                                        \
        udev = to_usb_device (dev);                                     \
-       len = snprintf(buf, 256, "%s", udev->name);                     \
-       if (len < 0)                                                    \
-               return 0;                                               \
-       buf[len] = '\n';                                                \
-       buf[len+1] = 0;                                                 \
-       return len+1;                                                   \
+       return sprintf(buf, "%s\n", udev->name);                        \
 }                                                                      \
 static DEVICE_ATTR(name, S_IRUGO, show_##name, NULL);
 
@@ -167,7 +356,8 @@ static DEVICE_ATTR(maxchild, S_IRUGO, show_maxchild, NULL);
 /* Descriptor fields */
 #define usb_descriptor_attr_le16(field, format_string)                 \
 static ssize_t                                                         \
-show_##field (struct device *dev, struct device_attribute *attr, char *buf)                            \
+show_##field (struct device *dev, struct device_attribute *attr,       \
+               char *buf)                                              \
 {                                                                      \
        struct usb_device *udev;                                        \
                                                                        \
@@ -183,7 +373,8 @@ usb_descriptor_attr_le16(bcdDevice, "%04x\n")
 
 #define usb_descriptor_attr(field, format_string)                      \
 static ssize_t                                                         \
-show_##field (struct device *dev, struct device_attribute *attr, char *buf)                            \
+show_##field (struct device *dev, struct device_attribute *attr,       \
+               char *buf)                                              \
 {                                                                      \
        struct usb_device *udev;                                        \
                                                                        \
@@ -236,19 +427,21 @@ void usb_create_sysfs_dev_files (struct usb_device *udev)
        if (udev->serial)
                device_create_file (dev, &dev_attr_serial);
        device_create_file (dev, &dev_attr_configuration);
+       usb_create_ep_files(&dev->kobj, &udev->ep0, udev);
 }
 
 void usb_remove_sysfs_dev_files (struct usb_device *udev)
 {
        struct device *dev = &udev->dev;
 
+       usb_remove_ep_files(&udev->ep0);
        sysfs_remove_group(&dev->kobj, &dev_attr_grp);
 
-       if (udev->descriptor.iManufacturer)
+       if (udev->manufacturer)
                device_remove_file(dev, &dev_attr_manufacturer);
-       if (udev->descriptor.iProduct)
+       if (udev->product)
                device_remove_file(dev, &dev_attr_product);
-       if (udev->descriptor.iSerialNumber)
+       if (udev->serial)
                device_remove_file(dev, &dev_attr_serial);
        device_remove_file (dev, &dev_attr_configuration);
 }
@@ -256,11 +449,13 @@ void usb_remove_sysfs_dev_files (struct usb_device *udev)
 /* Interface fields */
 #define usb_intf_attr(field, format_string)                            \
 static ssize_t                                                         \
-show_##field (struct device *dev, struct device_attribute *attr, char *buf)                            \
+show_##field (struct device *dev, struct device_attribute *attr,       \
+               char *buf)                                              \
 {                                                                      \
        struct usb_interface *intf = to_usb_interface (dev);            \
                                                                        \
-       return sprintf (buf, format_string, intf->cur_altsetting->desc.field); \
+       return sprintf (buf, format_string,                             \
+                       intf->cur_altsetting->desc.field);              \
 }                                                                      \
 static DEVICE_ATTR(field, S_IRUGO, show_##field, NULL);
 
@@ -271,7 +466,8 @@ usb_intf_attr (bInterfaceClass, "%02x\n")
 usb_intf_attr (bInterfaceSubClass, "%02x\n")
 usb_intf_attr (bInterfaceProtocol, "%02x\n")
 
-static ssize_t show_interface_string(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t show_interface_string(struct device *dev,
+               struct device_attribute *attr, char *buf)
 {
        struct usb_interface *intf;
        struct usb_device *udev;
@@ -288,34 +484,28 @@ static ssize_t show_interface_string(struct device *dev, struct device_attribute
 }
 static DEVICE_ATTR(interface, S_IRUGO, show_interface_string, NULL);
 
-static ssize_t show_modalias(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t show_modalias(struct device *dev,
+               struct device_attribute *attr, char *buf)
 {
        struct usb_interface *intf;
        struct usb_device *udev;
-       int len;
+       struct usb_host_interface *alt;
 
        intf = to_usb_interface(dev);
        udev = interface_to_usbdev(intf);
-
-       len = sprintf(buf, "usb:v%04Xp%04Xd%04Xdc%02Xdsc%02Xdp%02Xic",
-                              le16_to_cpu(udev->descriptor.idVendor),
-                              le16_to_cpu(udev->descriptor.idProduct),
-                              le16_to_cpu(udev->descriptor.bcdDevice),
-                              udev->descriptor.bDeviceClass,
-                              udev->descriptor.bDeviceSubClass,
-                              udev->descriptor.bDeviceProtocol);
-       buf += len;
-
-       if (udev->descriptor.bDeviceClass == 0) {
-               struct usb_host_interface *alt = intf->cur_altsetting;
-
-               return len + sprintf(buf, "%02Xisc%02Xip%02X\n",
-                              alt->desc.bInterfaceClass,
-                              alt->desc.bInterfaceSubClass,
-                              alt->desc.bInterfaceProtocol);
-       } else {
-               return len + sprintf(buf, "*isc*ip*\n");
-       }
+       alt = intf->cur_altsetting;
+
+       return sprintf(buf, "usb:v%04Xp%04Xd%04Xdc%02Xdsc%02Xdp%02X"
+                       "ic%02Xisc%02Xip%02X\n",
+                       le16_to_cpu(udev->descriptor.idVendor),
+                       le16_to_cpu(udev->descriptor.idProduct),
+                       le16_to_cpu(udev->descriptor.bcdDevice),
+                       udev->descriptor.bDeviceClass,
+                       udev->descriptor.bDeviceSubClass,
+                       udev->descriptor.bDeviceProtocol,
+                       alt->desc.bInterfaceClass,
+                       alt->desc.bInterfaceSubClass,
+                       alt->desc.bInterfaceProtocol);
 }
 static DEVICE_ATTR(modalias, S_IRUGO, show_modalias, NULL);
 
@@ -333,20 +523,47 @@ static struct attribute_group intf_attr_grp = {
        .attrs = intf_attrs,
 };
 
+static inline void usb_create_intf_ep_files(struct usb_interface *intf,
+               struct usb_device *udev)
+{
+       struct usb_host_interface *iface_desc;
+       int i;
+
+       iface_desc = intf->cur_altsetting;
+       for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i)
+               usb_create_ep_files(&intf->dev.kobj, &iface_desc->endpoint[i],
+                               udev);
+}
+
+static inline void usb_remove_intf_ep_files(struct usb_interface *intf)
+{
+       struct usb_host_interface *iface_desc;
+       int i;
+
+       iface_desc = intf->cur_altsetting;
+       for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i)
+               usb_remove_ep_files(&iface_desc->endpoint[i]);
+}
+
 void usb_create_sysfs_intf_files (struct usb_interface *intf)
 {
+       struct usb_device *udev = interface_to_usbdev(intf);
+       struct usb_host_interface *alt = intf->cur_altsetting;
+
        sysfs_create_group(&intf->dev.kobj, &intf_attr_grp);
 
-       if (intf->cur_altsetting->string)
+       if (alt->string == NULL)
+               alt->string = usb_cache_string(udev, alt->desc.iInterface);
+       if (alt->string)
                device_create_file(&intf->dev, &dev_attr_interface);
-               
+       usb_create_intf_ep_files(intf, udev);
 }
 
 void usb_remove_sysfs_intf_files (struct usb_interface *intf)
 {
+       usb_remove_intf_ep_files(intf);
        sysfs_remove_group(&intf->dev.kobj, &intf_attr_grp);
 
        if (intf->cur_altsetting->string)
                device_remove_file(&intf->dev, &dev_attr_interface);
-
 }
index b32898e..f2a1fed 100644 (file)
@@ -237,7 +237,8 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags)
            (dev->state < USB_STATE_DEFAULT) ||
            (!dev->bus) || (dev->devnum <= 0))
                return -ENODEV;
-       if (dev->state == USB_STATE_SUSPENDED)
+       if (dev->bus->controller->power.power_state.event != PM_EVENT_ON
+                       || dev->state == USB_STATE_SUSPENDED)
                return -EHOSTUNREACH;
        if (!(op = dev->bus->op) || !op->submit_urb)
                return -ENODEV;
index 4c57f3f..0eefff7 100644 (file)
@@ -107,10 +107,19 @@ static int usb_probe_interface(struct device *dev)
        id = usb_match_id (intf, driver->id_table);
        if (id) {
                dev_dbg (dev, "%s - got id\n", __FUNCTION__);
+
+               /* Interface "power state" doesn't correspond to any hardware
+                * state whatsoever.  We use it to record when it's bound to
+                * a driver that may start I/0:  it's not frozen/quiesced.
+                */
+               mark_active(intf);
                intf->condition = USB_INTERFACE_BINDING;
                error = driver->probe (intf, id);
-               intf->condition = error ? USB_INTERFACE_UNBOUND :
-                               USB_INTERFACE_BOUND;
+               if (error) {
+                       mark_quiesced(intf);
+                       intf->condition = USB_INTERFACE_UNBOUND;
+               } else
+                       intf->condition = USB_INTERFACE_BOUND;
        }
 
        return error;
@@ -136,6 +145,7 @@ static int usb_unbind_interface(struct device *dev)
                        0);
        usb_set_intfdata(intf, NULL);
        intf->condition = USB_INTERFACE_UNBOUND;
+       mark_quiesced(intf);
 
        return 0;
 }
@@ -299,6 +309,7 @@ int usb_driver_claim_interface(struct usb_driver *driver,
        dev->driver = &driver->driver;
        usb_set_intfdata(iface, priv);
        iface->condition = USB_INTERFACE_BOUND;
+       mark_active(iface);
 
        /* if interface was already added, bind now; else let
         * the future device_add() bind it, bypassing probe()
@@ -345,6 +356,7 @@ void usb_driver_release_interface(struct usb_driver *driver,
        dev->driver = NULL;
        usb_set_intfdata(iface, NULL);
        iface->condition = USB_INTERFACE_UNBOUND;
+       mark_quiesced(iface);
 }
 
 /**
@@ -557,6 +569,7 @@ static int usb_hotplug (struct device *dev, char **envp, int num_envp,
 {
        struct usb_interface *intf;
        struct usb_device *usb_dev;
+       struct usb_host_interface *alt;
        int i = 0;
        int length = 0;
 
@@ -573,7 +586,8 @@ static int usb_hotplug (struct device *dev, char **envp, int num_envp,
 
        intf = to_usb_interface(dev);
        usb_dev = interface_to_usbdev (intf);
-       
+       alt = intf->cur_altsetting;
+
        if (usb_dev->devnum < 0) {
                pr_debug ("usb %s: already deleted?\n", dev->bus_id);
                return -ENODEV;
@@ -615,46 +629,27 @@ static int usb_hotplug (struct device *dev, char **envp, int num_envp,
                                usb_dev->descriptor.bDeviceProtocol))
                return -ENOMEM;
 
-       if (usb_dev->descriptor.bDeviceClass == 0) {
-               struct usb_host_interface *alt = intf->cur_altsetting;
+       if (add_hotplug_env_var(envp, num_envp, &i,
+                               buffer, buffer_size, &length,
+                               "INTERFACE=%d/%d/%d",
+                               alt->desc.bInterfaceClass,
+                               alt->desc.bInterfaceSubClass,
+                               alt->desc.bInterfaceProtocol))
+               return -ENOMEM;
 
-               /* 2.4 only exposed interface zero.  in 2.5, hotplug
-                * agents are called for all interfaces, and can use
-                * $DEVPATH/bInterfaceNumber if necessary.
-                */
-               if (add_hotplug_env_var(envp, num_envp, &i,
-                                       buffer, buffer_size, &length,
-                                       "INTERFACE=%d/%d/%d",
-                                       alt->desc.bInterfaceClass,
-                                       alt->desc.bInterfaceSubClass,
-                                       alt->desc.bInterfaceProtocol))
-                       return -ENOMEM;
-
-               if (add_hotplug_env_var(envp, num_envp, &i,
-                                       buffer, buffer_size, &length,
-                                       "MODALIAS=usb:v%04Xp%04Xd%04Xdc%02Xdsc%02Xdp%02Xic%02Xisc%02Xip%02X",
-                                       le16_to_cpu(usb_dev->descriptor.idVendor),
-                                       le16_to_cpu(usb_dev->descriptor.idProduct),
-                                       le16_to_cpu(usb_dev->descriptor.bcdDevice),
-                                       usb_dev->descriptor.bDeviceClass,
-                                       usb_dev->descriptor.bDeviceSubClass,
-                                       usb_dev->descriptor.bDeviceProtocol,
-                                       alt->desc.bInterfaceClass,
-                                       alt->desc.bInterfaceSubClass,
-                                       alt->desc.bInterfaceProtocol))
-                       return -ENOMEM;
-       } else {
-               if (add_hotplug_env_var(envp, num_envp, &i,
-                                       buffer, buffer_size, &length,
-                                       "MODALIAS=usb:v%04Xp%04Xd%04Xdc%02Xdsc%02Xdp%02Xic*isc*ip*",
-                                       le16_to_cpu(usb_dev->descriptor.idVendor),
-                                       le16_to_cpu(usb_dev->descriptor.idProduct),
-                                       le16_to_cpu(usb_dev->descriptor.bcdDevice),
-                                       usb_dev->descriptor.bDeviceClass,
-                                       usb_dev->descriptor.bDeviceSubClass,
-                                       usb_dev->descriptor.bDeviceProtocol))
-                       return -ENOMEM;
-       }
+       if (add_hotplug_env_var(envp, num_envp, &i,
+                               buffer, buffer_size, &length,
+                               "MODALIAS=usb:v%04Xp%04Xd%04Xdc%02Xdsc%02Xdp%02Xic%02Xisc%02Xip%02X",
+                               le16_to_cpu(usb_dev->descriptor.idVendor),
+                               le16_to_cpu(usb_dev->descriptor.idProduct),
+                               le16_to_cpu(usb_dev->descriptor.bcdDevice),
+                               usb_dev->descriptor.bDeviceClass,
+                               usb_dev->descriptor.bDeviceSubClass,
+                               usb_dev->descriptor.bDeviceProtocol,
+                               alt->desc.bInterfaceClass,
+                               alt->desc.bInterfaceSubClass,
+                               alt->desc.bInterfaceProtocol))
+               return -ENOMEM;
 
        envp[i] = NULL;
 
@@ -709,12 +704,10 @@ usb_alloc_dev(struct usb_device *parent, struct usb_bus *bus, unsigned port1)
 {
        struct usb_device *dev;
 
-       dev = kmalloc(sizeof(*dev), GFP_KERNEL);
+       dev = kzalloc(sizeof(*dev), GFP_KERNEL);
        if (!dev)
                return NULL;
 
-       memset(dev, 0, sizeof(*dev));
-
        bus = usb_bus_get(bus);
        if (!bus) {
                kfree(dev);
@@ -1402,13 +1395,30 @@ void usb_buffer_unmap_sg (struct usb_device *dev, unsigned pipe,
                        usb_pipein (pipe) ? DMA_FROM_DEVICE : DMA_TO_DEVICE);
 }
 
+static int verify_suspended(struct device *dev, void *unused)
+{
+       return (dev->power.power_state.event == PM_EVENT_ON) ? -EBUSY : 0;
+}
+
 static int usb_generic_suspend(struct device *dev, pm_message_t message)
 {
-       struct usb_interface *intf;
-       struct usb_driver *driver;
+       struct usb_interface    *intf;
+       struct usb_driver       *driver;
+       int                     status;
 
-       if (dev->driver == &usb_generic_driver)
-               return usb_suspend_device (to_usb_device(dev), message);
+       /* USB devices enter SUSPEND state through their hubs, but can be
+        * marked for FREEZE as soon as their children are already idled.
+        * But those semantics are useless, so we equate the two (sigh).
+        */
+       if (dev->driver == &usb_generic_driver) {
+               if (dev->power.power_state.event == message.event)
+                       return 0;
+               /* we need to rule out bogus requests through sysfs */
+               status = device_for_each_child(dev, NULL, verify_suspended);
+               if (status)
+                       return status;
+               return usb_suspend_device (to_usb_device(dev));
+       }
 
        if ((dev->driver == NULL) ||
            (dev->driver_data == &usb_generic_driver_data))
@@ -1417,23 +1427,44 @@ static int usb_generic_suspend(struct device *dev, pm_message_t message)
        intf = to_usb_interface(dev);
        driver = to_usb_driver(dev->driver);
 
-       /* there's only one USB suspend state */
-       if (intf->dev.power.power_state.event)
+       /* with no hardware, USB interfaces only use FREEZE and ON states */
+       if (!is_active(intf))
                return 0;
 
-       if (driver->suspend)
-               return driver->suspend(intf, message);
-       return 0;
+       if (driver->suspend && driver->resume) {
+               status = driver->suspend(intf, message);
+               if (status)
+                       dev_err(dev, "%s error %d\n", "suspend", status);
+               else
+                       mark_quiesced(intf);
+       } else {
+               // FIXME else if there's no suspend method, disconnect...
+               dev_warn(dev, "no %s?\n", "suspend");
+               status = 0;
+       }
+       return status;
 }
 
 static int usb_generic_resume(struct device *dev)
 {
-       struct usb_interface *intf;
-       struct usb_driver *driver;
+       struct usb_interface    *intf;
+       struct usb_driver       *driver;
+       struct usb_device       *udev;
+       int                     status;
 
-       /* devices resume through their hub */
-       if (dev->driver == &usb_generic_driver)
+       if (dev->power.power_state.event == PM_EVENT_ON)
+               return 0;
+
+       /* mark things as "on" immediately, no matter what errors crop up */
+       dev->power.power_state.event = PM_EVENT_ON;
+
+       /* devices resume through their hubs */
+       if (dev->driver == &usb_generic_driver) {
+               udev = to_usb_device(dev);
+               if (udev->state == USB_STATE_NOTATTACHED)
+                       return 0;
                return usb_resume_device (to_usb_device(dev));
+       }
 
        if ((dev->driver == NULL) ||
            (dev->driver_data == &usb_generic_driver_data))
@@ -1442,8 +1473,22 @@ static int usb_generic_resume(struct device *dev)
        intf = to_usb_interface(dev);
        driver = to_usb_driver(dev->driver);
 
-       if (driver->resume)
-               return driver->resume(intf);
+       udev = interface_to_usbdev(intf);
+       if (udev->state == USB_STATE_NOTATTACHED)
+               return 0;
+
+       /* if driver was suspended, it has a resume method;
+        * however, sysfs can wrongly mark things as suspended
+        * (on the "no suspend method" FIXME path above)
+        */
+       if (driver->resume) {
+               status = driver->resume(intf);
+               if (status) {
+                       dev_err(dev, "%s error %d\n", "resume", status);
+                       mark_quiesced(intf);
+               }
+       } else
+               dev_warn(dev, "no %s?\n", "resume");
        return 0;
 }
 
index e6504f3..1c4a684 100644 (file)
@@ -13,12 +13,14 @@ extern void usb_disable_device (struct usb_device *dev, int skip_ep0);
 
 extern int usb_get_device_descriptor(struct usb_device *dev,
                unsigned int size);
+extern char *usb_cache_string(struct usb_device *udev, int index);
 extern int usb_set_configuration(struct usb_device *dev, int configuration);
 
 extern void usb_lock_all_devices(void);
 extern void usb_unlock_all_devices(void);
 
 extern void usb_kick_khubd(struct usb_device *dev);
+extern void usb_suspend_root_hub(struct usb_device *hdev);
 extern void usb_resume_root_hub(struct usb_device *dev);
 
 extern int  usb_hub_init(void);
@@ -28,6 +30,28 @@ extern void usb_major_cleanup(void);
 extern int usb_host_init(void);
 extern void usb_host_cleanup(void);
 
+extern int usb_suspend_device(struct usb_device *dev);
+extern int usb_resume_device(struct usb_device *dev);
+
+
+/* Interfaces and their "power state" are owned by usbcore */
+
+static inline void mark_active(struct usb_interface *f)
+{
+       f->dev.power.power_state.event = PM_EVENT_ON;
+}
+
+static inline void mark_quiesced(struct usb_interface *f)
+{
+       f->dev.power.power_state.event = PM_EVENT_FREEZE;
+}
+
+static inline int is_active(struct usb_interface *f)
+{
+       return f->dev.power.power_state.event == PM_EVENT_ON;
+}
+
+
 /* for labeling diagnostics */
 extern const char *usbcore_name;
 
@@ -39,9 +63,6 @@ extern void usbfs_conn_disc_event(void);
 
 extern int usbdev_init(void);
 extern void usbdev_cleanup(void);
-extern void usbdev_add(struct usb_device *dev);
-extern void usbdev_remove(struct usb_device *dev);
-extern struct usb_device *usbdev_lookup_minor(int minor);
 
 struct dev_state {
        struct list_head list;      /* state list */
@@ -58,3 +79,9 @@ struct dev_state {
        unsigned long ifclaimed;
 };
 
+/* internal notify stuff */
+extern void usb_notify_add_device(struct usb_device *udev);
+extern void usb_notify_remove_device(struct usb_device *udev);
+extern void usb_notify_add_bus(struct usb_bus *ubus);
+extern void usb_notify_remove_bus(struct usb_bus *ubus);
+
index 5032017..02106be 100644 (file)
@@ -967,6 +967,7 @@ static int dummy_udc_resume (struct device *dev)
 
 static struct device_driver dummy_udc_driver = {
        .name           = (char *) gadget_name,
+       .owner          = THIS_MODULE,
        .bus            = &platform_bus_type,
        .probe          = dummy_udc_probe,
        .remove         = dummy_udc_remove,
@@ -1751,7 +1752,7 @@ static int dummy_hub_control (
        return retval;
 }
 
-static int dummy_hub_suspend (struct usb_hcd *hcd)
+static int dummy_bus_suspend (struct usb_hcd *hcd)
 {
        struct dummy *dum = hcd_to_dummy (hcd);
 
@@ -1762,7 +1763,7 @@ static int dummy_hub_suspend (struct usb_hcd *hcd)
        return 0;
 }
 
-static int dummy_hub_resume (struct usb_hcd *hcd)
+static int dummy_bus_resume (struct usb_hcd *hcd)
 {
        struct dummy *dum = hcd_to_dummy (hcd);
 
@@ -1894,8 +1895,8 @@ static const struct hc_driver dummy_hcd = {
 
        .hub_status_data =      dummy_hub_status,
        .hub_control =          dummy_hub_control,
-       .hub_suspend =          dummy_hub_suspend,
-       .hub_resume =           dummy_hub_resume,
+       .bus_suspend =          dummy_bus_suspend,
+       .bus_resume =           dummy_bus_resume,
 };
 
 static int dummy_hcd_probe (struct device *dev)
@@ -1936,13 +1937,6 @@ static int dummy_hcd_suspend (struct device *dev, pm_message_t state)
        dev_dbg (dev, "%s\n", __FUNCTION__);
        hcd = dev_get_drvdata (dev);
 
-#ifndef CONFIG_USB_SUSPEND
-       /* Otherwise this would never happen */
-       usb_lock_device (hcd->self.root_hub);
-       dummy_hub_suspend (hcd);
-       usb_unlock_device (hcd->self.root_hub);
-#endif
-
        hcd->state = HC_STATE_SUSPENDED;
        return 0;
 }
@@ -1955,19 +1949,13 @@ static int dummy_hcd_resume (struct device *dev)
        hcd = dev_get_drvdata (dev);
        hcd->state = HC_STATE_RUNNING;
 
-#ifndef CONFIG_USB_SUSPEND
-       /* Otherwise this would never happen */
-       usb_lock_device (hcd->self.root_hub);
-       dummy_hub_resume (hcd);
-       usb_unlock_device (hcd->self.root_hub);
-#endif
-
        usb_hcd_poll_rh_status (hcd);
        return 0;
 }
 
 static struct device_driver dummy_hcd_driver = {
        .name           = (char *) driver_name,
+       .owner          = THIS_MODULE,
        .bus            = &platform_bus_type,
        .probe          = dummy_hcd_probe,
        .remove         = dummy_hcd_remove,
index f1024e8..8f402f8 100644 (file)
@@ -2533,6 +2533,7 @@ static struct usb_gadget_driver eth_driver = {
 
        .driver         = {
                .name           = (char *) shortname,
+               .owner          = THIS_MODULE,
                // .shutdown = ...
                // .suspend = ...
                // .resume = ...
index a41d9d4..ea09aaa 100644 (file)
 #include <linux/fs.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
+#include <linux/kthread.h>
 #include <linux/limits.h>
 #include <linux/list.h>
 #include <linux/module.h>
@@ -669,7 +670,6 @@ struct fsg_dev {
        wait_queue_head_t       thread_wqh;
        int                     thread_wakeup_needed;
        struct completion       thread_notifier;
-       int                     thread_pid;
        struct task_struct      *thread_task;
        sigset_t                thread_signal_mask;
 
@@ -1084,7 +1084,6 @@ static void wakeup_thread(struct fsg_dev *fsg)
 static void raise_exception(struct fsg_dev *fsg, enum fsg_state new_state)
 {
        unsigned long           flags;
-       struct task_struct      *thread_task;
 
        /* Do nothing if a higher-priority exception is already in progress.
         * If a lower-or-equal priority exception is in progress, preempt it
@@ -1093,9 +1092,9 @@ static void raise_exception(struct fsg_dev *fsg, enum fsg_state new_state)
        if (fsg->state <= new_state) {
                fsg->exception_req_tag = fsg->ep0_req_tag;
                fsg->state = new_state;
-               thread_task = fsg->thread_task;
-               if (thread_task)
-                       send_sig_info(SIGUSR1, SEND_SIG_FORCED, thread_task);
+               if (fsg->thread_task)
+                       send_sig_info(SIGUSR1, SEND_SIG_FORCED,
+                                       fsg->thread_task);
        }
        spin_unlock_irqrestore(&fsg->lock, flags);
 }
@@ -3383,11 +3382,6 @@ static int fsg_main_thread(void *fsg_)
 {
        struct fsg_dev          *fsg = (struct fsg_dev *) fsg_;
 
-       fsg->thread_task = current;
-
-       /* Release all our userspace resources */
-       daemonize("file-storage-gadget");
-
        /* Allow the thread to be killed by a signal, but set the signal mask
         * to block everything but INT, TERM, KILL, and USR1. */
        siginitsetinv(&fsg->thread_signal_mask, sigmask(SIGINT) |
@@ -3400,9 +3394,6 @@ static int fsg_main_thread(void *fsg_)
         * that expects a __user pointer and it will work okay. */
        set_fs(get_ds());
 
-       /* Wait for the gadget registration to finish up */
-       wait_for_completion(&fsg->thread_notifier);
-
        /* The main loop */
        while (fsg->state != FSG_STATE_TERMINATED) {
                if (exception_in_progress(fsg) || signal_pending(current)) {
@@ -3440,8 +3431,9 @@ static int fsg_main_thread(void *fsg_)
                spin_unlock_irq(&fsg->lock);
                }
 
+       spin_lock_irq(&fsg->lock);
        fsg->thread_task = NULL;
-       flush_signals(current);
+       spin_unlock_irq(&fsg->lock);
 
        /* In case we are exiting because of a signal, unregister the
         * gadget driver and close the backing file. */
@@ -3831,12 +3823,11 @@ static int __init fsg_bind(struct usb_gadget *gadget)
 
        /* Create the LUNs, open their backing files, and register the
         * LUN devices in sysfs. */
-       fsg->luns = kmalloc(i * sizeof(struct lun), GFP_KERNEL);
+       fsg->luns = kzalloc(i * sizeof(struct lun), GFP_KERNEL);
        if (!fsg->luns) {
                rc = -ENOMEM;
                goto out;
        }
-       memset(fsg->luns, 0, i * sizeof(struct lun));
        fsg->nluns = i;
 
        for (i = 0; i < fsg->nluns; ++i) {
@@ -3959,10 +3950,12 @@ static int __init fsg_bind(struct usb_gadget *gadget)
                sprintf(&serial[i], "%02X", c);
        }
 
-       if ((rc = kernel_thread(fsg_main_thread, fsg, (CLONE_VM | CLONE_FS |
-                       CLONE_FILES))) < 0)
+       fsg->thread_task = kthread_create(fsg_main_thread, fsg,
+                       "file-storage-gadget");
+       if (IS_ERR(fsg->thread_task)) {
+               rc = PTR_ERR(fsg->thread_task);
                goto out;
-       fsg->thread_pid = rc;
+       }
 
        INFO(fsg, DRIVER_DESC ", version: " DRIVER_VERSION "\n");
        INFO(fsg, "Number of LUNs=%d\n", fsg->nluns);
@@ -3994,7 +3987,12 @@ static int __init fsg_bind(struct usb_gadget *gadget)
        DBG(fsg, "removable=%d, stall=%d, buflen=%u\n",
                        mod_data.removable, mod_data.can_stall,
                        mod_data.buflen);
-       DBG(fsg, "I/O thread pid: %d\n", fsg->thread_pid);
+       DBG(fsg, "I/O thread pid: %d\n", fsg->thread_task->pid);
+
+       set_bit(REGISTERED, &fsg->atomic_bitflags);
+
+       /* Tell the thread to start working */
+       wake_up_process(fsg->thread_task);
        return 0;
 
 autoconf_fail:
@@ -4046,6 +4044,7 @@ static struct usb_gadget_driver           fsg_driver = {
 
        .driver         = {
                .name           = (char *) shortname,
+               .owner          = THIS_MODULE,
                // .release = ...
                // .suspend = ...
                // .resume = ...
@@ -4057,10 +4056,9 @@ static int __init fsg_alloc(void)
 {
        struct fsg_dev          *fsg;
 
-       fsg = kmalloc(sizeof *fsg, GFP_KERNEL);
+       fsg = kzalloc(sizeof *fsg, GFP_KERNEL);
        if (!fsg)
                return -ENOMEM;
-       memset(fsg, 0, sizeof *fsg);
        spin_lock_init(&fsg->lock);
        init_rwsem(&fsg->filesem);
        init_waitqueue_head(&fsg->thread_wqh);
@@ -4086,15 +4084,9 @@ static int __init fsg_init(void)
        if ((rc = fsg_alloc()) != 0)
                return rc;
        fsg = the_fsg;
-       if ((rc = usb_gadget_register_driver(&fsg_driver)) != 0) {
+       if ((rc = usb_gadget_register_driver(&fsg_driver)) != 0)
                fsg_free(fsg);
-               return rc;
-       }
-       set_bit(REGISTERED, &fsg->atomic_bitflags);
-
-       /* Tell the thread to start working */
-       complete(&fsg->thread_notifier);
-       return 0;
+       return rc;
 }
 module_init(fsg_init);
 
index b0f3cd6..6544697 100644 (file)
@@ -1970,6 +1970,7 @@ MODULE_DEVICE_TABLE (pci, pci_ids);
 static struct pci_driver goku_pci_driver = {
        .name =         (char *) driver_name,
        .id_table =     pci_ids,
+       .owner =        THIS_MODULE,
 
        .probe =        goku_probe,
        .remove =       goku_remove,
index 012d1e5..9b36739 100644 (file)
@@ -2140,6 +2140,7 @@ static int lh7a40x_udc_remove(struct device *_dev)
 
 static struct device_driver udc_driver = {
        .name = (char *)driver_name,
+       .owner = THIS_MODULE,
        .bus = &platform_bus_type,
        .probe = lh7a40x_udc_probe,
        .remove = lh7a40x_udc_remove
index c32e1f7..0dc6bb0 100644 (file)
@@ -2948,6 +2948,7 @@ MODULE_DEVICE_TABLE (pci, pci_ids);
 static struct pci_driver net2280_pci_driver = {
        .name =         (char *) driver_name,
        .id_table =     pci_ids,
+       .owner =        THIS_MODULE,
 
        .probe =        net2280_probe,
        .remove =       net2280_remove,
index b7885dc..41c96b0 100644 (file)
@@ -691,7 +691,7 @@ static void next_out_dma(struct omap_ep *ep, struct omap_req *req)
 }
 
 static void
-finish_out_dma(struct omap_ep *ep, struct omap_req *req, int status)
+finish_out_dma(struct omap_ep *ep, struct omap_req *req, int status, int one)
 {
        u16     count;
 
@@ -699,6 +699,8 @@ finish_out_dma(struct omap_ep *ep, struct omap_req *req, int status)
                ep->dma_counter = (u16) (req->req.dma + req->req.actual);
        count = dma_dest_len(ep, req->req.dma + req->req.actual);
        count += req->req.actual;
+       if (one)
+               count--;
        if (count <= req->req.length)
                req->req.actual = count;
 
@@ -747,7 +749,7 @@ static void dma_irq(struct omap_udc *udc, u16 irq_src)
                if (!list_empty(&ep->queue)) {
                        req = container_of(ep->queue.next,
                                        struct omap_req, queue);
-                       finish_out_dma(ep, req, 0);
+                       finish_out_dma(ep, req, 0, dman_stat & UDC_DMA_RX_SB);
                }
                UDC_IRQ_SRC_REG = UDC_RXN_EOT;
 
@@ -925,7 +927,7 @@ static void dma_channel_release(struct omap_ep *ep)
                while (UDC_RXDMA_CFG_REG & mask)
                        udelay(10);
                if (req)
-                       finish_out_dma(ep, req, -ECONNRESET);
+                       finish_out_dma(ep, req, -ECONNRESET, 0);
        }
        omap_free_dma(ep->lch);
        ep->dma_channel = 0;
@@ -1786,8 +1788,12 @@ static void devstate_irq(struct omap_udc *udc, u16 irq_src)
                                        udc->driver->suspend(&udc->gadget);
                                        spin_lock(&udc->lock);
                                }
+                               if (udc->transceiver)
+                                       otg_set_suspend(udc->transceiver, 1);
                        } else {
                                VDBG("resume\n");
+                               if (udc->transceiver)
+                                       otg_set_suspend(udc->transceiver, 0);
                                if (udc->gadget.speed == USB_SPEED_FULL
                                                && udc->driver->resume) {
                                        spin_unlock(&udc->lock);
@@ -2943,6 +2949,7 @@ static int omap_udc_resume(struct device *dev)
 
 static struct device_driver udc_driver = {
        .name           = (char *) driver_name,
+       .owner          = THIS_MODULE,
        .bus            = &platform_bus_type,
        .probe          = omap_udc_probe,
        .remove         = __exit_p(omap_udc_remove),
index 6470285..f83a926 100644 (file)
@@ -2631,6 +2631,7 @@ static int pxa2xx_udc_resume(struct device *dev)
 
 static struct device_driver udc_driver = {
        .name           = "pxa2xx-udc",
+       .owner          = THIS_MODULE,
        .bus            = &platform_bus_type,
        .probe          = pxa2xx_udc_probe,
        .shutdown       = pxa2xx_udc_shutdown,
index ec9c424..6c58636 100644 (file)
@@ -1302,6 +1302,7 @@ static struct usb_gadget_driver zero_driver = {
 
        .driver         = {
                .name           = (char *) shortname,
+               .owner          = THIS_MODULE,
                // .shutdown = ...
                // .suspend = ...
                // .resume = ...
index 350d14f..58321d3 100644 (file)
@@ -1,8 +1,9 @@
 #
-# Makefile for USB Host Controller Driver
-# framework and drivers
+# Makefile for USB Host Controller Drivers
 #
 
+obj-$(CONFIG_PCI)              += pci-quirks.o
+
 obj-$(CONFIG_USB_EHCI_HCD)     += ehci-hcd.o
 obj-$(CONFIG_USB_ISP116X_HCD)  += isp116x-hcd.o
 obj-$(CONFIG_USB_OHCI_HCD)     += ohci-hcd.o
index f5eb9e7..af3c05e 100644 (file)
@@ -182,6 +182,9 @@ static int ehci_halt (struct ehci_hcd *ehci)
 {
        u32     temp = readl (&ehci->regs->status);
 
+       /* disable any irqs left enabled by previous code */
+       writel (0, &ehci->regs->intr_enable);
+
        if ((temp & STS_HALT) != 0)
                return 0;
 
@@ -297,50 +300,17 @@ static void ehci_watchdog (unsigned long param)
        spin_unlock_irqrestore (&ehci->lock, flags);
 }
 
-#ifdef CONFIG_PCI
-
-/* EHCI 0.96 (and later) section 5.1 says how to kick BIOS/SMM/...
- * off the controller (maybe it can boot from highspeed USB disks).
+/* Reboot notifiers kick in for silicon on any bus (not just pci, etc).
+ * This forcibly disables dma and IRQs, helping kexec and other cases
+ * where the next system software may expect clean state.
  */
-static int bios_handoff (struct ehci_hcd *ehci, int where, u32 cap)
-{
-       struct pci_dev *pdev = to_pci_dev(ehci_to_hcd(ehci)->self.controller);
-
-       /* always say Linux will own the hardware */
-       pci_write_config_byte(pdev, where + 3, 1);
-
-       /* maybe wait a while for BIOS to respond */
-       if (cap & (1 << 16)) {
-               int msec = 5000;
-
-               do {
-                       msleep(10);
-                       msec -= 10;
-                       pci_read_config_dword(pdev, where, &cap);
-               } while ((cap & (1 << 16)) && msec);
-               if (cap & (1 << 16)) {
-                       ehci_err(ehci, "BIOS handoff failed (%d, %08x)\n",
-                               where, cap);
-                       // some BIOS versions seem buggy...
-                       // return 1;
-                       ehci_warn (ehci, "continuing after BIOS bug...\n");
-                       /* disable all SMIs, and clear "BIOS owns" flag */
-                       pci_write_config_dword(pdev, where + 4, 0);
-                       pci_write_config_byte(pdev, where + 2, 0);
-               } else
-                       ehci_dbg(ehci, "BIOS handoff succeeded\n");
-       }
-       return 0;
-}
-
-#endif
-
 static int
 ehci_reboot (struct notifier_block *self, unsigned long code, void *null)
 {
        struct ehci_hcd         *ehci;
 
        ehci = container_of (self, struct ehci_hcd, reboot_notifier);
+       (void) ehci_halt (ehci);
 
        /* make BIOS/etc use companion controller during reboot */
        writel (0, &ehci->regs->configured_flag);
@@ -363,156 +333,90 @@ static void ehci_port_power (struct ehci_hcd *ehci, int is_on)
        msleep(20);
 }
 
+/*-------------------------------------------------------------------------*/
+
+/*
+ * ehci_work is called from some interrupts, timers, and so on.
+ * it calls driver completion functions, after dropping ehci->lock.
+ */
+static void ehci_work (struct ehci_hcd *ehci, struct pt_regs *regs)
+{
+       timer_action_done (ehci, TIMER_IO_WATCHDOG);
+       if (ehci->reclaim_ready)
+               end_unlink_async (ehci, regs);
+
+       /* another CPU may drop ehci->lock during a schedule scan while
+        * it reports urb completions.  this flag guards against bogus
+        * attempts at re-entrant schedule scanning.
+        */
+       if (ehci->scanning)
+               return;
+       ehci->scanning = 1;
+       scan_async (ehci, regs);
+       if (ehci->next_uframe != -1)
+               scan_periodic (ehci, regs);
+       ehci->scanning = 0;
 
-/* called by khubd or root hub init threads */
+       /* the IO watchdog guards against hardware or driver bugs that
+        * misplace IRQs, and should let us run completely without IRQs.
+        * such lossage has been observed on both VT6202 and VT8235.
+        */
+       if (HC_IS_RUNNING (ehci_to_hcd(ehci)->state) &&
+                       (ehci->async->qh_next.ptr != NULL ||
+                        ehci->periodic_sched != 0))
+               timer_action (ehci, TIMER_IO_WATCHDOG);
+}
 
-static int ehci_hc_reset (struct usb_hcd *hcd)
+static void ehci_stop (struct usb_hcd *hcd)
 {
        struct ehci_hcd         *ehci = hcd_to_ehci (hcd);
-       u32                     temp;
-       unsigned                count = 256/4;
 
-       spin_lock_init (&ehci->lock);
+       ehci_dbg (ehci, "stop\n");
 
-       ehci->caps = hcd->regs;
-       ehci->regs = hcd->regs + HC_LENGTH (readl (&ehci->caps->hc_capbase));
-       dbg_hcs_params (ehci, "reset");
-       dbg_hcc_params (ehci, "reset");
+       /* Turn off port power on all root hub ports. */
+       ehci_port_power (ehci, 0);
 
-       /* cache this readonly data; minimize chip reads */
-       ehci->hcs_params = readl (&ehci->caps->hcs_params);
+       /* no more interrupts ... */
+       del_timer_sync (&ehci->watchdog);
 
-#ifdef CONFIG_PCI
-       if (hcd->self.controller->bus == &pci_bus_type) {
-               struct pci_dev  *pdev = to_pci_dev(hcd->self.controller);
+       spin_lock_irq(&ehci->lock);
+       if (HC_IS_RUNNING (hcd->state))
+               ehci_quiesce (ehci);
 
-               switch (pdev->vendor) {
-               case PCI_VENDOR_ID_TDI:
-                       if (pdev->device == PCI_DEVICE_ID_TDI_EHCI) {
-                               ehci->is_tdi_rh_tt = 1;
-                               tdi_reset (ehci);
-                       }
-                       break;
-               case PCI_VENDOR_ID_AMD:
-                       /* AMD8111 EHCI doesn't work, according to AMD errata */
-                       if (pdev->device == 0x7463) {
-                               ehci_info (ehci, "ignoring AMD8111 (errata)\n");
-                               return -EIO;
-                       }
-                       break;
-               case PCI_VENDOR_ID_NVIDIA:
-                       /* NVidia reports that certain chips don't handle
-                        * QH, ITD, or SITD addresses above 2GB.  (But TD,
-                        * data buffer, and periodic schedule are normal.)
-                        */
-                       switch (pdev->device) {
-                       case 0x003c:    /* MCP04 */
-                       case 0x005b:    /* CK804 */
-                       case 0x00d8:    /* CK8 */
-                       case 0x00e8:    /* CK8S */
-                               if (pci_set_consistent_dma_mask(pdev,
-                                                       DMA_31BIT_MASK) < 0)
-                                       ehci_warn (ehci, "can't enable NVidia "
-                                               "workaround for >2GB RAM\n");
-                               break;
-                       }
-                       break;
-               }
+       ehci_reset (ehci);
+       writel (0, &ehci->regs->intr_enable);
+       spin_unlock_irq(&ehci->lock);
 
-               /* optional debug port, normally in the first BAR */
-               temp = pci_find_capability (pdev, 0x0a);
-               if (temp) {
-                       pci_read_config_dword(pdev, temp, &temp);
-                       temp >>= 16;
-                       if ((temp & (3 << 13)) == (1 << 13)) {
-                               temp &= 0x1fff;
-                               ehci->debug = hcd->regs + temp;
-                               temp = readl (&ehci->debug->control);
-                               ehci_info (ehci, "debug port %d%s\n",
-                                       HCS_DEBUG_PORT(ehci->hcs_params),
-                                       (temp & DBGP_ENABLED)
-                                               ? " IN USE"
-                                               : "");
-                               if (!(temp & DBGP_ENABLED))
-                                       ehci->debug = NULL;
-                       }
-               }
+       /* let companion controllers work when we aren't */
+       writel (0, &ehci->regs->configured_flag);
+       unregister_reboot_notifier (&ehci->reboot_notifier);
 
-               temp = HCC_EXT_CAPS (readl (&ehci->caps->hcc_params));
-       } else
-               temp = 0;
-
-       /* EHCI 0.96 and later may have "extended capabilities" */
-       while (temp && count--) {
-               u32             cap;
-
-               pci_read_config_dword (to_pci_dev(hcd->self.controller),
-                               temp, &cap);
-               ehci_dbg (ehci, "capability %04x at %02x\n", cap, temp);
-               switch (cap & 0xff) {
-               case 1:                 /* BIOS/SMM/... handoff */
-                       if (bios_handoff (ehci, temp, cap) != 0)
-                               return -EOPNOTSUPP;
-                       break;
-               case 0:                 /* illegal reserved capability */
-                       ehci_warn (ehci, "illegal capability!\n");
-                       cap = 0;
-                       /* FALLTHROUGH */
-               default:                /* unknown */
-                       break;
-               }
-               temp = (cap >> 8) & 0xff;
-       }
-       if (!count) {
-               ehci_err (ehci, "bogus capabilities ... PCI problems!\n");
-               return -EIO;
-       }
-       if (ehci_is_TDI(ehci))
-               ehci_reset (ehci);
-#endif
+       remove_debug_files (ehci);
 
-       ehci_port_power (ehci, 0);
+       /* root hub is shut down separately (first, when possible) */
+       spin_lock_irq (&ehci->lock);
+       if (ehci->async)
+               ehci_work (ehci, NULL);
+       spin_unlock_irq (&ehci->lock);
+       ehci_mem_cleanup (ehci);
 
-       /* at least the Genesys GL880S needs fixup here */
-       temp = HCS_N_CC(ehci->hcs_params) * HCS_N_PCC(ehci->hcs_params);
-       temp &= 0x0f;
-       if (temp && HCS_N_PORTS(ehci->hcs_params) > temp) {
-               ehci_dbg (ehci, "bogus port configuration: "
-                       "cc=%d x pcc=%d < ports=%d\n",
-                       HCS_N_CC(ehci->hcs_params),
-                       HCS_N_PCC(ehci->hcs_params),
-                       HCS_N_PORTS(ehci->hcs_params));
-
-#ifdef CONFIG_PCI
-               if (hcd->self.controller->bus == &pci_bus_type) {
-                       struct pci_dev  *pdev;
-
-                       pdev = to_pci_dev(hcd->self.controller);
-                       switch (pdev->vendor) {
-                       case 0x17a0:            /* GENESYS */
-                               /* GL880S: should be PORTS=2 */
-                               temp |= (ehci->hcs_params & ~0xf);
-                               ehci->hcs_params = temp;
-                               break;
-                       case PCI_VENDOR_ID_NVIDIA:
-                               /* NF4: should be PCC=10 */
-                               break;
-                       }
-               }
+#ifdef EHCI_STATS
+       ehci_dbg (ehci, "irq normal %ld err %ld reclaim %ld (lost %ld)\n",
+               ehci->stats.normal, ehci->stats.error, ehci->stats.reclaim,
+               ehci->stats.lost_iaa);
+       ehci_dbg (ehci, "complete %ld unlink %ld\n",
+               ehci->stats.complete, ehci->stats.unlink);
 #endif
-       }
 
-       /* force HC to halt state */
-       return ehci_halt (ehci);
+       dbg_status (ehci, "ehci_stop completed", readl (&ehci->regs->status));
 }
 
-static int ehci_start (struct usb_hcd *hcd)
+static int ehci_run (struct usb_hcd *hcd)
 {
        struct ehci_hcd         *ehci = hcd_to_ehci (hcd);
        u32                     temp;
        int                     retval;
        u32                     hcc_params;
-       u8                      sbrn = 0;
        int                     first;
 
        /* skip some things on restart paths */
@@ -551,27 +455,6 @@ static int ehci_start (struct usb_hcd *hcd)
        }
        writel (ehci->periodic_dma, &ehci->regs->frame_list);
 
-#ifdef CONFIG_PCI
-       if (hcd->self.controller->bus == &pci_bus_type) {
-               struct pci_dev          *pdev;
-               u16                     port_wake;
-
-               pdev = to_pci_dev(hcd->self.controller);
-
-               /* Serial Bus Release Number is at PCI 0x60 offset */
-               pci_read_config_byte(pdev, 0x60, &sbrn);
-
-               /* port wake capability, reported by boot firmware */
-               pci_read_config_word(pdev, 0x62, &port_wake);
-               hcd->can_wakeup = (port_wake & 1) != 0;
-
-               /* help hc dma work well with cachelines */
-               retval = pci_set_mwi(pdev);
-               if (retval)
-                       ehci_dbg(ehci, "unable to enable MWI - not fatal.\n");
-       }
-#endif
-
        /*
         * dedicate a qh for the async ring head, since we couldn't unlink
         * a 'real' qh without stopping the async schedule [4.8].  use it
@@ -667,7 +550,7 @@ static int ehci_start (struct usb_hcd *hcd)
        temp = HC_VERSION(readl (&ehci->caps->hc_capbase));
        ehci_info (ehci,
                "USB %x.%x %s, EHCI %x.%02x, driver %s\n",
-               ((sbrn & 0xf0)>>4), (sbrn & 0x0f),
+               ((ehci->sbrn & 0xf0)>>4), (ehci->sbrn & 0x0f),
                first ? "initialized" : "restarted",
                temp >> 8, temp & 0xff, DRIVER_VERSION);
 
@@ -679,188 +562,6 @@ static int ehci_start (struct usb_hcd *hcd)
        return 0;
 }
 
-/* always called by thread; normally rmmod */
-
-static void ehci_stop (struct usb_hcd *hcd)
-{
-       struct ehci_hcd         *ehci = hcd_to_ehci (hcd);
-
-       ehci_dbg (ehci, "stop\n");
-
-       /* Turn off port power on all root hub ports. */
-       ehci_port_power (ehci, 0);
-
-       /* no more interrupts ... */
-       del_timer_sync (&ehci->watchdog);
-
-       spin_lock_irq(&ehci->lock);
-       if (HC_IS_RUNNING (hcd->state))
-               ehci_quiesce (ehci);
-
-       ehci_reset (ehci);
-       writel (0, &ehci->regs->intr_enable);
-       spin_unlock_irq(&ehci->lock);
-
-       /* let companion controllers work when we aren't */
-       writel (0, &ehci->regs->configured_flag);
-       unregister_reboot_notifier (&ehci->reboot_notifier);
-
-       remove_debug_files (ehci);
-
-       /* root hub is shut down separately (first, when possible) */
-       spin_lock_irq (&ehci->lock);
-       if (ehci->async)
-               ehci_work (ehci, NULL);
-       spin_unlock_irq (&ehci->lock);
-       ehci_mem_cleanup (ehci);
-
-#ifdef EHCI_STATS
-       ehci_dbg (ehci, "irq normal %ld err %ld reclaim %ld (lost %ld)\n",
-               ehci->stats.normal, ehci->stats.error, ehci->stats.reclaim,
-               ehci->stats.lost_iaa);
-       ehci_dbg (ehci, "complete %ld unlink %ld\n",
-               ehci->stats.complete, ehci->stats.unlink);
-#endif
-
-       dbg_status (ehci, "ehci_stop completed", readl (&ehci->regs->status));
-}
-
-static int ehci_get_frame (struct usb_hcd *hcd)
-{
-       struct ehci_hcd         *ehci = hcd_to_ehci (hcd);
-       return (readl (&ehci->regs->frame_index) >> 3) % ehci->periodic_size;
-}
-
-/*-------------------------------------------------------------------------*/
-
-#ifdef CONFIG_PM
-
-/* suspend/resume, section 4.3 */
-
-/* These routines rely on the bus (pci, platform, etc)
- * to handle powerdown and wakeup, and currently also on
- * transceivers that don't need any software attention to set up
- * the right sort of wakeup.  
- */
-
-static int ehci_suspend (struct usb_hcd *hcd, pm_message_t message)
-{
-       struct ehci_hcd         *ehci = hcd_to_ehci (hcd);
-
-       if (time_before (jiffies, ehci->next_statechange))
-               msleep (100);
-
-#ifdef CONFIG_USB_SUSPEND
-       (void) usb_suspend_device (hcd->self.root_hub, message);
-#else
-       usb_lock_device (hcd->self.root_hub);
-       (void) ehci_hub_suspend (hcd);
-       usb_unlock_device (hcd->self.root_hub);
-#endif
-
-       // save (PCI) FLADJ in case of Vaux power loss
-       // ... we'd only use it to handle clock skew
-
-       return 0;
-}
-
-static int ehci_resume (struct usb_hcd *hcd)
-{
-       struct ehci_hcd         *ehci = hcd_to_ehci (hcd);
-       unsigned                port;
-       struct usb_device       *root = hcd->self.root_hub;
-       int                     retval = -EINVAL;
-
-       // maybe restore (PCI) FLADJ
-
-       if (time_before (jiffies, ehci->next_statechange))
-               msleep (100);
-
-       /* If any port is suspended (or owned by the companion),
-        * we know we can/must resume the HC (and mustn't reset it).
-        */
-       for (port = HCS_N_PORTS (ehci->hcs_params); port > 0; ) {
-               u32     status;
-               port--;
-               status = readl (&ehci->regs->port_status [port]);
-               if (!(status & PORT_POWER))
-                       continue;
-               if (status & (PORT_SUSPEND | PORT_OWNER)) {
-                       down (&hcd->self.root_hub->serialize);
-                       retval = ehci_hub_resume (hcd);
-                       up (&hcd->self.root_hub->serialize);
-                       break;
-               }
-               if (!root->children [port])
-                       continue;
-               dbg_port (ehci, __FUNCTION__, port + 1, status);
-               usb_set_device_state (root->children[port],
-                                       USB_STATE_NOTATTACHED);
-       }
-
-       /* Else reset, to cope with power loss or flush-to-storage
-        * style "resume" having activated BIOS during reboot.
-        */
-       if (port == 0) {
-               (void) ehci_halt (ehci);
-               (void) ehci_reset (ehci);
-               (void) ehci_hc_reset (hcd);
-
-               /* emptying the schedule aborts any urbs */
-               spin_lock_irq (&ehci->lock);
-               if (ehci->reclaim)
-                       ehci->reclaim_ready = 1;
-               ehci_work (ehci, NULL);
-               spin_unlock_irq (&ehci->lock);
-
-               /* restart; khubd will disconnect devices */
-               retval = ehci_start (hcd);
-
-               /* here we "know" root ports should always stay powered;
-                * but some controllers may lose all power.
-                */
-               ehci_port_power (ehci, 1);
-       }
-
-       return retval;
-}
-
-#endif
-
-/*-------------------------------------------------------------------------*/
-
-/*
- * ehci_work is called from some interrupts, timers, and so on.
- * it calls driver completion functions, after dropping ehci->lock.
- */
-static void ehci_work (struct ehci_hcd *ehci, struct pt_regs *regs)
-{
-       timer_action_done (ehci, TIMER_IO_WATCHDOG);
-       if (ehci->reclaim_ready)
-               end_unlink_async (ehci, regs);
-
-       /* another CPU may drop ehci->lock during a schedule scan while
-        * it reports urb completions.  this flag guards against bogus
-        * attempts at re-entrant schedule scanning.
-        */
-       if (ehci->scanning)
-               return;
-       ehci->scanning = 1;
-       scan_async (ehci, regs);
-       if (ehci->next_uframe != -1)
-               scan_periodic (ehci, regs);
-       ehci->scanning = 0;
-
-       /* the IO watchdog guards against hardware or driver bugs that
-        * misplace IRQs, and should let us run completely without IRQs.
-        * such lossage has been observed on both VT6202 and VT8235. 
-        */
-       if (HC_IS_RUNNING (ehci_to_hcd(ehci)->state) &&
-                       (ehci->async->qh_next.ptr != NULL ||
-                        ehci->periodic_sched != 0))
-               timer_action (ehci, TIMER_IO_WATCHDOG);
-}
-
 /*-------------------------------------------------------------------------*/
 
 static irqreturn_t ehci_irq (struct usb_hcd *hcd, struct pt_regs *regs)
@@ -1171,106 +872,24 @@ done:
        return;
 }
 
-/*-------------------------------------------------------------------------*/
-
-static const struct hc_driver ehci_driver = {
-       .description =          hcd_name,
-       .product_desc =         "EHCI Host Controller",
-       .hcd_priv_size =        sizeof(struct ehci_hcd),
-
-       /*
-        * generic hardware linkage
-        */
-       .irq =                  ehci_irq,
-       .flags =                HCD_MEMORY | HCD_USB2,
-
-       /*
-        * basic lifecycle operations
-        */
-       .reset =                ehci_hc_reset,
-       .start =                ehci_start,
-#ifdef CONFIG_PM
-       .suspend =              ehci_suspend,
-       .resume =               ehci_resume,
-#endif
-       .stop =                 ehci_stop,
-
-       /*
-        * managing i/o requests and associated device resources
-        */
-       .urb_enqueue =          ehci_urb_enqueue,
-       .urb_dequeue =          ehci_urb_dequeue,
-       .endpoint_disable =     ehci_endpoint_disable,
-
-       /*
-        * scheduling support
-        */
-       .get_frame_number =     ehci_get_frame,
-
-       /*
-        * root hub support
-        */
-       .hub_status_data =      ehci_hub_status_data,
-       .hub_control =          ehci_hub_control,
-       .hub_suspend =          ehci_hub_suspend,
-       .hub_resume =           ehci_hub_resume,
-};
+static int ehci_get_frame (struct usb_hcd *hcd)
+{
+       struct ehci_hcd         *ehci = hcd_to_ehci (hcd);
+       return (readl (&ehci->regs->frame_index) >> 3) % ehci->periodic_size;
+}
 
 /*-------------------------------------------------------------------------*/
 
-/* EHCI 1.0 doesn't require PCI */
-
-#ifdef CONFIG_PCI
-
-/* PCI driver selection metadata; PCI hotplugging uses this */
-static const struct pci_device_id pci_ids [] = { {
-       /* handle any USB 2.0 EHCI controller */
-       PCI_DEVICE_CLASS(((PCI_CLASS_SERIAL_USB << 8) | 0x20), ~0),
-       .driver_data =  (unsigned long) &ehci_driver,
-       },
-       { /* end: all zeroes */ }
-};
-MODULE_DEVICE_TABLE (pci, pci_ids);
-
-/* pci driver glue; this is a "new style" PCI driver module */
-static struct pci_driver ehci_pci_driver = {
-       .name =         (char *) hcd_name,
-       .id_table =     pci_ids,
-
-       .probe =        usb_hcd_pci_probe,
-       .remove =       usb_hcd_pci_remove,
-
-#ifdef CONFIG_PM
-       .suspend =      usb_hcd_pci_suspend,
-       .resume =       usb_hcd_pci_resume,
-#endif
-};
-
-#endif /* PCI */
-
-
 #define DRIVER_INFO DRIVER_VERSION " " DRIVER_DESC
 
 MODULE_DESCRIPTION (DRIVER_INFO);
 MODULE_AUTHOR (DRIVER_AUTHOR);
 MODULE_LICENSE ("GPL");
 
-static int __init init (void) 
-{
-       if (usb_disabled())
-               return -ENODEV;
-
-       pr_debug ("%s: block sizes: qh %Zd qtd %Zd itd %Zd sitd %Zd\n",
-               hcd_name,
-               sizeof (struct ehci_qh), sizeof (struct ehci_qtd),
-               sizeof (struct ehci_itd), sizeof (struct ehci_sitd));
-
-       return pci_register_driver (&ehci_pci_driver);
-}
-module_init (init);
+#ifdef CONFIG_PCI
+#include "ehci-pci.c"
+#endif
 
-static void __exit cleanup (void) 
-{      
-       pci_unregister_driver (&ehci_pci_driver);
-}
-module_exit (cleanup);
+#if !defined(CONFIG_PCI)
+#error "missing bus glue for ehci-hcd"
+#endif
index 18d3f22..88cb4ad 100644 (file)
@@ -30,7 +30,7 @@
 
 #ifdef CONFIG_PM
 
-static int ehci_hub_suspend (struct usb_hcd *hcd)
+static int ehci_bus_suspend (struct usb_hcd *hcd)
 {
        struct ehci_hcd         *ehci = hcd_to_ehci (hcd);
        int                     port;
@@ -83,7 +83,7 @@ static int ehci_hub_suspend (struct usb_hcd *hcd)
 
 
 /* caller has locked the root hub, and should reset/reinit on error */
-static int ehci_hub_resume (struct usb_hcd *hcd)
+static int ehci_bus_resume (struct usb_hcd *hcd)
 {
        struct ehci_hcd         *ehci = hcd_to_ehci (hcd);
        u32                     temp;
@@ -159,8 +159,8 @@ static int ehci_hub_resume (struct usb_hcd *hcd)
 
 #else
 
-#define ehci_hub_suspend       NULL
-#define ehci_hub_resume                NULL
+#define ehci_bus_suspend       NULL
+#define ehci_bus_resume                NULL
 
 #endif /* CONFIG_PM */
 
diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c
new file mode 100644 (file)
index 0000000..1450088
--- /dev/null
@@ -0,0 +1,415 @@
+/*
+ * EHCI HCD (Host Controller Driver) PCI Bus Glue.
+ *
+ * Copyright (c) 2000-2004 by David Brownell
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef CONFIG_PCI
+#error "This file is PCI bus glue.  CONFIG_PCI must be defined."
+#endif
+
+/*-------------------------------------------------------------------------*/
+
+/* EHCI 0.96 (and later) section 5.1 says how to kick BIOS/SMM/...
+ * off the controller (maybe it can boot from highspeed USB disks).
+ */
+static int bios_handoff (struct ehci_hcd *ehci, int where, u32 cap)
+{
+       struct pci_dev *pdev = to_pci_dev(ehci_to_hcd(ehci)->self.controller);
+
+       /* always say Linux will own the hardware */
+       pci_write_config_byte(pdev, where + 3, 1);
+
+       /* maybe wait a while for BIOS to respond */
+       if (cap & (1 << 16)) {
+               int msec = 5000;
+
+               do {
+                       msleep(10);
+                       msec -= 10;
+                       pci_read_config_dword(pdev, where, &cap);
+               } while ((cap & (1 << 16)) && msec);
+               if (cap & (1 << 16)) {
+                       ehci_err(ehci, "BIOS handoff failed (%d, %08x)\n",
+                               where, cap);
+                       // some BIOS versions seem buggy...
+                       // return 1;
+                       ehci_warn (ehci, "continuing after BIOS bug...\n");
+                       /* disable all SMIs, and clear "BIOS owns" flag */
+                       pci_write_config_dword(pdev, where + 4, 0);
+                       pci_write_config_byte(pdev, where + 2, 0);
+               } else
+                       ehci_dbg(ehci, "BIOS handoff succeeded\n");
+       }
+       return 0;
+}
+
+/* called by khubd or root hub init threads */
+static int ehci_pci_reset (struct usb_hcd *hcd)
+{
+       struct ehci_hcd         *ehci = hcd_to_ehci (hcd);
+       u32                     temp;
+       unsigned                count = 256/4;
+
+       spin_lock_init (&ehci->lock);
+
+       ehci->caps = hcd->regs;
+       ehci->regs = hcd->regs + HC_LENGTH (readl (&ehci->caps->hc_capbase));
+       dbg_hcs_params (ehci, "reset");
+       dbg_hcc_params (ehci, "reset");
+
+       /* cache this readonly data; minimize chip reads */
+       ehci->hcs_params = readl (&ehci->caps->hcs_params);
+
+       if (hcd->self.controller->bus == &pci_bus_type) {
+               struct pci_dev  *pdev = to_pci_dev(hcd->self.controller);
+
+               switch (pdev->vendor) {
+               case PCI_VENDOR_ID_TDI:
+                       if (pdev->device == PCI_DEVICE_ID_TDI_EHCI) {
+                               ehci->is_tdi_rh_tt = 1;
+                               tdi_reset (ehci);
+                       }
+                       break;
+               case PCI_VENDOR_ID_AMD:
+                       /* AMD8111 EHCI doesn't work, according to AMD errata */
+                       if (pdev->device == 0x7463) {
+                               ehci_info (ehci, "ignoring AMD8111 (errata)\n");
+                               return -EIO;
+                       }
+                       break;
+               case PCI_VENDOR_ID_NVIDIA:
+                       /* NVidia reports that certain chips don't handle
+                        * QH, ITD, or SITD addresses above 2GB.  (But TD,
+                        * data buffer, and periodic schedule are normal.)
+                        */
+                       switch (pdev->device) {
+                       case 0x003c:    /* MCP04 */
+                       case 0x005b:    /* CK804 */
+                       case 0x00d8:    /* CK8 */
+                       case 0x00e8:    /* CK8S */
+                               if (pci_set_consistent_dma_mask(pdev,
+                                                       DMA_31BIT_MASK) < 0)
+                                       ehci_warn (ehci, "can't enable NVidia "
+                                               "workaround for >2GB RAM\n");
+                               break;
+                       }
+                       break;
+               }
+
+               /* optional debug port, normally in the first BAR */
+               temp = pci_find_capability (pdev, 0x0a);
+               if (temp) {
+                       pci_read_config_dword(pdev, temp, &temp);
+                       temp >>= 16;
+                       if ((temp & (3 << 13)) == (1 << 13)) {
+                               temp &= 0x1fff;
+                               ehci->debug = hcd->regs + temp;
+                               temp = readl (&ehci->debug->control);
+                               ehci_info (ehci, "debug port %d%s\n",
+                                       HCS_DEBUG_PORT(ehci->hcs_params),
+                                       (temp & DBGP_ENABLED)
+                                               ? " IN USE"
+                                               : "");
+                               if (!(temp & DBGP_ENABLED))
+                                       ehci->debug = NULL;
+                       }
+               }
+
+               temp = HCC_EXT_CAPS (readl (&ehci->caps->hcc_params));
+       } else
+               temp = 0;
+
+       /* EHCI 0.96 and later may have "extended capabilities" */
+       while (temp && count--) {
+               u32             cap;
+
+               pci_read_config_dword (to_pci_dev(hcd->self.controller),
+                               temp, &cap);
+               ehci_dbg (ehci, "capability %04x at %02x\n", cap, temp);
+               switch (cap & 0xff) {
+               case 1:                 /* BIOS/SMM/... handoff */
+                       if (bios_handoff (ehci, temp, cap) != 0)
+                               return -EOPNOTSUPP;
+                       break;
+               case 0:                 /* illegal reserved capability */
+                       ehci_warn (ehci, "illegal capability!\n");
+                       cap = 0;
+                       /* FALLTHROUGH */
+               default:                /* unknown */
+                       break;
+               }
+               temp = (cap >> 8) & 0xff;
+       }
+       if (!count) {
+               ehci_err (ehci, "bogus capabilities ... PCI problems!\n");
+               return -EIO;
+       }
+       if (ehci_is_TDI(ehci))
+               ehci_reset (ehci);
+
+       ehci_port_power (ehci, 0);
+
+       /* at least the Genesys GL880S needs fixup here */
+       temp = HCS_N_CC(ehci->hcs_params) * HCS_N_PCC(ehci->hcs_params);
+       temp &= 0x0f;
+       if (temp && HCS_N_PORTS(ehci->hcs_params) > temp) {
+               ehci_dbg (ehci, "bogus port configuration: "
+                       "cc=%d x pcc=%d < ports=%d\n",
+                       HCS_N_CC(ehci->hcs_params),
+                       HCS_N_PCC(ehci->hcs_params),
+                       HCS_N_PORTS(ehci->hcs_params));
+
+               if (hcd->self.controller->bus == &pci_bus_type) {
+                       struct pci_dev  *pdev;
+
+                       pdev = to_pci_dev(hcd->self.controller);
+                       switch (pdev->vendor) {
+                       case 0x17a0:            /* GENESYS */
+                               /* GL880S: should be PORTS=2 */
+                               temp |= (ehci->hcs_params & ~0xf);
+                               ehci->hcs_params = temp;
+                               break;
+                       case PCI_VENDOR_ID_NVIDIA:
+                               /* NF4: should be PCC=10 */
+                               break;
+                       }
+               }
+       }
+
+       /* force HC to halt state */
+       return ehci_halt (ehci);
+}
+
+static int ehci_pci_start (struct usb_hcd *hcd)
+{
+       struct ehci_hcd         *ehci = hcd_to_ehci (hcd);
+       int result = 0;
+
+       if (hcd->self.controller->bus == &pci_bus_type) {
+               struct pci_dev          *pdev;
+               u16                     port_wake;
+
+               pdev = to_pci_dev(hcd->self.controller);
+
+               /* Serial Bus Release Number is at PCI 0x60 offset */
+               pci_read_config_byte(pdev, 0x60, &ehci->sbrn);
+
+               /* port wake capability, reported by boot firmware */
+               pci_read_config_word(pdev, 0x62, &port_wake);
+               hcd->can_wakeup = (port_wake & 1) != 0;
+
+               /* help hc dma work well with cachelines */
+               result = pci_set_mwi(pdev);
+               if (result)
+                       ehci_dbg(ehci, "unable to enable MWI - not fatal.\n");
+       }
+
+       return ehci_run (hcd);
+}
+
+/* always called by thread; normally rmmod */
+
+static void ehci_pci_stop (struct usb_hcd *hcd)
+{
+       ehci_stop (hcd);
+}
+
+/*-------------------------------------------------------------------------*/
+
+#ifdef CONFIG_PM
+
+/* suspend/resume, section 4.3 */
+
+/* These routines rely on the bus (pci, platform, etc)
+ * to handle powerdown and wakeup, and currently also on
+ * transceivers that don't need any software attention to set up
+ * the right sort of wakeup.
+ */
+
+static int ehci_pci_suspend (struct usb_hcd *hcd, pm_message_t message)
+{
+       struct ehci_hcd         *ehci = hcd_to_ehci (hcd);
+
+       if (time_before (jiffies, ehci->next_statechange))
+               msleep (100);
+
+#ifdef CONFIG_USB_SUSPEND
+       (void) usb_suspend_device (hcd->self.root_hub);
+#else
+       usb_lock_device (hcd->self.root_hub);
+       (void) ehci_bus_suspend (hcd);
+       usb_unlock_device (hcd->self.root_hub);
+#endif
+
+       // save (PCI) FLADJ in case of Vaux power loss
+       // ... we'd only use it to handle clock skew
+
+       return 0;
+}
+
+static int ehci_pci_resume (struct usb_hcd *hcd)
+{
+       struct ehci_hcd         *ehci = hcd_to_ehci (hcd);
+       unsigned                port;
+       struct usb_device       *root = hcd->self.root_hub;
+       int                     retval = -EINVAL;
+
+       // maybe restore (PCI) FLADJ
+
+       if (time_before (jiffies, ehci->next_statechange))
+               msleep (100);
+
+       /* If any port is suspended (or owned by the companion),
+        * we know we can/must resume the HC (and mustn't reset it).
+        */
+       for (port = HCS_N_PORTS (ehci->hcs_params); port > 0; ) {
+               u32     status;
+               port--;
+               status = readl (&ehci->regs->port_status [port]);
+               if (!(status & PORT_POWER))
+                       continue;
+               if (status & (PORT_SUSPEND | PORT_OWNER)) {
+                       down (&hcd->self.root_hub->serialize);
+                       retval = ehci_bus_resume (hcd);
+                       up (&hcd->self.root_hub->serialize);
+                       break;
+               }
+               if (!root->children [port])
+                       continue;
+               dbg_port (ehci, __FUNCTION__, port + 1, status);
+               usb_set_device_state (root->children[port],
+                                       USB_STATE_NOTATTACHED);
+       }
+
+       /* Else reset, to cope with power loss or flush-to-storage
+        * style "resume" having activated BIOS during reboot.
+        */
+       if (port == 0) {
+               (void) ehci_halt (ehci);
+               (void) ehci_reset (ehci);
+               (void) ehci_pci_reset (hcd);
+
+               /* emptying the schedule aborts any urbs */
+               spin_lock_irq (&ehci->lock);
+               if (ehci->reclaim)
+                       ehci->reclaim_ready = 1;
+               ehci_work (ehci, NULL);
+               spin_unlock_irq (&ehci->lock);
+
+               /* restart; khubd will disconnect devices */
+               retval = ehci_run (hcd);
+
+               /* here we "know" root ports should always stay powered;
+                * but some controllers may lose all power.
+                */
+               ehci_port_power (ehci, 1);
+       }
+
+       return retval;
+}
+#endif
+
+static const struct hc_driver ehci_pci_hc_driver = {
+       .description =          hcd_name,
+       .product_desc =         "EHCI Host Controller",
+       .hcd_priv_size =        sizeof(struct ehci_hcd),
+
+       /*
+        * generic hardware linkage
+        */
+       .irq =                  ehci_irq,
+       .flags =                HCD_MEMORY | HCD_USB2,
+
+       /*
+        * basic lifecycle operations
+        */
+       .reset =                ehci_pci_reset,
+       .start =                ehci_pci_start,
+#ifdef CONFIG_PM
+       .suspend =              ehci_pci_suspend,
+       .resume =               ehci_pci_resume,
+#endif
+       .stop =                 ehci_pci_stop,
+
+       /*
+        * managing i/o requests and associated device resources
+        */
+       .urb_enqueue =          ehci_urb_enqueue,
+       .urb_dequeue =          ehci_urb_dequeue,
+       .endpoint_disable =     ehci_endpoint_disable,
+
+       /*
+        * scheduling support
+        */
+       .get_frame_number =     ehci_get_frame,
+
+       /*
+        * root hub support
+        */
+       .hub_status_data =      ehci_hub_status_data,
+       .hub_control =          ehci_hub_control,
+       .bus_suspend =          ehci_bus_suspend,
+       .bus_resume =           ehci_bus_resume,
+};
+
+/*-------------------------------------------------------------------------*/
+
+/* PCI driver selection metadata; PCI hotplugging uses this */
+static const struct pci_device_id pci_ids [] = { {
+       /* handle any USB 2.0 EHCI controller */
+       PCI_DEVICE_CLASS(((PCI_CLASS_SERIAL_USB << 8) | 0x20), ~0),
+       .driver_data =  (unsigned long) &ehci_pci_hc_driver,
+       },
+       { /* end: all zeroes */ }
+};
+MODULE_DEVICE_TABLE (pci, pci_ids);
+
+/* pci driver glue; this is a "new style" PCI driver module */
+static struct pci_driver ehci_pci_driver = {
+       .name =         (char *) hcd_name,
+       .id_table =     pci_ids,
+       .owner =        THIS_MODULE,
+
+       .probe =        usb_hcd_pci_probe,
+       .remove =       usb_hcd_pci_remove,
+
+#ifdef CONFIG_PM
+       .suspend =      usb_hcd_pci_suspend,
+       .resume =       usb_hcd_pci_resume,
+#endif
+};
+
+static int __init ehci_hcd_pci_init (void)
+{
+       if (usb_disabled())
+               return -ENODEV;
+
+       pr_debug ("%s: block sizes: qh %Zd qtd %Zd itd %Zd sitd %Zd\n",
+               hcd_name,
+               sizeof (struct ehci_qh), sizeof (struct ehci_qtd),
+               sizeof (struct ehci_itd), sizeof (struct ehci_sitd));
+
+       return pci_register_driver (&ehci_pci_driver);
+}
+module_init (ehci_hcd_pci_init);
+
+static void __exit ehci_hcd_pci_cleanup (void)
+{
+       pci_unregister_driver (&ehci_pci_driver);
+}
+module_exit (ehci_hcd_pci_cleanup);
index f34a051..18e257c 100644 (file)
@@ -97,6 +97,7 @@ struct ehci_hcd {                     /* one per controller */
 #else
 #      define COUNT(x) do {} while (0)
 #endif
+       u8                      sbrn;           /* packed release number */
 };
 
 /* convert between an HCD pointer and the corresponding EHCI_HCD */ 
index 642f350..ddb8fc5 100644 (file)
@@ -638,7 +638,7 @@ static irqreturn_t isp116x_irq(struct usb_hcd *hcd, struct pt_regs *regs)
                                  + msecs_to_jiffies(20) + 1);
                if (intstat & HCINT_RD) {
                        DBG("---- remote wakeup\n");
-                       schedule_work(&isp116x->rh_resume);
+                       usb_hcd_resume_root_hub(hcd);
                        ret = IRQ_HANDLED;
                }
                irqstat &= ~HCuPINT_OPR;
@@ -1160,7 +1160,7 @@ static int isp116x_hub_control(struct usb_hcd *hcd,
 
 #ifdef CONFIG_PM
 
-static int isp116x_hub_suspend(struct usb_hcd *hcd)
+static int isp116x_bus_suspend(struct usb_hcd *hcd)
 {
        struct isp116x *isp116x = hcd_to_isp116x(hcd);
        unsigned long flags;
@@ -1200,7 +1200,7 @@ static int isp116x_hub_suspend(struct usb_hcd *hcd)
        return ret;
 }
 
-static int isp116x_hub_resume(struct usb_hcd *hcd)
+static int isp116x_bus_resume(struct usb_hcd *hcd)
 {
        struct isp116x *isp116x = hcd_to_isp116x(hcd);
        u32 val;
@@ -1263,21 +1263,11 @@ static int isp116x_hub_resume(struct usb_hcd *hcd)
        return 0;
 }
 
-static void isp116x_rh_resume(void *_hcd)
-{
-       struct usb_hcd *hcd = _hcd;
-
-       usb_resume_device(hcd->self.root_hub);
-}
 
 #else
 
-#define        isp116x_hub_suspend     NULL
-#define        isp116x_hub_resume      NULL
-
-static void isp116x_rh_resume(void *_hcd)
-{
-}
+#define        isp116x_bus_suspend     NULL
+#define        isp116x_bus_resume      NULL
 
 #endif
 
@@ -1636,8 +1626,8 @@ static struct hc_driver isp116x_hc_driver = {
 
        .hub_status_data = isp116x_hub_status_data,
        .hub_control = isp116x_hub_control,
-       .hub_suspend = isp116x_hub_suspend,
-       .hub_resume = isp116x_hub_resume,
+       .bus_suspend = isp116x_bus_suspend,
+       .bus_resume = isp116x_bus_resume,
 };
 
 /*----------------------------------------------------------------*/
@@ -1732,7 +1722,6 @@ static int __init isp116x_probe(struct device *dev)
        isp116x->addr_reg = addr_reg;
        spin_lock_init(&isp116x->lock);
        INIT_LIST_HEAD(&isp116x->async);
-       INIT_WORK(&isp116x->rh_resume, isp116x_rh_resume, hcd);
        isp116x->board = dev->platform_data;
 
        if (!isp116x->board) {
@@ -1777,16 +1766,10 @@ static int __init isp116x_probe(struct device *dev)
 static int isp116x_suspend(struct device *dev, pm_message_t state)
 {
        int ret = 0;
-       struct usb_hcd *hcd = dev_get_drvdata(dev);
 
        VDBG("%s: state %x\n", __func__, state);
 
-       ret = usb_suspend_device(hcd->self.root_hub, state);
-       if (!ret) {
-               dev->power.power_state = state;
-               INFO("%s suspended\n", hcd_name);
-       } else
-               ERR("%s suspend failed\n", hcd_name);
+       dev->power.power_state = state;
 
        return ret;
 }
@@ -1797,15 +1780,11 @@ static int isp116x_suspend(struct device *dev, pm_message_t state)
 static int isp116x_resume(struct device *dev)
 {
        int ret = 0;
-       struct usb_hcd *hcd = dev_get_drvdata(dev);
 
        VDBG("%s:  state %x\n", __func__, dev->power.power_state);
 
-       ret = usb_resume_device(hcd->self.root_hub);
-       if (!ret) {
-               dev->power.power_state = PMSG_ON;
-               VDBG("%s resumed\n", (char *)hcd_name);
-       }
+       dev->power.power_state = PMSG_ON;
+
        return ret;
 }
 
index 5887347..c6fec96 100644 (file)
@@ -253,7 +253,6 @@ static const int cc_to_error[16] = {
 
 struct isp116x {
        spinlock_t lock;
-       struct work_struct rh_resume;
 
        void __iomem *addr_reg;
        void __iomem *data_reg;
index 3981bf1..a277e25 100644 (file)
@@ -214,6 +214,11 @@ static const struct hc_driver ohci_au1xxx_hc_driver = {
         */
        .hub_status_data =      ohci_hub_status_data,
        .hub_control =          ohci_hub_control,
+#ifdef CONFIG_PM
+       .bus_suspend =          ohci_bus_suspend,
+       .bus_resume =           ohci_bus_resume,
+#endif
+       .start_port_reset =     ohci_start_port_reset,
 };
 
 /*-------------------------------------------------------------------------*/
@@ -259,6 +264,7 @@ static int ohci_hcd_au1xxx_drv_resume(struct device *dev)
 
 static struct device_driver ohci_hcd_au1xxx_driver = {
        .name           = "au1xxx-ohci",
+       .owner          = THIS_MODULE,
        .bus            = &platform_bus_type,
        .probe          = ohci_hcd_au1xxx_drv_probe,
        .remove         = ohci_hcd_au1xxx_drv_remove,
index 7924c74..7bfffcb 100644 (file)
@@ -193,10 +193,6 @@ ohci_dump_status (struct ohci_hcd *controller, char **next, unsigned *size)
 
        maybe_print_eds (controller, "donehead",
                        ohci_readl (controller, &regs->donehead), next, size);
-
-       /* broken fminterval means traffic won't flow! */ 
-       ohci_dbg (controller, "fminterval %08x\n", 
-                       ohci_readl (controller, &regs->fminterval));
 }
 
 #define dbg_port_sw(hc,num,value,next,size) \
index f8da8c7..5c0c6c8 100644 (file)
@@ -723,7 +723,7 @@ static irqreturn_t ohci_irq (struct usb_hcd *hcd, struct pt_regs *ptregs)
                ohci_vdbg (ohci, "resume detect\n");
                ohci_writel (ohci, OHCI_INTR_RD, &regs->intrstatus);
                if (hcd->state != HC_STATE_QUIESCING)
-                       schedule_work(&ohci->rh_resume);
+                       usb_hcd_resume_root_hub(hcd);
        }
 
        if (ints & OHCI_INTR_WDH) {
@@ -791,7 +791,7 @@ static void ohci_stop (struct usb_hcd *hcd)
 
 /* must not be called from interrupt context */
 
-#if    defined(CONFIG_USB_SUSPEND) || defined(CONFIG_PM)
+#ifdef CONFIG_PM
 
 static int ohci_restart (struct ohci_hcd *ohci)
 {
index ce7b28d..e01e77b 100644 (file)
@@ -36,7 +36,7 @@
 
 /*-------------------------------------------------------------------------*/
 
-#if    defined(CONFIG_USB_SUSPEND) || defined(CONFIG_PM)
+#ifdef CONFIG_PM
 
 #define OHCI_SCHED_ENABLES \
        (OHCI_CTRL_CLE|OHCI_CTRL_BLE|OHCI_CTRL_PLE|OHCI_CTRL_IE)
@@ -45,7 +45,7 @@ static void dl_done_list (struct ohci_hcd *, struct pt_regs *);
 static void finish_unlinks (struct ohci_hcd *, u16 , struct pt_regs *);
 static int ohci_restart (struct ohci_hcd *ohci);
 
-static int ohci_hub_suspend (struct usb_hcd *hcd)
+static int ohci_bus_suspend (struct usb_hcd *hcd)
 {
        struct ohci_hcd         *ohci = hcd_to_ohci (hcd);
        int                     status = 0;
@@ -73,7 +73,6 @@ static int ohci_hub_suspend (struct usb_hcd *hcd)
        ohci_dbg (ohci, "suspend root hub\n");
 
        /* First stop any processing */
-       hcd->state = HC_STATE_QUIESCING;
        if (ohci->hc_control & OHCI_SCHED_ENABLES) {
                int             limit;
 
@@ -108,7 +107,9 @@ static int ohci_hub_suspend (struct usb_hcd *hcd)
        else
                ohci->hc_control &= ~OHCI_CTRL_RWE;
 
-       /* Suspend hub */
+       /* Suspend hub ... this is the "global (to this bus) suspend" mode,
+        * which doesn't imply ports will first be individually suspended.
+        */
        ohci->hc_control &= ~OHCI_CTRL_HCFS;
        ohci->hc_control |= OHCI_USB_SUSPEND;
        ohci_writel (ohci, ohci->hc_control, &ohci->regs->control);
@@ -118,8 +119,9 @@ static int ohci_hub_suspend (struct usb_hcd *hcd)
        ohci->next_statechange = jiffies + msecs_to_jiffies (5);
 
 done:
+       /* external suspend vs self autosuspend ... same effect */
        if (status == 0)
-               hcd->state = HC_STATE_SUSPENDED;
+               usb_hcd_suspend_root_hub(hcd);
        spin_unlock_irqrestore (&ohci->lock, flags);
        return status;
 }
@@ -133,7 +135,7 @@ static inline struct ed *find_head (struct ed *ed)
 }
 
 /* caller has locked the root hub */
-static int ohci_hub_resume (struct usb_hcd *hcd)
+static int ohci_bus_resume (struct usb_hcd *hcd)
 {
        struct ohci_hcd         *ohci = hcd_to_ohci (hcd);
        u32                     temp, enables;
@@ -146,7 +148,7 @@ static int ohci_hub_resume (struct usb_hcd *hcd)
        ohci->hc_control = ohci_readl (ohci, &ohci->regs->control);
 
        if (ohci->hc_control & (OHCI_CTRL_IR | OHCI_SCHED_ENABLES)) {
-               /* this can happen after suspend-to-disk */
+               /* this can happen after resuming a swsusp snapshot */
                if (hcd->state == HC_STATE_RESUMING) {
                        ohci_dbg (ohci, "BIOS/SMM active, control %03x\n",
                                        ohci->hc_control);
@@ -169,11 +171,12 @@ static int ohci_hub_resume (struct usb_hcd *hcd)
                ohci_info (ohci, "wakeup\n");
                break;
        case OHCI_USB_OPER:
-               ohci_dbg (ohci, "already resumed\n");
-               status = 0;
+               /* this can happen after resuming a swsusp snapshot */
+               ohci_dbg (ohci, "snapshot resume? reinit\n");
+               status = -EBUSY;
                break;
        default:                /* RESET, we lost power */
-               ohci_dbg (ohci, "root hub hardware reset\n");
+               ohci_dbg (ohci, "lost power\n");
                status = -EBUSY;
        }
        spin_unlock_irq (&ohci->lock);
@@ -198,8 +201,7 @@ static int ohci_hub_resume (struct usb_hcd *hcd)
        }
 
        /* Some controllers (lucent erratum) need extra-long delays */
-       hcd->state = HC_STATE_RESUMING;
-       mdelay (20 /* usb 11.5.1.10 */ + 15);
+       msleep (20 /* usb 11.5.1.10 */ + 12 /* 32 msec counter */ + 1);
 
        temp = ohci_readl (ohci, &ohci->regs->control);
        temp &= OHCI_CTRL_HCFS;
@@ -273,28 +275,10 @@ static int ohci_hub_resume (struct usb_hcd *hcd)
                (void) ohci_readl (ohci, &ohci->regs->control);
        }
 
-       hcd->state = HC_STATE_RUNNING;
        return 0;
 }
 
-static void ohci_rh_resume (void *_hcd)
-{
-       struct usb_hcd  *hcd = _hcd;
-
-       usb_lock_device (hcd->self.root_hub);
-       (void) ohci_hub_resume (hcd);
-       usb_unlock_device (hcd->self.root_hub);
-}
-
-#else
-
-static void ohci_rh_resume (void *_hcd)
-{
-       struct ohci_hcd *ohci = hcd_to_ohci (_hcd);
-       ohci_dbg(ohci, "rh_resume ??\n");
-}
-
-#endif /* CONFIG_USB_SUSPEND || CONFIG_PM */
+#endif /* CONFIG_PM */
 
 /*-------------------------------------------------------------------------*/
 
@@ -367,7 +351,6 @@ done:
 #ifdef CONFIG_PM
        /* save power by suspending idle root hubs;
         * INTR_RD wakes us when there's work
-        * NOTE: if we can do this, we don't need a root hub timer!
         */
        if (can_suspend
                        && !changed
@@ -379,8 +362,7 @@ done:
                        && usb_trylock_device (hcd->self.root_hub)
                        ) {
                ohci_vdbg (ohci, "autosuspend\n");
-               (void) ohci_hub_suspend (hcd);
-               hcd->state = HC_STATE_RUNNING;
+               (void) ohci_bus_suspend (hcd);
                usb_unlock_device (hcd->self.root_hub);
        }
 #endif
@@ -554,7 +536,7 @@ static int ohci_hub_control (
                        temp = RH_PS_POCI;
                        if ((ohci->hc_control & OHCI_CTRL_HCFS)
                                        != OHCI_USB_OPER)
-                               schedule_work (&ohci->rh_resume);
+                               usb_hcd_resume_root_hub(hcd);
                        break;
                case USB_PORT_FEAT_C_SUSPEND:
                        temp = RH_PS_PSSC;
index 859aca7..238fa4a 100644 (file)
@@ -193,6 +193,11 @@ static const struct hc_driver ohci_lh7a404_hc_driver = {
         */
        .hub_status_data =      ohci_hub_status_data,
        .hub_control =          ohci_hub_control,
+#ifdef CONFIG_PM
+       .bus_suspend =          ohci_bus_suspend,
+       .bus_resume =           ohci_bus_resume,
+#endif
+       .start_port_reset =     ohci_start_port_reset,
 };
 
 /*-------------------------------------------------------------------------*/
@@ -239,6 +244,7 @@ static int ohci_hcd_lh7a404_drv_resume(struct device *dev)
 
 static struct device_driver ohci_hcd_lh7a404_driver = {
        .name           = "lh7a404-ohci",
+       .owner          = THIS_MODULE,
        .bus            = &platform_bus_type,
        .probe          = ohci_hcd_lh7a404_drv_probe,
        .remove         = ohci_hcd_lh7a404_drv_remove,
index 9fb83df..bfbe328 100644 (file)
@@ -28,7 +28,6 @@ static void ohci_hcd_init (struct ohci_hcd *ohci)
        ohci->next_statechange = jiffies;
        spin_lock_init (&ohci->lock);
        INIT_LIST_HEAD (&ohci->pending);
-       INIT_WORK (&ohci->rh_resume, ohci_rh_resume, ohci_to_hcd(ohci));
        ohci->reboot_notifier.notifier_call = ohci_reboot;
 }
 
index a574216..45efeed 100644 (file)
@@ -420,9 +420,9 @@ static const struct hc_driver ohci_omap_hc_driver = {
         */
        .hub_status_data =      ohci_hub_status_data,
        .hub_control =          ohci_hub_control,
-#ifdef CONFIG_USB_SUSPEND
-       .hub_suspend =          ohci_hub_suspend,
-       .hub_resume =           ohci_hub_resume,
+#ifdef CONFIG_PM
+       .bus_suspend =          ohci_bus_suspend,
+       .bus_resume =           ohci_bus_resume,
 #endif
        .start_port_reset =     ohci_start_port_reset,
 };
@@ -458,41 +458,29 @@ static int ohci_hcd_omap_drv_remove(struct device *dev)
 static int ohci_omap_suspend(struct device *dev, pm_message_t message)
 {
        struct ohci_hcd *ohci = hcd_to_ohci(dev_get_drvdata(dev));
-       int             status = -EINVAL;
-
-       down(&ohci_to_hcd(ohci)->self.root_hub->serialize);
-       status = ohci_hub_suspend(ohci_to_hcd(ohci));
-       if (status == 0) {
-               omap_ohci_clock_power(0);
-               ohci_to_hcd(ohci)->self.root_hub->state =
-                       USB_STATE_SUSPENDED;
-               ohci_to_hcd(ohci)->state = HC_STATE_SUSPENDED;
-               dev->power.power_state = PMSG_SUSPEND;
-       }
-       up(&ohci_to_hcd(ohci)->self.root_hub->serialize);
-       return status;
+
+       if (time_before(jiffies, ohci->next_statechange))
+               msleep(5);
+       ohci->next_statechange = jiffies;
+
+       omap_ohci_clock_power(0);
+       ohci_to_hcd(ohci)->state = HC_STATE_SUSPENDED;
+       dev->power.power_state = PMSG_SUSPEND;
+       return 0;
 }
 
 static int ohci_omap_resume(struct device *dev)
 {
        struct ohci_hcd *ohci = hcd_to_ohci(dev_get_drvdata(dev));
-       int             status = 0;
 
        if (time_before(jiffies, ohci->next_statechange))
                msleep(5);
        ohci->next_statechange = jiffies;
+
        omap_ohci_clock_power(1);
-#ifdef CONFIG_USB_SUSPEND
-       /* get extra cleanup even if remote wakeup isn't in use */
-       status = usb_resume_device(ohci_to_hcd(ohci)->self.root_hub);
-#else
-       down(&ohci_to_hcd(ohci)->self.root_hub->serialize);
-       status = ohci_hub_resume(ohci_to_hcd(ohci));
-       up(&ohci_to_hcd(ohci)->self.root_hub->serialize);
-#endif
-       if (status == 0)
-               dev->power.power_state = PMSG_ON;
-       return status;
+       dev->power.power_state = PMSG_ON;
+       usb_hcd_resume_root_hub(dev_get_drvdata(dev));
+       return 0;
 }
 
 #endif
@@ -504,6 +492,7 @@ static int ohci_omap_resume(struct device *dev)
  */
 static struct device_driver ohci_hcd_omap_driver = {
        .name           = "ohci",
+       .owner          = THIS_MODULE,
        .bus            = &platform_bus_type,
        .probe          = ohci_hcd_omap_drv_probe,
        .remove         = ohci_hcd_omap_drv_remove,
index eede6be..bf1d5ab 100644 (file)
@@ -112,23 +112,13 @@ ohci_pci_start (struct usb_hcd *hcd)
 
 static int ohci_pci_suspend (struct usb_hcd *hcd, pm_message_t message)
 {
-       struct ohci_hcd         *ohci = hcd_to_ohci (hcd);
-
-       /* suspend root hub, hoping it keeps power during suspend */
-       if (time_before (jiffies, ohci->next_statechange))
-               msleep (100);
-
-#ifdef CONFIG_USB_SUSPEND
-       (void) usb_suspend_device (hcd->self.root_hub, message);
-#else
-       usb_lock_device (hcd->self.root_hub);
-       (void) ohci_hub_suspend (hcd);
-       usb_unlock_device (hcd->self.root_hub);
-#endif
+       /* root hub was already suspended */
 
-       /* let things settle down a bit */
-       msleep (100);
-       
+       /* FIXME these PMAC things get called in the wrong places.  ASIC
+        * clocks should be turned off AFTER entering D3, and on BEFORE
+        * trying to enter D0.  Evidently the PCI layer doesn't currently
+        * provide the right sort of platform hooks for this ...
+        */
 #ifdef CONFIG_PPC_PMAC
        if (_machine == _MACH_Pmac) {
                struct device_node      *of_node;
@@ -145,9 +135,6 @@ static int ohci_pci_suspend (struct usb_hcd *hcd, pm_message_t message)
 
 static int ohci_pci_resume (struct usb_hcd *hcd)
 {
-       struct ohci_hcd         *ohci = hcd_to_ohci (hcd);
-       int                     retval = 0;
-
 #ifdef CONFIG_PPC_PMAC
        if (_machine == _MACH_Pmac) {
                struct device_node *of_node;
@@ -159,19 +146,8 @@ static int ohci_pci_resume (struct usb_hcd *hcd)
        }
 #endif /* CONFIG_PPC_PMAC */
 
-       /* resume root hub */
-       if (time_before (jiffies, ohci->next_statechange))
-               msleep (100);
-#ifdef CONFIG_USB_SUSPEND
-       /* get extra cleanup even if remote wakeup isn't in use */
-       retval = usb_resume_device (hcd->self.root_hub);
-#else
-       usb_lock_device (hcd->self.root_hub);
-       retval = ohci_hub_resume (hcd);
-       usb_unlock_device (hcd->self.root_hub);
-#endif
-
-       return retval;
+       usb_hcd_resume_root_hub(hcd);
+       return 0;
 }
 
 #endif /* CONFIG_PM */
@@ -218,9 +194,9 @@ static const struct hc_driver ohci_pci_hc_driver = {
         */
        .hub_status_data =      ohci_hub_status_data,
        .hub_control =          ohci_hub_control,
-#ifdef CONFIG_USB_SUSPEND
-       .hub_suspend =          ohci_hub_suspend,
-       .hub_resume =           ohci_hub_resume,
+#ifdef CONFIG_PM
+       .bus_suspend =          ohci_bus_suspend,
+       .bus_resume =           ohci_bus_resume,
 #endif
        .start_port_reset =     ohci_start_port_reset,
 };
@@ -240,6 +216,7 @@ MODULE_DEVICE_TABLE (pci, pci_ids);
 static struct pci_driver ohci_pci_driver = {
        .name =         (char *) hcd_name,
        .id_table =     pci_ids,
+       .owner =        THIS_MODULE,
 
        .probe =        usb_hcd_pci_probe,
        .remove =       usb_hcd_pci_remove,
index 2515333..4832e57 100644 (file)
@@ -163,9 +163,9 @@ static const struct hc_driver ohci_ppc_soc_hc_driver = {
         */
        .hub_status_data =      ohci_hub_status_data,
        .hub_control =          ohci_hub_control,
-#ifdef CONFIG_USB_SUSPEND
-       .hub_suspend =          ohci_hub_suspend,
-       .hub_resume =           ohci_hub_resume,
+#ifdef CONFIG_PM
+       .bus_suspend =          ohci_bus_suspend,
+       .bus_resume =           ohci_bus_resume,
 #endif
        .start_port_reset =     ohci_start_port_reset,
 };
@@ -193,10 +193,11 @@ static int ohci_hcd_ppc_soc_drv_remove(struct device *dev)
 
 static struct device_driver ohci_hcd_ppc_soc_driver = {
        .name           = "ppc-soc-ohci",
+       .owner          = THIS_MODULE,
        .bus            = &platform_bus_type,
        .probe          = ohci_hcd_ppc_soc_drv_probe,
        .remove         = ohci_hcd_ppc_soc_drv_remove,
-#if    defined(CONFIG_USB_SUSPEND) || defined(CONFIG_PM)
+#ifdef CONFIG_PM
        /*.suspend      = ohci_hcd_ppc_soc_drv_suspend,*/
        /*.resume       = ohci_hcd_ppc_soc_drv_resume,*/
 #endif
index f042261..d287dcc 100644 (file)
@@ -278,10 +278,11 @@ static const struct hc_driver ohci_pxa27x_hc_driver = {
         */
        .hub_status_data =      ohci_hub_status_data,
        .hub_control =          ohci_hub_control,
-#ifdef  CONFIG_USB_SUSPEND
-       .hub_suspend =          ohci_hub_suspend,
-       .hub_resume =           ohci_hub_resume,
+#ifdef  CONFIG_PM
+       .bus_suspend =          ohci_bus_suspend,
+       .bus_resume =           ohci_bus_resume,
 #endif
+       .start_port_reset =     ohci_start_port_reset,
 };
 
 /*-------------------------------------------------------------------------*/
index da7d547..fab420a 100644 (file)
@@ -448,11 +448,11 @@ static const struct hc_driver ohci_s3c2410_hc_driver = {
         */
        .hub_status_data =      ohci_s3c2410_hub_status_data,
        .hub_control =          ohci_s3c2410_hub_control,
-
-#if defined(CONFIG_USB_SUSPEND) && 0
-       .hub_suspend =          ohci_hub_suspend,
-       .hub_resume =           ohci_hub_resume,
+#ifdef CONFIG_PM
+       .bus_suspend =          ohci_bus_suspend,
+       .bus_resume =           ohci_bus_resume,
 #endif
+       .start_port_reset =     ohci_start_port_reset,
 };
 
 /* device driver */
@@ -474,6 +474,7 @@ static int ohci_hcd_s3c2410_drv_remove(struct device *dev)
 
 static struct device_driver ohci_hcd_s3c2410_driver = {
        .name           = "s3c2410-ohci",
+       .owner          = THIS_MODULE,
        .bus            = &platform_bus_type,
        .probe          = ohci_hcd_s3c2410_drv_probe,
        .remove         = ohci_hcd_s3c2410_drv_remove,
index 814d2be..fb3221e 100644 (file)
@@ -235,10 +235,11 @@ static const struct hc_driver ohci_sa1111_hc_driver = {
         */
        .hub_status_data =      ohci_hub_status_data,
        .hub_control =          ohci_hub_control,
-#ifdef CONFIG_USB_SUSPEND
-       .hub_suspend =          ohci_hub_suspend,
-       .hub_resume =           ohci_hub_resume,
+#ifdef CONFIG_PM
+       .bus_suspend =          ohci_bus_suspend,
+       .bus_resume =           ohci_bus_resume,
 #endif
+       .start_port_reset =     ohci_start_port_reset,
 };
 
 /*-------------------------------------------------------------------------*/
index 8a9b9d9..caacf14 100644 (file)
@@ -389,7 +389,6 @@ struct ohci_hcd {
        unsigned long           next_statechange;       /* suspend/resume */
        u32                     fminterval;             /* saved register */
 
-       struct work_struct      rh_resume;
        struct notifier_block   reboot_notifier;
 
        unsigned long           flags;          /* for HC bugs */
diff --git a/drivers/usb/host/pci-quirks.c b/drivers/usb/host/pci-quirks.c
new file mode 100644 (file)
index 0000000..b7fd3f6
--- /dev/null
@@ -0,0 +1,296 @@
+/*
+ * This file contains code to reset and initialize USB host controllers.
+ * Some of it includes work-arounds for PCI hardware and BIOS quirks.
+ * It may need to run early during booting -- before USB would normally
+ * initialize -- to ensure that Linux doesn't use any legacy modes.
+ *
+ *  Copyright (c) 1999 Martin Mares <mj@ucw.cz>
+ *  (and others)
+ */
+
+#include <linux/config.h>
+#ifdef CONFIG_USB_DEBUG
+#define DEBUG
+#else
+#undef DEBUG
+#endif
+
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/acpi.h>
+
+
+#define UHCI_USBLEGSUP         0xc0            /* legacy support */
+#define UHCI_USBCMD            0               /* command register */
+#define UHCI_USBINTR           4               /* interrupt register */
+#define UHCI_USBLEGSUP_RWC     0x8f00          /* the R/WC bits */
+#define UHCI_USBLEGSUP_RO      0x5040          /* R/O and reserved bits */
+#define UHCI_USBCMD_RUN                0x0001          /* RUN/STOP bit */
+#define UHCI_USBCMD_HCRESET    0x0002          /* Host Controller reset */
+#define UHCI_USBCMD_EGSM       0x0008          /* Global Suspend Mode */
+#define UHCI_USBCMD_CONFIGURE  0x0040          /* Config Flag */
+#define UHCI_USBINTR_RESUME    0x0002          /* Resume interrupt enable */
+
+#define OHCI_CONTROL           0x04
+#define OHCI_CMDSTATUS         0x08
+#define OHCI_INTRSTATUS                0x0c
+#define OHCI_INTRENABLE                0x10
+#define OHCI_INTRDISABLE       0x14
+#define OHCI_OCR               (1 << 3)        /* ownership change request */
+#define OHCI_CTRL_RWC          (1 << 9)        /* remote wakeup connected */
+#define OHCI_CTRL_IR           (1 << 8)        /* interrupt routing */
+#define OHCI_INTR_OC           (1 << 30)       /* ownership change */
+
+#define EHCI_HCC_PARAMS                0x08            /* extended capabilities */
+#define EHCI_USBCMD            0               /* command register */
+#define EHCI_USBCMD_RUN                (1 << 0)        /* RUN/STOP bit */
+#define EHCI_USBSTS            4               /* status register */
+#define EHCI_USBSTS_HALTED     (1 << 12)       /* HCHalted bit */
+#define EHCI_USBINTR           8               /* interrupt register */
+#define EHCI_USBLEGSUP         0               /* legacy support register */
+#define EHCI_USBLEGSUP_BIOS    (1 << 16)       /* BIOS semaphore */
+#define EHCI_USBLEGSUP_OS      (1 << 24)       /* OS semaphore */
+#define EHCI_USBLEGCTLSTS      4               /* legacy control/status */
+#define EHCI_USBLEGCTLSTS_SOOE (1 << 13)       /* SMI on ownership change */
+
+
+/*
+ * Make sure the controller is completely inactive, unable to
+ * generate interrupts or do DMA.
+ */
+void uhci_reset_hc(struct pci_dev *pdev, unsigned long base)
+{
+       /* Turn off PIRQ enable and SMI enable.  (This also turns off the
+        * BIOS's USB Legacy Support.)  Turn off all the R/WC bits too.
+        */
+       pci_write_config_word(pdev, UHCI_USBLEGSUP, UHCI_USBLEGSUP_RWC);
+
+       /* Reset the HC - this will force us to get a
+        * new notification of any already connected
+        * ports due to the virtual disconnect that it
+        * implies.
+        */
+       outw(UHCI_USBCMD_HCRESET, base + UHCI_USBCMD);
+       mb();
+       udelay(5);
+       if (inw(base + UHCI_USBCMD) & UHCI_USBCMD_HCRESET)
+               dev_warn(&pdev->dev, "HCRESET not completed yet!\n");
+
+       /* Just to be safe, disable interrupt requests and
+        * make sure the controller is stopped.
+        */
+       outw(0, base + UHCI_USBINTR);
+       outw(0, base + UHCI_USBCMD);
+}
+EXPORT_SYMBOL_GPL(uhci_reset_hc);
+
+/*
+ * Initialize a controller that was newly discovered or has just been
+ * resumed.  In either case we can't be sure of its previous state.
+ *
+ * Returns: 1 if the controller was reset, 0 otherwise.
+ */
+int uhci_check_and_reset_hc(struct pci_dev *pdev, unsigned long base)
+{
+       u16 legsup;
+       unsigned int cmd, intr;
+
+       /*
+        * When restarting a suspended controller, we expect all the
+        * settings to be the same as we left them:
+        *
+        *      PIRQ and SMI disabled, no R/W bits set in USBLEGSUP;
+        *      Controller is stopped and configured with EGSM set;
+        *      No interrupts enabled except possibly Resume Detect.
+        *
+        * If any of these conditions are violated we do a complete reset.
+        */
+       pci_read_config_word(pdev, UHCI_USBLEGSUP, &legsup);
+       if (legsup & ~(UHCI_USBLEGSUP_RO | UHCI_USBLEGSUP_RWC)) {
+               dev_dbg(&pdev->dev, "%s: legsup = 0x%04x\n",
+                               __FUNCTION__, legsup);
+               goto reset_needed;
+       }
+
+       cmd = inw(base + UHCI_USBCMD);
+       if ((cmd & UHCI_USBCMD_RUN) || !(cmd & UHCI_USBCMD_CONFIGURE) ||
+                       !(cmd & UHCI_USBCMD_EGSM)) {
+               dev_dbg(&pdev->dev, "%s: cmd = 0x%04x\n",
+                               __FUNCTION__, cmd);
+               goto reset_needed;
+       }
+
+       intr = inw(base + UHCI_USBINTR);
+       if (intr & (~UHCI_USBINTR_RESUME)) {
+               dev_dbg(&pdev->dev, "%s: intr = 0x%04x\n",
+                               __FUNCTION__, intr);
+               goto reset_needed;
+       }
+       return 0;
+
+reset_needed:
+       dev_dbg(&pdev->dev, "Performing full reset\n");
+       uhci_reset_hc(pdev, base);
+       return 1;
+}
+EXPORT_SYMBOL_GPL(uhci_check_and_reset_hc);
+
+static void __devinit quirk_usb_handoff_uhci(struct pci_dev *pdev)
+{
+       unsigned long base = 0;
+       int i;
+
+       for (i = 0; i < PCI_ROM_RESOURCE; i++)
+               if ((pci_resource_flags(pdev, i) & IORESOURCE_IO)) {
+                       base = pci_resource_start(pdev, i);
+                       break;
+               }
+
+       if (base)
+               uhci_check_and_reset_hc(pdev, base);
+}
+
+static void __devinit quirk_usb_handoff_ohci(struct pci_dev *pdev)
+{
+       void __iomem *base;
+       int wait_time;
+       u32 control;
+
+       base = ioremap_nocache(pci_resource_start(pdev, 0),
+                                    pci_resource_len(pdev, 0));
+       if (base == NULL) return;
+
+/* On PA-RISC, PDC can leave IR set incorrectly; ignore it there. */
+#ifndef __hppa__
+       control = readl(base + OHCI_CONTROL);
+       if (control & OHCI_CTRL_IR) {
+               wait_time = 500; /* arbitrary; 5 seconds */
+               writel(OHCI_INTR_OC, base + OHCI_INTRENABLE);
+               writel(OHCI_OCR, base + OHCI_CMDSTATUS);
+               while (wait_time > 0 &&
+                               readl(base + OHCI_CONTROL) & OHCI_CTRL_IR) {
+                       wait_time -= 10;
+                       msleep(10);
+               }
+               if (wait_time <= 0)
+                       printk(KERN_WARNING "%s %s: early BIOS handoff "
+                                       "failed (BIOS bug ?)\n",
+                                       pdev->dev.bus_id, "OHCI");
+
+               /* reset controller, preserving RWC */
+               writel(control & OHCI_CTRL_RWC, base + OHCI_CONTROL);
+       }
+#endif
+
+       /*
+        * disable interrupts
+        */
+       writel(~(u32)0, base + OHCI_INTRDISABLE);
+       writel(~(u32)0, base + OHCI_INTRSTATUS);
+
+       iounmap(base);
+}
+
+static void __devinit quirk_usb_disable_ehci(struct pci_dev *pdev)
+{
+       int wait_time, delta;
+       void __iomem *base, *op_reg_base;
+       u32 hcc_params, val, temp;
+       u8 cap_length;
+
+       base = ioremap_nocache(pci_resource_start(pdev, 0),
+                               pci_resource_len(pdev, 0));
+       if (base == NULL) return;
+
+       cap_length = readb(base);
+       op_reg_base = base + cap_length;
+       hcc_params = readl(base + EHCI_HCC_PARAMS);
+       hcc_params = (hcc_params >> 8) & 0xff;
+       if (hcc_params) {
+               pci_read_config_dword(pdev,
+                                       hcc_params + EHCI_USBLEGSUP,
+                                       &val);
+               if (((val & 0xff) == 1) && (val & EHCI_USBLEGSUP_BIOS)) {
+                       /*
+                        * Ok, BIOS is in smm mode, try to hand off...
+                        */
+                       pci_read_config_dword(pdev,
+                                               hcc_params + EHCI_USBLEGCTLSTS,
+                                               &temp);
+                       pci_write_config_dword(pdev,
+                                               hcc_params + EHCI_USBLEGCTLSTS,
+                                               temp | EHCI_USBLEGCTLSTS_SOOE);
+                       val |= EHCI_USBLEGSUP_OS;
+                       pci_write_config_dword(pdev,
+                                               hcc_params + EHCI_USBLEGSUP,
+                                               val);
+
+                       wait_time = 500;
+                       do {
+                               msleep(10);
+                               wait_time -= 10;
+                               pci_read_config_dword(pdev,
+                                               hcc_params + EHCI_USBLEGSUP,
+                                               &val);
+                       } while (wait_time && (val & EHCI_USBLEGSUP_BIOS));
+                       if (!wait_time) {
+                               /*
+                                * well, possibly buggy BIOS...
+                                */
+                               printk(KERN_WARNING "%s %s: early BIOS handoff "
+                                               "failed (BIOS bug ?)\n",
+                                       pdev->dev.bus_id, "EHCI");
+                               pci_write_config_dword(pdev,
+                                               hcc_params + EHCI_USBLEGSUP,
+                                               EHCI_USBLEGSUP_OS);
+                               pci_write_config_dword(pdev,
+                                               hcc_params + EHCI_USBLEGCTLSTS,
+                                               0);
+                       }
+               }
+       }
+
+       /*
+        * halt EHCI & disable its interrupts in any case
+        */
+       val = readl(op_reg_base + EHCI_USBSTS);
+       if ((val & EHCI_USBSTS_HALTED) == 0) {
+               val = readl(op_reg_base + EHCI_USBCMD);
+               val &= ~EHCI_USBCMD_RUN;
+               writel(val, op_reg_base + EHCI_USBCMD);
+
+               wait_time = 2000;
+               delta = 100;
+               do {
+                       writel(0x3f, op_reg_base + EHCI_USBSTS);
+                       udelay(delta);
+                       wait_time -= delta;
+                       val = readl(op_reg_base + EHCI_USBSTS);
+                       if ((val == ~(u32)0) || (val & EHCI_USBSTS_HALTED)) {
+                               break;
+                       }
+               } while (wait_time > 0);
+       }
+       writel(0, op_reg_base + EHCI_USBINTR);
+       writel(0x3f, op_reg_base + EHCI_USBSTS);
+
+       iounmap(base);
+
+       return;
+}
+
+
+
+static void __devinit quirk_usb_early_handoff(struct pci_dev *pdev)
+{
+       if (pdev->class == PCI_CLASS_SERIAL_USB_UHCI)
+               quirk_usb_handoff_uhci(pdev);
+       else if (pdev->class == PCI_CLASS_SERIAL_USB_OHCI)
+               quirk_usb_handoff_ohci(pdev);
+       else if (pdev->class == PCI_CLASS_SERIAL_USB_EHCI)
+               quirk_usb_disable_ehci(pdev);
+}
+DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, quirk_usb_early_handoff);
index b5e7a47..40169d9 100644 (file)
@@ -1363,7 +1363,7 @@ error:
 #ifdef CONFIG_PM
 
 static int
-sl811h_hub_suspend(struct usb_hcd *hcd)
+sl811h_bus_suspend(struct usb_hcd *hcd)
 {
        // SOFs off
        DBG("%s\n", __FUNCTION__);
@@ -1371,7 +1371,7 @@ sl811h_hub_suspend(struct usb_hcd *hcd)
 }
 
 static int
-sl811h_hub_resume(struct usb_hcd *hcd)
+sl811h_bus_resume(struct usb_hcd *hcd)
 {
        // SOFs on
        DBG("%s\n", __FUNCTION__);
@@ -1380,8 +1380,8 @@ sl811h_hub_resume(struct usb_hcd *hcd)
 
 #else
 
-#define        sl811h_hub_suspend      NULL
-#define        sl811h_hub_resume       NULL
+#define        sl811h_bus_suspend      NULL
+#define        sl811h_bus_resume       NULL
 
 #endif
 
@@ -1623,8 +1623,8 @@ static struct hc_driver sl811h_hc_driver = {
         */
        .hub_status_data =      sl811h_hub_status_data,
        .hub_control =          sl811h_hub_control,
-       .hub_suspend =          sl811h_hub_suspend,
-       .hub_resume =           sl811h_hub_resume,
+       .bus_suspend =          sl811h_bus_suspend,
+       .bus_resume =           sl811h_bus_resume,
 };
 
 /*-------------------------------------------------------------------------*/
@@ -1791,7 +1791,7 @@ sl811h_suspend(struct device *dev, pm_message_t state)
        int             retval = 0;
 
        if (state.event == PM_EVENT_FREEZE)
-               retval = sl811h_hub_suspend(hcd);
+               retval = sl811h_bus_suspend(hcd);
        else if (state.event == PM_EVENT_SUSPEND)
                port_power(sl811, 0);
        if (retval == 0)
@@ -1816,7 +1816,7 @@ sl811h_resume(struct device *dev)
        }
 
        dev->power.power_state = PMSG_ON;
-       return sl811h_hub_resume(hcd);
+       return sl811h_bus_resume(hcd);
 }
 
 #else
@@ -1831,6 +1831,7 @@ sl811h_resume(struct device *dev)
 struct device_driver sl811h_driver = {
        .name =         (char *) hcd_name,
        .bus =          &platform_bus_type,
+       .owner =        THIS_MODULE,
 
        .probe =        sl811h_probe,
        .remove =       __devexit_p(sl811h_remove),
index 4538a98..151154d 100644 (file)
@@ -348,7 +348,6 @@ static int uhci_show_urbp(struct uhci_hcd *uhci, struct urb_priv *urbp, char *bu
 
        if (urbp->urb->status != -EINPROGRESS)
                out += sprintf(out, "Status=%d ", urbp->urb->status);
-       //out += sprintf(out, "Inserttime=%lx ",urbp->inserttime);
        //out += sprintf(out, "FSBRtime=%lx ",urbp->fsbrtime);
 
        count = 0;
@@ -446,11 +445,11 @@ static int uhci_sprint_schedule(struct uhci_hcd *uhci, char *buf, int len)
        out += sprintf(out, "Frame List\n");
        for (i = 0; i < UHCI_NUMFRAMES; ++i) {
                int shown = 0;
-               td = uhci->fl->frame_cpu[i];
+               td = uhci->frame_cpu[i];
                if (!td)
                        continue;
 
-               if (td->dma_handle != (dma_addr_t)uhci->fl->frame[i]) {
+               if (td->dma_handle != (dma_addr_t)uhci->frame[i]) {
                        show_frame_num();
                        out += sprintf(out, "    frame list does not match td->dma_handle!\n");
                }
index 0c02489..15e0a51 100644 (file)
@@ -101,37 +101,16 @@ static void uhci_get_current_frame_number(struct uhci_hcd *uhci);
 #include "uhci-q.c"
 #include "uhci-hub.c"
 
+extern void uhci_reset_hc(struct pci_dev *pdev, unsigned long base);
+extern int uhci_check_and_reset_hc(struct pci_dev *pdev, unsigned long base);
+
 /*
- * Make sure the controller is completely inactive, unable to
- * generate interrupts or do DMA.
+ * Finish up a host controller reset and update the recorded state.
  */
-static void reset_hc(struct uhci_hcd *uhci)
+static void finish_reset(struct uhci_hcd *uhci)
 {
        int port;
 
-       /* Turn off PIRQ enable and SMI enable.  (This also turns off the
-        * BIOS's USB Legacy Support.)  Turn off all the R/WC bits too.
-        */
-       pci_write_config_word(to_pci_dev(uhci_dev(uhci)), USBLEGSUP,
-                       USBLEGSUP_RWC);
-
-       /* Reset the HC - this will force us to get a
-        * new notification of any already connected
-        * ports due to the virtual disconnect that it
-        * implies.
-        */
-       outw(USBCMD_HCRESET, uhci->io_addr + USBCMD);
-       mb();
-       udelay(5);
-       if (inw(uhci->io_addr + USBCMD) & USBCMD_HCRESET)
-               dev_warn(uhci_dev(uhci), "HCRESET not completed yet!\n");
-
-       /* Just to be safe, disable interrupt requests and
-        * make sure the controller is stopped.
-        */
-       outw(0, uhci->io_addr + USBINTR);
-       outw(0, uhci->io_addr + USBCMD);
-
        /* HCRESET doesn't affect the Suspend, Reset, and Resume Detect
         * bits in the port status and control registers.
         * We have to clear them by hand.
@@ -153,7 +132,8 @@ static void reset_hc(struct uhci_hcd *uhci)
  */
 static void hc_died(struct uhci_hcd *uhci)
 {
-       reset_hc(uhci);
+       uhci_reset_hc(to_pci_dev(uhci_dev(uhci)), uhci->io_addr);
+       finish_reset(uhci);
        uhci->hc_inaccessible = 1;
 }
 
@@ -163,44 +143,8 @@ static void hc_died(struct uhci_hcd *uhci)
  */
 static void check_and_reset_hc(struct uhci_hcd *uhci)
 {
-       u16 legsup;
-       unsigned int cmd, intr;
-
-       /*
-        * When restarting a suspended controller, we expect all the
-        * settings to be the same as we left them:
-        *
-        *      PIRQ and SMI disabled, no R/W bits set in USBLEGSUP;
-        *      Controller is stopped and configured with EGSM set;
-        *      No interrupts enabled except possibly Resume Detect.
-        *
-        * If any of these conditions are violated we do a complete reset.
-        */
-       pci_read_config_word(to_pci_dev(uhci_dev(uhci)), USBLEGSUP, &legsup);
-       if (legsup & ~(USBLEGSUP_RO | USBLEGSUP_RWC)) {
-               dev_dbg(uhci_dev(uhci), "%s: legsup = 0x%04x\n",
-                               __FUNCTION__, legsup);
-               goto reset_needed;
-       }
-
-       cmd = inw(uhci->io_addr + USBCMD);
-       if ((cmd & USBCMD_RS) || !(cmd & USBCMD_CF) || !(cmd & USBCMD_EGSM)) {
-               dev_dbg(uhci_dev(uhci), "%s: cmd = 0x%04x\n",
-                               __FUNCTION__, cmd);
-               goto reset_needed;
-       }
-
-       intr = inw(uhci->io_addr + USBINTR);
-       if (intr & (~USBINTR_RESUME)) {
-               dev_dbg(uhci_dev(uhci), "%s: intr = 0x%04x\n",
-                               __FUNCTION__, intr);
-               goto reset_needed;
-       }
-       return;
-
-reset_needed:
-       dev_dbg(uhci_dev(uhci), "Performing full reset\n");
-       reset_hc(uhci);
+       if (uhci_check_and_reset_hc(to_pci_dev(uhci_dev(uhci)), uhci->io_addr))
+               finish_reset(uhci);
 }
 
 /*
@@ -212,13 +156,13 @@ static void configure_hc(struct uhci_hcd *uhci)
        outb(USBSOF_DEFAULT, uhci->io_addr + USBSOF);
 
        /* Store the frame list base address */
-       outl(uhci->fl->dma_handle, uhci->io_addr + USBFLBASEADD);
+       outl(uhci->frame_dma_handle, uhci->io_addr + USBFLBASEADD);
 
        /* Set the current frame number */
        outw(uhci->frame_number, uhci->io_addr + USBFRNUM);
 
-       /* Mark controller as running before we enable interrupts */
-       uhci_to_hcd(uhci)->state = HC_STATE_RUNNING;
+       /* Mark controller as not halted before we enable interrupts */
+       uhci_to_hcd(uhci)->state = HC_STATE_SUSPENDED;
        mb();
 
        /* Enable PIRQ */
@@ -319,6 +263,7 @@ __acquires(uhci->lock)
 
 static void start_rh(struct uhci_hcd *uhci)
 {
+       uhci_to_hcd(uhci)->state = HC_STATE_RUNNING;
        uhci->is_stopped = 0;
        smp_wmb();
 
@@ -437,36 +382,21 @@ static void release_uhci(struct uhci_hcd *uhci)
        int i;
 
        for (i = 0; i < UHCI_NUM_SKELQH; i++)
-               if (uhci->skelqh[i]) {
-                       uhci_free_qh(uhci, uhci->skelqh[i]);
-                       uhci->skelqh[i] = NULL;
-               }
+               uhci_free_qh(uhci, uhci->skelqh[i]);
 
-       if (uhci->term_td) {
-               uhci_free_td(uhci, uhci->term_td);
-               uhci->term_td = NULL;
-       }
+       uhci_free_td(uhci, uhci->term_td);
 
-       if (uhci->qh_pool) {
-               dma_pool_destroy(uhci->qh_pool);
-               uhci->qh_pool = NULL;
-       }
+       dma_pool_destroy(uhci->qh_pool);
 
-       if (uhci->td_pool) {
-               dma_pool_destroy(uhci->td_pool);
-               uhci->td_pool = NULL;
-       }
+       dma_pool_destroy(uhci->td_pool);
 
-       if (uhci->fl) {
-               dma_free_coherent(uhci_dev(uhci), sizeof(*uhci->fl),
-                               uhci->fl, uhci->fl->dma_handle);
-               uhci->fl = NULL;
-       }
+       kfree(uhci->frame_cpu);
 
-       if (uhci->dentry) {
-               debugfs_remove(uhci->dentry);
-               uhci->dentry = NULL;
-       }
+       dma_free_coherent(uhci_dev(uhci),
+                       UHCI_NUMFRAMES * sizeof(*uhci->frame),
+                       uhci->frame, uhci->frame_dma_handle);
+
+       debugfs_remove(uhci->dentry);
 }
 
 static int uhci_reset(struct usb_hcd *hcd)
@@ -545,7 +475,6 @@ static int uhci_start(struct usb_hcd *hcd)
        struct uhci_hcd *uhci = hcd_to_uhci(hcd);
        int retval = -EBUSY;
        int i;
-       dma_addr_t dma_handle;
        struct dentry *dentry;
 
        hcd->uses_new_polling = 1;
@@ -579,17 +508,23 @@ static int uhci_start(struct usb_hcd *hcd)
 
        init_waitqueue_head(&uhci->waitqh);
 
-       uhci->fl = dma_alloc_coherent(uhci_dev(uhci), sizeof(*uhci->fl),
-                       &dma_handle, 0);
-       if (!uhci->fl) {
+       uhci->frame = dma_alloc_coherent(uhci_dev(uhci),
+                       UHCI_NUMFRAMES * sizeof(*uhci->frame),
+                       &uhci->frame_dma_handle, 0);
+       if (!uhci->frame) {
                dev_err(uhci_dev(uhci), "unable to allocate "
                                "consistent memory for frame list\n");
-               goto err_alloc_fl;
+               goto err_alloc_frame;
        }
+       memset(uhci->frame, 0, UHCI_NUMFRAMES * sizeof(*uhci->frame));
 
-       memset((void *)uhci->fl, 0, sizeof(*uhci->fl));
-
-       uhci->fl->dma_handle = dma_handle;
+       uhci->frame_cpu = kcalloc(UHCI_NUMFRAMES, sizeof(*uhci->frame_cpu),
+                       GFP_KERNEL);
+       if (!uhci->frame_cpu) {
+               dev_err(uhci_dev(uhci), "unable to allocate "
+                               "memory for frame pointers\n");
+               goto err_alloc_frame_cpu;
+       }
 
        uhci->td_pool = dma_pool_create("uhci_td", uhci_dev(uhci),
                        sizeof(struct uhci_td), 16, 0);
@@ -672,7 +607,7 @@ static int uhci_start(struct usb_hcd *hcd)
                        irq = 7;
 
                /* Only place we don't use the frame list routines */
-               uhci->fl->frame[i] = UHCI_PTR_QH |
+               uhci->frame[i] = UHCI_PTR_QH |
                                cpu_to_le32(uhci->skelqh[irq]->dma_handle);
        }
 
@@ -690,31 +625,29 @@ static int uhci_start(struct usb_hcd *hcd)
  * error exits:
  */
 err_alloc_skelqh:
-       for (i = 0; i < UHCI_NUM_SKELQH; i++)
-               if (uhci->skelqh[i]) {
+       for (i = 0; i < UHCI_NUM_SKELQH; i++) {
+               if (uhci->skelqh[i])
                        uhci_free_qh(uhci, uhci->skelqh[i]);
-                       uhci->skelqh[i] = NULL;
-               }
+       }
 
        uhci_free_td(uhci, uhci->term_td);
-       uhci->term_td = NULL;
 
 err_alloc_term_td:
        dma_pool_destroy(uhci->qh_pool);
-       uhci->qh_pool = NULL;
 
 err_create_qh_pool:
        dma_pool_destroy(uhci->td_pool);
-       uhci->td_pool = NULL;
 
 err_create_td_pool:
-       dma_free_coherent(uhci_dev(uhci), sizeof(*uhci->fl),
-                       uhci->fl, uhci->fl->dma_handle);
-       uhci->fl = NULL;
+       kfree(uhci->frame_cpu);
+
+err_alloc_frame_cpu:
+       dma_free_coherent(uhci_dev(uhci),
+                       UHCI_NUMFRAMES * sizeof(*uhci->frame),
+                       uhci->frame, uhci->frame_dma_handle);
 
-err_alloc_fl:
+err_alloc_frame:
        debugfs_remove(uhci->dentry);
-       uhci->dentry = NULL;
 
 err_create_debug_entry:
        return retval;
@@ -726,7 +659,7 @@ static void uhci_stop(struct usb_hcd *hcd)
 
        spin_lock_irq(&uhci->lock);
        if (!uhci->hc_inaccessible)
-               reset_hc(uhci);
+               hc_died(uhci);
        uhci_scan_schedule(uhci, NULL);
        spin_unlock_irq(&uhci->lock);
 
@@ -774,14 +707,8 @@ static int uhci_suspend(struct usb_hcd *hcd, pm_message_t message)
        if (uhci->hc_inaccessible)      /* Dead or already suspended */
                goto done;
 
-#ifndef CONFIG_USB_SUSPEND
-       /* Otherwise this would never happen */
-       suspend_rh(uhci, UHCI_RH_SUSPENDED);
-#endif
-
        if (uhci->rh_state > UHCI_RH_SUSPENDED) {
                dev_warn(uhci_dev(uhci), "Root hub isn't suspended!\n");
-               hcd->state = HC_STATE_RUNNING;
                rc = -EBUSY;
                goto done;
        };
@@ -820,10 +747,6 @@ static int uhci_resume(struct usb_hcd *hcd)
        check_and_reset_hc(uhci);
        configure_hc(uhci);
 
-#ifndef CONFIG_USB_SUSPEND
-       /* Otherwise this would never happen */
-       wakeup_rh(uhci);
-#endif
        if (uhci->rh_state == UHCI_RH_RESET)
                suspend_rh(uhci, UHCI_RH_SUSPENDED);
 
@@ -881,8 +804,8 @@ static const struct hc_driver uhci_driver = {
 #ifdef CONFIG_PM
        .suspend =              uhci_suspend,
        .resume =               uhci_resume,
-       .hub_suspend =          uhci_rh_suspend,
-       .hub_resume =           uhci_rh_resume,
+       .bus_suspend =          uhci_rh_suspend,
+       .bus_resume =           uhci_rh_resume,
 #endif
        .stop =                 uhci_stop,
 
@@ -908,6 +831,7 @@ MODULE_DEVICE_TABLE(pci, uhci_pci_ids);
 static struct pci_driver uhci_pci_driver = {
        .name =         (char *)hcd_name,
        .id_table =     uhci_pci_ids,
+       .owner =        THIS_MODULE,
 
        .probe =        usb_hcd_pci_probe,
        .remove =       usb_hcd_pci_remove,
index 282f40b..e576db5 100644 (file)
@@ -7,6 +7,7 @@
 #define usb_packetid(pipe)     (usb_pipein(pipe) ? USB_PID_IN : USB_PID_OUT)
 #define PIPE_DEVEP_MASK                0x0007ff00
 
+
 /*
  * Universal Host Controller Interface data structures and defines
  */
 #define UHCI_MAX_SOF_NUMBER    2047    /* in an SOF packet */
 #define CAN_SCHEDULE_FRAMES    1000    /* how far future frames can be scheduled */
 
-struct uhci_frame_list {
-       __le32 frame[UHCI_NUMFRAMES];
-
-       void *frame_cpu[UHCI_NUMFRAMES];
-
-       dma_addr_t dma_handle;
-};
 
-struct urb_priv;
+/*
+ *     Queue Headers
+ */
 
 /*
  * One role of a QH is to hold a queue of TDs for some endpoint.  Each QH is
@@ -116,13 +112,13 @@ struct uhci_qh {
 
        struct urb_priv *urbp;
 
-       struct list_head list;          /* P: uhci->frame_list_lock */
-       struct list_head remove_list;   /* P: uhci->remove_list_lock */
+       struct list_head list;
+       struct list_head remove_list;
 } __attribute__((aligned(16)));
 
 /*
  * We need a special accessor for the element pointer because it is
- * subject to asynchronous updates by the controller
+ * subject to asynchronous updates by the controller.
  */
 static __le32 inline qh_element(struct uhci_qh *qh) {
        __le32 element = qh->element;
@@ -131,6 +127,11 @@ static __le32 inline qh_element(struct uhci_qh *qh) {
        return element;
 }
 
+
+/*
+ *     Transfer Descriptors
+ */
+
 /*
  * for TD <status>:
  */
@@ -183,17 +184,10 @@ static __le32 inline qh_element(struct uhci_qh *qh) {
  *
  * That's silly, the hardware doesn't care. The hardware only cares that
  * the hardware words are 16-byte aligned, and we can have any amount of
- * sw space after the TD entry as far as I can tell.
- *
- * But let's just go with the documentation, at least for 32-bit machines.
- * On 64-bit machines we probably want to take advantage of the fact that
- * hw doesn't really care about the size of the sw-only area.
- *
- * Alas, not anymore, we have more than 4 words for software, woops.
- * Everything still works tho, surprise! -jerdfelt
+ * sw space after the TD entry.
  *
  * td->link points to either another TD (not necessarily for the same urb or
- * even the same endpoint), or nothing (PTR_TERM), or a QH (for queued urbs)
+ * even the same endpoint), or nothing (PTR_TERM), or a QH (for queued urbs).
  */
 struct uhci_td {
        /* Hardware fields */
@@ -205,18 +199,16 @@ struct uhci_td {
        /* Software fields */
        dma_addr_t dma_handle;
 
-       struct urb *urb;
-
-       struct list_head list;          /* P: urb->lock */
-       struct list_head remove_list;   /* P: uhci->td_remove_list_lock */
+       struct list_head list;
+       struct list_head remove_list;
 
        int frame;                      /* for iso: what frame? */
-       struct list_head fl_list;       /* P: uhci->frame_list_lock */
+       struct list_head fl_list;
 } __attribute__((aligned(16)));
 
 /*
  * We need a special accessor for the control/status word because it is
- * subject to asynchronous updates by the controller
+ * subject to asynchronous updates by the controller.
  */
 static u32 inline td_status(struct uhci_td *td) {
        __le32 status = td->status;
@@ -226,6 +218,10 @@ static u32 inline td_status(struct uhci_td *td) {
 }
 
 
+/*
+ *     Skeleton Queue Headers
+ */
+
 /*
  * The UHCI driver places Interrupt, Control and Bulk into QH's both
  * to group together TD's for one transfer, and also to faciliate queuing
@@ -256,15 +252,15 @@ static u32 inline td_status(struct uhci_td *td) {
  *
  * The terminating QH is used for 2 reasons:
  * - To place a terminating TD which is used to workaround a PIIX bug
- *   (see Intel errata for explanation)
+ *   (see Intel errata for explanation), and
  * - To loop back to the full-speed control queue for full-speed bandwidth
- *   reclamation
+ *   reclamation.
  *
  * Isochronous transfers are stored before the start of the skeleton
  * schedule and don't use QH's. While the UHCI spec doesn't forbid the
- * use of QH's for Isochronous, it doesn't use them either. Since we don't
- * need to use them either, we follow the spec diagrams in hope that it'll
- * be more compatible with future UHCI implementations.
+ * use of QH's for Isochronous, it doesn't use them either. And the spec
+ * says that queues never advance on an error completion status, which
+ * makes them totally unsuitable for Isochronous transfers.
  */
 
 #define UHCI_NUM_SKELQH                12
@@ -314,8 +310,13 @@ static inline int __interval_to_skel(int interval)
        return 0;                               /* int128 for 128-255 ms (Max.) */
 }
 
+
+/*
+ *     The UHCI controller and root hub
+ */
+
 /*
- * States for the root hub.
+ * States for the root hub:
  *
  * To prevent "bouncing" in the presence of electrical noise,
  * when there are no devices attached we delay for 1 second in the
@@ -326,7 +327,7 @@ static inline int __interval_to_skel(int interval)
  */
 enum uhci_rh_state {
        /* In the following states the HC must be halted.
-        * These two must come first */
+        * These two must come first. */
        UHCI_RH_RESET,
        UHCI_RH_SUSPENDED,
 
@@ -338,13 +339,13 @@ enum uhci_rh_state {
        UHCI_RH_SUSPENDING,
 
        /* In the following states it's an error if the HC is halted.
-        * These two must come last */
+        * These two must come last. */
        UHCI_RH_RUNNING,                /* The normal state */
        UHCI_RH_RUNNING_NODEVS,         /* Running with no devices attached */
 };
 
 /*
- * This describes the full uhci information.
+ * The full UHCI controller information:
  */
 struct uhci_hcd {
 
@@ -361,7 +362,11 @@ struct uhci_hcd {
        struct uhci_qh *skelqh[UHCI_NUM_SKELQH];        /* Skeleton QH's */
 
        spinlock_t lock;
-       struct uhci_frame_list *fl;             /* P: uhci->lock */
+
+       dma_addr_t frame_dma_handle;            /* Hardware frame list */
+       __le32 *frame;
+       void **frame_cpu;                       /* CPU's frame list */
+
        int fsbr;                               /* Full-speed bandwidth reclamation */
        unsigned long fsbrtimeout;              /* FSBR delay */
 
@@ -385,22 +390,22 @@ struct uhci_hcd {
        unsigned long ports_timeout;            /* Time to stop signalling */
 
        /* Main list of URB's currently controlled by this HC */
-       struct list_head urb_list;              /* P: uhci->lock */
+       struct list_head urb_list;
 
        /* List of QH's that are done, but waiting to be unlinked (race) */
-       struct list_head qh_remove_list;        /* P: uhci->lock */
+       struct list_head qh_remove_list;
        unsigned int qh_remove_age;             /* Age in frames */
 
        /* List of TD's that are done, but waiting to be freed (race) */
-       struct list_head td_remove_list;        /* P: uhci->lock */
+       struct list_head td_remove_list;
        unsigned int td_remove_age;             /* Age in frames */
 
        /* List of asynchronously unlinked URB's */
-       struct list_head urb_remove_list;       /* P: uhci->lock */
+       struct list_head urb_remove_list;
        unsigned int urb_remove_age;            /* Age in frames */
 
        /* List of URB's awaiting completion callback */
-       struct list_head complete_list;         /* P: uhci->lock */
+       struct list_head complete_list;
 
        int rh_numports;                        /* Number of root-hub ports */
 
@@ -419,13 +424,17 @@ static inline struct usb_hcd *uhci_to_hcd(struct uhci_hcd *uhci)
 
 #define uhci_dev(u)    (uhci_to_hcd(u)->self.controller)
 
+
+/*
+ *     Private per-URB data
+ */
 struct urb_priv {
        struct list_head urb_list;
 
        struct urb *urb;
 
        struct uhci_qh *qh;             /* QH for this URB */
-       struct list_head td_list;       /* P: urb->lock */
+       struct list_head td_list;
 
        unsigned fsbr : 1;              /* URB turned on FSBR */
        unsigned fsbr_timeout : 1;      /* URB timed out on FSBR */
@@ -434,12 +443,12 @@ struct urb_priv {
                                                /*  a control transfer, retrigger */
                                                /*  the status phase */
 
-       unsigned long inserttime;       /* In jiffies */
        unsigned long fsbrtime;         /* In jiffies */
 
-       struct list_head queue_list;    /* P: uhci->frame_list_lock */
+       struct list_head queue_list;
 };
 
+
 /*
  * Locking in uhci.c
  *
@@ -459,6 +468,5 @@ struct urb_priv {
 
 #define PCI_VENDOR_ID_GENESYS          0x17a0
 #define PCI_DEVICE_ID_GL880S_UHCI      0x8083
-#define PCI_DEVICE_ID_GL880S_EHCI      0x8084
 
 #endif
index 4e0fbe2..7e46887 100644 (file)
@@ -89,10 +89,10 @@ static void uhci_insert_td_frame_list(struct uhci_hcd *uhci, struct uhci_td *td,
        td->frame = framenum;
 
        /* Is there a TD already mapped there? */
-       if (uhci->fl->frame_cpu[framenum]) {
+       if (uhci->frame_cpu[framenum]) {
                struct uhci_td *ftd, *ltd;
 
-               ftd = uhci->fl->frame_cpu[framenum];
+               ftd = uhci->frame_cpu[framenum];
                ltd = list_entry(ftd->fl_list.prev, struct uhci_td, fl_list);
 
                list_add_tail(&td->fl_list, &ftd->fl_list);
@@ -101,29 +101,32 @@ static void uhci_insert_td_frame_list(struct uhci_hcd *uhci, struct uhci_td *td,
                wmb();
                ltd->link = cpu_to_le32(td->dma_handle);
        } else {
-               td->link = uhci->fl->frame[framenum];
+               td->link = uhci->frame[framenum];
                wmb();
-               uhci->fl->frame[framenum] = cpu_to_le32(td->dma_handle);
-               uhci->fl->frame_cpu[framenum] = td;
+               uhci->frame[framenum] = cpu_to_le32(td->dma_handle);
+               uhci->frame_cpu[framenum] = td;
        }
 }
 
-static void uhci_remove_td(struct uhci_hcd *uhci, struct uhci_td *td)
+static inline void uhci_remove_td_frame_list(struct uhci_hcd *uhci,
+               struct uhci_td *td)
 {
        /* If it's not inserted, don't remove it */
-       if (td->frame == -1 && list_empty(&td->fl_list))
+       if (td->frame == -1) {
+               WARN_ON(!list_empty(&td->fl_list));
                return;
+       }
 
-       if (td->frame != -1 && uhci->fl->frame_cpu[td->frame] == td) {
+       if (uhci->frame_cpu[td->frame] == td) {
                if (list_empty(&td->fl_list)) {
-                       uhci->fl->frame[td->frame] = td->link;
-                       uhci->fl->frame_cpu[td->frame] = NULL;
+                       uhci->frame[td->frame] = td->link;
+                       uhci->frame_cpu[td->frame] = NULL;
                } else {
                        struct uhci_td *ntd;
 
                        ntd = list_entry(td->fl_list.next, struct uhci_td, fl_list);
-                       uhci->fl->frame[td->frame] = cpu_to_le32(ntd->dma_handle);
-                       uhci->fl->frame_cpu[td->frame] = ntd;
+                       uhci->frame[td->frame] = cpu_to_le32(ntd->dma_handle);
+                       uhci->frame_cpu[td->frame] = ntd;
                }
        } else {
                struct uhci_td *ptd;
@@ -132,13 +135,20 @@ static void uhci_remove_td(struct uhci_hcd *uhci, struct uhci_td *td)
                ptd->link = td->link;
        }
 
-       wmb();
-       td->link = UHCI_PTR_TERM;
-
        list_del_init(&td->fl_list);
        td->frame = -1;
 }
 
+static void unlink_isochronous_tds(struct uhci_hcd *uhci, struct urb *urb)
+{
+       struct urb_priv *urbp = (struct urb_priv *) urb->hcpriv;
+       struct uhci_td *td;
+
+       list_for_each_entry(td, &urbp->td_list, list)
+               uhci_remove_td_frame_list(uhci, td);
+       wmb();
+}
+
 /*
  * Inserts a td list into qh.
  */
@@ -443,7 +453,6 @@ static struct urb_priv *uhci_alloc_urb_priv(struct uhci_hcd *uhci, struct urb *u
 
        memset((void *)urbp, 0, sizeof(*urbp));
 
-       urbp->inserttime = jiffies;
        urbp->fsbrtime = jiffies;
        urbp->urb = urb;
        
@@ -462,8 +471,6 @@ static void uhci_add_td_to_urb(struct urb *urb, struct uhci_td *td)
 {
        struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv;
 
-       td->urb = urb;
-
        list_add_tail(&td->list, &urbp->td_list);
 }
 
@@ -473,8 +480,6 @@ static void uhci_remove_td_from_urb(struct uhci_td *td)
                return;
 
        list_del_init(&td->list);
-
-       td->urb = NULL;
 }
 
 static void uhci_destroy_urb_priv(struct uhci_hcd *uhci, struct urb *urb)
@@ -503,7 +508,6 @@ static void uhci_destroy_urb_priv(struct uhci_hcd *uhci, struct urb *urb)
 
        list_for_each_entry_safe(td, tmp, &urbp->td_list, list) {
                uhci_remove_td_from_urb(td);
-               uhci_remove_td(uhci, td);
                list_add(&td->remove_list, &uhci->td_remove_list);
        }
 
@@ -1073,6 +1077,7 @@ static int uhci_submit_isochronous(struct uhci_hcd *uhci, struct urb *urb)
        struct uhci_td *td;
        int i, ret, frame;
        int status, destination;
+       struct urb_priv *urbp = (struct urb_priv *) urb->hcpriv;
 
        status = TD_CTRL_ACTIVE | TD_CTRL_IOS;
        destination = (urb->pipe & PIPE_DEVEP_MASK) | usb_packetid(urb->pipe);
@@ -1081,11 +1086,7 @@ static int uhci_submit_isochronous(struct uhci_hcd *uhci, struct urb *urb)
        if (ret)
                return ret;
 
-       frame = urb->start_frame;
-       for (i = 0; i < urb->number_of_packets; i++, frame += urb->interval) {
-               if (!urb->iso_frame_desc[i].length)
-                       continue;
-
+       for (i = 0; i < urb->number_of_packets; i++) {
                td = uhci_alloc_td(uhci);
                if (!td)
                        return -ENOMEM;
@@ -1096,8 +1097,12 @@ static int uhci_submit_isochronous(struct uhci_hcd *uhci, struct urb *urb)
 
                if (i + 1 >= urb->number_of_packets)
                        td->status |= cpu_to_le32(TD_CTRL_IOC);
+       }
 
+       frame = urb->start_frame;
+       list_for_each_entry(td, &urbp->td_list, list) {
                uhci_insert_td_frame_list(uhci, td, frame);
+               frame += urb->interval;
        }
 
        return -EINPROGRESS;
@@ -1110,7 +1115,7 @@ static int uhci_result_isochronous(struct uhci_hcd *uhci, struct urb *urb)
        int status;
        int i, ret = 0;
 
-       urb->actual_length = 0;
+       urb->actual_length = urb->error_count = 0;
 
        i = 0;
        list_for_each_entry(td, &urbp->td_list, list) {
@@ -1134,6 +1139,7 @@ static int uhci_result_isochronous(struct uhci_hcd *uhci, struct urb *urb)
 
                i++;
        }
+       unlink_isochronous_tds(uhci, urb);
 
        return ret;
 }
@@ -1366,6 +1372,8 @@ static int uhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb)
                goto done;
        list_del_init(&urbp->urb_list);
 
+       if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS)
+               unlink_isochronous_tds(uhci, urb);
        uhci_unlink_generic(uhci, urb);
 
        uhci_get_current_frame_number(uhci);
index a330a4b..1d973bc 100644 (file)
@@ -425,9 +425,8 @@ static void mdc800_usb_download_notify (struct urb *urb, struct pt_regs *res)
 static struct usb_driver mdc800_usb_driver;
 static struct file_operations mdc800_device_ops;
 static struct usb_class_driver mdc800_class = {
-       .name =         "usb/mdc800%d",
+       .name =         "mdc800%d",
        .fops =         &mdc800_device_ops,
-       .mode =         S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP,
        .minor_base =   MDC800_DEVICE_MINOR_BASE,
 };
 
@@ -976,13 +975,13 @@ static struct usb_driver mdc800_usb_driver =
        Init and Cleanup this driver (Main Functions)
 *************************************************************************/
 
-#define try(A)           if (!(A)) goto cleanup_on_fail;
-
 static int __init usb_mdc800_init (void)
 {
        int retval = -ENODEV;
        /* Allocate Memory */
-       try (mdc800=kmalloc (sizeof (struct mdc800_data), GFP_KERNEL));
+       mdc800=kmalloc (sizeof (struct mdc800_data), GFP_KERNEL);
+       if (!mdc800)
+               goto cleanup_on_fail;
 
        memset(mdc800, 0, sizeof(struct mdc800_data));
        mdc800->dev = NULL;
@@ -998,13 +997,25 @@ static int __init usb_mdc800_init (void)
        mdc800->downloaded = 0;
        mdc800->written = 0;
 
-       try (mdc800->irq_urb_buffer=kmalloc (8, GFP_KERNEL));
-       try (mdc800->write_urb_buffer=kmalloc (8, GFP_KERNEL));
-       try (mdc800->download_urb_buffer=kmalloc (64, GFP_KERNEL));
+       mdc800->irq_urb_buffer=kmalloc (8, GFP_KERNEL);
+       if (!mdc800->irq_urb_buffer)
+               goto cleanup_on_fail;
+       mdc800->write_urb_buffer=kmalloc (8, GFP_KERNEL);
+       if (!mdc800->write_urb_buffer)
+               goto cleanup_on_fail;
+       mdc800->download_urb_buffer=kmalloc (64, GFP_KERNEL);
+       if (!mdc800->download_urb_buffer)
+               goto cleanup_on_fail;
 
-       try (mdc800->irq_urb=usb_alloc_urb (0, GFP_KERNEL));
-       try (mdc800->download_urb=usb_alloc_urb (0, GFP_KERNEL));
-       try (mdc800->write_urb=usb_alloc_urb (0, GFP_KERNEL));
+       mdc800->irq_urb=usb_alloc_urb (0, GFP_KERNEL);
+       if (!mdc800->irq_urb)
+               goto cleanup_on_fail;
+       mdc800->download_urb=usb_alloc_urb (0, GFP_KERNEL);
+       if (!mdc800->download_urb)
+               goto cleanup_on_fail;
+       mdc800->write_urb=usb_alloc_urb (0, GFP_KERNEL);
+       if (!mdc800->write_urb)
+               goto cleanup_on_fail;
 
        /* Register the driver */
        retval = usb_register(&mdc800_usb_driver);
index c84e148..c89d076 100644 (file)
@@ -773,11 +773,10 @@ static int mts_usb_probe(struct usb_interface *intf,
        }
        
        
-       new_desc = kmalloc(sizeof(struct mts_desc), GFP_KERNEL);
+       new_desc = kzalloc(sizeof(struct mts_desc), GFP_KERNEL);
        if (!new_desc)
                goto out;
 
-       memset(new_desc, 0, sizeof(*new_desc));
        new_desc->urb = usb_alloc_urb(0, GFP_KERNEL);
        if (!new_desc->urb)
                goto out_kfree;
index 1c52053..1c3b472 100644 (file)
@@ -2154,7 +2154,7 @@ aiptek_probe(struct usb_interface *intf, const struct usb_device_id *id)
         * input_handles associated with this input device.
         * What identifies an evdev input_handler is that it begins
         * with 'event', continues with a digit, and that in turn
-        * is mapped to /{devfs}/input/eventN.
+        * is mapped to input/eventN.
         */
        list_for_each_safe(node, next, &inputdev->h_list) {
                inputhandle = to_handle(node);
index 411a064..79ddce4 100644 (file)
@@ -1784,6 +1784,9 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf)
        hid->urbctrl->transfer_dma = hid->ctrlbuf_dma;
        hid->urbctrl->transfer_flags |= (URB_NO_TRANSFER_DMA_MAP | URB_NO_SETUP_DMA_MAP);
 
+       /* May be needed for some devices */
+       usb_clear_halt(hid->dev, hid->urbin->pipe);
+
        return hid;
 
 fail:
@@ -1887,7 +1890,6 @@ static int hid_suspend(struct usb_interface *intf, pm_message_t message)
        struct hid_device *hid = usb_get_intfdata (intf);
 
        usb_kill_urb(hid->urbin);
-       intf->dev.power.power_state = PMSG_SUSPEND;
        dev_dbg(&intf->dev, "suspend\n");
        return 0;
 }
@@ -1897,7 +1899,6 @@ static int hid_resume(struct usb_interface *intf)
        struct hid_device *hid = usb_get_intfdata (intf);
        int status;
 
-       intf->dev.power.power_state = PMSG_ON;
        if (hid->open)
                status = usb_submit_urb(hid->urbin, GFP_NOIO);
        else
index d324278..440377c 100644 (file)
@@ -732,9 +732,8 @@ static struct file_operations hiddev_fops = {
 };
 
 static struct usb_class_driver hiddev_class = {
-       .name =         "usb/hid/hiddev%d",
+       .name =         "hiddev%d",
        .fops =         &hiddev_fops,
-       .mode =         S_IFCHR | S_IRUGO | S_IWUSR,
        .minor_base =   HIDDEV_MINOR_BASE,
 };
 
index 52ff27f..a424094 100644 (file)
@@ -79,7 +79,7 @@ struct seg7_conversion_map {
 
 static inline int map_to_seg7(struct seg7_conversion_map *map, int c)
 {
-       return c & 0x7f ? map->table[c] : -EINVAL;
+       return c >= 0 && c < sizeof(map->table) ? map->table[c] : -EINVAL;
 }
 
 #define SEG7_CONVERSION_MAP(_name, _map)       \
index 3766ccc..0043e6e 100644 (file)
@@ -75,7 +75,9 @@ struct touchkit_usb {
 
 static struct usb_device_id touchkit_devices[] = {
        {USB_DEVICE(0x3823, 0x0001)},
+       {USB_DEVICE(0x0123, 0x0001)},
        {USB_DEVICE(0x0eef, 0x0001)},
+       {USB_DEVICE(0x0eef, 0x0002)},
        {}
 };
 
index 6ca2fae..27b23c5 100644 (file)
@@ -707,9 +707,8 @@ static struct file_operations dabusb_fops =
 };
 
 static struct usb_class_driver dabusb_class = {
-       .name =         "usb/dabusb%d",
+       .name =         "dabusb%d",
        .fops =         &dabusb_fops,
-       .mode =         S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP,
        .minor_base =   DABUSB_MINOR,
 };
 
index ae4681f..5f33f7c 100644 (file)
@@ -1873,9 +1873,8 @@ static struct file_operations auerswald_fops =
 };
 
 static struct usb_class_driver auerswald_class = {
-       .name =         "usb/auer%d",
+       .name =         "auer%d",
        .fops =         &auerswald_fops,
-       .mode =         S_IFCHR | S_IRUGO | S_IWUGO,
        .minor_base =   AUER_MINOR_BASE,
 };
 
index 733acc2..1dc3e0f 100644 (file)
@@ -105,11 +105,10 @@ static struct file_operations idmouse_fops = {
        .release = idmouse_release,
 };
 
-/* class driver information for devfs */
+/* class driver information */
 static struct usb_class_driver idmouse_class = {
-       .name = "usb/idmouse%d",
+       .name = "idmouse%d",
        .fops = &idmouse_fops,
-       .mode = S_IFCHR | S_IRUSR | S_IRGRP | S_IROTH, /* filemode (char, 444) */
        .minor_base = USB_IDMOUSE_MINOR_BASE,
 };
 
@@ -320,20 +319,8 @@ static ssize_t idmouse_read(struct file *file, char __user *buffer, size_t count
                return -ENODEV;
        }
 
-       if (*ppos >= IMGSIZE) {
-               up (&dev->sem);
-               return 0;
-       }
-
-       count = min ((loff_t)count, IMGSIZE - (*ppos));
-
-       if (copy_to_user (buffer, dev->bulk_in_buffer + *ppos, count)) {
-               result = -EFAULT;
-       } else {
-               result = count;
-               *ppos += count;
-       }
-
+       result = simple_read_from_buffer(buffer, count, ppos,
+                                       dev->bulk_in_buffer, IMGSIZE);
        /* unlock the device */
        up(&dev->sem);
        return result;
index 7d06105..2703e20 100644 (file)
@@ -271,12 +271,11 @@ static struct file_operations tower_fops = {
 
 /*
  * usb class driver info in order to get a minor number from the usb core,
- * and to have the device registered with devfs and the driver core
+ * and to have the device registered with the driver core
  */
 static struct usb_class_driver tower_class = {
-       .name =         "usb/legousbtower%d",
+       .name =         "legousbtower%d",
        .fops =         &tower_fops,
-       .mode =         S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH,
        .minor_base =   LEGO_USB_TOWER_MINOR_BASE,
 };
 
index 26f77e2..7d02d8e 100644 (file)
@@ -443,9 +443,8 @@ file_operations usb_rio_fops = {
 };
 
 static struct usb_class_driver usb_rio_class = {
-       .name =         "usb/rio500%d",
+       .name =         "rio500%d",
        .fops =         &usb_rio_fops,
-       .mode =         S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP,
        .minor_base =   RIO_MINOR,
 };
 
index 39db315..c946c9a 100644 (file)
@@ -2440,7 +2440,7 @@ int
 sisusb_reset_text_mode(struct sisusb_usb_data *sisusb, int init)
 {
        int ret = 0, slot = sisusb->font_slot, i;
-       struct font_desc *myfont;
+       const struct font_desc *myfont;
        u8 *tempbuf;
        u16 *tempbufb;
        size_t written;
@@ -3239,12 +3239,7 @@ static struct file_operations usb_sisusb_fops = {
 };
 
 static struct usb_class_driver usb_sisusb_class = {
-#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,13)
-       .name =         "usb/sisusbvga%d",
-       .mode =         S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP,
-#else
        .name =         "sisusbvga%d",
-#endif
        .fops =         &usb_sisusb_fops,
        .minor_base =   SISUSB_MINOR
 };
index 096ab30..85f3725 100644 (file)
@@ -251,13 +251,12 @@ static struct file_operations lcd_fops = {
 };
 
 /*
- *  * usb class driver info in order to get a minor number from the usb core,
- *   * and to have the device registered with devfs and the driver core
- *    */
+ * usb class driver info in order to get a minor number from the usb core,
+ * and to have the device registered with the driver core
+ */
 static struct usb_class_driver lcd_class = {
-        .name =         "usb/lcd%d",
+        .name =         "lcd%d",
         .fops =         &lcd_fops,
-        .mode =         S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH,
         .minor_base =   USBLCD_MINOR,
 };
 
index 54799eb..90a9625 100644 (file)
@@ -983,6 +983,7 @@ test_ctrl_queue (struct usbtest_dev *dev, struct usbtest_param *param)
                reqp->number = i % NUM_SUBCASES;
                reqp->expected = expected;
                u->setup_packet = (char *) &reqp->setup;
+               u->transfer_flags |= URB_NO_SETUP_DMA_MAP;
 
                u->context = &context;
                u->complete = ctrl_complete;
@@ -1948,21 +1949,11 @@ usbtest_probe (struct usb_interface *intf, const struct usb_device_id *id)
 
 static int usbtest_suspend (struct usb_interface *intf, pm_message_t message)
 {
-       struct usbtest_dev      *dev = usb_get_intfdata (intf);
-
-       down (&dev->sem);
-       intf->dev.power.power_state = PMSG_SUSPEND;
-       up (&dev->sem);
        return 0;
 }
 
 static int usbtest_resume (struct usb_interface *intf)
 {
-       struct usbtest_dev      *dev = usb_get_intfdata (intf);
-
-       down (&dev->sem);
-       intf->dev.power.power_state = PMSG_ON;
-       up (&dev->sem);
        return 0;
 }
 
index 508a210..c34944c 100644 (file)
@@ -11,6 +11,7 @@
 #include <linux/usb.h>
 #include <linux/debugfs.h>
 #include <linux/smp_lock.h>
+#include <linux/notifier.h>
 
 #include "usb_mon.h"
 #include "../core/hcd.h"
@@ -205,6 +206,23 @@ static void mon_bus_remove(struct usb_bus *ubus)
        up(&mon_lock);
 }
 
+static int mon_notify(struct notifier_block *self, unsigned long action,
+                     void *dev)
+{
+       switch (action) {
+       case USB_BUS_ADD:
+               mon_bus_add(dev);
+               break;
+       case USB_BUS_REMOVE:
+               mon_bus_remove(dev);
+       }
+       return NOTIFY_OK;
+}
+
+static struct notifier_block mon_nb = {
+       .notifier_call =        mon_notify,
+};
+
 /*
  * Ops
  */
@@ -212,8 +230,6 @@ static struct usb_mon_operations mon_ops_0 = {
        .urb_submit =   mon_submit,
        .urb_submit_error = mon_submit_error,
        .urb_complete = mon_complete,
-       .bus_add =      mon_bus_add,
-       .bus_remove =   mon_bus_remove,
 };
 
 /*
@@ -329,6 +345,8 @@ static int __init mon_init(void)
        }
        // MOD_INC_USE_COUNT(which_module?);
 
+       usb_register_notify(&mon_nb);
+
        down(&usb_bus_list_lock);
        list_for_each_entry (ubus, &usb_bus_list, bus_list) {
                mon_bus_init(mondir, ubus);
@@ -342,6 +360,7 @@ static void __exit mon_exit(void)
        struct mon_bus *mbus;
        struct list_head *p;
 
+       usb_unregister_notify(&mon_nb);
        usb_mon_deregister();
 
        down(&mon_lock);
index 8c010bb..efd6ca7 100644 (file)
@@ -294,7 +294,7 @@ config USB_NET_ZAURUS
          This also supports some related device firmware, as used in some
          PDAs from Olympus and some cell phones from Motorola.
 
-         If you install an alternate ROM image, such as the Linux 2.6 based
+         If you install an alternate image, such as the Linux 2.6 based
          versions of OpenZaurus, you should no longer need to support this
          protocol.  Only the "eth-fd" or "net_fd" drivers in these devices
          really need this non-conformant variant of CDC Ethernet (or in
index c82655d..6bef1be 100644 (file)
@@ -469,7 +469,7 @@ static int kaweth_reset(struct kaweth_device *kaweth)
                                0,
                                KAWETH_CONTROL_TIMEOUT);
 
-       udelay(10000);
+       mdelay(10);
 
        kaweth_dbg("kaweth_reset() returns %d.",result);
 
index 6a4ffe6..537eb18 100644 (file)
@@ -1384,7 +1384,6 @@ static int pegasus_suspend (struct usb_interface *intf, pm_message_t message)
                usb_kill_urb(pegasus->rx_urb);
                usb_kill_urb(pegasus->intr_urb);
        }
-       intf->dev.power.power_state = PMSG_SUSPEND;
        return 0;
 }
 
@@ -1392,7 +1391,6 @@ static int pegasus_resume (struct usb_interface *intf)
 {
        struct pegasus *pegasus = usb_get_intfdata(intf);
 
-       intf->dev.power.power_state = PMSG_ON;
        netif_device_attach (pegasus->net);
        if (netif_running(pegasus->net)) {
                pegasus->rx_urb->status = 0;
index b98f2a8..9fbd59b 100644 (file)
@@ -181,6 +181,8 @@ PEGASUS_DEV( "Accton USB 10/100 Ethernet Adapter", VENDOR_ACCTON, 0x1046,
                DEFAULT_GPIO_RESET )
 PEGASUS_DEV( "SpeedStream USB 10/100 Ethernet", VENDOR_ACCTON, 0x5046,
                DEFAULT_GPIO_RESET | PEGASUS_II )
+PEGASUS_DEV( "Philips USB 10/100 Ethernet", VENDOR_ACCTON, 0xb004,
+               DEFAULT_GPIO_RESET | PEGASUS_II )
 PEGASUS_DEV( "ADMtek ADM8511 \"Pegasus II\" USB Ethernet",
                VENDOR_ADMTEK, 0x8511,
                DEFAULT_GPIO_RESET | PEGASUS_II | HAS_HOME_PNA )
index c3d4e35..787dd35 100644 (file)
@@ -909,6 +909,7 @@ static void rtl8150_disconnect(struct usb_interface *intf)
        usb_set_intfdata(intf, NULL);
        if (dev) {
                set_bit(RTL8150_UNPLUG, &dev->flags);
+               tasklet_disable(&dev->tl);
                unregister_netdev(dev->netdev);
                unlink_all_urbs(dev);
                free_all_urbs(dev);
index fce81d7..74f05c9 100644 (file)
@@ -1185,7 +1185,6 @@ int usbnet_suspend (struct usb_interface *intf, pm_message_t message)
        netif_device_detach (dev->net);
        (void) unlink_urbs (dev, &dev->rxq);
        (void) unlink_urbs (dev, &dev->txq);
-       intf->dev.power.power_state = PMSG_SUSPEND;
        return 0;
 }
 EXPORT_SYMBOL_GPL(usbnet_suspend);
@@ -1194,7 +1193,6 @@ int usbnet_resume (struct usb_interface *intf)
 {
        struct usbnet           *dev = usb_get_intfdata(intf);
 
-       intf->dev.power.power_state = PMSG_ON;
        netif_device_attach (dev->net);
        tasklet_schedule (&dev->bh);
        return 0;
diff --git a/drivers/usb/serial/ChangeLog.old b/drivers/usb/serial/ChangeLog.old
new file mode 100644 (file)
index 0000000..c1b2799
--- /dev/null
@@ -0,0 +1,730 @@
+This is the contents of some of the drivers/usb/serial/ files that had  old
+changelog comments.  They were quite old, and out of date, and we don't keep
+them anymore, so I've put them here, away from the source files, in case
+people still care to see them.
+
+- Greg Kroah-Hartman <greg@kroah.com> October 20, 2005
+
+-----------------------------------------------------------------------
+usb-serial.h Change Log comments:
+
+ (03/26/2002) gkh
+       removed the port->tty check from port_paranoia_check() due to serial
+       consoles not having a tty device assigned to them.
+
+ (12/03/2001) gkh
+       removed active from the port structure.
+       added documentation to the usb_serial_device_type structure
+
+ (10/10/2001) gkh
+       added vendor and product to serial structure.  Needed to determine device
+       owner when the device is disconnected.
+
+ (05/30/2001) gkh
+       added sem to port structure and removed port_lock
+
+ (10/05/2000) gkh
+       Added interrupt_in_endpointAddress and bulk_in_endpointAddress to help
+       fix bug with urb->dev not being set properly, now that the usb core
+       needs it.
+
+ (09/11/2000) gkh
+       Added usb_serial_debug_data function to help get rid of #DEBUG in the
+       drivers.
+
+ (08/28/2000) gkh
+       Added port_lock to port structure.
+
+ (08/08/2000) gkh
+       Added open_count to port structure.
+
+ (07/23/2000) gkh
+       Added bulk_out_endpointAddress to port structure.
+
+ (07/19/2000) gkh, pberger, and borchers
+       Modifications to allow usb-serial drivers to be modules.
+
+-----------------------------------------------------------------------
+usb-serial.c Change Log comments:
+
+ (12/10/2002) gkh
+       Split the ports off into their own struct device, and added a
+       usb-serial bus driver.
+
+ (11/19/2002) gkh
+       removed a few #ifdefs for the generic code and cleaned up the failure
+       logic in initialization.
+
+ (10/02/2002) gkh
+       moved the console code to console.c and out of this file.
+
+ (06/05/2002) gkh
+       moved location of startup() call in serial_probe() until after all
+       of the port information and endpoints are initialized.  This makes
+       things easier for some drivers.
+
+ (04/10/2002) gkh
+       added serial_read_proc function which creates a
+       /proc/tty/driver/usb-serial file.
+
+ (03/27/2002) gkh
+       Got USB serial console code working properly and merged into the main
+       version of the tree.  Thanks to Randy Dunlap for the initial version
+       of this code, and for pushing me to finish it up.
+       The USB serial console works with any usb serial driver device.
+
+ (03/21/2002) gkh
+       Moved all manipulation of port->open_count into the core.  Now the
+       individual driver's open and close functions are called only when the
+       first open() and last close() is called.  Making the drivers a bit
+       smaller and simpler.
+       Fixed a bug if a driver didn't have the owner field set.
+
+ (02/26/2002) gkh
+       Moved all locking into the main serial_* functions, instead of having
+       the individual drivers have to grab the port semaphore.  This should
+       reduce races.
+       Reworked the MOD_INC logic a bit to always increment and decrement, even
+       if the generic driver is being used.
+
+ (10/10/2001) gkh
+       usb_serial_disconnect() now sets the serial->dev pointer is to NULL to
+       help prevent child drivers from accessing the device since it is now
+       gone.
+
+ (09/13/2001) gkh
+       Moved generic driver initialize after we have registered with the USB
+       core.  Thanks to Randy Dunlap for pointing this problem out.
+
+ (07/03/2001) gkh
+       Fixed module paramater size.  Thanks to John Brockmeyer for the pointer.
+       Fixed vendor and product getting defined through the MODULE_PARM macro
+       if the Generic driver wasn't compiled in.
+       Fixed problem with generic_shutdown() not being called for drivers that
+       don't have a shutdown() function.
+
+ (06/06/2001) gkh
+       added evil hack that is needed for the prolific pl2303 device due to the
+       crazy way its endpoints are set up.
+
+ (05/30/2001) gkh
+       switched from using spinlock to a semaphore, which fixes lots of problems.
+
+ (04/08/2001) gb
+       Identify version on module load.
+
+ 2001_02_05 gkh
+       Fixed buffer overflows bug with the generic serial driver.  Thanks to
+       Todd Squires <squirest@ct0.com> for fixing this.
+
+ (01/10/2001) gkh
+       Fixed bug where the generic serial adaptor grabbed _any_ device that was
+       offered to it.
+
+ (12/12/2000) gkh
+       Removed MOD_INC and MOD_DEC from poll and disconnect functions, and
+       moved them to the serial_open and serial_close functions.
+       Also fixed bug with there not being a MOD_DEC for the generic driver
+       (thanks to Gary Brubaker for finding this.)
+
+ (11/29/2000) gkh
+       Small NULL pointer initialization cleanup which saves a bit of disk image
+
+ (11/01/2000) Adam J. Richter
+       instead of using idVendor/idProduct pairs, usb serial drivers
+       now identify their hardware interest with usb_device_id tables,
+       which they usually have anyhow for use with MODULE_DEVICE_TABLE.
+
+ (10/05/2000) gkh
+       Fixed bug with urb->dev not being set properly, now that the usb
+       core needs it.
+
+ (09/11/2000) gkh
+       Removed DEBUG #ifdefs with call to usb_serial_debug_data
+
+ (08/28/2000) gkh
+       Added port_lock to port structure.
+       Added locks for SMP safeness to generic driver
+       Fixed the ability to open a generic device's port more than once.
+
+ (07/23/2000) gkh
+       Added bulk_out_endpointAddress to port structure.
+
+ (07/19/2000) gkh, pberger, and borchers
+       Modifications to allow usb-serial drivers to be modules.
+
+ (07/03/2000) gkh
+       Added more debugging to serial_ioctl call
+
+ (06/25/2000) gkh
+       Changed generic_write_bulk_callback to not call wake_up_interruptible
+       directly, but to have port_softint do it at a safer time.
+
+ (06/23/2000) gkh
+       Cleaned up debugging statements in a quest to find UHCI timeout bug.
+
+ (05/22/2000) gkh
+       Changed the makefile, enabling the big CONFIG_USB_SERIAL_SOMTHING to be
+       removed from the individual device source files.
+
+ (05/03/2000) gkh
+       Added the Digi Acceleport driver from Al Borchers and Peter Berger.
+
+ (05/02/2000) gkh
+       Changed devfs and tty register code to work properly now. This was based on
+       the ACM driver changes by Vojtech Pavlik.
+
+ (04/27/2000) Ryan VanderBijl
+       Put calls to *_paranoia_checks into one function.
+
+ (04/23/2000) gkh
+       Fixed bug that Randy Dunlap found for Generic devices with no bulk out ports.
+       Moved when the startup code printed out the devices that are supported.
+
+ (04/19/2000) gkh
+       Added driver for ZyXEL omni.net lcd plus ISDN TA
+       Made startup info message specify which drivers were compiled in.
+
+ (04/03/2000) gkh
+       Changed the probe process to remove the module unload races.
+       Changed where the tty layer gets initialized to have devfs work nicer.
+       Added initial devfs support.
+
+ (03/26/2000) gkh
+       Split driver up into device specific pieces.
+
+ (03/19/2000) gkh
+       Fixed oops that could happen when device was removed while a program
+       was talking to the device.
+       Removed the static urbs and now all urbs are created and destroyed
+       dynamically.
+       Reworked the internal interface. Now everything is based on the
+       usb_serial_port structure instead of the larger usb_serial structure.
+       This fixes the bug that a multiport device could not have more than
+       one port open at one time.
+
+ (03/17/2000) gkh
+       Added config option for debugging messages.
+       Added patch for keyspan pda from Brian Warner.
+
+ (03/06/2000) gkh
+       Added the keyspan pda code from Brian Warner <warner@lothar.com>
+       Moved a bunch of the port specific stuff into its own structure. This
+       is in anticipation of the true multiport devices (there's a bug if you
+       try to access more than one port of any multiport device right now)
+
+ (02/21/2000) gkh
+       Made it so that any serial devices only have to specify which functions
+       they want to overload from the generic function calls (great,
+       inheritance in C, in a driver, just what I wanted...)
+       Added support for set_termios and ioctl function calls. No drivers take
+       advantage of this yet.
+       Removed the #ifdef MODULE, now there is no module specific code.
+       Cleaned up a few comments in usb-serial.h that were wrong (thanks again
+       to Miles Lott).
+       Small fix to get_free_serial.
+
+ (02/14/2000) gkh
+       Removed the Belkin and Peracom functionality from the driver due to
+       the lack of support from the vendor, and me not wanting people to
+       accidenatly buy the device, expecting it to work with Linux.
+       Added read_bulk_callback and write_bulk_callback to the type structure
+       for the needs of the FTDI and WhiteHEAT driver.
+       Changed all reverences to FTDI to FTDI_SIO at the request of Bill
+       Ryder.
+       Changed the output urb size back to the max endpoint size to make
+       the ftdi_sio driver have it easier, and due to the fact that it didn't
+       really increase the speed any.
+
+ (02/11/2000) gkh
+       Added VISOR_FUNCTION_CONSOLE to the visor startup function. This was a
+       patch from Miles Lott (milos@insync.net).
+       Fixed bug with not restoring the minor range that a device grabs, if
+       the startup function fails (thanks Miles for finding this).
+
+ (02/05/2000) gkh
+       Added initial framework for the Keyspan PDA serial converter so that
+       Brian Warner has a place to put his code.
+       Made the ezusb specific functions generic enough that different
+       devices can use them (whiteheat and keyspan_pda both need them).
+       Split out a whole bunch of structure and other stuff to a separate
+       usb-serial.h file.
+       Made the Visor connection messages a little more understandable, now
+       that Miles Lott (milos@insync.net) has gotten the Generic channel to
+       work. Also made them always show up in the log file.
+
+ (01/25/2000) gkh
+       Added initial framework for FTDI serial converter so that Bill Ryder
+       has a place to put his code.
+       Added the vendor specific info from Handspring. Now we can print out
+       informational debug messages as well as understand what is happening.
+
+ (01/23/2000) gkh
+       Fixed problem of crash when trying to open a port that didn't have a
+       device assigned to it. Made the minor node finding a little smarter,
+       now it looks to find a continuous space for the new device.
+
+ (01/21/2000) gkh
+       Fixed bug in visor_startup with patch from Miles Lott (milos@insync.net)
+       Fixed get_serial_by_minor which was all messed up for multi port
+       devices. Fixed multi port problem for generic devices. Now the number
+       of ports is determined by the number of bulk out endpoints for the
+       generic device.
+
+ (01/19/2000) gkh
+       Removed lots of cruft that was around from the old (pre urb) driver
+       interface.
+       Made the serial_table dynamic. This should save lots of memory when
+       the number of minor nodes goes up to 256.
+       Added initial support for devices that have more than one port.
+       Added more debugging comments for the Visor, and added a needed
+       set_configuration call.
+
+ (01/17/2000) gkh
+       Fixed the WhiteHEAT firmware (my processing tool had a bug)
+       and added new debug loader firmware for it.
+       Removed the put_char function as it isn't really needed.
+       Added visor startup commands as found by the Win98 dump.
+
+ (01/13/2000) gkh
+       Fixed the vendor id for the generic driver to the one I meant it to be.
+
+ (01/12/2000) gkh
+       Forget the version numbering...that's pretty useless...
+       Made the driver able to be compiled so that the user can select which
+       converter they want to use. This allows people who only want the Visor
+       support to not pay the memory size price of the WhiteHEAT.
+       Fixed bug where the generic driver (idVendor=0000 and idProduct=0000)
+       grabbed the root hub. Not good.
+
+ version 0.4.0 (01/10/2000) gkh
+       Added whiteheat.h containing the firmware for the ConnectTech WhiteHEAT
+       device. Added startup function to allow firmware to be downloaded to
+       a device if it needs to be.
+       Added firmware download logic to the WhiteHEAT device.
+       Started to add #defines to split up the different drivers for potential
+       configuration option.
+
+ version 0.3.1 (12/30/99) gkh
+      Fixed problems with urb for bulk out.
+      Added initial support for multiple sets of endpoints. This enables
+      the Handspring Visor to be attached successfully. Only the first
+      bulk in / bulk out endpoint pair is being used right now.
+
+ version 0.3.0 (12/27/99) gkh
+       Added initial support for the Handspring Visor based on a patch from
+       Miles Lott (milos@sneety.insync.net)
+       Cleaned up the code a bunch and converted over to using urbs only.
+
+ version 0.2.3 (12/21/99) gkh
+       Added initial support for the Connect Tech WhiteHEAT converter.
+       Incremented the number of ports in expectation of getting the
+       WhiteHEAT to work properly (4 ports per connection).
+       Added notification on insertion and removal of what port the
+       device is/was connected to (and what kind of device it was).
+
+ version 0.2.2 (12/16/99) gkh
+       Changed major number to the new allocated number. We're legal now!
+
+ version 0.2.1 (12/14/99) gkh
+       Fixed bug that happens when device node is opened when there isn't a
+       device attached to it. Thanks to marek@webdesign.no for noticing this.
+
+ version 0.2.0 (11/10/99) gkh
+       Split up internals to make it easier to add different types of serial
+       converters to the code.
+       Added a "generic" driver that gets it's vendor and product id
+       from when the module is loaded. Thanks to David E. Nelson (dnelson@jump.net)
+       for the idea and sample code (from the usb scanner driver.)
+       Cleared up any licensing questions by releasing it under the GNU GPL.
+
+ version 0.1.2 (10/25/99) gkh
+       Fixed bug in detecting device.
+
+ version 0.1.1 (10/05/99) gkh
+       Changed the major number to not conflict with anything else.
+
+ version 0.1 (09/28/99) gkh
+       Can recognize the two different devices and start up a read from
+       device when asked to. Writes also work. No control signals yet, this
+       all is vendor specific data (i.e. no spec), also no control for
+       different baud rates or other bit settings.
+       Currently we are using the same devid as the acm driver. This needs
+       to change.
+
+-----------------------------------------------------------------------
+visor.c Change Log comments:
+
+ (06/03/2003) Judd Montgomery <judd at jpilot.org>
+     Added support for module parameter options for untested/unknown
+     devices.
+
+ (03/09/2003) gkh
+       Added support for the Sony Clie NZ90V device.  Thanks to Martin Brachtl
+       <brachtl@redgrep.cz> for the information.
+
+ (03/05/2003) gkh
+       Think Treo support is now working.
+
+ (04/03/2002) gkh
+       Added support for the Sony OS 4.1 devices.  Thanks to Hiroyuki ARAKI
+       <hiro@zob.ne.jp> for the information.
+
+ (03/27/2002) gkh
+       Removed assumptions that port->tty was always valid (is not true
+       for usb serial console devices.)
+
+ (03/23/2002) gkh
+       Added support for the Palm i705 device, thanks to Thomas Riemer
+       <tom@netmech.com> for the information.
+
+ (03/21/2002) gkh
+       Added support for the Palm m130 device, thanks to Udo Eisenbarth
+       <udo.eisenbarth@web.de> for the information.
+
+ (02/27/2002) gkh
+       Reworked the urb handling logic.  We have no more pool, but dynamically
+       allocate the urb and the transfer buffer on the fly.  In testing this
+       does not incure any measurable overhead.  This also relies on the fact
+       that we have proper reference counting logic for urbs.
+
+ (02/21/2002) SilaS
+  Added initial support for the Palm m515 devices.
+
+ (02/14/2002) gkh
+       Added support for the Clie S-360 device.
+
+ (12/18/2001) gkh
+       Added better Clie support for 3.5 devices.  Thanks to Geoffrey Levand
+       for the patch.
+
+ (11/11/2001) gkh
+       Added support for the m125 devices, and added check to prevent oopses
+       for Clié devices that lie about the number of ports they have.
+
+ (08/30/2001) gkh
+       Added support for the Clie devices, both the 3.5 and 4.0 os versions.
+       Many thanks to Daniel Burke, and Bryan Payne for helping with this.
+
+ (08/23/2001) gkh
+       fixed a few potential bugs pointed out by Oliver Neukum.
+
+ (05/30/2001) gkh
+       switched from using spinlock to a semaphore, which fixes lots of problems.
+
+ (05/28/2000) gkh
+       Added initial support for the Palm m500 and Palm m505 devices.
+
+ (04/08/2001) gb
+       Identify version on module load.
+
+ (01/21/2000) gkh
+       Added write_room and chars_in_buffer, as they were previously using the
+       generic driver versions which is all wrong now that we are using an urb
+       pool.  Thanks to Wolfgang Grandegger for pointing this out to me.
+       Removed count assignment in the write function, which was not needed anymore
+       either.  Thanks to Al Borchers for pointing this out.
+
+ (12/12/2000) gkh
+       Moved MOD_DEC to end of visor_close to be nicer, as the final write
+       message can sleep.
+
+ (11/12/2000) gkh
+       Fixed bug with data being dropped on the floor by forcing tty->low_latency
+       to be on.  Hopefully this fixes the OHCI issue!
+
+ (11/01/2000) Adam J. Richter
+       usb_device_id table support
+
+ (10/05/2000) gkh
+       Fixed bug with urb->dev not being set properly, now that the usb
+       core needs it.
+
+ (09/11/2000) gkh
+       Got rid of always calling kmalloc for every urb we wrote out to the
+       device.
+       Added visor_read_callback so we can keep track of bytes in and out for
+       those people who like to know the speed of their device.
+       Removed DEBUG #ifdefs with call to usb_serial_debug_data
+
+ (09/06/2000) gkh
+       Fixed oops in visor_exit.  Need to uncomment usb_unlink_urb call _after_
+       the host controller drivers set urb->dev = NULL when the urb is finished.
+
+ (08/28/2000) gkh
+       Added locks for SMP safeness.
+
+ (08/08/2000) gkh
+       Fixed endian problem in visor_startup.
+       Fixed MOD_INC and MOD_DEC logic and the ability to open a port more
+       than once.
+
+ (07/23/2000) gkh
+       Added pool of write urbs to speed up transfers to the visor.
+
+ (07/19/2000) gkh
+       Added module_init and module_exit functions to handle the fact that this
+       driver is a loadable module now.
+
+ (07/03/2000) gkh
+       Added visor_set_ioctl and visor_set_termios functions (they don't do much
+       of anything, but are good for debugging.)
+
+ (06/25/2000) gkh
+       Fixed bug in visor_unthrottle that should help with the disconnect in PPP
+       bug that people have been reporting.
+
+ (06/23/2000) gkh
+       Cleaned up debugging statements in a quest to find UHCI timeout bug.
+
+ (04/27/2000) Ryan VanderBijl
+       Fixed memory leak in visor_close
+
+ (03/26/2000) gkh
+       Split driver up into device specific pieces.
+
+-----------------------------------------------------------------------
+pl2303.c Change Log comments:
+
+ 2002_Mar_26 gkh
+       allowed driver to work properly if there is no tty assigned to a port
+       (this happens for serial console devices.)
+
+ 2001_Oct_06 gkh
+       Added RTS and DTR line control.  Thanks to joe@bndlg.de for parts of it.
+
+ 2001_Sep_19 gkh
+       Added break support.
+
+ 2001_Aug_30 gkh
+       fixed oops in write_bulk_callback.
+
+ 2001_Aug_28 gkh
+       reworked buffer logic to be like other usb-serial drivers.  Hopefully
+       removing some reported problems.
+
+ 2001_Jun_06 gkh
+       finished porting to 2.4 format.
+
+
+-----------------------------------------------------------------------
+io_edgeport.c Change Log comments:
+
+ 2003_04_03 al borchers
+  - fixed a bug (that shows up with dosemu) where the tty struct is
+    used in a callback after it has been freed
+
+ 2.3 2002_03_08 greg kroah-hartman
+       - fixed bug when multiple devices were attached at the same time.
+
+ 2.2 2001_11_14 greg kroah-hartman
+       - fixed bug in edge_close that kept the port from being used more
+         than once.
+       - fixed memory leak on device removal.
+       - fixed potential double free of memory when command urb submitting
+         failed.
+       - other small cleanups when the device is removed
+
+ 2.1 2001_07_09 greg kroah-hartman
+       - added support for TIOCMBIS and TIOCMBIC.
+
+     (04/08/2001) gb
+       - Identify version on module load.
+
+ 2.0 2001_03_05 greg kroah-hartman
+       - reworked entire driver to fit properly in with the other usb-serial
+         drivers.  Occasional oopses still happen, but it's a good start.
+
+ 1.2.3 (02/23/2001) greg kroah-hartman
+       - changed device table to work properly for 2.4.x final format.
+       - fixed problem with dropping data at high data rates.
+
+ 1.2.2 (11/27/2000) greg kroah-hartman
+       - cleaned up more NTisms.
+       - Added device table for 2.4.0-test11
+
+ 1.2.1 (11/08/2000) greg kroah-hartman
+       - Started to clean up NTisms.
+       - Fixed problem with dev field of urb for kernels >= 2.4.0-test9
+
+ 1.2 (10/17/2000) David Iacovelli
+       Remove all EPIC code and GPL source
+  Fix RELEVANT_IFLAG macro to include flow control
+  changes port configuration changes.
+  Fix redefinition of SERIAL_MAGIC
+  Change all timeout values to 5 seconds
+  Tried to fix the UHCI multiple urb submission, but failed miserably.
+  it seems to work fine with OHCI.
+  ( Greg take a look at the #if 0 at end of WriteCmdUsb() we must
+    find a way to work arount this UHCI bug )
+
+ 1.1 (10/11/2000) David Iacovelli
+  Fix XON/XOFF flow control to support both IXON and IXOFF
+
+ 0.9.27 (06/30/2000) David Iacovelli
+  Added transmit queue and now allocate urb for command writes.
+
+ 0.9.26 (06/29/2000) David Iacovelli
+  Add support for 80251 based edgeport
+
+ 0.9.25 (06/27/2000) David Iacovelli
+  Do not close the port if it has multiple opens.
+
+ 0.9.24 (05/26/2000) David Iacovelli
+  Add IOCTLs to support RXTX and JAVA POS
+  and first cut at running BlackBox Demo
+
+ 0.9.23 (05/24/2000) David Iacovelli
+  Add IOCTLs to support RXTX and JAVA POS
+
+ 0.9.22 (05/23/2000) David Iacovelli
+  fixed bug in enumeration.  If epconfig turns on mapping by
+  path after a device is already plugged in, we now update
+  the mapping correctly
+
+ 0.9.21 (05/16/2000) David Iacovelli
+  Added BlockUntilChaseResp() to also wait for txcredits
+  Updated the way we allocate and handle write URBs
+       Add debug code to dump buffers
+
+ 0.9.20 (05/01/2000) David Iacovelli
+       change driver to use usb/tts/
+
+ 0.9.19 (05/01/2000) David Iacovelli
+  Update code to compile if DEBUG is off
+
+ 0.9.18 (04/28/2000) David Iacovelli
+  cleanup and test tty_register with devfs
+
+ 0.9.17 (04/27/2000) greg kroah-hartman
+       changed tty_register around to be like the way it
+       was before, but now it works properly with devfs.
+
+ 0.9.16 (04/26/2000) david iacovelli
+  Fixed bug in GetProductInfo()
+
+ 0.9.15 (04/25/2000) david iacovelli
+       Updated enumeration
+
+ 0.9.14 (04/24/2000) david iacovelli
+  Removed all config/status IOCTLS and
+  converted to using /proc/edgeport
+  still playing with devfs
+
+ 0.9.13 (04/24/2000) david iacovelli
+  Removed configuration based on ttyUSB0
+  Added support for configuration using /prod/edgeport
+  first attempt at using devfs (not working yet!)
+  Added IOCTL to GetProductInfo()
+  Added support for custom baud rates
+       Add support for random port numbers
+
+ 0.9.12 (04/18/2000) david iacovelli
+       added additional configuration IOCTLs
+  use ttyUSB0 for configuration
+
+ 0.9.11 (04/17/2000) greg kroah-hartman
+       fixed module initialization race conditions.
+       made all urbs dynamically allocated.
+       made driver devfs compatible. now it only registers the tty device
+       when the device is actually plugged in.
+
+ 0.9.10 (04/13/2000) greg kroah-hartman
+       added proc interface framework.
+
+ 0.9.9 (04/13/2000) david iacovelli
+       added enumeration code and ioctls to configure the device
+
+ 0.9.8 (04/12/2000) david iacovelli
+  Change interrupt read start when device is plugged in
+  and stop when device is removed
+       process interrupt reads when all ports are closed
+  (keep value of rxBytesAvail consistent with the edgeport)
+  set the USB_BULK_QUEUE flag so that we can shove a bunch
+  of urbs at once down the pipe
+
+ 0.9.7 (04/10/2000) david iacovelli
+       start to add enumeration code.
+  generate serial number for epic devices
+  add support for kdb
+
+ 0.9.6 (03/30/2000) david iacovelli
+  add IOCTL to get string, manufacture, and boot descriptors
+
+ 0.9.5 (03/14/2000) greg kroah-hartman
+       more error checking added to SerialOpen to try to fix UHCI open problem
+
+ 0.9.4 (03/09/2000) greg kroah-hartman
+       added more error checking to handle oops when data is hanging
+       around and tty is abruptly closed.
+
+ 0.9.3 (03/09/2000) david iacovelli
+       Add epic support for xon/xoff chars
+       play with performance
+
+ 0.9.2 (03/08/2000) greg kroah-hartman
+       changed most "info" calls to "dbg"
+       implemented flow control properly in the termios call
+
+ 0.9.1 (03/08/2000) david iacovelli
+       added EPIC support
+       enabled bootloader update
+
+ 0.9 (03/08/2000) greg kroah-hartman
+       Release to IO networks.
+       Integrated changes that David made
+  made getting urbs for writing SMP safe
+
+ 0.8 (03/07/2000) greg kroah-hartman
+       Release to IO networks.
+       Fixed problems that were seen in code by David.
+  Now both Edgeport/4 and Edgeport/2 works properly.
+  Changed most of the functions to use port instead of serial.
+
+ 0.7 (02/27/2000) greg kroah-hartman
+       Milestone 3 release.
+       Release to IO Networks
+       ioctl for waiting on line change implemented.
+       ioctl for getting statistics implemented.
+       multiport support working.
+       lsr and msr registers are now handled properly.
+       change break now hooked up and working.
+       support for all known Edgeport devices.
+
+ 0.6 (02/22/2000) greg kroah-hartman
+       Release to IO networks.
+       CHASE is implemented correctly when port is closed.
+       SerialOpen now blocks correctly until port is fully opened.
+
+ 0.5 (02/20/2000) greg kroah-hartman
+       Release to IO networks.
+       Known problems:
+               modem status register changes are not sent on to the user
+               CHASE is not implemented when the port is closed.
+
+ 0.4 (02/16/2000) greg kroah-hartman
+       Second cut at the CeBit demo.
+       Doesn't leak memory on every write to the port
+       Still small leaks on startup.
+       Added support for Edgeport/2 and Edgeport/8
+
+ 0.3 (02/15/2000) greg kroah-hartman
+       CeBit demo release.
+       Force the line settings to 4800, 8, 1, e for the demo.
+       Warning! This version leaks memory like crazy!
+
+ 0.2 (01/30/2000) greg kroah-hartman
+       Milestone 1 release.
+       Device is found by USB subsystem, enumerated, fimware is downloaded
+       and the descriptors are printed to the debug log, config is set, and
+       green light starts to blink. Open port works, and data can be sent
+       and received at the default settings of the UART. Loopback connector
+       and debug log confirms this.
+
+ 0.1 (01/23/2000) greg kroah-hartman
+       Initial release to help IO Networks try to set up their test system.
+       Edgeport4 is recognized, firmware is downloaded, config is set so
+       device blinks green light every 3 sec. Port is bound, but opening,
+       closing, and sending data do not work properly.
+
+
index 9438909..7b5e8e4 100644 (file)
@@ -394,6 +394,15 @@ config USB_SERIAL_MCT_U232
          To compile this driver as a module, choose M here: the
          module will be called mct_u232.
 
+config USB_SERIAL_NOKIA_DKU2
+       tristate "USB Nokia DKU2 Driver"
+       depends on USB_SERIAL
+       help
+         Say Y here if you want to use a Nokia DKU2 device.
+
+         To compile this driver as a module, choose M here: the
+         module will be called nokia_dku2.
+
 config USB_SERIAL_PL2303
        tristate "USB Prolific 2303 Single Port Serial Driver"
        depends on USB_SERIAL
index 6c7cdcc..55fd461 100644 (file)
@@ -31,6 +31,7 @@ obj-$(CONFIG_USB_SERIAL_KEYSPAN_PDA)          += keyspan_pda.o
 obj-$(CONFIG_USB_SERIAL_KLSI)                  += kl5kusb105.o
 obj-$(CONFIG_USB_SERIAL_KOBIL_SCT)             += kobil_sct.o
 obj-$(CONFIG_USB_SERIAL_MCT_U232)              += mct_u232.o
+obj-$(CONFIG_USB_SERIAL_NOKIA_DKU2)            += nokia_dku2.o
 obj-$(CONFIG_USB_SERIAL_OMNINET)               += omninet.o
 obj-$(CONFIG_USB_SERIAL_OPTION)                        += option.o
 obj-$(CONFIG_USB_SERIAL_PL2303)                        += pl2303.o
index 926d4c2..1f29d88 100644 (file)
@@ -30,9 +30,11 @@ static struct usb_driver airprime_driver = {
        .id_table =     id_table,
 };
 
-static struct usb_serial_device_type airprime_device = {
-       .owner =                THIS_MODULE,
-       .name =                 "airprime",
+static struct usb_serial_driver airprime_device = {
+       .driver = {
+               .owner =        THIS_MODULE,
+               .name =         "airprime",
+       },
        .id_table =             id_table,
        .num_interrupt_in =     NUM_DONT_CARE,
        .num_bulk_in =          NUM_DONT_CARE,
index abb1b2c..84bc0ee 100644 (file)
@@ -121,10 +121,12 @@ static struct usb_driver belkin_driver = {
 };
 
 /* All of the device info needed for the serial converters */
-static struct usb_serial_device_type belkin_device = {
-       .owner =                THIS_MODULE,
-       .name =                 "Belkin / Peracom / GoHubs USB Serial Adapter",
-       .short_name =           "belkin",
+static struct usb_serial_driver belkin_device = {
+       .driver = {
+               .owner =        THIS_MODULE,
+               .name =         "belkin",
+       },
+       .description =          "Belkin / Peracom / GoHubs USB Serial Adapter",
        .id_table =             id_table_combined,
        .num_interrupt_in =     1,
        .num_bulk_in =          1,
index 2f612c2..664139a 100644 (file)
@@ -18,7 +18,7 @@
 
 static int usb_serial_device_match (struct device *dev, struct device_driver *drv)
 {
-       struct usb_serial_device_type *driver;
+       struct usb_serial_driver *driver;
        const struct usb_serial_port *port;
 
        /*
@@ -44,7 +44,7 @@ struct bus_type usb_serial_bus_type = {
 
 static int usb_serial_device_probe (struct device *dev)
 {
-       struct usb_serial_device_type *driver;
+       struct usb_serial_driver *driver;
        struct usb_serial_port *port;
        int retval = 0;
        int minor;
@@ -57,13 +57,13 @@ static int usb_serial_device_probe (struct device *dev)
 
        driver = port->serial->type;
        if (driver->port_probe) {
-               if (!try_module_get(driver->owner)) {
+               if (!try_module_get(driver->driver.owner)) {
                        dev_err(dev, "module get failed, exiting\n");
                        retval = -EIO;
                        goto exit;
                }
                retval = driver->port_probe (port);
-               module_put(driver->owner);
+               module_put(driver->driver.owner);
                if (retval)
                        goto exit;
        }
@@ -72,7 +72,7 @@ static int usb_serial_device_probe (struct device *dev)
        tty_register_device (usb_serial_tty_driver, minor, dev);
        dev_info(&port->serial->dev->dev, 
                 "%s converter now attached to ttyUSB%d\n",
-                driver->name, minor);
+                driver->description, minor);
 
 exit:
        return retval;
@@ -80,7 +80,7 @@ exit:
 
 static int usb_serial_device_remove (struct device *dev)
 {
-       struct usb_serial_device_type *driver;
+       struct usb_serial_driver *driver;
        struct usb_serial_port *port;
        int retval = 0;
        int minor;
@@ -92,43 +92,38 @@ static int usb_serial_device_remove (struct device *dev)
 
        driver = port->serial->type;
        if (driver->port_remove) {
-               if (!try_module_get(driver->owner)) {
+               if (!try_module_get(driver->driver.owner)) {
                        dev_err(dev, "module get failed, exiting\n");
                        retval = -EIO;
                        goto exit;
                }
                retval = driver->port_remove (port);
-               module_put(driver->owner);
+               module_put(driver->driver.owner);
        }
 exit:
        minor = port->number;
        tty_unregister_device (usb_serial_tty_driver, minor);
        dev_info(dev, "%s converter now disconnected from ttyUSB%d\n",
-                driver->name, minor);
+                driver->description, minor);
 
        return retval;
 }
 
-int usb_serial_bus_register(struct usb_serial_device_type *device)
+int usb_serial_bus_register(struct usb_serial_driver *driver)
 {
        int retval;
 
-       if (device->short_name)
-               device->driver.name = (char *)device->short_name;
-       else
-               device->driver.name = (char *)device->name;
-       device->driver.bus = &usb_serial_bus_type;
-       device->driver.probe = usb_serial_device_probe;
-       device->driver.remove = usb_serial_device_remove;
-       device->driver.owner = device->owner;
+       driver->driver.bus = &usb_serial_bus_type;
+       driver->driver.probe = usb_serial_device_probe;
+       driver->driver.remove = usb_serial_device_remove;
 
-       retval = driver_register(&device->driver);
+       retval = driver_register(&driver->driver);
 
        return retval;
 }
 
-void usb_serial_bus_deregister(struct usb_serial_device_type *device)
+void usb_serial_bus_deregister(struct usb_serial_driver *driver)
 {
-       driver_unregister (&device->driver);
+       driver_unregister(&driver->driver);
 }
 
index 97c78c2..c5334dd 100644 (file)
@@ -67,15 +67,17 @@ MODULE_DEVICE_TABLE (usb, id_table);
 
 static struct usb_driver cp2101_driver = {
        .owner          = THIS_MODULE,
-       .name           = "CP2101",
+       .name           = "cp2101",
        .probe          = usb_serial_probe,
        .disconnect     = usb_serial_disconnect,
        .id_table       = id_table,
 };
 
-static struct usb_serial_device_type cp2101_device = {
-       .owner                  = THIS_MODULE,
-       .name                   = "CP2101",
+static struct usb_serial_driver cp2101_device = {
+       .driver = {
+               .owner =        THIS_MODULE,
+               .name =         "cp2101",
+       },
        .id_table               = id_table,
        .num_interrupt_in       = 0,
        .num_bulk_in            = 0,
index b5b4310..e581e4a 100644 (file)
@@ -83,10 +83,12 @@ static struct usb_driver cyberjack_driver = {
        .id_table =     id_table,
 };
 
-static struct usb_serial_device_type cyberjack_device = {
-       .owner =                THIS_MODULE,
-       .name =                 "Reiner SCT Cyberjack USB card reader",
-       .short_name =           "cyberjack",
+static struct usb_serial_driver cyberjack_device = {
+       .driver = {
+               .owner =        THIS_MODULE,
+               .name =         "cyberjack",
+       },
+       .description =          "Reiner SCT Cyberjack USB card reader",
        .id_table =             id_table,
        .num_interrupt_in =     1,
        .num_bulk_in =          1,
index 9ee1aaf..af9290e 100644 (file)
@@ -176,10 +176,12 @@ static unsigned int         cypress_buf_put(struct cypress_buf *cb, const char *buf, u
 static unsigned int      cypress_buf_get(struct cypress_buf *cb, char *buf, unsigned int count);
 
 
-static struct usb_serial_device_type cypress_earthmate_device = {
-       .owner =                        THIS_MODULE,
-       .name =                         "DeLorme Earthmate USB",
-       .short_name =                   "earthmate",
+static struct usb_serial_driver cypress_earthmate_device = {
+       .driver = {
+               .owner =                THIS_MODULE,
+               .name =                 "earthmate",
+       },
+       .description =                  "DeLorme Earthmate USB",
        .id_table =                     id_table_earthmate,
        .num_interrupt_in =             1,
        .num_interrupt_out =            1,
@@ -203,10 +205,12 @@ static struct usb_serial_device_type cypress_earthmate_device = {
        .write_int_callback =           cypress_write_int_callback,
 };
 
-static struct usb_serial_device_type cypress_hidcom_device = {
-       .owner =                        THIS_MODULE,
-       .name =                         "HID->COM RS232 Adapter",
-       .short_name =                   "cyphidcom",
+static struct usb_serial_driver cypress_hidcom_device = {
+       .driver = {
+               .owner =                THIS_MODULE,
+               .name =                 "cyphidcom",
+       },
+       .description =                  "HID->COM RS232 Adapter",
        .id_table =                     id_table_cyphidcomrs232,
        .num_interrupt_in =             1,
        .num_interrupt_out =            1,
index a19a47f..dc74644 100644 (file)
@@ -503,10 +503,12 @@ static struct usb_driver digi_driver = {
 
 /* device info needed for the Digi serial converter */
 
-static struct usb_serial_device_type digi_acceleport_2_device = {
-       .owner =                        THIS_MODULE,
-       .name =                         "Digi 2 port USB adapter",
-       .short_name =                   "digi_2",
+static struct usb_serial_driver digi_acceleport_2_device = {
+       .driver = {
+               .owner =                THIS_MODULE,
+               .name =                 "digi_2",
+       },
+       .description =                  "Digi 2 port USB adapter",
        .id_table =                     id_table_2,
        .num_interrupt_in =             0,
        .num_bulk_in =                  4,
@@ -530,10 +532,12 @@ static struct usb_serial_device_type digi_acceleport_2_device = {
        .shutdown =                     digi_shutdown,
 };
 
-static struct usb_serial_device_type digi_acceleport_4_device = {
-       .owner =                        THIS_MODULE,
-       .name =                         "Digi 4 port USB adapter",
-       .short_name =                   "digi_4",
+static struct usb_serial_driver digi_acceleport_4_device = {
+       .driver = {
+               .owner =                THIS_MODULE,
+               .name =                 "digi_4",
+       },
+       .description =                  "Digi 4 port USB adapter",
        .id_table =                     id_table_4,
        .num_interrupt_in =             0,
        .num_bulk_in =                  5,
index 8d562ab..0b0546d 100644 (file)
@@ -112,9 +112,11 @@ static struct usb_driver empeg_driver = {
        .id_table =     id_table,
 };
 
-static struct usb_serial_device_type empeg_device = {
-       .owner =                THIS_MODULE,
-       .name =                 "Empeg",
+static struct usb_serial_driver empeg_device = {
+       .driver = {
+               .owner =        THIS_MODULE,
+               .name =         "empeg",
+       },
        .id_table =             id_table,
        .num_interrupt_in =     0,
        .num_bulk_in =          1,
index 5a8631c..61204bf 100644 (file)
@@ -411,6 +411,8 @@ static struct usb_device_id id_table_combined [] = {
        { USB_DEVICE(FTDI_VID, FTDI_ELV_UM100_PID) },
        { USB_DEVICE(FTDI_VID, FTDI_ELV_UR100_PID) },
        { USB_DEVICE(FTDI_VID, FTDI_ELV_ALC8500_PID) },
+       { USB_DEVICE(FTDI_VID, FTDI_PYRAMID_PID) },
+       { USB_DEVICE(FTDI_VID, FTDI_ELV_FHZ1000PC_PID) },
        /*
         * These will probably use user-space drivers.  Uncomment them if
         * you need them or use the user-specified vendor/product module
@@ -428,7 +430,6 @@ static struct usb_device_id id_table_combined [] = {
        /* { USB_DEVICE(FTDI_VID, FTDI_ELV_T1100_PID) }, */
        /* { USB_DEVICE(FTDI_VID, FTDI_ELV_PCD200_PID) }, */
        /* { USB_DEVICE(FTDI_VID, FTDI_ELV_ULA200_PID) }, */
-       /* { USB_DEVICE(FTDI_VID, FTDI_ELV_FHZ1000PC_PID) }, */
        /* { USB_DEVICE(FTDI_VID, FTDI_ELV_CSI8_PID) }, */
        /* { USB_DEVICE(FTDI_VID, FTDI_ELV_EM1000DL_PID) }, */
        /* { USB_DEVICE(FTDI_VID, FTDI_ELV_PCK100_PID) }, */
@@ -471,6 +472,9 @@ static struct usb_device_id id_table_combined [] = {
        { USB_DEVICE(FTDI_VID, FTDI_MHAM_Y6_PID) },
        { USB_DEVICE(FTDI_VID, FTDI_MHAM_Y8_PID) },
        { USB_DEVICE(EVOLUTION_VID, EVOLUTION_ER1_PID) },
+       { USB_DEVICE(FTDI_VID, FTDI_ARTEMIS_PID) },
+       { USB_DEVICE(FTDI_VID, FTDI_ATIK_ATK16_PID) },
+       { USB_DEVICE(FTDI_VID, FTDI_ATIK_ATK16HR_PID) },
        { },                                    /* Optional parameter entry */
        { }                                     /* Terminating entry */
 };
@@ -558,10 +562,12 @@ static unsigned short int ftdi_232am_baud_to_divisor (int baud);
 static __u32 ftdi_232bm_baud_base_to_divisor (int baud, int base);
 static __u32 ftdi_232bm_baud_to_divisor (int baud);
 
-static struct usb_serial_device_type ftdi_sio_device = {
-       .owner =                THIS_MODULE,
-       .name =                 "FTDI USB Serial Device",
-       .short_name =           "ftdi_sio",
+static struct usb_serial_driver ftdi_sio_device = {
+       .driver = {
+               .owner =        THIS_MODULE,
+               .name =         "ftdi_sio",
+       },
+       .description =          "FTDI USB Serial Device",
        .id_table =             id_table_combined,
        .num_interrupt_in =     0,
        .num_bulk_in =          1,
index 2c35d74..ddb63df 100644 (file)
 /* an infrared receiver for user access control with IR tags */
 #define FTDI_PIEGROUP_PID      0xF208  /* Product Id */
 
+/*
+ * Definitions for Artemis astronomical USB based cameras
+ * Check it at http://www.artemisccd.co.uk/
+ */
+#define FTDI_ARTEMIS_PID       0xDF28  /* All Artemis Cameras */
+
+/*
+ * Definitions for ATIK Instruments astronomical USB based cameras
+ * Check it at http://www.atik-instruments.com/
+ */
+#define FTDI_ATIK_ATK16_PID    0xDF30  /* ATIK ATK-16 Camera */
+#define FTDI_ATIK_ATK16HR_PID  0xDF31  /* ATIK ATK-16HR Camera */
+
 /*
  * Protego product ids
  */
 #define EVOLUTION_VID          0xDEEE  /* Vendor ID */
 #define EVOLUTION_ER1_PID      0x0300  /* ER1 Control Module */
 
+/* Pyramid Computer GmbH */
+#define FTDI_PYRAMID_PID       0xE6C8  /* Pyramid Appliance Display */
+
 /* Commands */
 #define FTDI_SIO_RESET                 0 /* Reset the port */
 #define FTDI_SIO_MODEM_CTRL    1 /* Set the modem control register */
index 2ef614d..35820bd 100644 (file)
@@ -1468,16 +1468,13 @@ static void garmin_shutdown (struct usb_serial *serial)
 }
 
 
-
-
-
-
-
 /* All of the device info needed */
-static struct usb_serial_device_type garmin_device = {
-       .owner               = THIS_MODULE,
-       .name                = "Garmin GPS usb/tty",
-       .short_name          = "garmin_gps",
+static struct usb_serial_driver garmin_device = {
+       .driver = {
+               .owner =        THIS_MODULE,
+               .name =         "garmin_gps",
+       },
+       .description =          "Garmin GPS usb/tty",
        .id_table            = id_table,
        .num_interrupt_in    = 1,
        .num_bulk_in         = 1,
index 5f7d319..8909208 100644 (file)
@@ -36,10 +36,11 @@ MODULE_PARM_DESC(product, "User specified USB idProduct");
 static struct usb_device_id generic_device_ids[2]; /* Initially all zeroes. */
 
 /* All of the device info needed for the Generic Serial Converter */
-struct usb_serial_device_type usb_serial_generic_device = {
-       .owner =                THIS_MODULE,
-       .name =                 "Generic",
-       .short_name =           "generic",
+struct usb_serial_driver usb_serial_generic_device = {
+       .driver = {
+               .owner =        THIS_MODULE,
+               .name =         "generic",
+       },
        .id_table =             generic_device_ids,
        .num_interrupt_in =     NUM_DONT_CARE,
        .num_bulk_in =          NUM_DONT_CARE,
index 64d55fb..8eadfb7 100644 (file)
@@ -38,15 +38,17 @@ MODULE_DEVICE_TABLE(usb, id_table);
 
 static struct usb_driver hp49gp_driver = {
        .owner =        THIS_MODULE,
-       .name =         "HP4X",
+       .name =         "hp4X",
        .probe =        usb_serial_probe,
        .disconnect =   usb_serial_disconnect,
        .id_table =     id_table,
 };
 
-static struct usb_serial_device_type hp49gp_device = {
-       .owner =                THIS_MODULE,
-       .name =                 "HP4X",
+static struct usb_serial_driver hp49gp_device = {
+       .driver = {
+               .owner =        THIS_MODULE,
+               .name =         "hp4X",
+       },
        .id_table =             id_table,
        .num_interrupt_in =     NUM_DONT_CARE,
        .num_bulk_in =          NUM_DONT_CARE,
index 04bfe27..dc4c498 100644 (file)
  * Networks technical support, or Peter Berger <pberger@brimson.com>,
  * or Al Borchers <alborchers@steinerpoint.com>.
  *
- * Version history:
- * 
- * 2003_04_03 al borchers
- *  - fixed a bug (that shows up with dosemu) where the tty struct is
- *    used in a callback after it has been freed
- *
- * 2.3 2002_03_08 greg kroah-hartman
- *     - fixed bug when multiple devices were attached at the same time.
- *
- * 2.2 2001_11_14 greg kroah-hartman
- *     - fixed bug in edge_close that kept the port from being used more
- *       than once.
- *     - fixed memory leak on device removal.
- *     - fixed potential double free of memory when command urb submitting
- *       failed.
- *     - other small cleanups when the device is removed
- *     
- * 2.1 2001_07_09 greg kroah-hartman
- *     - added support for TIOCMBIS and TIOCMBIC.
- *
- *     (04/08/2001) gb
- *     - Identify version on module load.
- *
- * 2.0 2001_03_05 greg kroah-hartman
- *     - reworked entire driver to fit properly in with the other usb-serial
- *       drivers.  Occasional oopses still happen, but it's a good start.
- *
- * 1.2.3 (02/23/2001) greg kroah-hartman
- *     - changed device table to work properly for 2.4.x final format.
- *     - fixed problem with dropping data at high data rates.
- *
- * 1.2.2 (11/27/2000) greg kroah-hartman
- *     - cleaned up more NTisms.
- *     - Added device table for 2.4.0-test11
- *
- * 1.2.1 (11/08/2000) greg kroah-hartman
- *     - Started to clean up NTisms.
- *     - Fixed problem with dev field of urb for kernels >= 2.4.0-test9
- *
- * 1.2 (10/17/2000) David Iacovelli
- *     Remove all EPIC code and GPL source
- *  Fix RELEVANT_IFLAG macro to include flow control 
- *  changes port configuration changes.
- *  Fix redefinition of SERIAL_MAGIC
- *  Change all timeout values to 5 seconds
- *  Tried to fix the UHCI multiple urb submission, but failed miserably.
- *  it seems to work fine with OHCI.
- *  ( Greg take a look at the #if 0 at end of WriteCmdUsb() we must 
- *    find a way to work arount this UHCI bug )
- *
- * 1.1 (10/11/2000) David Iacovelli
- *  Fix XON/XOFF flow control to support both IXON and IXOFF
- *
- * 0.9.27 (06/30/2000) David Iacovelli
- *  Added transmit queue and now allocate urb for command writes.
- *
- * 0.9.26 (06/29/2000) David Iacovelli
- *  Add support for 80251 based edgeport
- *
- * 0.9.25 (06/27/2000) David Iacovelli
- *  Do not close the port if it has multiple opens.
- *
- * 0.9.24 (05/26/2000) David Iacovelli
- *  Add IOCTLs to support RXTX and JAVA POS 
- *  and first cut at running BlackBox Demo
- *
- * 0.9.23 (05/24/2000) David Iacovelli
- *  Add IOCTLs to support RXTX and JAVA POS
- *
- * 0.9.22 (05/23/2000) David Iacovelli
- *  fixed bug in enumeration.  If epconfig turns on mapping by
- *  path after a device is already plugged in, we now update
- *  the mapping correctly
- *
- * 0.9.21 (05/16/2000) David Iacovelli
- *  Added BlockUntilChaseResp() to also wait for txcredits
- *  Updated the way we allocate and handle write URBs 
- *     Add debug code to dump buffers
- *
- * 0.9.20 (05/01/2000) David Iacovelli
- *     change driver to use usb/tts/
- *
- * 0.9.19 (05/01/2000) David Iacovelli
- *  Update code to compile if DEBUG is off
- *
- * 0.9.18 (04/28/2000) David Iacovelli
- *  cleanup and test tty_register with devfs
- *
- * 0.9.17 (04/27/2000) greg kroah-hartman
- *     changed tty_register around to be like the way it
- *     was before, but now it works properly with devfs.
- *
- * 0.9.16 (04/26/2000) david iacovelli
- *  Fixed bug in GetProductInfo()
- *
- * 0.9.15 (04/25/2000) david iacovelli
- *     Updated enumeration
- *
- * 0.9.14 (04/24/2000) david iacovelli
- *  Removed all config/status IOCTLS and 
- *  converted to using /proc/edgeport
- *  still playing with devfs
- *
- * 0.9.13 (04/24/2000) david iacovelli
- *  Removed configuration based on ttyUSB0
- *  Added support for configuration using /prod/edgeport
- *  first attempt at using devfs (not working yet!)
- *  Added IOCTL to GetProductInfo()
- *  Added support for custom baud rates
- *     Add support for random port numbers
- *
- * 0.9.12 (04/18/2000) david iacovelli
- *     added additional configuration IOCTLs
- *  use ttyUSB0 for configuration
- *
- * 0.9.11 (04/17/2000) greg kroah-hartman
- *     fixed module initialization race conditions.
- *     made all urbs dynamically allocated.
- *     made driver devfs compatible. now it only registers the tty device
- *     when the device is actually plugged in.
- *
- * 0.9.10 (04/13/2000) greg kroah-hartman
- *     added proc interface framework.
- *
- * 0.9.9 (04/13/2000) david iacovelli
- *     added enumeration code and ioctls to configure the device
- *
- * 0.9.8 (04/12/2000) david iacovelli
- *  Change interrupt read start when device is plugged in
- *  and stop when device is removed
- *     process interrupt reads when all ports are closed 
- *  (keep value of rxBytesAvail consistent with the edgeport)
- *  set the USB_BULK_QUEUE flag so that we can shove a bunch 
- *  of urbs at once down the pipe 
- *
- * 0.9.7 (04/10/2000) david iacovelli
- *     start to add enumeration code.
- *  generate serial number for epic devices
- *  add support for kdb
- *
- * 0.9.6 (03/30/2000) david iacovelli
- *  add IOCTL to get string, manufacture, and boot descriptors
- *
- * 0.9.5 (03/14/2000) greg kroah-hartman
- *     more error checking added to SerialOpen to try to fix UHCI open problem
- *
- * 0.9.4 (03/09/2000) greg kroah-hartman
- *     added more error checking to handle oops when data is hanging
- *     around and tty is abruptly closed.
- *
- * 0.9.3 (03/09/2000) david iacovelli
- *     Add epic support for xon/xoff chars
- *     play with performance
- *
- * 0.9.2 (03/08/2000) greg kroah-hartman
- *     changed most "info" calls to "dbg"
- *     implemented flow control properly in the termios call
- *
- * 0.9.1 (03/08/2000) david iacovelli
- *     added EPIC support
- *     enabled bootloader update
- *
- * 0.9 (03/08/2000) greg kroah-hartman
- *     Release to IO networks.
- *     Integrated changes that David made
- *  made getting urbs for writing SMP safe
- *
- * 0.8 (03/07/2000) greg kroah-hartman
- *     Release to IO networks.
- *     Fixed problems that were seen in code by David.
- *  Now both Edgeport/4 and Edgeport/2 works properly.
- *  Changed most of the functions to use port instead of serial.
- *
- * 0.7 (02/27/2000) greg kroah-hartman
- *     Milestone 3 release.
- *     Release to IO Networks
- *     ioctl for waiting on line change implemented.
- *     ioctl for getting statistics implemented.
- *     multiport support working.
- *     lsr and msr registers are now handled properly.
- *     change break now hooked up and working.
- *     support for all known Edgeport devices.
- *
- * 0.6 (02/22/2000) greg kroah-hartman
- *     Release to IO networks.
- *     CHASE is implemented correctly when port is closed.
- *     SerialOpen now blocks correctly until port is fully opened.
- *
- * 0.5 (02/20/2000) greg kroah-hartman
- *     Release to IO networks.
- *     Known problems:
- *             modem status register changes are not sent on to the user
- *             CHASE is not implemented when the port is closed.
- *
- * 0.4 (02/16/2000) greg kroah-hartman
- *     Second cut at the CeBit demo.
- *     Doesn't leak memory on every write to the port
- *     Still small leaks on startup.
- *     Added support for Edgeport/2 and Edgeport/8
- *
- * 0.3 (02/15/2000) greg kroah-hartman
- *     CeBit demo release.
- *     Force the line settings to 4800, 8, 1, e for the demo.
- *     Warning! This version leaks memory like crazy!
- *
- * 0.2 (01/30/2000) greg kroah-hartman
- *     Milestone 1 release.
- *     Device is found by USB subsystem, enumerated, fimware is downloaded
- *     and the descriptors are printed to the debug log, config is set, and
- *     green light starts to blink. Open port works, and data can be sent
- *     and received at the default settings of the UART. Loopback connector
- *     and debug log confirms this.
- * 
- * 0.1 (01/23/2000) greg kroah-hartman
- *     Initial release to help IO Networks try to set up their test system. 
- *     Edgeport4 is recognized, firmware is downloaded, config is set so 
- *     device blinks green light every 3 sec. Port is bound, but opening,
- *     closing, and sending data do not work properly.
- * 
  */
 
 #include <linux/config.h>
index e7ffe02..fad561c 100644 (file)
@@ -75,10 +75,12 @@ static struct usb_device_id id_table_combined [] = {
 
 MODULE_DEVICE_TABLE (usb, id_table_combined);
 
-static struct usb_serial_device_type edgeport_2port_device = {
-       .owner                  = THIS_MODULE,
-       .name                   = "Edgeport 2 port adapter",
-       .short_name             = "edgeport_2",
+static struct usb_serial_driver edgeport_2port_device = {
+       .driver = {
+               .owner          = THIS_MODULE,
+               .name           = "edgeport_2",
+       },
+       .description            = "Edgeport 2 port adapter",
        .id_table               = edgeport_2port_id_table,
        .num_interrupt_in       = 1,
        .num_bulk_in            = 1,
@@ -103,10 +105,12 @@ static struct usb_serial_device_type edgeport_2port_device = {
        .write_bulk_callback    = edge_bulk_out_data_callback,
 };
 
-static struct usb_serial_device_type edgeport_4port_device = {
-       .owner                  = THIS_MODULE,
-       .name                   = "Edgeport 4 port adapter",
-       .short_name             = "edgeport_4",
+static struct usb_serial_driver edgeport_4port_device = {
+       .driver = {
+               .owner          = THIS_MODULE,
+               .name           = "edgeport_4",
+       },
+       .description            = "Edgeport 4 port adapter",
        .id_table               = edgeport_4port_id_table,
        .num_interrupt_in       = 1,
        .num_bulk_in            = 1,
@@ -131,10 +135,12 @@ static struct usb_serial_device_type edgeport_4port_device = {
        .write_bulk_callback    = edge_bulk_out_data_callback,
 };
 
-static struct usb_serial_device_type edgeport_8port_device = {
-       .owner                  = THIS_MODULE,
-       .name                   = "Edgeport 8 port adapter",
-       .short_name             = "edgeport_8",
+static struct usb_serial_driver edgeport_8port_device = {
+       .driver = {
+               .owner          = THIS_MODULE,
+               .name           = "edgeport_8",
+       },
+       .description            = "Edgeport 8 port adapter",
        .id_table               = edgeport_8port_id_table,
        .num_interrupt_in       = 1,
        .num_bulk_in            = 1,
index ebf9967..832b6d6 100644 (file)
@@ -2982,10 +2982,12 @@ static unsigned int edge_buf_get(struct edge_buf *eb, char *buf,
 }
 
 
-static struct usb_serial_device_type edgeport_1port_device = {
-       .owner                  = THIS_MODULE,
-       .name                   = "Edgeport TI 1 port adapter",
-       .short_name             = "edgeport_ti_1",
+static struct usb_serial_driver edgeport_1port_device = {
+       .driver = {
+               .owner          = THIS_MODULE,
+               .name           = "edgeport_ti_1",
+       },
+       .description            = "Edgeport TI 1 port adapter",
        .id_table               = edgeport_1port_id_table,
        .num_interrupt_in       = 1,
        .num_bulk_in            = 1,
@@ -3010,10 +3012,12 @@ static struct usb_serial_device_type edgeport_1port_device = {
        .write_bulk_callback    = edge_bulk_out_callback,
 };
 
-static struct usb_serial_device_type edgeport_2port_device = {
-       .owner                  = THIS_MODULE,
-       .name                   = "Edgeport TI 2 port adapter",
-       .short_name             = "edgeport_ti_2",
+static struct usb_serial_driver edgeport_2port_device = {
+       .driver = {
+               .owner          = THIS_MODULE,
+               .name           = "edgeport_ti_2",
+       },
+       .description            = "Edgeport TI 2 port adapter",
        .id_table               = edgeport_2port_id_table,
        .num_interrupt_in       = 1,
        .num_bulk_in            = 2,
index c05c2a2..d5d0664 100644 (file)
@@ -92,24 +92,7 @@ static void ipaq_destroy_lists(struct usb_serial_port *port);
 static struct usb_device_id ipaq_id_table [] = {
        /* The first entry is a placeholder for the insmod-specified device */
        { USB_DEVICE(0x049F, 0x0003) },
-       { USB_DEVICE(0x1690, 0x0601) }, /* Askey USB Sync */
-       { USB_DEVICE(0x0960, 0x0065) }, /* BCOM USB Sync 0065 */
-       { USB_DEVICE(0x0960, 0x0066) }, /* BCOM USB Sync 0066 */
-       { USB_DEVICE(0x0960, 0x0067) }, /* BCOM USB Sync 0067 */
-       { USB_DEVICE(0x07CF, 0x2001) }, /* CASIO USB Sync 2001 */
-       { USB_DEVICE(0x07CF, 0x2002) }, /* CASIO USB Sync 2002 */
-       { USB_DEVICE(0x07CF, 0x2003) }, /* CASIO USB Sync 2003 */
-       { USB_DEVICE(0x049F, 0x0003) }, /* Compaq iPAQ USB Sync */
-       { USB_DEVICE(0x049F, 0x0032) }, /* Compaq iPAQ USB Sync */
-       { USB_DEVICE(0x413C, 0x4001) }, /* Dell Axim USB Sync */
-       { USB_DEVICE(0x413C, 0x4002) }, /* Dell Axim USB Sync */
-       { USB_DEVICE(0x413C, 0x4003) }, /* Dell Axim USB Sync */
-       { USB_DEVICE(0x413C, 0x4004) }, /* Dell Axim USB Sync */
-       { USB_DEVICE(0x413C, 0x4005) }, /* Dell Axim USB Sync */
-       { USB_DEVICE(0x413C, 0x4006) }, /* Dell Axim USB Sync */
-       { USB_DEVICE(0x413C, 0x4007) }, /* Dell Axim USB Sync */
-       { USB_DEVICE(0x413C, 0x4008) }, /* Dell Axim USB Sync */
-       { USB_DEVICE(0x413C, 0x4009) }, /* Dell Axim USB Sync */
+       { USB_DEVICE(0x0104, 0x00BE) }, /* Socket USB Sync */
        { USB_DEVICE(0x03F0, 0x1016) }, /* HP USB Sync */
        { USB_DEVICE(0x03F0, 0x1116) }, /* HP USB Sync 1611 */
        { USB_DEVICE(0x03F0, 0x1216) }, /* HP USB Sync 1612 */
@@ -125,7 +108,13 @@ static struct usb_device_id ipaq_id_table [] = {
        { USB_DEVICE(0x03F0, 0x5016) }, /* HP USB Sync 1650 */
        { USB_DEVICE(0x03F0, 0x5116) }, /* HP USB Sync 1651 */
        { USB_DEVICE(0x03F0, 0x5216) }, /* HP USB Sync 1652 */
-       { USB_DEVICE(0x094B, 0x0001) }, /* Linkup Systems USB Sync */
+       { USB_DEVICE(0x0409, 0x00D5) }, /* NEC USB Sync */
+       { USB_DEVICE(0x0409, 0x00D6) }, /* NEC USB Sync */
+       { USB_DEVICE(0x0409, 0x00D7) }, /* NEC USB Sync */
+       { USB_DEVICE(0x0409, 0x8024) }, /* NEC USB Sync */
+       { USB_DEVICE(0x0409, 0x8025) }, /* NEC USB Sync */
+       { USB_DEVICE(0x043E, 0x9C01) }, /* LGE USB Sync */
+       { USB_DEVICE(0x045E, 0x00CE) }, /* Microsoft USB Sync */
        { USB_DEVICE(0x045E, 0x0400) }, /* Windows Powered Pocket PC 2002 */
        { USB_DEVICE(0x045E, 0x0401) }, /* Windows Powered Pocket PC 2002 */
        { USB_DEVICE(0x045E, 0x0402) }, /* Windows Powered Pocket PC 2002 */
@@ -251,17 +240,81 @@ static struct usb_device_id ipaq_id_table [] = {
        { USB_DEVICE(0x045E, 0x04E8) }, /* Windows Powered Smartphone 2003 */
        { USB_DEVICE(0x045E, 0x04E9) }, /* Windows Powered Smartphone 2003 */
        { USB_DEVICE(0x045E, 0x04EA) }, /* Windows Powered Smartphone 2003 */
-       { USB_DEVICE(0x0961, 0x0010) }, /* Portatec USB Sync */
-       { USB_DEVICE(0x5E04, 0xCE00) }, /* SAGEM Wireless Assistant */
-       { USB_DEVICE(0x0104, 0x00BE) }, /* Socket USB Sync */
+       { USB_DEVICE(0x049F, 0x0003) }, /* Compaq iPAQ USB Sync */
+       { USB_DEVICE(0x049F, 0x0032) }, /* Compaq iPAQ USB Sync */
+       { USB_DEVICE(0x04A4, 0x0014) }, /* Hitachi USB Sync */
+       { USB_DEVICE(0x04AD, 0x0301) }, /* USB Sync 0301 */
+       { USB_DEVICE(0x04AD, 0x0302) }, /* USB Sync 0302 */
+       { USB_DEVICE(0x04AD, 0x0303) }, /* USB Sync 0303 */
+       { USB_DEVICE(0x04C5, 0x1058) }, /* FUJITSU USB Sync */
+       { USB_DEVICE(0x04C5, 0x1079) }, /* FUJITSU USB Sync */
+       { USB_DEVICE(0x04DA, 0x2500) }, /* Panasonic USB Sync */
+       { USB_DEVICE(0x04E8, 0x5F00) }, /* Samsung NEXiO USB Sync */
+       { USB_DEVICE(0x04E8, 0x5F01) }, /* Samsung NEXiO USB Sync */
+       { USB_DEVICE(0x04E8, 0x5F02) }, /* Samsung NEXiO USB Sync */
+       { USB_DEVICE(0x04E8, 0x5F03) }, /* Samsung NEXiO USB Sync */
+       { USB_DEVICE(0x04E8, 0x5F04) }, /* Samsung NEXiO USB Sync */
+       { USB_DEVICE(0x04E8, 0x6611) }, /* Samsung MITs USB Sync */
+       { USB_DEVICE(0x04E8, 0x6613) }, /* Samsung MITs USB Sync */
+       { USB_DEVICE(0x04E8, 0x6615) }, /* Samsung MITs USB Sync */
+       { USB_DEVICE(0x04E8, 0x6617) }, /* Samsung MITs USB Sync */
+       { USB_DEVICE(0x04E8, 0x6619) }, /* Samsung MITs USB Sync */
+       { USB_DEVICE(0x04E8, 0x661B) }, /* Samsung MITs USB Sync */
+       { USB_DEVICE(0x04E8, 0x662E) }, /* Samsung MITs USB Sync */
+       { USB_DEVICE(0x04E8, 0x6630) }, /* Samsung MITs USB Sync */
+       { USB_DEVICE(0x04E8, 0x6632) }, /* Samsung MITs USB Sync */
+       { USB_DEVICE(0x04f1, 0x3011) }, /* JVC USB Sync */
+       { USB_DEVICE(0x04F1, 0x3012) }, /* JVC USB Sync */
+       { USB_DEVICE(0x0502, 0x1631) }, /* c10 Series */
+       { USB_DEVICE(0x0502, 0x1632) }, /* c20 Series */
+       { USB_DEVICE(0x0502, 0x16E1) }, /* Acer n10 Handheld USB Sync */
+       { USB_DEVICE(0x0502, 0x16E2) }, /* Acer n20 Handheld USB Sync */
+       { USB_DEVICE(0x0502, 0x16E3) }, /* Acer n30 Handheld USB Sync */
+       { USB_DEVICE(0x0536, 0x01A0) }, /* HHP PDT */
+       { USB_DEVICE(0x0543, 0x0ED9) }, /* ViewSonic Color Pocket PC V35 */
+       { USB_DEVICE(0x0543, 0x1527) }, /* ViewSonic Color Pocket PC V36 */
+       { USB_DEVICE(0x0543, 0x1529) }, /* ViewSonic Color Pocket PC V37 */
+       { USB_DEVICE(0x0543, 0x152B) }, /* ViewSonic Color Pocket PC V38 */
+       { USB_DEVICE(0x0543, 0x152E) }, /* ViewSonic Pocket PC */
+       { USB_DEVICE(0x0543, 0x1921) }, /* ViewSonic Communicator Pocket PC */
+       { USB_DEVICE(0x0543, 0x1922) }, /* ViewSonic Smartphone */
+       { USB_DEVICE(0x0543, 0x1923) }, /* ViewSonic Pocket PC V30 */
+       { USB_DEVICE(0x05E0, 0x2000) }, /* Symbol USB Sync */
+       { USB_DEVICE(0x05E0, 0x2001) }, /* Symbol USB Sync 0x2001 */
+       { USB_DEVICE(0x05E0, 0x2002) }, /* Symbol USB Sync 0x2002 */
+       { USB_DEVICE(0x05E0, 0x2003) }, /* Symbol USB Sync 0x2003 */
+       { USB_DEVICE(0x05E0, 0x2004) }, /* Symbol USB Sync 0x2004 */
+       { USB_DEVICE(0x05E0, 0x2005) }, /* Symbol USB Sync 0x2005 */
+       { USB_DEVICE(0x05E0, 0x2006) }, /* Symbol USB Sync 0x2006 */
+       { USB_DEVICE(0x05E0, 0x2007) }, /* Symbol USB Sync 0x2007 */
+       { USB_DEVICE(0x05E0, 0x2008) }, /* Symbol USB Sync 0x2008 */
+       { USB_DEVICE(0x05E0, 0x2009) }, /* Symbol USB Sync 0x2009 */
+       { USB_DEVICE(0x05E0, 0x200A) }, /* Symbol USB Sync 0x200A */
+       { USB_DEVICE(0x067E, 0x1001) }, /* Intermec Mobile Computer */
+       { USB_DEVICE(0x07CF, 0x2001) }, /* CASIO USB Sync 2001 */
+       { USB_DEVICE(0x07CF, 0x2002) }, /* CASIO USB Sync 2002 */
+       { USB_DEVICE(0x07CF, 0x2003) }, /* CASIO USB Sync 2003 */
        { USB_DEVICE(0x0930, 0x0700) }, /* TOSHIBA USB Sync 0700 */
        { USB_DEVICE(0x0930, 0x0705) }, /* TOSHIBA Pocket PC e310 */
+       { USB_DEVICE(0x0930, 0x0706) }, /* TOSHIBA Pocket PC e740 */
        { USB_DEVICE(0x0930, 0x0707) }, /* TOSHIBA Pocket PC e330 Series */
        { USB_DEVICE(0x0930, 0x0708) }, /* TOSHIBA Pocket PC e350 Series */
-       { USB_DEVICE(0x0930, 0x0706) }, /* TOSHIBA Pocket PC e740 */
        { USB_DEVICE(0x0930, 0x0709) }, /* TOSHIBA Pocket PC e750 Series */
        { USB_DEVICE(0x0930, 0x070A) }, /* TOSHIBA Pocket PC e400 Series */
        { USB_DEVICE(0x0930, 0x070B) }, /* TOSHIBA Pocket PC e800 Series */
+       { USB_DEVICE(0x094B, 0x0001) }, /* Linkup Systems USB Sync */
+       { USB_DEVICE(0x0960, 0x0065) }, /* BCOM USB Sync 0065 */
+       { USB_DEVICE(0x0960, 0x0066) }, /* BCOM USB Sync 0066 */
+       { USB_DEVICE(0x0960, 0x0067) }, /* BCOM USB Sync 0067 */
+       { USB_DEVICE(0x0961, 0x0010) }, /* Portatec USB Sync */
+       { USB_DEVICE(0x099E, 0x0052) }, /* Trimble GeoExplorer */
+       { USB_DEVICE(0x099E, 0x4000) }, /* TDS Data Collector */
+       { USB_DEVICE(0x0B05, 0x4200) }, /* ASUS USB Sync */
+       { USB_DEVICE(0x0B05, 0x4201) }, /* ASUS USB Sync */
+       { USB_DEVICE(0x0B05, 0x4202) }, /* ASUS USB Sync */
+       { USB_DEVICE(0x0B05, 0x420F) }, /* ASUS USB Sync */
+       { USB_DEVICE(0x0B05, 0x9200) }, /* ASUS USB Sync */
+       { USB_DEVICE(0x0B05, 0x9202) }, /* ASUS USB Sync */
        { USB_DEVICE(0x0BB4, 0x00CE) }, /* HTC USB Sync */
        { USB_DEVICE(0x0BB4, 0x0A01) }, /* PocketPC USB Sync */
        { USB_DEVICE(0x0BB4, 0x0A02) }, /* PocketPC USB Sync */
@@ -422,116 +475,67 @@ static struct usb_device_id ipaq_id_table [] = {
        { USB_DEVICE(0x0BB4, 0x0A9D) }, /* SmartPhone USB Sync */
        { USB_DEVICE(0x0BB4, 0x0A9E) }, /* SmartPhone USB Sync */
        { USB_DEVICE(0x0BB4, 0x0A9F) }, /* SmartPhone USB Sync */
-       { USB_DEVICE(0x0409, 0x00D5) }, /* NEC USB Sync */
-       { USB_DEVICE(0x0409, 0x00D6) }, /* NEC USB Sync */
-       { USB_DEVICE(0x0409, 0x00D7) }, /* NEC USB Sync */
-       { USB_DEVICE(0x0409, 0x8024) }, /* NEC USB Sync */
-       { USB_DEVICE(0x0409, 0x8025) }, /* NEC USB Sync */
-       { USB_DEVICE(0x04A4, 0x0014) }, /* Hitachi USB Sync */
        { USB_DEVICE(0x0BF8, 0x1001) }, /* Fujitsu Siemens Computers USB Sync */
-       { USB_DEVICE(0x0F98, 0x0201) }, /* Cyberbank USB Sync */
-       { USB_DEVICE(0x0502, 0x16E1) }, /* Acer n10 Handheld USB Sync */
-       { USB_DEVICE(0x0502, 0x16E3) }, /* Acer n30 Handheld USB Sync */
-       { USB_DEVICE(0x0502, 0x16E2) }, /* Acer n20 Handheld USB Sync */
-       { USB_DEVICE(0x0502, 0x1631) }, /* c10 Series */
-       { USB_DEVICE(0x0502, 0x1632) }, /* c20 Series */
-       { USB_DEVICE(0x0B05, 0x9202) }, /* ASUS USB Sync */
-       { USB_DEVICE(0x0B05, 0x420F) }, /* ASUS USB Sync */
-       { USB_DEVICE(0x0B05, 0x4200) }, /* ASUS USB Sync */
-       { USB_DEVICE(0x0B05, 0x4201) }, /* ASUS USB Sync */
-       { USB_DEVICE(0x0B05, 0x4202) }, /* ASUS USB Sync */
-       { USB_DEVICE(0x0B05, 0x9200) }, /* ASUS USB Sync */
+       { USB_DEVICE(0x0C44, 0x03A2) }, /* Motorola iDEN Smartphone */
        { USB_DEVICE(0x0C8E, 0x6000) }, /* Cesscom Luxian Series */
-       { USB_DEVICE(0x04AD, 0x0301) }, /* USB Sync 0301 */
-       { USB_DEVICE(0x04AD, 0x0302) }, /* USB Sync 0302 */
-       { USB_DEVICE(0x04AD, 0x0303) }, /* USB Sync 0303 */
+       { USB_DEVICE(0x0CAD, 0x9001) }, /* Motorola PowerPad Pocket PC Device */
+       { USB_DEVICE(0x0F4E, 0x0200) }, /* Freedom Scientific USB Sync */
+       { USB_DEVICE(0x0F98, 0x0201) }, /* Cyberbank USB Sync */
+       { USB_DEVICE(0x0FB8, 0x3001) }, /* Wistron USB Sync */
+       { USB_DEVICE(0x0FB8, 0x3002) }, /* Wistron USB Sync */
+       { USB_DEVICE(0x0FB8, 0x3003) }, /* Wistron USB Sync */
+       { USB_DEVICE(0x0FB8, 0x4001) }, /* Wistron USB Sync */
+       { USB_DEVICE(0x1066, 0x00CE) }, /* E-TEN USB Sync */
        { USB_DEVICE(0x1066, 0x0300) }, /* E-TEN P3XX Pocket PC */
        { USB_DEVICE(0x1066, 0x0500) }, /* E-TEN P5XX Pocket PC */
        { USB_DEVICE(0x1066, 0x0600) }, /* E-TEN P6XX Pocket PC */
        { USB_DEVICE(0x1066, 0x0700) }, /* E-TEN P7XX Pocket PC */
-       { USB_DEVICE(0x1066, 0x00CE) }, /* E-TEN USB Sync */
-       { USB_DEVICE(0x0F4E, 0x0200) }, /* Freedom Scientific USB Sync */
-       { USB_DEVICE(0x04C5, 0x1058) }, /* FUJITSU USB Sync */
-       { USB_DEVICE(0x04C5, 0x1079) }, /* FUJITSU USB Sync */
-       { USB_DEVICE(0x067E, 0x1001) }, /* Intermec Mobile Computer */
-       { USB_DEVICE(0x04f1, 0x3011) }, /* JVC USB Sync */
-       { USB_DEVICE(0x04F1, 0x3012) }, /* JVC USB Sync */
-       { USB_DEVICE(0x3708, 0x20CE) }, /* Legend USB Sync */
-       { USB_DEVICE(0x3708, 0x21CE) }, /* Lenovo USB Sync */
-       { USB_DEVICE(0x043E, 0x9C01) }, /* LGE USB Sync */
-       { USB_DEVICE(0x04DA, 0x2500) }, /* Panasonic USB Sync */
-       { USB_DEVICE(0x3340, 0x0B1C) }, /* Generic PPC StrongARM */
-       { USB_DEVICE(0x3340, 0x0E3A) }, /* Generic PPC USB Sync */
-       { USB_DEVICE(0x3340, 0x0F3A) }, /* Generic SmartPhone USB Sync */
-       { USB_DEVICE(0x3340, 0x0F1C) }, /* Itautec USB Sync */
-       { USB_DEVICE(0x3340, 0x1326) }, /* Itautec USB Sync */
-       { USB_DEVICE(0x3340, 0x3326) }, /* MEDION Winodws Moble USB Sync */
+       { USB_DEVICE(0x1114, 0x0001) }, /* Psion Teklogix Sync 753x */
+       { USB_DEVICE(0x1114, 0x0004) }, /* Psion Teklogix Sync netBookPro */
+       { USB_DEVICE(0x1114, 0x0006) }, /* Psion Teklogix Sync 7525 */
+       { USB_DEVICE(0x1182, 0x1388) }, /* VES USB Sync */
+       { USB_DEVICE(0x11D9, 0x1002) }, /* Rugged Pocket PC 2003 */
+       { USB_DEVICE(0x11D9, 0x1003) }, /* Rugged Pocket PC 2003 */
+       { USB_DEVICE(0x1231, 0xCE01) }, /* USB Sync 03 */
+       { USB_DEVICE(0x1231, 0xCE02) }, /* USB Sync 03 */
+       { USB_DEVICE(0x1690, 0x0601) }, /* Askey USB Sync */
+       { USB_DEVICE(0x22B8, 0x4204) }, /* Motorola MPx200 Smartphone */
+       { USB_DEVICE(0x22B8, 0x4214) }, /* Motorola MPc GSM */
+       { USB_DEVICE(0x22B8, 0x4224) }, /* Motorola MPx220 Smartphone */
+       { USB_DEVICE(0x22B8, 0x4234) }, /* Motorola MPc CDMA */
+       { USB_DEVICE(0x22B8, 0x4244) }, /* Motorola MPx100 Smartphone */
+       { USB_DEVICE(0x3340, 0x011C) }, /* Mio DigiWalker PPC StrongARM */
        { USB_DEVICE(0x3340, 0x0326) }, /* Mio DigiWalker 338 */
        { USB_DEVICE(0x3340, 0x0426) }, /* Mio DigiWalker 338 */
-       { USB_DEVICE(0x3340, 0x011C) }, /* Mio DigiWalker PPC StrongARM */
-       { USB_DEVICE(0x3340, 0x053A) }, /* Mio DigiWalker SmartPhone USB Sync */
        { USB_DEVICE(0x3340, 0x043A) }, /* Mio DigiWalker USB Sync */
-       { USB_DEVICE(0x3340, 0x071C) }, /* MiTAC USB Sync */
        { USB_DEVICE(0x3340, 0x051C) }, /* MiTAC USB Sync 528 */
-       { USB_DEVICE(0x3340, 0x2326) }, /* Vobis USB Sync */
+       { USB_DEVICE(0x3340, 0x053A) }, /* Mio DigiWalker SmartPhone USB Sync */
+       { USB_DEVICE(0x3340, 0x071C) }, /* MiTAC USB Sync */
+       { USB_DEVICE(0x3340, 0x0B1C) }, /* Generic PPC StrongARM */
+       { USB_DEVICE(0x3340, 0x0E3A) }, /* Generic PPC USB Sync */
+       { USB_DEVICE(0x3340, 0x0F1C) }, /* Itautec USB Sync */
+       { USB_DEVICE(0x3340, 0x0F3A) }, /* Generic SmartPhone USB Sync */
+       { USB_DEVICE(0x3340, 0x1326) }, /* Itautec USB Sync */
        { USB_DEVICE(0x3340, 0x191C) }, /* YAKUMO USB Sync */
+       { USB_DEVICE(0x3340, 0x2326) }, /* Vobis USB Sync */
+       { USB_DEVICE(0x3340, 0x3326) }, /* MEDION Winodws Moble USB Sync */
+       { USB_DEVICE(0x3708, 0x20CE) }, /* Legend USB Sync */
+       { USB_DEVICE(0x3708, 0x21CE) }, /* Lenovo USB Sync */
        { USB_DEVICE(0x4113, 0x0210) }, /* Mobile Media Technology USB Sync */
        { USB_DEVICE(0x4113, 0x0211) }, /* Mobile Media Technology USB Sync */
        { USB_DEVICE(0x4113, 0x0400) }, /* Mobile Media Technology USB Sync */
        { USB_DEVICE(0x4113, 0x0410) }, /* Mobile Media Technology USB Sync */
-       { USB_DEVICE(0x0CAD, 0x9001) }, /* Motorola PowerPad Pocket PC Device */
-       { USB_DEVICE(0x0C44, 0x03A2) }, /* Motorola iDEN Smartphone */
-       { USB_DEVICE(0x04E8, 0x6611) }, /* Samsung MITs USB Sync */
-       { USB_DEVICE(0x04E8, 0x6613) }, /* Samsung MITs USB Sync */
-       { USB_DEVICE(0x04E8, 0x6615) }, /* Samsung MITs USB Sync */
-       { USB_DEVICE(0x04E8, 0x6617) }, /* Samsung MITs USB Sync */
-       { USB_DEVICE(0x04E8, 0x6619) }, /* Samsung MITs USB Sync */
-       { USB_DEVICE(0x04E8, 0x661B) }, /* Samsung MITs USB Sync */
-       { USB_DEVICE(0x04E8, 0x5F00) }, /* Samsung NEXiO USB Sync */
-       { USB_DEVICE(0x04E8, 0x5F01) }, /* Samsung NEXiO USB Sync */
-       { USB_DEVICE(0x04E8, 0x5F02) }, /* Samsung NEXiO USB Sync */
-       { USB_DEVICE(0x04E8, 0x5F03) }, /* Samsung NEXiO USB Sync */
-       { USB_DEVICE(0x04E8, 0x5F04) }, /* Samsung NEXiO USB Sync */
-       { USB_DEVICE(0x04E8, 0x662E) }, /* Samsung MITs USB Sync */
-       { USB_DEVICE(0x04E8, 0x6630) }, /* Samsung MITs USB Sync */
-       { USB_DEVICE(0x04E8, 0x6632) }, /* Samsung MITs USB Sync */
+       { USB_DEVICE(0x413C, 0x4001) }, /* Dell Axim USB Sync */
+       { USB_DEVICE(0x413C, 0x4002) }, /* Dell Axim USB Sync */
+       { USB_DEVICE(0x413C, 0x4003) }, /* Dell Axim USB Sync */
+       { USB_DEVICE(0x413C, 0x4004) }, /* Dell Axim USB Sync */
+       { USB_DEVICE(0x413C, 0x4005) }, /* Dell Axim USB Sync */
+       { USB_DEVICE(0x413C, 0x4006) }, /* Dell Axim USB Sync */
+       { USB_DEVICE(0x413C, 0x4007) }, /* Dell Axim USB Sync */
+       { USB_DEVICE(0x413C, 0x4008) }, /* Dell Axim USB Sync */
+       { USB_DEVICE(0x413C, 0x4009) }, /* Dell Axim USB Sync */
        { USB_DEVICE(0x4505, 0x0010) }, /* Smartphone */
-       { USB_DEVICE(0x05E0, 0x2000) }, /* Symbol USB Sync */
-       { USB_DEVICE(0x05E0, 0x2001) }, /* Symbol USB Sync 0x2001 */
-       { USB_DEVICE(0x05E0, 0x2002) }, /* Symbol USB Sync 0x2002 */
-       { USB_DEVICE(0x05E0, 0x2003) }, /* Symbol USB Sync 0x2003 */
-       { USB_DEVICE(0x05E0, 0x2004) }, /* Symbol USB Sync 0x2004 */
-       { USB_DEVICE(0x05E0, 0x2005) }, /* Symbol USB Sync 0x2005 */
-       { USB_DEVICE(0x05E0, 0x2006) }, /* Symbol USB Sync 0x2006 */
-       { USB_DEVICE(0x05E0, 0x2007) }, /* Symbol USB Sync 0x2007 */
-       { USB_DEVICE(0x05E0, 0x2008) }, /* Symbol USB Sync 0x2008 */
-       { USB_DEVICE(0x05E0, 0x2009) }, /* Symbol USB Sync 0x2009 */
-       { USB_DEVICE(0x05E0, 0x200A) }, /* Symbol USB Sync 0x200A */
-       { USB_DEVICE(0x1182, 0x1388) }, /* VES USB Sync */
-       { USB_DEVICE(0x0543, 0x0ED9) }, /* ViewSonic Color Pocket PC V35 */
-       { USB_DEVICE(0x0543, 0x1527) }, /* ViewSonic Color Pocket PC V36 */
-       { USB_DEVICE(0x0543, 0x1529) }, /* ViewSonic Color Pocket PC V37 */
-       { USB_DEVICE(0x0543, 0x152B) }, /* ViewSonic Color Pocket PC V38 */
-       { USB_DEVICE(0x0543, 0x152E) }, /* ViewSonic Pocket PC */
-       { USB_DEVICE(0x0543, 0x1921) }, /* ViewSonic Communicator Pocket PC */
-       { USB_DEVICE(0x0543, 0x1922) }, /* ViewSonic Smartphone */
-       { USB_DEVICE(0x0543, 0x1923) }, /* ViewSonic Pocket PC V30 */
-       { USB_DEVICE(0x0536, 0x01A0) }, /* HHP PDT */
-       { USB_DEVICE(0x099E, 0x0052) }, /* Trimble GeoExplorer */
-       { USB_DEVICE(0x099E, 0x4000) }, /* TDS Data Collector */
-       { USB_DEVICE(0x0FB8, 0x3001) }, /* Wistron USB Sync */
-       { USB_DEVICE(0x0FB8, 0x3002) }, /* Wistron USB Sync */
-       { USB_DEVICE(0x0FB8, 0x3003) }, /* Wistron USB Sync */
-       { USB_DEVICE(0x0FB8, 0x4001) }, /* Wistron USB Sync */
-       { USB_DEVICE(0x11D9, 0x1003) }, /* Rugged Pocket PC 2003 */
-       { USB_DEVICE(0x11D9, 0x1002) }, /* Rugged Pocket PC 2003 */
-       { USB_DEVICE(0x22B8, 0x4204) }, /* Motorola MPx200 Smartphone */
-       { USB_DEVICE(0x22B8, 0x4214) }, /* Motorola MPc GSM */
-       { USB_DEVICE(0x22B8, 0x4224) }, /* Motorola MPx220 Smartphone */
-       { USB_DEVICE(0x22B8, 0x4234) }, /* Motorola MPc CDMA */
-       { USB_DEVICE(0x22B8, 0x4244) }, /* Motorola MPx100 Smartphone */
-       { USB_DEVICE(0x1231, 0xCE01) }, /* USB Sync 03 */
-       { USB_DEVICE(0x1231, 0xCE02) }, /* USB Sync 03 */
+       { USB_DEVICE(0x5E04, 0xCE00) }, /* SAGEM Wireless Assistant */
        { }                             /* Terminating entry */
 };
 
@@ -547,9 +551,12 @@ static struct usb_driver ipaq_driver = {
 
 
 /* All of the device info needed for the Compaq iPAQ */
-static struct usb_serial_device_type ipaq_device = {
-       .owner =                THIS_MODULE,
-       .name =                 "PocketPC PDA",
+static struct usb_serial_driver ipaq_device = {
+       .driver = {
+               .owner =        THIS_MODULE,
+               .name =         "ipaq",
+       },
+       .description =          "PocketPC PDA",
        .id_table =             ipaq_id_table,
        .num_interrupt_in =     NUM_DONT_CARE,
        .num_bulk_in =          1,
index 85e2424..a02fada 100644 (file)
@@ -443,10 +443,12 @@ static int ipw_disconnect(struct usb_serial_port *port)
        return 0;
 }
 
-static struct usb_serial_device_type ipw_device = {
-       .owner =                THIS_MODULE,
-       .name =                 "IPWireless converter",
-       .short_name =           "ipw",
+static struct usb_serial_driver ipw_device = {
+       .driver = {
+               .owner =        THIS_MODULE,
+               .name =         "ipw",
+       },
+       .description =          "IPWireless converter",
        .id_table =             usb_ipw_ids,
        .num_interrupt_in =     NUM_DONT_CARE,
        .num_bulk_in =          1,
index 937b2fd..19f329e 100644 (file)
@@ -133,9 +133,12 @@ static struct usb_driver ir_driver = {
 };
 
 
-static struct usb_serial_device_type ir_device = {
-       .owner =                THIS_MODULE,
-       .name =                 "IR Dongle",
+static struct usb_serial_driver ir_device = {
+       .driver = {
+               .owner =        THIS_MODULE,
+               .name =         "ir-usb",
+       },
+       .description =          "IR Dongle",
        .id_table =             id_table,
        .num_interrupt_in =     1,
        .num_bulk_in =          1,
index e9b45b7..5cfc13b 100644 (file)
@@ -570,10 +570,12 @@ static struct usb_device_id keyspan_4port_ids[] = {
 };
 
 /* Structs for the devices, pre and post renumeration. */
-static struct usb_serial_device_type keyspan_pre_device = {
-       .owner                  = THIS_MODULE,
-       .name                   = "Keyspan - (without firmware)",
-       .short_name             = "keyspan_no_firm",
+static struct usb_serial_driver keyspan_pre_device = {
+       .driver = {
+               .owner          = THIS_MODULE,
+               .name           = "keyspan_no_firm",
+       },
+       .description            = "Keyspan - (without firmware)",
        .id_table               = keyspan_pre_ids,
        .num_interrupt_in       = NUM_DONT_CARE,
        .num_bulk_in            = NUM_DONT_CARE,
@@ -582,10 +584,12 @@ static struct usb_serial_device_type keyspan_pre_device = {
        .attach                 = keyspan_fake_startup,
 };
 
-static struct usb_serial_device_type keyspan_1port_device = {
-       .owner                  = THIS_MODULE,
-       .name                   = "Keyspan 1 port adapter",
-       .short_name             = "keyspan_1",
+static struct usb_serial_driver keyspan_1port_device = {
+       .driver = {
+               .owner          = THIS_MODULE,
+               .name           = "keyspan_1",
+       },
+       .description            = "Keyspan 1 port adapter",
        .id_table               = keyspan_1port_ids,
        .num_interrupt_in       = NUM_DONT_CARE,
        .num_bulk_in            = NUM_DONT_CARE,
@@ -607,10 +611,12 @@ static struct usb_serial_device_type keyspan_1port_device = {
        .shutdown               = keyspan_shutdown,
 };
 
-static struct usb_serial_device_type keyspan_2port_device = {
-       .owner                  = THIS_MODULE,
-       .name                   = "Keyspan 2 port adapter",
-       .short_name             = "keyspan_2",
+static struct usb_serial_driver keyspan_2port_device = {
+       .driver = {
+               .owner          = THIS_MODULE,
+               .name           = "keyspan_2",
+       },
+       .description            = "Keyspan 2 port adapter",
        .id_table               = keyspan_2port_ids,
        .num_interrupt_in       = NUM_DONT_CARE,
        .num_bulk_in            = NUM_DONT_CARE,
@@ -632,10 +638,12 @@ static struct usb_serial_device_type keyspan_2port_device = {
        .shutdown               = keyspan_shutdown,
 };
 
-static struct usb_serial_device_type keyspan_4port_device = {
-       .owner                  = THIS_MODULE,
-       .name                   = "Keyspan 4 port adapter",
-       .short_name             = "keyspan_4",
+static struct usb_serial_driver keyspan_4port_device = {
+       .driver = {
+               .owner          = THIS_MODULE,
+               .name           = "keyspan_4",
+       },
+       .description            = "Keyspan 4 port adapter",
        .id_table               = keyspan_4port_ids,
        .num_interrupt_in       = NUM_DONT_CARE,
        .num_bulk_in            = 5,
index 635c384..cd4f48b 100644 (file)
@@ -783,10 +783,12 @@ static void keyspan_pda_shutdown (struct usb_serial *serial)
 }
 
 #ifdef KEYSPAN
-static struct usb_serial_device_type keyspan_pda_fake_device = {
-       .owner =                THIS_MODULE,
-       .name =                 "Keyspan PDA - (prerenumeration)",
-       .short_name =           "keyspan_pda_pre",
+static struct usb_serial_driver keyspan_pda_fake_device = {
+       .driver = {
+               .owner =        THIS_MODULE,
+               .name =         "keyspan_pda_pre",
+       },
+       .description =          "Keyspan PDA - (prerenumeration)",
        .id_table =             id_table_fake,
        .num_interrupt_in =     NUM_DONT_CARE,
        .num_bulk_in =          NUM_DONT_CARE,
@@ -797,10 +799,12 @@ static struct usb_serial_device_type keyspan_pda_fake_device = {
 #endif
 
 #ifdef XIRCOM
-static struct usb_serial_device_type xircom_pgs_fake_device = {
-       .owner =                THIS_MODULE,
-       .name =                 "Xircom / Entregra PGS - (prerenumeration)",
-       .short_name =           "xircom_no_firm",
+static struct usb_serial_driver xircom_pgs_fake_device = {
+       .driver = {
+               .owner =        THIS_MODULE,
+               .name =         "xircom_no_firm",
+       },
+       .description =          "Xircom / Entregra PGS - (prerenumeration)",
        .id_table =             id_table_fake_xircom,
        .num_interrupt_in =     NUM_DONT_CARE,
        .num_bulk_in =          NUM_DONT_CARE,
@@ -810,10 +814,12 @@ static struct usb_serial_device_type xircom_pgs_fake_device = {
 };
 #endif
 
-static struct usb_serial_device_type keyspan_pda_device = {
-       .owner =                THIS_MODULE,
-       .name =                 "Keyspan PDA",
-       .short_name =           "keyspan_pda",
+static struct usb_serial_driver keyspan_pda_device = {
+       .driver = {
+               .owner =        THIS_MODULE,
+               .name =         "keyspan_pda",
+       },
+       .description =          "Keyspan PDA",
        .id_table =             id_table_std,
        .num_interrupt_in =     1,
        .num_bulk_in =          0,
index a11e829..a8951c0 100644 (file)
@@ -123,10 +123,12 @@ static struct usb_driver kl5kusb105d_driver = {
        .id_table =     id_table,
 };
 
-static struct usb_serial_device_type kl5kusb105d_device = {
-       .owner =             THIS_MODULE,
-       .name =              "KL5KUSB105D / PalmConnect",
-       .short_name =        "kl5kusb105d",
+static struct usb_serial_driver kl5kusb105d_device = {
+       .driver = {
+               .owner =        THIS_MODULE,
+               .name =         "kl5kusb105d",
+       },
+       .description =       "KL5KUSB105D / PalmConnect",
        .id_table =          id_table,
        .num_interrupt_in =  1,
        .num_bulk_in =       1,
index fe4c98a..9456dd9 100644 (file)
@@ -105,9 +105,12 @@ static struct usb_driver kobil_driver = {
 };
 
 
-static struct usb_serial_device_type kobil_device = {
-       .owner =                THIS_MODULE,
-       .name =                 "KOBIL USB smart card terminal",
+static struct usb_serial_driver kobil_device = {
+       .driver = {
+               .owner =        THIS_MODULE,
+               .name =         "kobil",
+       },
+       .description =          "KOBIL USB smart card terminal",
        .id_table =             id_table,
        .num_interrupt_in =     NUM_DONT_CARE,
        .num_bulk_in =          0,
index 50b6369..ca5dbad 100644 (file)
@@ -132,10 +132,12 @@ static struct usb_driver mct_u232_driver = {
        .id_table =     id_table_combined,
 };
 
-static struct usb_serial_device_type mct_u232_device = {
-       .owner =             THIS_MODULE,
-       .name =              "MCT U232",
-       .short_name =        "mct_u232",
+static struct usb_serial_driver mct_u232_device = {
+       .driver = {
+               .owner =        THIS_MODULE,
+               .name =         "mct_u232",
+       },
+       .description =       "MCT U232",
        .id_table =          id_table_combined,
        .num_interrupt_in =  2,
        .num_bulk_in =       0,
diff --git a/drivers/usb/serial/nokia_dku2.c b/drivers/usb/serial/nokia_dku2.c
new file mode 100644 (file)
index 0000000..fad01be
--- /dev/null
@@ -0,0 +1,142 @@
+/*
+ *  Nokia DKU2 USB driver
+ *
+ *  Copyright (C) 2004
+ *  Author: C Kemp
+ *
+ *  This program is largely derived from work by the linux-usb group
+ *  and associated source files.  Please see the usb/serial files for
+ *  individual credits and copyrights.
+ *
+ *  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.
+ *
+ *  20.09.2005 - Matthias Blaesing <matthias.blaesing@rwth-aachen.de>
+ *  Added short name to device structure to make driver load into kernel 2.6.13
+ *
+ *  20.09.2005 - Matthias Blaesing <matthias.blaesing@rwth-aachen.de>
+ *  Added usb_deregister to exit code - to allow remove and reinsert of module
+ */
+
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/tty.h>
+#include <linux/tty_driver.h>
+#include <linux/tty_flip.h>
+#include <linux/module.h>
+#include <linux/usb.h>
+#include "usb-serial.h"
+
+
+#define NOKIA_VENDOR_ID                0x0421
+#define NOKIA7600_PRODUCT_ID   0x0400
+#define NOKIA6230_PRODUCT_ID   0x040f
+#define NOKIA6170_PRODUCT_ID   0x0416
+#define NOKIA6670_PRODUCT_ID   0x041d
+#define NOKIA6680_PRODUCT_ID   0x041e
+#define NOKIA6230i_PRODUCT_ID  0x0428
+
+#define NOKIA_AT_PORT  0x82
+#define NOKIA_FBUS_PORT        0x86
+
+/*
+ * Version Information
+ */
+#define DRIVER_VERSION "v0.2"
+#define DRIVER_AUTHOR  "C Kemp"
+#define DRIVER_DESC    "Nokia DKU2 Driver"
+
+static struct usb_device_id id_table [] = {
+       { USB_DEVICE(NOKIA_VENDOR_ID, NOKIA7600_PRODUCT_ID) },
+       { USB_DEVICE(NOKIA_VENDOR_ID, NOKIA6230_PRODUCT_ID) },
+       { USB_DEVICE(NOKIA_VENDOR_ID, NOKIA6170_PRODUCT_ID) },
+       { USB_DEVICE(NOKIA_VENDOR_ID, NOKIA6670_PRODUCT_ID) },
+       { USB_DEVICE(NOKIA_VENDOR_ID, NOKIA6680_PRODUCT_ID) },
+       { USB_DEVICE(NOKIA_VENDOR_ID, NOKIA6230i_PRODUCT_ID) },
+       { }                     /* Terminating entry */
+};
+MODULE_DEVICE_TABLE(usb, id_table);
+
+/* The only thing which makes this device different from a generic
+ * device is that we have to set an alternative configuration to make
+ * the relevant endpoints available. In 2.6 this is really easy... */
+static int nokia_probe(struct usb_serial *serial,
+                      const struct usb_device_id *id)
+{
+       int retval = -ENODEV;
+
+       if (serial->interface->altsetting[0].endpoint[0].desc.bEndpointAddress == NOKIA_AT_PORT) {
+               /* the AT port */
+               dev_info(&serial->dev->dev, "Nokia AT Port:\n");
+               retval = 0;
+       } else if (serial->interface->num_altsetting == 2 &&
+                  serial->interface->altsetting[1].endpoint[0].desc.bEndpointAddress == NOKIA_FBUS_PORT) {
+               /* the FBUS port */
+               dev_info(&serial->dev->dev, "Nokia FBUS Port:\n");
+               usb_set_interface(serial->dev, 10, 1);
+               retval = 0;
+       }
+
+       return retval;
+}
+
+static struct usb_driver nokia_driver = {
+       .owner =        THIS_MODULE,
+       .name =         "nokia_dku2",
+       .probe =        usb_serial_probe,
+       .disconnect =   usb_serial_disconnect,
+       .id_table =     id_table,
+};
+
+static struct usb_serial_driver nokia_serial_driver = {
+       .driver = {
+               .owner =        THIS_MODULE,
+               .name =         "nokia_dku2",
+       },
+       .description =          "Nokia 7600/6230(i)/6170/66x0 DKU2 driver",
+       .id_table =             id_table,
+       .num_interrupt_in =     1,
+       .num_bulk_in =          1,
+       .num_bulk_out =         1,
+       .num_ports =            1,
+       .probe =                nokia_probe,
+};
+
+static int __init nokia_init(void)
+{
+        int retval;
+
+       retval = usb_serial_register(&nokia_serial_driver);
+       if (retval)
+               return retval;
+
+       retval = usb_register(&nokia_driver);
+       if (retval) {
+               usb_serial_deregister(&nokia_serial_driver);
+               return retval;
+       }
+
+       info(DRIVER_VERSION " " DRIVER_AUTHOR);
+       info(DRIVER_DESC);
+
+       return retval;
+}
+
+static void __exit nokia_exit(void)
+{
+       usb_deregister(&nokia_driver);
+       usb_serial_deregister(&nokia_serial_driver);
+}
+
+module_init(nokia_init);
+module_exit(nokia_exit);
+
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL");
index 6a99ae1..3caf970 100644 (file)
@@ -88,10 +88,12 @@ static struct usb_driver omninet_driver = {
 };
 
 
-static struct usb_serial_device_type zyxel_omninet_device = {
-       .owner =                THIS_MODULE,
-       .name =                 "ZyXEL - omni.net lcd plus usb",
-       .short_name =           "omninet",
+static struct usb_serial_driver zyxel_omninet_device = {
+       .driver = {
+               .owner =        THIS_MODULE,
+               .name =         "omninet",
+       },
+       .description =          "ZyXEL - omni.net lcd plus usb",
        .id_table =             id_table,
        .num_interrupt_in =     1,
        .num_bulk_in =          1,
index 4989e57..7716000 100644 (file)
@@ -105,10 +105,12 @@ static struct usb_driver option_driver = {
 /* The card has three separate interfaces, wich the serial driver
  * recognizes separately, thus num_port=1.
  */
-static struct usb_serial_device_type option_3port_device = {
-       .owner             = THIS_MODULE,
-       .name              = "Option 3G data card",
-       .short_name        = "option",
+static struct usb_serial_driver option_3port_device = {
+       .driver = {
+               .owner =        THIS_MODULE,
+               .name =         "option",
+       },
+       .description       = "Option 3G data card",
        .id_table          = option_ids,
        .num_interrupt_in  = NUM_DONT_CARE,
        .num_bulk_in       = NUM_DONT_CARE,
index 3cf245b..165c119 100644 (file)
@@ -8,31 +8,10 @@
  *
  *     This program is free software; you can redistribute it and/or modify
  *     it under the terms of the GNU General Public License as published by
- *     the Free Software Foundation; either version 2 of the License, or
- *     (at your option) any later version.
+ *     the Free Software Foundation; either version 2 of the License.
  *
  * See Documentation/usb/usb-serial.txt for more information on using this driver
  *
- * 2002_Mar_26 gkh
- *     allowed driver to work properly if there is no tty assigned to a port
- *     (this happens for serial console devices.)
- *
- * 2001_Oct_06 gkh
- *     Added RTS and DTR line control.  Thanks to joe@bndlg.de for parts of it.
- *
- * 2001_Sep_19 gkh
- *     Added break support.
- *
- * 2001_Aug_30 gkh
- *     fixed oops in write_bulk_callback.
- *
- * 2001_Aug_28 gkh
- *     reworked buffer logic to be like other usb-serial drivers.  Hopefully
- *     removing some reported problems.
- *
- * 2001_Jun_06 gkh
- *     finished porting to 2.4 format.
- * 
  */
 
 #include <linux/config.h>
@@ -55,7 +34,6 @@
 /*
  * Version Information
  */
-#define DRIVER_VERSION "v0.12"
 #define DRIVER_DESC "Prolific PL2303 USB to serial adaptor driver"
 
 static int debug;
@@ -175,9 +153,11 @@ static unsigned int pl2303_buf_get(struct pl2303_buf *pb, char *buf,
 
 
 /* All of the device info needed for the PL2303 SIO serial converter */
-static struct usb_serial_device_type pl2303_device = {
-       .owner =                THIS_MODULE,
-       .name =                 "PL-2303",
+static struct usb_serial_driver pl2303_device = {
+       .driver = {
+               .owner =        THIS_MODULE,
+               .name =         "pl2303",
+       },
        .id_table =             id_table,
        .num_interrupt_in =     NUM_DONT_CARE,
        .num_bulk_in =          1,
@@ -1195,7 +1175,7 @@ static int __init pl2303_init (void)
        retval = usb_register(&pl2303_driver);
        if (retval)
                goto failed_usb_register;
-       info(DRIVER_DESC " " DRIVER_VERSION);
+       info(DRIVER_DESC);
        return 0;
 failed_usb_register:
        usb_serial_deregister(&pl2303_device);
@@ -1215,7 +1195,6 @@ module_init(pl2303_init);
 module_exit(pl2303_exit);
 
 MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_VERSION(DRIVER_VERSION);
 MODULE_LICENSE("GPL");
 
 module_param(debug, bool, S_IRUGO | S_IWUSR);
index 96a1756..c22bdc0 100644 (file)
@@ -92,7 +92,7 @@ MODULE_DESCRIPTION (DRIVER_DESC);
 MODULE_LICENSE("GPL");
 
 #if defined(CONFIG_USBD_SAFE_SERIAL_VENDOR) && !defined(CONFIG_USBD_SAFE_SERIAL_PRODUCT)
-#abort "SAFE_SERIAL_VENDOR defined without SAFE_SERIAL_PRODUCT"
+#error "SAFE_SERIAL_VENDOR defined without SAFE_SERIAL_PRODUCT"
 #endif
 
 #if ! defined(CONFIG_USBD_SAFE_SERIAL_VENDOR)
@@ -397,9 +397,11 @@ static int safe_startup (struct usb_serial *serial)
        return 0;
 }
 
-static struct usb_serial_device_type safe_device = {
-       .owner =                THIS_MODULE,
-       .name =                 "Safe",
+static struct usb_serial_driver safe_device = {
+       .driver = {
+               .owner =        THIS_MODULE,
+               .name =         "safe_serial",
+       },
        .id_table =             id_table,
        .num_interrupt_in =     NUM_DONT_CARE,
        .num_bulk_in =          NUM_DONT_CARE,
index 59c88de..205dbf7 100644 (file)
@@ -255,9 +255,12 @@ static struct usb_driver ti_usb_driver = {
        .id_table               = ti_id_table_combined,
 };
 
-static struct usb_serial_device_type ti_1port_device = {
-       .owner                  = THIS_MODULE,
-       .name                   = "TI USB 3410 1 port adapter",
+static struct usb_serial_driver ti_1port_device = {
+       .driver = {
+               .owner          = THIS_MODULE,
+               .name           = "ti_usb_3410_5052_1",
+       },
+       .description            = "TI USB 3410 1 port adapter",
        .id_table               = ti_id_table_3410,
        .num_interrupt_in       = 1,
        .num_bulk_in            = 1,
@@ -282,9 +285,12 @@ static struct usb_serial_device_type ti_1port_device = {
        .write_bulk_callback    = ti_bulk_out_callback,
 };
 
-static struct usb_serial_device_type ti_2port_device = {
-       .owner                  = THIS_MODULE,
-       .name                   = "TI USB 5052 2 port adapter",
+static struct usb_serial_driver ti_2port_device = {
+       .driver = {
+               .owner          = THIS_MODULE,
+               .name           = "ti_usb_3410_5052_2",
+       },
+       .description            = "TI USB 5052 2 port adapter",
        .id_table               = ti_id_table_5052,
        .num_interrupt_in       = 1,
        .num_bulk_in            = 2,
index e77fbdf..0c4881d 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * USB Serial Converter driver
  *
- * Copyright (C) 1999 - 2004 Greg Kroah-Hartman (greg@kroah.com)
+ * Copyright (C) 1999 - 2005 Greg Kroah-Hartman (greg@kroah.com)
  * Copyright (C) 2000 Peter Berger (pberger@brimson.com)
  * Copyright (C) 2000 Al Borchers (borchers@steinerpoint.com)
  *
  *     modify it under the terms of the GNU General Public License version
  *     2 as published by the Free Software Foundation.
  *
- * This driver was originally based on the ACM driver by Armin Fuerst (which was 
+ * This driver was originally based on the ACM driver by Armin Fuerst (which was
  * based on a driver by Brad Keryan)
  *
  * See Documentation/usb/usb-serial.txt for more information on using this driver
  *
- * (12/10/2002) gkh
- *     Split the ports off into their own struct device, and added a
- *     usb-serial bus driver.
- *
- * (11/19/2002) gkh
- *     removed a few #ifdefs for the generic code and cleaned up the failure
- *     logic in initialization.
- *
- * (10/02/2002) gkh
- *     moved the console code to console.c and out of this file.
- *
- * (06/05/2002) gkh
- *     moved location of startup() call in serial_probe() until after all
- *     of the port information and endpoints are initialized.  This makes
- *     things easier for some drivers.
- *
- * (04/10/2002) gkh
- *     added serial_read_proc function which creates a
- *     /proc/tty/driver/usb-serial file.
- *
- * (03/27/2002) gkh
- *     Got USB serial console code working properly and merged into the main
- *     version of the tree.  Thanks to Randy Dunlap for the initial version
- *     of this code, and for pushing me to finish it up.
- *     The USB serial console works with any usb serial driver device.
- *
- * (03/21/2002) gkh
- *     Moved all manipulation of port->open_count into the core.  Now the
- *     individual driver's open and close functions are called only when the
- *     first open() and last close() is called.  Making the drivers a bit
- *     smaller and simpler.
- *     Fixed a bug if a driver didn't have the owner field set.
- *
- * (02/26/2002) gkh
- *     Moved all locking into the main serial_* functions, instead of having 
- *     the individual drivers have to grab the port semaphore.  This should
- *     reduce races.
- *     Reworked the MOD_INC logic a bit to always increment and decrement, even
- *     if the generic driver is being used.
- *
- * (10/10/2001) gkh
- *     usb_serial_disconnect() now sets the serial->dev pointer is to NULL to
- *     help prevent child drivers from accessing the device since it is now
- *     gone.
- *
- * (09/13/2001) gkh
- *     Moved generic driver initialize after we have registered with the USB
- *     core.  Thanks to Randy Dunlap for pointing this problem out.
- *
- * (07/03/2001) gkh
- *     Fixed module paramater size.  Thanks to John Brockmeyer for the pointer.
- *     Fixed vendor and product getting defined through the MODULE_PARM macro
- *     if the Generic driver wasn't compiled in.
- *     Fixed problem with generic_shutdown() not being called for drivers that
- *     don't have a shutdown() function.
- *
- * (06/06/2001) gkh
- *     added evil hack that is needed for the prolific pl2303 device due to the
- *     crazy way its endpoints are set up.
- *
- * (05/30/2001) gkh
- *     switched from using spinlock to a semaphore, which fixes lots of problems.
- *
- * (04/08/2001) gb
- *     Identify version on module load.
- *
- * 2001_02_05 gkh
- *     Fixed buffer overflows bug with the generic serial driver.  Thanks to
- *     Todd Squires <squirest@ct0.com> for fixing this.
- *
- * (01/10/2001) gkh
- *     Fixed bug where the generic serial adaptor grabbed _any_ device that was
- *     offered to it.
- *
- * (12/12/2000) gkh
- *     Removed MOD_INC and MOD_DEC from poll and disconnect functions, and
- *     moved them to the serial_open and serial_close functions.
- *     Also fixed bug with there not being a MOD_DEC for the generic driver
- *     (thanks to Gary Brubaker for finding this.)
- *
- * (11/29/2000) gkh
- *     Small NULL pointer initialization cleanup which saves a bit of disk image
- *
- * (11/01/2000) Adam J. Richter
- *     instead of using idVendor/idProduct pairs, usb serial drivers
- *     now identify their hardware interest with usb_device_id tables,
- *     which they usually have anyhow for use with MODULE_DEVICE_TABLE.
- *
- * (10/05/2000) gkh
- *     Fixed bug with urb->dev not being set properly, now that the usb
- *     core needs it.
- * 
- * (09/11/2000) gkh
- *     Removed DEBUG #ifdefs with call to usb_serial_debug_data
- *
- * (08/28/2000) gkh
- *     Added port_lock to port structure.
- *     Added locks for SMP safeness to generic driver
- *     Fixed the ability to open a generic device's port more than once.
- *
- * (07/23/2000) gkh
- *     Added bulk_out_endpointAddress to port structure.
- *
- * (07/19/2000) gkh, pberger, and borchers
- *     Modifications to allow usb-serial drivers to be modules.
- *
- * (07/03/2000) gkh
- *     Added more debugging to serial_ioctl call
- * 
- * (06/25/2000) gkh
- *     Changed generic_write_bulk_callback to not call wake_up_interruptible
- *     directly, but to have port_softint do it at a safer time.
- *
- * (06/23/2000) gkh
- *     Cleaned up debugging statements in a quest to find UHCI timeout bug.
- *
- * (05/22/2000) gkh
- *     Changed the makefile, enabling the big CONFIG_USB_SERIAL_SOMTHING to be 
- *     removed from the individual device source files.
- *
- * (05/03/2000) gkh
- *     Added the Digi Acceleport driver from Al Borchers and Peter Berger.
- * 
- * (05/02/2000) gkh
- *     Changed devfs and tty register code to work properly now. This was based on
- *     the ACM driver changes by Vojtech Pavlik.
- *
- * (04/27/2000) Ryan VanderBijl
- *     Put calls to *_paranoia_checks into one function.
- * 
- * (04/23/2000) gkh
- *     Fixed bug that Randy Dunlap found for Generic devices with no bulk out ports.
- *     Moved when the startup code printed out the devices that are supported.
- *
- * (04/19/2000) gkh
- *     Added driver for ZyXEL omni.net lcd plus ISDN TA
- *     Made startup info message specify which drivers were compiled in.
- *
- * (04/03/2000) gkh
- *     Changed the probe process to remove the module unload races.
- *     Changed where the tty layer gets initialized to have devfs work nicer.
- *     Added initial devfs support.
- *
- * (03/26/2000) gkh
- *     Split driver up into device specific pieces.
- * 
- * (03/19/2000) gkh
- *     Fixed oops that could happen when device was removed while a program
- *     was talking to the device.
- *     Removed the static urbs and now all urbs are created and destroyed
- *     dynamically.
- *     Reworked the internal interface. Now everything is based on the 
- *     usb_serial_port structure instead of the larger usb_serial structure.
- *     This fixes the bug that a multiport device could not have more than
- *     one port open at one time.
- *
- * (03/17/2000) gkh
- *     Added config option for debugging messages.
- *     Added patch for keyspan pda from Brian Warner.
- *
- * (03/06/2000) gkh
- *     Added the keyspan pda code from Brian Warner <warner@lothar.com>
- *     Moved a bunch of the port specific stuff into its own structure. This
- *     is in anticipation of the true multiport devices (there's a bug if you
- *     try to access more than one port of any multiport device right now)
- *
- * (02/21/2000) gkh
- *     Made it so that any serial devices only have to specify which functions
- *     they want to overload from the generic function calls (great, 
- *     inheritance in C, in a driver, just what I wanted...)
- *     Added support for set_termios and ioctl function calls. No drivers take
- *     advantage of this yet.
- *     Removed the #ifdef MODULE, now there is no module specific code.
- *     Cleaned up a few comments in usb-serial.h that were wrong (thanks again
- *     to Miles Lott).
- *     Small fix to get_free_serial.
- *
- * (02/14/2000) gkh
- *     Removed the Belkin and Peracom functionality from the driver due to
- *     the lack of support from the vendor, and me not wanting people to 
- *     accidenatly buy the device, expecting it to work with Linux.
- *     Added read_bulk_callback and write_bulk_callback to the type structure
- *     for the needs of the FTDI and WhiteHEAT driver.
- *     Changed all reverences to FTDI to FTDI_SIO at the request of Bill
- *     Ryder.
- *     Changed the output urb size back to the max endpoint size to make
- *     the ftdi_sio driver have it easier, and due to the fact that it didn't
- *     really increase the speed any.
- *
- * (02/11/2000) gkh
- *     Added VISOR_FUNCTION_CONSOLE to the visor startup function. This was a
- *     patch from Miles Lott (milos@insync.net).
- *     Fixed bug with not restoring the minor range that a device grabs, if
- *     the startup function fails (thanks Miles for finding this).
- *
- * (02/05/2000) gkh
- *     Added initial framework for the Keyspan PDA serial converter so that
- *     Brian Warner has a place to put his code.
- *     Made the ezusb specific functions generic enough that different
- *     devices can use them (whiteheat and keyspan_pda both need them).
- *     Split out a whole bunch of structure and other stuff to a separate
- *     usb-serial.h file.
- *     Made the Visor connection messages a little more understandable, now
- *     that Miles Lott (milos@insync.net) has gotten the Generic channel to
- *     work. Also made them always show up in the log file.
- * 
- * (01/25/2000) gkh
- *     Added initial framework for FTDI serial converter so that Bill Ryder
- *     has a place to put his code.
- *     Added the vendor specific info from Handspring. Now we can print out
- *     informational debug messages as well as understand what is happening.
- *
- * (01/23/2000) gkh
- *     Fixed problem of crash when trying to open a port that didn't have a
- *     device assigned to it. Made the minor node finding a little smarter,
- *     now it looks to find a continuous space for the new device.
- *
- * (01/21/2000) gkh
- *     Fixed bug in visor_startup with patch from Miles Lott (milos@insync.net)
- *     Fixed get_serial_by_minor which was all messed up for multi port 
- *     devices. Fixed multi port problem for generic devices. Now the number
- *     of ports is determined by the number of bulk out endpoints for the
- *     generic device.
- *
- * (01/19/2000) gkh
- *     Removed lots of cruft that was around from the old (pre urb) driver 
- *     interface.
- *     Made the serial_table dynamic. This should save lots of memory when
- *     the number of minor nodes goes up to 256.
- *     Added initial support for devices that have more than one port. 
- *     Added more debugging comments for the Visor, and added a needed 
- *     set_configuration call.
- *
- * (01/17/2000) gkh
- *     Fixed the WhiteHEAT firmware (my processing tool had a bug)
- *     and added new debug loader firmware for it.
- *     Removed the put_char function as it isn't really needed.
- *     Added visor startup commands as found by the Win98 dump.
- * 
- * (01/13/2000) gkh
- *     Fixed the vendor id for the generic driver to the one I meant it to be.
- *
- * (01/12/2000) gkh
- *     Forget the version numbering...that's pretty useless...
- *     Made the driver able to be compiled so that the user can select which
- *     converter they want to use. This allows people who only want the Visor
- *     support to not pay the memory size price of the WhiteHEAT.
- *     Fixed bug where the generic driver (idVendor=0000 and idProduct=0000)
- *     grabbed the root hub. Not good.
- * 
- * version 0.4.0 (01/10/2000) gkh
- *     Added whiteheat.h containing the firmware for the ConnectTech WhiteHEAT
- *     device. Added startup function to allow firmware to be downloaded to
- *     a device if it needs to be.
- *     Added firmware download logic to the WhiteHEAT device.
- *     Started to add #defines to split up the different drivers for potential
- *     configuration option.
- *     
- * version 0.3.1 (12/30/99) gkh
- *      Fixed problems with urb for bulk out.
- *      Added initial support for multiple sets of endpoints. This enables
- *      the Handspring Visor to be attached successfully. Only the first
- *      bulk in / bulk out endpoint pair is being used right now.
- *
- * version 0.3.0 (12/27/99) gkh
- *     Added initial support for the Handspring Visor based on a patch from
- *     Miles Lott (milos@sneety.insync.net)
- *     Cleaned up the code a bunch and converted over to using urbs only.
- *
- * version 0.2.3 (12/21/99) gkh
- *     Added initial support for the Connect Tech WhiteHEAT converter.
- *     Incremented the number of ports in expectation of getting the
- *     WhiteHEAT to work properly (4 ports per connection).
- *     Added notification on insertion and removal of what port the
- *     device is/was connected to (and what kind of device it was).
- *
- * version 0.2.2 (12/16/99) gkh
- *     Changed major number to the new allocated number. We're legal now!
- *
- * version 0.2.1 (12/14/99) gkh
- *     Fixed bug that happens when device node is opened when there isn't a
- *     device attached to it. Thanks to marek@webdesign.no for noticing this.
- *
- * version 0.2.0 (11/10/99) gkh
- *     Split up internals to make it easier to add different types of serial 
- *     converters to the code.
- *     Added a "generic" driver that gets it's vendor and product id
- *     from when the module is loaded. Thanks to David E. Nelson (dnelson@jump.net)
- *     for the idea and sample code (from the usb scanner driver.)
- *     Cleared up any licensing questions by releasing it under the GNU GPL.
- *
- * version 0.1.2 (10/25/99) gkh
- *     Fixed bug in detecting device.
- *
- * version 0.1.1 (10/05/99) gkh
- *     Changed the major number to not conflict with anything else.
- *
- * version 0.1 (09/28/99) gkh
- *     Can recognize the two different devices and start up a read from
- *     device when asked to. Writes also work. No control signals yet, this
- *     all is vendor specific data (i.e. no spec), also no control for
- *     different baud rates or other bit settings.
- *     Currently we are using the same devid as the acm driver. This needs
- *     to change.
- * 
  */
 
 #include <linux/config.h>
 /*
  * Version Information
  */
-#define DRIVER_VERSION "v2.0"
 #define DRIVER_AUTHOR "Greg Kroah-Hartman, greg@kroah.com, http://www.kroah.com/linux/"
 #define DRIVER_DESC "USB Serial Driver core"
 
@@ -427,7 +121,7 @@ static void destroy_serial(struct kref *kref)
 
        serial = to_usb_serial(kref);
 
-       dbg ("%s - %s", __FUNCTION__, serial->type->name);
+       dbg("%s - %s", __FUNCTION__, serial->type->description);
 
        serial->type->shutdown(serial);
 
@@ -507,7 +201,7 @@ static int serial_open (struct tty_struct *tty, struct file * filp)
                /* lock this module before we call it
                 * this may fail, which means we must bail out,
                 * safe because we are called with BKL held */
-               if (!try_module_get(serial->type->owner)) {
+               if (!try_module_get(serial->type->driver.owner)) {
                        retval = -ENODEV;
                        goto bailout_kref_put;
                }
@@ -522,7 +216,7 @@ static int serial_open (struct tty_struct *tty, struct file * filp)
        return 0;
 
 bailout_module_put:
-       module_put(serial->type->owner);
+       module_put(serial->type->driver.owner);
 bailout_kref_put:
        kref_put(&serial->kref, destroy_serial);
        port->open_count = 0;
@@ -553,7 +247,7 @@ static void serial_close(struct tty_struct *tty, struct file * filp)
                        port->tty = NULL;
                }
 
-               module_put(port->serial->type->owner);
+               module_put(port->serial->type->driver.owner);
        }
 
        kref_put(&port->serial->kref, destroy_serial);
@@ -711,16 +405,16 @@ static int serial_read_proc (char *page, char **start, off_t off, int count, int
        char tmp[40];
 
        dbg("%s", __FUNCTION__);
-       length += sprintf (page, "usbserinfo:1.0 driver:%s\n", DRIVER_VERSION);
+       length += sprintf (page, "usbserinfo:1.0 driver:2.0\n");
        for (i = 0; i < SERIAL_TTY_MINORS && length < PAGE_SIZE; ++i) {
                serial = usb_serial_get_by_index(i);
                if (serial == NULL)
                        continue;
 
                length += sprintf (page+length, "%d:", i);
-               if (serial->type->owner)
-                       length += sprintf (page+length, " module:%s", module_name(serial->type->owner));
-               length += sprintf (page+length, " name:\"%s\"", serial->type->name);
+               if (serial->type->driver.owner)
+                       length += sprintf (page+length, " module:%s", module_name(serial->type->driver.owner));
+               length += sprintf (page+length, " name:\"%s\"", serial->type->description);
                length += sprintf (page+length, " vendor:%04x product:%04x", 
                                   le16_to_cpu(serial->dev->descriptor.idVendor), 
                                   le16_to_cpu(serial->dev->descriptor.idProduct));
@@ -823,7 +517,7 @@ static void port_release(struct device *dev)
 
 static struct usb_serial * create_serial (struct usb_device *dev, 
                                          struct usb_interface *interface,
-                                         struct usb_serial_device_type *type)
+                                         struct usb_serial_driver *driver)
 {
        struct usb_serial *serial;
 
@@ -834,22 +528,22 @@ static struct usb_serial * create_serial (struct usb_device *dev,
        }
        memset (serial, 0, sizeof(*serial));
        serial->dev = usb_get_dev(dev);
-       serial->type = type;
+       serial->type = driver;
        serial->interface = interface;
        kref_init(&serial->kref);
 
        return serial;
 }
 
-static struct usb_serial_device_type *search_serial_device(struct usb_interface *iface)
+static struct usb_serial_driver *search_serial_device(struct usb_interface *iface)
 {
        struct list_head *p;
        const struct usb_device_id *id;
-       struct usb_serial_device_type *t;
+       struct usb_serial_driver *t;
 
        /* List trough know devices and see if the usb id matches */
        list_for_each(p, &usb_serial_driver_list) {
-               t = list_entry(p, struct usb_serial_device_type, driver_list);
+               t = list_entry(p, struct usb_serial_driver, driver_list);
                id = usb_match_id(iface, t->id_table);
                if (id != NULL) {
                        dbg("descriptor matches");
@@ -872,7 +566,7 @@ int usb_serial_probe(struct usb_interface *interface,
        struct usb_endpoint_descriptor *interrupt_out_endpoint[MAX_NUM_PORTS];
        struct usb_endpoint_descriptor *bulk_in_endpoint[MAX_NUM_PORTS];
        struct usb_endpoint_descriptor *bulk_out_endpoint[MAX_NUM_PORTS];
-       struct usb_serial_device_type *type = NULL;
+       struct usb_serial_driver *type = NULL;
        int retval;
        int minor;
        int buffer_size;
@@ -900,7 +594,7 @@ int usb_serial_probe(struct usb_interface *interface,
        if (type->probe) {
                const struct usb_device_id *id;
 
-               if (!try_module_get(type->owner)) {
+               if (!try_module_get(type->driver.owner)) {
                        dev_err(&interface->dev, "module get failed, exiting\n");
                        kfree (serial);
                        return -EIO;
@@ -908,7 +602,7 @@ int usb_serial_probe(struct usb_interface *interface,
 
                id = usb_match_id(interface, type->id_table);
                retval = type->probe(serial, id);
-               module_put(type->owner);
+               module_put(type->driver.owner);
 
                if (retval) {
                        dbg ("sub driver rejected device");
@@ -992,7 +686,7 @@ int usb_serial_probe(struct usb_interface *interface,
 #endif
 
        /* found all that we need */
-       dev_info(&interface->dev, "%s converter detected\n", type->name);
+       dev_info(&interface->dev, "%s converter detected\n", type->description);
 
 #ifdef CONFIG_USB_SERIAL_GENERIC
        if (type == &usb_serial_generic_device) {
@@ -1007,13 +701,13 @@ int usb_serial_probe(struct usb_interface *interface,
        if (!num_ports) {
                /* if this device type has a calc_num_ports function, call it */
                if (type->calc_num_ports) {
-                       if (!try_module_get(type->owner)) {
+                       if (!try_module_get(type->driver.owner)) {
                                dev_err(&interface->dev, "module get failed, exiting\n");
                                kfree (serial);
                                return -EIO;
                        }
                        num_ports = type->calc_num_ports (serial);
-                       module_put(type->owner);
+                       module_put(type->driver.owner);
                }
                if (!num_ports)
                        num_ports = type->num_ports;
@@ -1158,12 +852,12 @@ int usb_serial_probe(struct usb_interface *interface,
        
        /* if this device type has an attach function, call it */
        if (type->attach) {
-               if (!try_module_get(type->owner)) {
+               if (!try_module_get(type->driver.owner)) {
                        dev_err(&interface->dev, "module get failed, exiting\n");
                        goto probe_error;
                }
                retval = type->attach (serial);
-               module_put(type->owner);
+               module_put(type->driver.owner);
                if (retval < 0)
                        goto probe_error;
                if (retval > 0) {
@@ -1330,7 +1024,7 @@ static int __init usb_serial_init(void)
                goto exit_generic;
        }
 
-       info(DRIVER_DESC " " DRIVER_VERSION);
+       info(DRIVER_DESC);
 
        return result;
 
@@ -1375,7 +1069,7 @@ module_exit(usb_serial_exit);
                        }                                               \
        } while (0)
 
-static void fixup_generic(struct usb_serial_device_type *device)
+static void fixup_generic(struct usb_serial_driver *device)
 {
        set_to_generic_if_null(device, open);
        set_to_generic_if_null(device, write);
@@ -1387,30 +1081,33 @@ static void fixup_generic(struct usb_serial_device_type *device)
        set_to_generic_if_null(device, shutdown);
 }
 
-int usb_serial_register(struct usb_serial_device_type *new_device)
+int usb_serial_register(struct usb_serial_driver *driver)
 {
        int retval;
 
-       fixup_generic(new_device);
+       fixup_generic(driver);
+
+       if (!driver->description)
+               driver->description = driver->driver.name;
 
        /* Add this device to our list of devices */
-       list_add(&new_device->driver_list, &usb_serial_driver_list);
+       list_add(&driver->driver_list, &usb_serial_driver_list);
 
-       retval = usb_serial_bus_register(new_device);
+       retval = usb_serial_bus_register(driver);
        if (retval) {
-               err("problem %d when registering driver %s", retval, new_device->name);
-               list_del(&new_device->driver_list);
+               err("problem %d when registering driver %s", retval, driver->description);
+               list_del(&driver->driver_list);
        }
        else
-               info("USB Serial support registered for %s", new_device->name);
+               info("USB Serial support registered for %s", driver->description);
 
        return retval;
 }
 
 
-void usb_serial_deregister(struct usb_serial_device_type *device)
+void usb_serial_deregister(struct usb_serial_driver *device)
 {
-       info("USB Serial deregistering driver %s", device->name);
+       info("USB Serial deregistering driver %s", device->description);
        list_del(&device->driver_list);
        usb_serial_bus_deregister(device);
 }
@@ -1429,7 +1126,6 @@ EXPORT_SYMBOL_GPL(usb_serial_port_softint);
 /* Module information */
 MODULE_AUTHOR( DRIVER_AUTHOR );
 MODULE_DESCRIPTION( DRIVER_DESC );
-MODULE_VERSION( DRIVER_VERSION );
 MODULE_LICENSE("GPL");
 
 module_param(debug, bool, S_IRUGO | S_IWUSR);
index 57f92f0..238a5a8 100644 (file)
@@ -1,53 +1,13 @@
 /*
  * USB Serial Converter driver
  *
- *     Copyright (C) 1999 - 2004
+ *     Copyright (C) 1999 - 2005
  *         Greg Kroah-Hartman (greg@kroah.com)
  *
  *     This program is free software; you can redistribute it and/or modify
  *     it under the terms of the GNU General Public License as published by
- *     the Free Software Foundation; either version 2 of the License, or
- *     (at your option) any later version.
+ *     the Free Software Foundation; either version 2 of the License.
  *
- * See Documentation/usb/usb-serial.txt for more information on using this driver
- *
- * (03/26/2002) gkh
- *     removed the port->tty check from port_paranoia_check() due to serial
- *     consoles not having a tty device assigned to them.
- *
- * (12/03/2001) gkh
- *     removed active from the port structure.
- *     added documentation to the usb_serial_device_type structure
- *
- * (10/10/2001) gkh
- *     added vendor and product to serial structure.  Needed to determine device
- *     owner when the device is disconnected.
- *
- * (05/30/2001) gkh
- *     added sem to port structure and removed port_lock
- *
- * (10/05/2000) gkh
- *     Added interrupt_in_endpointAddress and bulk_in_endpointAddress to help
- *     fix bug with urb->dev not being set properly, now that the usb core
- *     needs it.
- * 
- * (09/11/2000) gkh
- *     Added usb_serial_debug_data function to help get rid of #DEBUG in the
- *     drivers.
- *
- * (08/28/2000) gkh
- *     Added port_lock to port structure.
- *
- * (08/08/2000) gkh
- *     Added open_count to port structure.
- *
- * (07/23/2000) gkh
- *     Added bulk_out_endpointAddress to port structure.
- *
- * (07/19/2000) gkh, pberger, and borchers
- *     Modifications to allow usb-serial drivers to be modules.
- *
- * 
  */
 
 
@@ -143,7 +103,7 @@ static inline void usb_set_serial_port_data (struct usb_serial_port *port, void
 /**
  * usb_serial - structure used by the usb-serial core for a device
  * @dev: pointer to the struct usb_device for this device
- * @type: pointer to the struct usb_serial_device_type for this device
+ * @type: pointer to the struct usb_serial_driver for this device
  * @interface: pointer to the struct usb_interface for this device
  * @minor: the starting minor number for this device
  * @num_ports: the number of ports this device has
@@ -159,7 +119,7 @@ static inline void usb_set_serial_port_data (struct usb_serial_port *port, void
  */
 struct usb_serial {
        struct usb_device *             dev;
-       struct usb_serial_device_type * type;
+       struct usb_serial_driver *      type;
        struct usb_interface *          interface;
        unsigned char                   minor;
        unsigned char                   num_ports;
@@ -188,13 +148,9 @@ static inline void usb_set_serial_data (struct usb_serial *serial, void *data)
 }
 
 /**
- * usb_serial_device_type - a structure that defines a usb serial device
- * @owner: pointer to the module that owns this device.
- * @name: pointer to a string that describes this device.  This string used
+ * usb_serial_driver - describes a usb serial driver
+ * @description: pointer to a string that describes this driver.  This string used
  *     in the syslog messages when a device is inserted or removed.
- * @short_name: a pointer to a string that describes this device in
- *     KOBJ_NAME_LEN characters or less.  This is used for the sysfs interface
- *     to describe the driver.
  * @id_table: pointer to a list of usb_device_id structures that define all
  *     of the devices this structure can support.
  * @num_interrupt_in: the number of interrupt in endpoints this device will
@@ -221,16 +177,19 @@ static inline void usb_set_serial_data (struct usb_serial *serial, void *data)
  * @shutdown: pointer to the driver's shutdown function.  This will be
  *     called when the device is removed from the system.
  *
- * This structure is defines a USB Serial device.  It provides all of
+ * This structure is defines a USB Serial driver.  It provides all of
  * the information that the USB serial core code needs.  If the function
  * pointers are defined, then the USB serial core code will call them when
  * the corresponding tty port functions are called.  If they are not
  * called, the generic serial function will be used instead.
+ *
+ * The driver.owner field should be set to the module owner of this driver.
+ * The driver.name field should be set to the name of this driver (remember
+ * it will show up in sysfs, so it needs to be short and to the point.
+ * Useing the module name is a good idea.)
  */
-struct usb_serial_device_type {
-       struct module *owner;
-       char    *name;
-       char    *short_name;
+struct usb_serial_driver {
+       const char *description;
        const struct usb_device_id *id_table;
        char    num_interrupt_in;
        char    num_interrupt_out;
@@ -269,10 +228,10 @@ struct usb_serial_device_type {
        void (*read_bulk_callback)(struct urb *urb, struct pt_regs *regs);
        void (*write_bulk_callback)(struct urb *urb, struct pt_regs *regs);
 };
-#define to_usb_serial_driver(d) container_of(d, struct usb_serial_device_type, driver)
+#define to_usb_serial_driver(d) container_of(d, struct usb_serial_driver, driver)
 
-extern int  usb_serial_register(struct usb_serial_device_type *new_device);
-extern void usb_serial_deregister(struct usb_serial_device_type *device);
+extern int  usb_serial_register(struct usb_serial_driver *driver);
+extern void usb_serial_deregister(struct usb_serial_driver *driver);
 extern void usb_serial_port_softint(void *private);
 
 extern int usb_serial_probe(struct usb_interface *iface, const struct usb_device_id *id);
@@ -303,10 +262,10 @@ extern void usb_serial_generic_shutdown (struct usb_serial *serial);
 extern int usb_serial_generic_register (int debug);
 extern void usb_serial_generic_deregister (void);
 
-extern int usb_serial_bus_register (struct usb_serial_device_type *device);
-extern void usb_serial_bus_deregister (struct usb_serial_device_type *device);
+extern int usb_serial_bus_register (struct usb_serial_driver *device);
+extern void usb_serial_bus_deregister (struct usb_serial_driver *device);
 
-extern struct usb_serial_device_type usb_serial_generic_device;
+extern struct usb_serial_driver usb_serial_generic_device;
 extern struct bus_type usb_serial_bus_type;
 extern struct tty_driver *usb_serial_tty_driver;
 
index 31c57ad..a473c1c 100644 (file)
  *
  *     This program is free software; you can redistribute it and/or modify
  *     it under the terms of the GNU General Public License as published by
- *     the Free Software Foundation; either version 2 of the License, or
- *     (at your option) any later version.
+ *     the Free Software Foundation; either version 2 of the License.
  *
  * See Documentation/usb/usb-serial.txt for more information on using this driver
  *
- * (06/03/2003) Judd Montgomery <judd at jpilot.org>
- *     Added support for module parameter options for untested/unknown
- *     devices.
- *
- * (03/09/2003) gkh
- *     Added support for the Sony Clie NZ90V device.  Thanks to Martin Brachtl
- *     <brachtl@redgrep.cz> for the information.
- *
- * (03/05/2003) gkh
- *     Think Treo support is now working.
- *
- * (04/03/2002) gkh
- *     Added support for the Sony OS 4.1 devices.  Thanks to Hiroyuki ARAKI
- *     <hiro@zob.ne.jp> for the information.
- *
- * (03/27/2002) gkh
- *     Removed assumptions that port->tty was always valid (is not true
- *     for usb serial console devices.)
- *
- * (03/23/2002) gkh
- *     Added support for the Palm i705 device, thanks to Thomas Riemer
- *     <tom@netmech.com> for the information.
- *
- * (03/21/2002) gkh
- *     Added support for the Palm m130 device, thanks to Udo Eisenbarth
- *     <udo.eisenbarth@web.de> for the information.
- *
- * (02/27/2002) gkh
- *     Reworked the urb handling logic.  We have no more pool, but dynamically
- *     allocate the urb and the transfer buffer on the fly.  In testing this
- *     does not incure any measurable overhead.  This also relies on the fact
- *     that we have proper reference counting logic for urbs.
- *
- * (02/21/2002) SilaS
- *  Added initial support for the Palm m515 devices.
- *
- * (02/14/2002) gkh
- *     Added support for the Clie S-360 device.
- *
- * (12/18/2001) gkh
- *     Added better Clie support for 3.5 devices.  Thanks to Geoffrey Levand
- *     for the patch.
- *
- * (11/11/2001) gkh
- *     Added support for the m125 devices, and added check to prevent oopses
- *     for Clié devices that lie about the number of ports they have.
- *
- * (08/30/2001) gkh
- *     Added support for the Clie devices, both the 3.5 and 4.0 os versions.
- *     Many thanks to Daniel Burke, and Bryan Payne for helping with this.
- *
- * (08/23/2001) gkh
- *     fixed a few potential bugs pointed out by Oliver Neukum.
- *
- * (05/30/2001) gkh
- *     switched from using spinlock to a semaphore, which fixes lots of problems.
- *
- * (05/28/2000) gkh
- *     Added initial support for the Palm m500 and Palm m505 devices.
- *
- * (04/08/2001) gb
- *     Identify version on module load.
- *
- * (01/21/2000) gkh
- *     Added write_room and chars_in_buffer, as they were previously using the
- *     generic driver versions which is all wrong now that we are using an urb
- *     pool.  Thanks to Wolfgang Grandegger for pointing this out to me.
- *     Removed count assignment in the write function, which was not needed anymore
- *     either.  Thanks to Al Borchers for pointing this out.
- *
- * (12/12/2000) gkh
- *     Moved MOD_DEC to end of visor_close to be nicer, as the final write 
- *     message can sleep.
- * 
- * (11/12/2000) gkh
- *     Fixed bug with data being dropped on the floor by forcing tty->low_latency
- *     to be on.  Hopefully this fixes the OHCI issue!
- *
- * (11/01/2000) Adam J. Richter
- *     usb_device_id table support
- * 
- * (10/05/2000) gkh
- *     Fixed bug with urb->dev not being set properly, now that the usb
- *     core needs it.
- * 
- * (09/11/2000) gkh
- *     Got rid of always calling kmalloc for every urb we wrote out to the
- *     device.
- *     Added visor_read_callback so we can keep track of bytes in and out for
- *     those people who like to know the speed of their device.
- *     Removed DEBUG #ifdefs with call to usb_serial_debug_data
- *
- * (09/06/2000) gkh
- *     Fixed oops in visor_exit.  Need to uncomment usb_unlink_urb call _after_
- *     the host controller drivers set urb->dev = NULL when the urb is finished.
- *
- * (08/28/2000) gkh
- *     Added locks for SMP safeness.
- *
- * (08/08/2000) gkh
- *     Fixed endian problem in visor_startup.
- *     Fixed MOD_INC and MOD_DEC logic and the ability to open a port more 
- *     than once.
- * 
- * (07/23/2000) gkh
- *     Added pool of write urbs to speed up transfers to the visor.
- * 
- * (07/19/2000) gkh
- *     Added module_init and module_exit functions to handle the fact that this
- *     driver is a loadable module now.
- *
- * (07/03/2000) gkh
- *     Added visor_set_ioctl and visor_set_termios functions (they don't do much
- *     of anything, but are good for debugging.)
- * 
- * (06/25/2000) gkh
- *     Fixed bug in visor_unthrottle that should help with the disconnect in PPP
- *     bug that people have been reporting.
- *
- * (06/23/2000) gkh
- *     Cleaned up debugging statements in a quest to find UHCI timeout bug.
- *
- * (04/27/2000) Ryan VanderBijl
- *     Fixed memory leak in visor_close
- *
- * (03/26/2000) gkh
- *     Split driver up into device specific pieces.
- * 
  */
 
 #include <linux/config.h>
 /*
  * Version Information
  */
-#define DRIVER_VERSION "v2.1"
 #define DRIVER_AUTHOR "Greg Kroah-Hartman <greg@kroah.com>"
 #define DRIVER_DESC "USB HandSpring Visor / Palm OS driver"
 
@@ -311,10 +181,12 @@ static struct usb_driver visor_driver = {
 };
 
 /* All of the device info needed for the Handspring Visor, and Palm 4.0 devices */
-static struct usb_serial_device_type handspring_device = {
-       .owner =                THIS_MODULE,
-       .name =                 "Handspring Visor / Palm OS",
-       .short_name =           "visor",
+static struct usb_serial_driver handspring_device = {
+       .driver = {
+               .owner =        THIS_MODULE,
+               .name =         "visor",
+       },
+       .description =          "Handspring Visor / Palm OS",
        .id_table =             id_table,
        .num_interrupt_in =     NUM_DONT_CARE,
        .num_bulk_in =          2,
@@ -339,10 +211,12 @@ static struct usb_serial_device_type handspring_device = {
 };
 
 /* All of the device info needed for the Clie UX50, TH55 Palm 5.0 devices */
-static struct usb_serial_device_type clie_5_device = {
-       .owner =                THIS_MODULE,
-       .name =                 "Sony Clie 5.0",
-       .short_name =           "clie_5",
+static struct usb_serial_driver clie_5_device = {
+       .driver = {
+               .owner =        THIS_MODULE,
+               .name =         "clie_5",
+       },
+       .description =          "Sony Clie 5.0",
        .id_table =             clie_id_5_table,
        .num_interrupt_in =     NUM_DONT_CARE,
        .num_bulk_in =          2,
@@ -367,10 +241,12 @@ static struct usb_serial_device_type clie_5_device = {
 };
 
 /* device info for the Sony Clie OS version 3.5 */
-static struct usb_serial_device_type clie_3_5_device = {
-       .owner =                THIS_MODULE,
-       .name =                 "Sony Clie 3.5",
-       .short_name =           "clie_3.5",
+static struct usb_serial_driver clie_3_5_device = {
+       .driver = {
+               .owner =        THIS_MODULE,
+               .name =         "clie_3.5",
+       },
+       .description =          "Sony Clie 3.5",
        .id_table =             clie_id_3_5_table,
        .num_interrupt_in =     0,
        .num_bulk_in =          1,
@@ -782,7 +658,7 @@ static int palm_os_3_probe (struct usb_serial *serial, const struct usb_device_i
                                        break;
                        }
                        dev_info(dev, "%s: port %d, is for %s use\n",
-                               serial->type->name,
+                               serial->type->description,
                                connection_info->connections[i].port, string);
                }
        }
@@ -791,11 +667,11 @@ static int palm_os_3_probe (struct usb_serial *serial, const struct usb_device_i
        */
        if (num_ports == 0 || num_ports > 2) {
                dev_warn (dev, "%s: No valid connect info available\n",
-                       serial->type->name);
+                       serial->type->description);
                num_ports = 2;
        }
   
-       dev_info(dev, "%s: Number of ports: %d\n", serial->type->name,
+       dev_info(dev, "%s: Number of ports: %d\n", serial->type->description,
                num_ports);
 
        /*
@@ -1125,7 +1001,7 @@ static int __init visor_init (void)
        retval = usb_register(&visor_driver);
        if (retval) 
                goto failed_usb_register;
-       info(DRIVER_DESC " " DRIVER_VERSION);
+       info(DRIVER_DESC);
 
        return 0;
 failed_usb_register:
index cf3bc30..18c3183 100644 (file)
@@ -156,10 +156,12 @@ static void whiteheat_unthrottle  (struct usb_serial_port *port);
 static void whiteheat_read_callback    (struct urb *urb, struct pt_regs *regs);
 static void whiteheat_write_callback   (struct urb *urb, struct pt_regs *regs);
 
-static struct usb_serial_device_type whiteheat_fake_device = {
-       .owner =                THIS_MODULE,
-       .name =                 "Connect Tech - WhiteHEAT - (prerenumeration)",
-       .short_name =           "whiteheatnofirm",
+static struct usb_serial_driver whiteheat_fake_device = {
+       .driver = {
+               .owner =        THIS_MODULE,
+               .name =         "whiteheatnofirm",
+       },
+       .description =          "Connect Tech - WhiteHEAT - (prerenumeration)",
        .id_table =             id_table_prerenumeration,
        .num_interrupt_in =     NUM_DONT_CARE,
        .num_bulk_in =          NUM_DONT_CARE,
@@ -169,10 +171,12 @@ static struct usb_serial_device_type whiteheat_fake_device = {
        .attach =               whiteheat_firmware_attach,
 };
 
-static struct usb_serial_device_type whiteheat_device = {
-       .owner =                THIS_MODULE,
-       .name =                 "Connect Tech - WhiteHEAT",
-       .short_name =           "whiteheat",
+static struct usb_serial_driver whiteheat_device = {
+       .driver = {
+               .owner =        THIS_MODULE,
+               .name =         "whiteheat",
+       },
+       .description =          "Connect Tech - WhiteHEAT",
        .id_table =             id_table_std,
        .num_interrupt_in =     NUM_DONT_CARE,
        .num_bulk_in =          NUM_DONT_CARE,
@@ -382,10 +386,10 @@ static int whiteheat_attach (struct usb_serial *serial)
        usb_clear_halt(serial->dev, pipe);
        ret = usb_bulk_msg (serial->dev, pipe, command, 2, &alen, COMMAND_TIMEOUT_MS);
        if (ret) {
-               err("%s: Couldn't send command [%d]", serial->type->name, ret);
+               err("%s: Couldn't send command [%d]", serial->type->description, ret);
                goto no_firmware;
        } else if (alen != sizeof(command)) {
-               err("%s: Send command incomplete [%d]", serial->type->name, alen);
+               err("%s: Send command incomplete [%d]", serial->type->description, alen);
                goto no_firmware;
        }
 
@@ -394,19 +398,19 @@ static int whiteheat_attach (struct usb_serial *serial)
        usb_clear_halt(serial->dev, pipe);
        ret = usb_bulk_msg (serial->dev, pipe, result, sizeof(*hw_info) + 1, &alen, COMMAND_TIMEOUT_MS);
        if (ret) {
-               err("%s: Couldn't get results [%d]", serial->type->name, ret);
+               err("%s: Couldn't get results [%d]", serial->type->description, ret);
                goto no_firmware;
        } else if (alen != sizeof(result)) {
-               err("%s: Get results incomplete [%d]", serial->type->name, alen);
+               err("%s: Get results incomplete [%d]", serial->type->description, alen);
                goto no_firmware;
        } else if (result[0] != command[0]) {
-               err("%s: Command failed [%d]", serial->type->name, result[0]);
+               err("%s: Command failed [%d]", serial->type->description, result[0]);
                goto no_firmware;
        }
 
        hw_info = (struct whiteheat_hw_info *)&result[1];
 
-       info("%s: Driver %s: Firmware v%d.%02d", serial->type->name,
+       info("%s: Driver %s: Firmware v%d.%02d", serial->type->description,
             DRIVER_VERSION, hw_info->sw_major_rev, hw_info->sw_minor_rev);
 
        for (i = 0; i < serial->num_ports; i++) {
@@ -414,7 +418,7 @@ static int whiteheat_attach (struct usb_serial *serial)
 
                info = (struct whiteheat_private *)kmalloc(sizeof(struct whiteheat_private), GFP_KERNEL);
                if (info == NULL) {
-                       err("%s: Out of memory for port structures\n", serial->type->name);
+                       err("%s: Out of memory for port structures\n", serial->type->description);
                        goto no_private;
                }
 
@@ -484,7 +488,7 @@ static int whiteheat_attach (struct usb_serial *serial)
 
        command_info = (struct whiteheat_command_private *)kmalloc(sizeof(struct whiteheat_command_private), GFP_KERNEL);
        if (command_info == NULL) {
-               err("%s: Out of memory for port structures\n", serial->type->name);
+               err("%s: Out of memory for port structures\n", serial->type->description);
                goto no_command_private;
        }
 
@@ -501,9 +505,9 @@ static int whiteheat_attach (struct usb_serial *serial)
 
 no_firmware:
        /* Firmware likely not running */
-       err("%s: Unable to retrieve firmware version, try replugging\n", serial->type->name);
-       err("%s: If the firmware is not running (status led not blinking)\n", serial->type->name);
-       err("%s: please contact support@connecttech.com\n", serial->type->name);
+       err("%s: Unable to retrieve firmware version, try replugging\n", serial->type->description);
+       err("%s: If the firmware is not running (status led not blinking)\n", serial->type->description);
+       err("%s: please contact support@connecttech.com\n", serial->type->description);
        return -ENODEV;
 
 no_command_private:
index bb9819c..1a9679f 100644 (file)
@@ -2,7 +2,8 @@
 # USB Storage driver configuration
 #
 
-comment "NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information"
+comment "NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'"
+comment "may also be needed; see USB_STORAGE Help for more information"
        depends on USB
 
 config USB_STORAGE
index 356342c..33c55a6 100644 (file)
@@ -1,4 +1,4 @@
-/* Driver for SCM Microsystems USB-ATAPI cable
+/* Driver for SCM Microsystems (a.k.a. Shuttle) USB-ATAPI cable
  *
  * $Id: shuttle_usbat.c,v 1.17 2002/04/22 03:39:43 mdharm Exp $
  *
@@ -67,10 +67,10 @@ static int usbat_flash_transport(struct scsi_cmnd * srb, struct us_data *us);
 static int usbat_hp8200e_transport(struct scsi_cmnd *srb, struct us_data *us);
 
 /*
- * Convenience function to produce an ATAPI read/write sectors command
+ * Convenience function to produce an ATA read/write sectors command
  * Use cmd=0x20 for read, cmd=0x30 for write
  */
-static void usbat_pack_atapi_sector_cmd(unsigned char *buf,
+static void usbat_pack_ata_sector_cmd(unsigned char *buf,
                                        unsigned char thistime,
                                        u32 sector, unsigned char cmd)
 {
@@ -196,10 +196,12 @@ static int usbat_check_status(struct us_data *us)
        if (rc != USB_STOR_XFER_GOOD)
                return USB_STOR_TRANSPORT_FAILED;
 
-       if (*reply & 0x01 && *reply != 0x51) // error/check condition (0x51 is ok)
+       /* error/check condition (0x51 is ok) */
+       if (*reply & 0x01 && *reply != 0x51)
                return USB_STOR_TRANSPORT_FAILED;
 
-       if (*reply & 0x20) // device fault
+       /* device fault */
+       if (*reply & 0x20)
                return USB_STOR_TRANSPORT_FAILED;
 
        return USB_STOR_TRANSPORT_GOOD;
@@ -222,29 +224,39 @@ static int usbat_set_shuttle_features(struct us_data *us,
        command[0] = 0x40;
        command[1] = USBAT_CMD_SET_FEAT;
 
-       // The only bit relevant to ATA access is bit 6
-       // which defines 8 bit data access (set) or 16 bit (unset)
+       /*
+        * The only bit relevant to ATA access is bit 6
+        * which defines 8 bit data access (set) or 16 bit (unset)
+        */
        command[2] = epp_control;
 
-       // If FCQ is set in the qualifier (defined in R/W cmd), then bits U0, U1,
-       // ET1 and ET2 define an external event to be checked for on event of a
-       // _read_blocks or _write_blocks operation. The read/write will not take
-       // place unless the defined trigger signal is active.
+       /*
+        * If FCQ is set in the qualifier (defined in R/W cmd), then bits U0, U1,
+        * ET1 and ET2 define an external event to be checked for on event of a
+        * _read_blocks or _write_blocks operation. The read/write will not take
+        * place unless the defined trigger signal is active.
+        */
        command[3] = external_trigger;
 
-       // The resultant byte of the mask operation (see mask_byte) is compared for
-       // equivalence with this test pattern. If equal, the read/write will take
-       // place.
+       /*
+        * The resultant byte of the mask operation (see mask_byte) is compared for
+        * equivalence with this test pattern. If equal, the read/write will take
+        * place.
+        */
        command[4] = test_pattern;
 
-       // This value is logically ANDed with the status register field specified
-       // in the read/write command.
+       /*
+        * This value is logically ANDed with the status register field specified
+        * in the read/write command.
+        */
        command[5] = mask_byte;
 
-       // If ALQ is set in the qualifier, this field contains the address of the
-       // registers where the byte count should be read for transferring the data.
-       // If ALQ is not set, then this field contains the number of bytes to be
-       // transferred.
+       /*
+        * If ALQ is set in the qualifier, this field contains the address of the
+        * registers where the byte count should be read for transferring the data.
+        * If ALQ is not set, then this field contains the number of bytes to be
+        * transferred.
+        */
        command[6] = subcountL;
        command[7] = subcountH;
 
@@ -273,26 +285,26 @@ static int usbat_wait_not_busy(struct us_data *us, int minutes)
 
                if (result!=USB_STOR_XFER_GOOD)
                        return USB_STOR_TRANSPORT_ERROR;
-               if (*status & 0x01) { // check condition
+               if (*status & 0x01) { /* check condition */
                        result = usbat_read(us, USBAT_ATA, 0x10, status);
                        return USB_STOR_TRANSPORT_FAILED;
                }
-               if (*status & 0x20) // device fault
+               if (*status & 0x20) /* device fault */
                        return USB_STOR_TRANSPORT_FAILED;
 
-               if ((*status & 0x80)==0x00) { // not busy
+               if ((*status & 0x80)==0x00) { /* not busy */
                        US_DEBUGP("Waited not busy for %d steps\n", i);
                        return USB_STOR_TRANSPORT_GOOD;
                }
 
                if (i<500)
-                       msleep(10); // 5 seconds
+                       msleep(10); /* 5 seconds */
                else if (i<700)
-                       msleep(50); // 10 seconds
+                       msleep(50); /* 10 seconds */
                else if (i<1200)
-                       msleep(100); // 50 seconds
+                       msleep(100); /* 50 seconds */
                else
-                       msleep(1000); // X minutes
+                       msleep(1000); /* X minutes */
        }
 
        US_DEBUGP("Waited not busy for %d minutes, timing out.\n",
@@ -412,9 +424,12 @@ static int usbat_hp8200e_rw_block_test(struct us_data *us,
 
                if (i==0) {
                        cmdlen = 16;
-                       // Write to multiple registers
-                       // Not really sure the 0x07, 0x17, 0xfc, 0xe7 is necessary here,
-                       // but that's what came out of the trace every single time.
+                       /*
+                        * Write to multiple registers
+                        * Not really sure the 0x07, 0x17, 0xfc, 0xe7 is
+                        * necessary here, but that's what came out of the
+                        * trace every single time.
+                        */
                        command[0] = 0x40;
                        command[1] = access | USBAT_CMD_WRITE_REGS;
                        command[2] = 0x07;
@@ -426,7 +441,7 @@ static int usbat_hp8200e_rw_block_test(struct us_data *us,
                } else
                        cmdlen = 8;
 
-               // Conditionally read or write blocks
+               /* Conditionally read or write blocks */
                command[cmdlen-8] = (direction==DMA_TO_DEVICE ? 0x40 : 0xC0);
                command[cmdlen-7] = access |
                                (direction==DMA_TO_DEVICE ?
@@ -456,11 +471,6 @@ static int usbat_hp8200e_rw_block_test(struct us_data *us,
 
                }
 
-
-               //US_DEBUGP("Transfer %s %d bytes, sg buffers %d\n",
-               //      direction == DMA_TO_DEVICE ? "out" : "in",
-               //      len, use_sg);
-
                result = usb_stor_bulk_transfer_sg(us,
                        pipe, content, len, use_sg, NULL);
 
@@ -508,9 +518,9 @@ static int usbat_hp8200e_rw_block_test(struct us_data *us,
 
                        if (result!=USB_STOR_XFER_GOOD)
                                return USB_STOR_TRANSPORT_ERROR;
-                       if (*status & 0x01) // check condition
+                       if (*status & 0x01) /* check condition */
                                return USB_STOR_TRANSPORT_FAILED;
-                       if (*status & 0x20) // device fault
+                       if (*status & 0x20) /* device fault */
                                return USB_STOR_TRANSPORT_FAILED;
 
                        US_DEBUGP("Redoing %s\n",
@@ -547,32 +557,32 @@ static int usbat_multiple_write(struct us_data *us,
 
        BUG_ON(num_registers > US_IOBUF_SIZE/2);
 
-       // Write to multiple registers, ATA access
+       /* Write to multiple registers, ATA access */
        command[0] = 0x40;
        command[1] = USBAT_ATA | USBAT_CMD_WRITE_REGS;
 
-       // No relevance
+       /* No relevance */
        command[2] = 0;
        command[3] = 0;
        command[4] = 0;
        command[5] = 0;
 
-       // Number of bytes to be transferred (incl. addresses and data)
+       /* Number of bytes to be transferred (incl. addresses and data) */
        command[6] = LSB_of(num_registers*2);
        command[7] = MSB_of(num_registers*2);
 
-       // The setup command
+       /* The setup command */
        result = usbat_execute_command(us, command, 8);
        if (result != USB_STOR_XFER_GOOD)
                return USB_STOR_TRANSPORT_ERROR;
 
-       // Create the reg/data, reg/data sequence
+       /* Create the reg/data, reg/data sequence */
        for (i=0; i<num_registers; i++) {
                data[i<<1] = registers[i];
                data[1+(i<<1)] = data_out[i];
        }
 
-       // Send the data
+       /* Send the data */
        result = usbat_bulk_write(us, data, num_registers*2);
        if (result != USB_STOR_XFER_GOOD)
                return USB_STOR_TRANSPORT_ERROR;
@@ -606,17 +616,17 @@ static int usbat_read_blocks(struct us_data *us,
        command[1] = USBAT_ATA | USBAT_CMD_COND_READ_BLOCK;
        command[2] = USBAT_ATA_DATA;
        command[3] = USBAT_ATA_STATUS;
-       command[4] = 0xFD; // Timeout (ms);
+       command[4] = 0xFD; /* Timeout (ms); */
        command[5] = USBAT_QUAL_FCQ;
        command[6] = LSB_of(len);
        command[7] = MSB_of(len);
 
-       // Multiple block read setup command
+       /* Multiple block read setup command */
        result = usbat_execute_command(us, command, 8);
        if (result != USB_STOR_XFER_GOOD)
                return USB_STOR_TRANSPORT_FAILED;
        
-       // Read the blocks we just asked for
+       /* Read the blocks we just asked for */
        result = usbat_bulk_read(us, buffer, len);
        if (result != USB_STOR_XFER_GOOD)
                return USB_STOR_TRANSPORT_FAILED;
@@ -647,17 +657,17 @@ static int usbat_write_blocks(struct us_data *us,
        command[1] = USBAT_ATA | USBAT_CMD_COND_WRITE_BLOCK;
        command[2] = USBAT_ATA_DATA;
        command[3] = USBAT_ATA_STATUS;
-       command[4] = 0xFD; // Timeout (ms)
+       command[4] = 0xFD; /* Timeout (ms) */
        command[5] = USBAT_QUAL_FCQ;
        command[6] = LSB_of(len);
        command[7] = MSB_of(len);
 
-       // Multiple block write setup command
+       /* Multiple block write setup command */
        result = usbat_execute_command(us, command, 8);
        if (result != USB_STOR_XFER_GOOD)
                return USB_STOR_TRANSPORT_FAILED;
        
-       // Write the data
+       /* Write the data */
        result = usbat_bulk_write(us, buffer, len);
        if (result != USB_STOR_XFER_GOOD)
                return USB_STOR_TRANSPORT_FAILED;
@@ -711,16 +721,20 @@ static int usbat_device_reset(struct us_data *us)
 {
        int rc;
 
-       // Reset peripheral, enable peripheral control signals
-       // (bring reset signal up)
+       /*
+        * Reset peripheral, enable peripheral control signals
+        * (bring reset signal up)
+        */
        rc = usbat_write_user_io(us,
                                                         USBAT_UIO_DRVRST | USBAT_UIO_OE1 | USBAT_UIO_OE0,
                                                         USBAT_UIO_EPAD | USBAT_UIO_1);
        if (rc != USB_STOR_XFER_GOOD)
                return USB_STOR_TRANSPORT_ERROR;
                        
-       // Enable peripheral control signals
-       // (bring reset signal down)
+       /*
+        * Enable peripheral control signals
+        * (bring reset signal down)
+        */
        rc = usbat_write_user_io(us,
                                                         USBAT_UIO_OE1  | USBAT_UIO_OE0,
                                                         USBAT_UIO_EPAD | USBAT_UIO_1);
@@ -737,7 +751,7 @@ static int usbat_device_enable_cdt(struct us_data *us)
 {
        int rc;
 
-       // Enable peripheral control signals and card detect
+       /* Enable peripheral control signals and card detect */
        rc = usbat_write_user_io(us,
                                                         USBAT_UIO_ACKD | USBAT_UIO_OE1  | USBAT_UIO_OE0,
                                                         USBAT_UIO_EPAD | USBAT_UIO_1);
@@ -786,7 +800,7 @@ static int usbat_flash_check_media(struct us_data *us,
        if (rc != USB_STOR_XFER_GOOD)
                return USB_STOR_TRANSPORT_ERROR;
 
-       // Check for media existence
+       /* Check for media existence */
        rc = usbat_flash_check_media_present(uio);
        if (rc == USBAT_FLASH_MEDIA_NONE) {
                info->sense_key = 0x02;
@@ -795,11 +809,11 @@ static int usbat_flash_check_media(struct us_data *us,
                return USB_STOR_TRANSPORT_FAILED;
        }
 
-       // Check for media change
+       /* Check for media change */
        rc = usbat_flash_check_media_changed(uio);
        if (rc == USBAT_FLASH_MEDIA_CHANGED) {
 
-               // Reset and re-enable card detect
+               /* Reset and re-enable card detect */
                rc = usbat_device_reset(us);
                if (rc != USB_STOR_TRANSPORT_GOOD)
                        return rc;
@@ -855,15 +869,15 @@ static int usbat_identify_device(struct us_data *us,
        if (rc != USB_STOR_XFER_GOOD)
                return USB_STOR_TRANSPORT_ERROR;
 
-       // Check for error bit
-       if (status & 0x01) {
-                // Device is a CompactFlash reader/writer
-               US_DEBUGP("usbat_identify_device: Detected Flash reader/writer\n");
-               info->devicetype = USBAT_DEV_FLASH;
-       } else {
-               // Device is HP 8200
+       /* Check for error bit, or if the command 'fell through' */
+       if (status == 0xA1 || !(status & 0x01)) {
+               /* Device is HP 8200 */
                US_DEBUGP("usbat_identify_device: Detected HP8200 CDRW\n");
                info->devicetype = USBAT_DEV_HP8200;
+       } else {
+               /* Device is a CompactFlash reader/writer */
+               US_DEBUGP("usbat_identify_device: Detected Flash reader/writer\n");
+               info->devicetype = USBAT_DEV_FLASH;
        }
 
        return USB_STOR_TRANSPORT_GOOD;
@@ -916,7 +930,7 @@ static int usbat_flash_get_sector_count(struct us_data *us,
        if (!reply)
                return USB_STOR_TRANSPORT_ERROR;
 
-       // ATAPI command : IDENTIFY DEVICE
+       /* ATA command : IDENTIFY DEVICE */
        rc = usbat_multiple_write(us, registers, command, 3);
        if (rc != USB_STOR_XFER_GOOD) {
                US_DEBUGP("usbat_flash_get_sector_count: Gah! identify_device failed\n");
@@ -924,7 +938,7 @@ static int usbat_flash_get_sector_count(struct us_data *us,
                goto leave;
        }
 
-       // Read device status
+       /* Read device status */
        if (usbat_get_status(us, &status) != USB_STOR_XFER_GOOD) {
                rc = USB_STOR_TRANSPORT_ERROR;
                goto leave;
@@ -932,7 +946,7 @@ static int usbat_flash_get_sector_count(struct us_data *us,
 
        msleep(100);
 
-       // Read the device identification data
+       /* Read the device identification data */
        rc = usbat_read_block(us, reply, 512);
        if (rc != USB_STOR_TRANSPORT_GOOD)
                goto leave;
@@ -977,19 +991,23 @@ static int usbat_flash_read_data(struct us_data *us,
        if (result != USB_STOR_TRANSPORT_GOOD)
                return result;
 
-       // we're working in LBA mode.  according to the ATA spec,
-       // we can support up to 28-bit addressing.  I don't know if Jumpshot
-       // supports beyond 24-bit addressing.  It's kind of hard to test
-       // since it requires > 8GB CF card.
+       /*
+        * we're working in LBA mode.  according to the ATA spec,
+        * we can support up to 28-bit addressing.  I don't know if Jumpshot
+        * supports beyond 24-bit addressing.  It's kind of hard to test
+        * since it requires > 8GB CF card.
+        */
 
        if (sector > 0x0FFFFFFF)
                return USB_STOR_TRANSPORT_ERROR;
 
        totallen = sectors * info->ssize;
 
-       // Since we don't read more than 64 KB at a time, we have to create
-       // a bounce buffer and move the data a piece at a time between the
-       // bounce buffer and the actual transfer buffer.
+       /*
+        * Since we don't read more than 64 KB at a time, we have to create
+        * a bounce buffer and move the data a piece at a time between the
+        * bounce buffer and the actual transfer buffer.
+        */
 
        alloclen = min(totallen, 65536u);
        buffer = kmalloc(alloclen, GFP_NOIO);
@@ -997,27 +1015,29 @@ static int usbat_flash_read_data(struct us_data *us,
                return USB_STOR_TRANSPORT_ERROR;
 
        do {
-               // loop, never allocate or transfer more than 64k at once
-               // (min(128k, 255*info->ssize) is the real limit)
+               /*
+                * loop, never allocate or transfer more than 64k at once
+                * (min(128k, 255*info->ssize) is the real limit)
+                */
                len = min(totallen, alloclen);
                thistime = (len / info->ssize) & 0xff;
  
-               // ATAPI command 0x20 (READ SECTORS)
-               usbat_pack_atapi_sector_cmd(command, thistime, sector, 0x20);
+               /* ATA command 0x20 (READ SECTORS) */
+               usbat_pack_ata_sector_cmd(command, thistime, sector, 0x20);
 
-               // Write/execute ATAPI read command
+               /* Write/execute ATA read command */
                result = usbat_multiple_write(us, registers, command, 7);
                if (result != USB_STOR_TRANSPORT_GOOD)
                        goto leave;
 
-               // Read the data we just requested
+               /* Read the data we just requested */
                result = usbat_read_blocks(us, buffer, len);
                if (result != USB_STOR_TRANSPORT_GOOD)
                        goto leave;
         
                US_DEBUGP("usbat_flash_read_data:  %d bytes\n", len);
        
-               // Store the data in the transfer buffer
+               /* Store the data in the transfer buffer */
                usb_stor_access_xfer_buf(buffer, len, us->srb,
                                         &sg_idx, &sg_offset, TO_XFER_BUF);
 
@@ -1061,19 +1081,23 @@ static int usbat_flash_write_data(struct us_data *us,
        if (result != USB_STOR_TRANSPORT_GOOD)
                return result;
 
-       // we're working in LBA mode.  according to the ATA spec,
-       // we can support up to 28-bit addressing.  I don't know if Jumpshot
-       // supports beyond 24-bit addressing.  It's kind of hard to test
-       // since it requires > 8GB CF card.
+       /*
+        * we're working in LBA mode.  according to the ATA spec,
+        * we can support up to 28-bit addressing.  I don't know if the device
+        * supports beyond 24-bit addressing.  It's kind of hard to test
+        * since it requires > 8GB media.
+        */
 
        if (sector > 0x0FFFFFFF)
                return USB_STOR_TRANSPORT_ERROR;
 
        totallen = sectors * info->ssize;
 
-       // Since we don't write more than 64 KB at a time, we have to create
-       // a bounce buffer and move the data a piece at a time between the
-       // bounce buffer and the actual transfer buffer.
+       /*
+        * Since we don't write more than 64 KB at a time, we have to create
+        * a bounce buffer and move the data a piece at a time between the
+        * bounce buffer and the actual transfer buffer.
+        */
 
        alloclen = min(totallen, 65536u);
        buffer = kmalloc(alloclen, GFP_NOIO);
@@ -1081,24 +1105,26 @@ static int usbat_flash_write_data(struct us_data *us,
                return USB_STOR_TRANSPORT_ERROR;
 
        do {
-               // loop, never allocate or transfer more than 64k at once
-               // (min(128k, 255*info->ssize) is the real limit)
+               /*
+                * loop, never allocate or transfer more than 64k at once
+                * (min(128k, 255*info->ssize) is the real limit)
+                */
                len = min(totallen, alloclen);
                thistime = (len / info->ssize) & 0xff;
 
-               // Get the data from the transfer buffer
+               /* Get the data from the transfer buffer */
                usb_stor_access_xfer_buf(buffer, len, us->srb,
                                         &sg_idx, &sg_offset, FROM_XFER_BUF);
 
-               // ATAPI command 0x30 (WRITE SECTORS)
-               usbat_pack_atapi_sector_cmd(command, thistime, sector, 0x30);           
+               /* ATA command 0x30 (WRITE SECTORS) */
+               usbat_pack_ata_sector_cmd(command, thistime, sector, 0x30);
 
-               // Write/execute ATAPI write command
+               /* Write/execute ATA write command */
                result = usbat_multiple_write(us, registers, command, 7);
                if (result != USB_STOR_TRANSPORT_GOOD)
                        goto leave;
 
-               // Write the data
+               /* Write the data */
                result = usbat_write_blocks(us, buffer, len);
                if (result != USB_STOR_TRANSPORT_GOOD)
                        goto leave;
@@ -1169,42 +1195,44 @@ static int usbat_hp8200e_handle_read10(struct us_data *us,
                        srb->transfersize);
        }
 
-       // Since we only read in one block at a time, we have to create
-       // a bounce buffer and move the data a piece at a time between the
-       // bounce buffer and the actual transfer buffer.
+       /*
+        * Since we only read in one block at a time, we have to create
+        * a bounce buffer and move the data a piece at a time between the
+        * bounce buffer and the actual transfer buffer.
+        */
 
        len = (65535/srb->transfersize) * srb->transfersize;
        US_DEBUGP("Max read is %d bytes\n", len);
        len = min(len, srb->request_bufflen);
        buffer = kmalloc(len, GFP_NOIO);
-       if (buffer == NULL) // bloody hell!
+       if (buffer == NULL) /* bloody hell! */
                return USB_STOR_TRANSPORT_FAILED;
        sector = short_pack(data[7+3], data[7+2]);
        sector <<= 16;
        sector |= short_pack(data[7+5], data[7+4]);
        transferred = 0;
 
-       sg_segment = 0; // for keeping track of where we are in
-       sg_offset = 0;  // the scatter/gather list
+       sg_segment = 0; /* for keeping track of where we are in */
+       sg_offset = 0;  /* the scatter/gather list */
 
        while (transferred != srb->request_bufflen) {
 
                if (len > srb->request_bufflen - transferred)
                        len = srb->request_bufflen - transferred;
 
-               data[3] = len&0xFF;       // (cylL) = expected length (L)
-               data[4] = (len>>8)&0xFF;  // (cylH) = expected length (H)
+               data[3] = len&0xFF;       /* (cylL) = expected length (L) */
+               data[4] = (len>>8)&0xFF;  /* (cylH) = expected length (H) */
 
-               // Fix up the SCSI command sector and num sectors
+               /* Fix up the SCSI command sector and num sectors */
 
-               data[7+2] = MSB_of(sector>>16); // SCSI command sector
+               data[7+2] = MSB_of(sector>>16); /* SCSI command sector */
                data[7+3] = LSB_of(sector>>16);
                data[7+4] = MSB_of(sector&0xFFFF);
                data[7+5] = LSB_of(sector&0xFFFF);
                if (data[7+0] == GPCMD_READ_CD)
                        data[7+6] = 0;
-               data[7+7] = MSB_of(len / srb->transfersize); // SCSI command
-               data[7+8] = LSB_of(len / srb->transfersize); // num sectors
+               data[7+7] = MSB_of(len / srb->transfersize); /* SCSI command */
+               data[7+8] = LSB_of(len / srb->transfersize); /* num sectors */
 
                result = usbat_hp8200e_rw_block_test(us, USBAT_ATA, 
                        registers, data, 19,
@@ -1217,16 +1245,16 @@ static int usbat_hp8200e_handle_read10(struct us_data *us,
                if (result != USB_STOR_TRANSPORT_GOOD)
                        break;
 
-               // Store the data in the transfer buffer
+               /* Store the data in the transfer buffer */
                usb_stor_access_xfer_buf(buffer, len, srb,
                                 &sg_segment, &sg_offset, TO_XFER_BUF);
 
-               // Update the amount transferred and the sector number
+               /* Update the amount transferred and the sector number */
 
                transferred += len;
                sector += len / srb->transfersize;
 
-       } // while transferred != srb->request_bufflen
+       } /* while transferred != srb->request_bufflen */
 
        kfree(buffer);
        return result;
@@ -1237,7 +1265,7 @@ static int usbat_select_and_test_registers(struct us_data *us)
        int selector;
        unsigned char *status = us->iobuf;
 
-       // try device = master, then device = slave.
+       /* try device = master, then device = slave. */
        for (selector = 0xA0; selector <= 0xB0; selector += 0x10) {
                if (usbat_write(us, USBAT_ATA, USBAT_ATA_DEVICE, selector) !=
                                USB_STOR_XFER_GOOD)
@@ -1298,7 +1326,7 @@ int init_usbat(struct us_data *us)
        memset(us->extra, 0, sizeof(struct usbat_info));
        info = (struct usbat_info *) (us->extra);
 
-       // Enable peripheral control signals
+       /* Enable peripheral control signals */
        rc = usbat_write_user_io(us,
                                 USBAT_UIO_OE1 | USBAT_UIO_OE0,
                                 USBAT_UIO_EPAD | USBAT_UIO_1);
@@ -1337,7 +1365,7 @@ int init_usbat(struct us_data *us)
 
        US_DEBUGP("INIT 5\n");
 
-       // Enable peripheral control signals and card detect
+       /* Enable peripheral control signals and card detect */
        rc = usbat_device_enable_cdt(us);
        if (rc != USB_STOR_TRANSPORT_GOOD)
                return rc;
@@ -1364,7 +1392,7 @@ int init_usbat(struct us_data *us)
 
        US_DEBUGP("INIT 9\n");
 
-       // At this point, we need to detect which device we are using
+       /* At this point, we need to detect which device we are using */
        if (usbat_set_transport(us, info))
                return USB_STOR_TRANSPORT_ERROR;
 
@@ -1414,10 +1442,10 @@ static int usbat_hp8200e_transport(struct scsi_cmnd *srb, struct us_data *us)
        data[0] = 0x00;
        data[1] = 0x00;
        data[2] = 0x00;
-       data[3] = len&0xFF;             // (cylL) = expected length (L)
-       data[4] = (len>>8)&0xFF;        // (cylH) = expected length (H)
-       data[5] = 0xB0;                 // (device sel) = slave
-       data[6] = 0xA0;                 // (command) = ATA PACKET COMMAND
+       data[3] = len&0xFF;             /* (cylL) = expected length (L) */
+       data[4] = (len>>8)&0xFF;        /* (cylH) = expected length (H) */
+       data[5] = 0xB0;                 /* (device sel) = slave */
+       data[6] = 0xA0;                 /* (command) = ATA PACKET COMMAND */
 
        for (i=7; i<19; i++) {
                registers[i] = 0x10;
@@ -1466,13 +1494,15 @@ static int usbat_hp8200e_transport(struct scsi_cmnd *srb, struct us_data *us)
                return result;
        }
 
-       // Write the 12-byte command header.
-
-       // If the command is BLANK then set the timer for 75 minutes.
-       // Otherwise set it for 10 minutes.
-
-       // NOTE: THE 8200 DOCUMENTATION STATES THAT BLANKING A CDRW
-       // AT SPEED 4 IS UNRELIABLE!!!
+       /*
+        * Write the 12-byte command header.
+        *
+        * If the command is BLANK then set the timer for 75 minutes.
+        * Otherwise set it for 10 minutes.
+        *
+        * NOTE: THE 8200 DOCUMENTATION STATES THAT BLANKING A CDRW
+        * AT SPEED 4 IS UNRELIABLE!!!
+        */
 
        if ( (result = usbat_write_block(us, 
                        USBAT_ATA, srb->cmnd, 12,
@@ -1481,19 +1511,18 @@ static int usbat_hp8200e_transport(struct scsi_cmnd *srb, struct us_data *us)
                return result;
        }
 
-       // If there is response data to be read in 
-       // then do it here.
+       /* If there is response data to be read in then do it here. */
 
        if (len != 0 && (srb->sc_data_direction == DMA_FROM_DEVICE)) {
 
-               // How many bytes to read in? Check cylL register
+               /* How many bytes to read in? Check cylL register */
 
                if (usbat_read(us, USBAT_ATA, USBAT_ATA_LBA_ME, status) != 
                        USB_STOR_XFER_GOOD) {
                        return USB_STOR_TRANSPORT_ERROR;
                }
 
-               if (len > 0xFF) { // need to read cylH also
+               if (len > 0xFF) { /* need to read cylH also */
                        len = *status;
                        if (usbat_read(us, USBAT_ATA, USBAT_ATA_LBA_HI, status) !=
                                    USB_STOR_XFER_GOOD) {
@@ -1556,13 +1585,16 @@ static int usbat_flash_transport(struct scsi_cmnd * srb, struct us_data *us)
                if (rc != USB_STOR_TRANSPORT_GOOD)
                        return rc;
 
-               info->ssize = 0x200;  // hard coded 512 byte sectors as per ATA spec
+               /* hard coded 512 byte sectors as per ATA spec */
+               info->ssize = 0x200;
                US_DEBUGP("usbat_flash_transport: READ_CAPACITY: %ld sectors, %ld bytes per sector\n",
                          info->sectors, info->ssize);
 
-               // build the reply
-               // note: must return the sector number of the last sector,
-               // *not* the total number of sectors
+               /*
+                * build the reply
+                * note: must return the sector number of the last sector,
+                * *not* the total number of sectors
+                */
                ((__be32 *) ptr)[0] = cpu_to_be32(info->sectors - 1);
                ((__be32 *) ptr)[1] = cpu_to_be32(info->ssize);
                usb_stor_set_xfer_buf(ptr, 8, srb);
@@ -1586,7 +1618,9 @@ static int usbat_flash_transport(struct scsi_cmnd * srb, struct us_data *us)
        }
 
        if (srb->cmnd[0] == READ_12) {
-               // I don't think we'll ever see a READ_12 but support it anyway...
+               /*
+                * I don't think we'll ever see a READ_12 but support it anyway
+                */
                block = ((u32)(srb->cmnd[2]) << 24) | ((u32)(srb->cmnd[3]) << 16) |
                        ((u32)(srb->cmnd[4]) <<  8) | ((u32)(srb->cmnd[5]));
 
@@ -1608,7 +1642,9 @@ static int usbat_flash_transport(struct scsi_cmnd * srb, struct us_data *us)
        }
 
        if (srb->cmnd[0] == WRITE_12) {
-               // I don't think we'll ever see a WRITE_12 but support it anyway...
+               /*
+                * I don't think we'll ever see a WRITE_12 but support it anyway
+                */
                block = ((u32)(srb->cmnd[2]) << 24) | ((u32)(srb->cmnd[3]) << 16) |
                        ((u32)(srb->cmnd[4]) <<  8) | ((u32)(srb->cmnd[5]));
 
@@ -1645,8 +1681,10 @@ static int usbat_flash_transport(struct scsi_cmnd * srb, struct us_data *us)
        }
 
        if (srb->cmnd[0] == ALLOW_MEDIUM_REMOVAL) {
-               // sure.  whatever.  not like we can stop the user from popping
-               // the media out of the device (no locking doors, etc)
+               /*
+                * sure.  whatever.  not like we can stop the user from popping
+                * the media out of the device (no locking doors, etc)
+                */
                return USB_STOR_TRANSPORT_GOOD;
        }
 
index 5b8e867..25e7d8b 100644 (file)
@@ -55,8 +55,8 @@
 #define USBAT_UIO_WRITE        0
 
 /* Qualifier bits */
-#define USBAT_QUAL_FCQ 0x20 // full compare
-#define USBAT_QUAL_ALQ 0x10 // auto load subcount
+#define USBAT_QUAL_FCQ 0x20    /* full compare */
+#define USBAT_QUAL_ALQ 0x10    /* auto load subcount */
 
 /* USBAT Flash Media status types */
 #define USBAT_FLASH_MEDIA_NONE 0
 #define USBAT_FLASH_MEDIA_CHANGED      1
 
 /* USBAT ATA registers */
-#define USBAT_ATA_DATA      0x10  // read/write data (R/W)
-#define USBAT_ATA_FEATURES  0x11  // set features (W)
-#define USBAT_ATA_ERROR     0x11  // error (R)
-#define USBAT_ATA_SECCNT    0x12  // sector count (R/W)
-#define USBAT_ATA_SECNUM    0x13  // sector number (R/W)
-#define USBAT_ATA_LBA_ME    0x14  // cylinder low (R/W)
-#define USBAT_ATA_LBA_HI    0x15  // cylinder high (R/W)
-#define USBAT_ATA_DEVICE    0x16  // head/device selection (R/W)
-#define USBAT_ATA_STATUS    0x17  // device status (R)
-#define USBAT_ATA_CMD       0x17  // device command (W)
-#define USBAT_ATA_ALTSTATUS 0x0E  // status (no clear IRQ) (R)
+#define USBAT_ATA_DATA      0x10  /* read/write data (R/W) */
+#define USBAT_ATA_FEATURES  0x11  /* set features (W) */
+#define USBAT_ATA_ERROR     0x11  /* error (R) */
+#define USBAT_ATA_SECCNT    0x12  /* sector count (R/W) */
+#define USBAT_ATA_SECNUM    0x13  /* sector number (R/W) */
+#define USBAT_ATA_LBA_ME    0x14  /* cylinder low (R/W) */
+#define USBAT_ATA_LBA_HI    0x15  /* cylinder high (R/W) */
+#define USBAT_ATA_DEVICE    0x16  /* head/device selection (R/W) */
+#define USBAT_ATA_STATUS    0x17  /* device status (R) */
+#define USBAT_ATA_CMD       0x17  /* device command (W) */
+#define USBAT_ATA_ALTSTATUS 0x0E  /* status (no clear IRQ) (R) */
 
 /* USBAT User I/O Data registers */
-#define USBAT_UIO_EPAD         0x80 // Enable Peripheral Control Signals
-#define USBAT_UIO_CDT          0x40 // Card Detect (Read Only)
-                                    // CDT = ACKD & !UI1 & !UI0
-#define USBAT_UIO_1            0x20 // I/O 1
-#define USBAT_UIO_0            0x10 // I/O 0
-#define USBAT_UIO_EPP_ATA      0x08 // 1=EPP mode, 0=ATA mode
-#define USBAT_UIO_UI1          0x04 // Input 1
-#define USBAT_UIO_UI0          0x02 // Input 0
-#define USBAT_UIO_INTR_ACK     0x01 // Interrupt (ATA & ISA)/Acknowledge (EPP)
+#define USBAT_UIO_EPAD         0x80 /* Enable Peripheral Control Signals */
+#define USBAT_UIO_CDT          0x40 /* Card Detect (Read Only) */
+                                    /* CDT = ACKD & !UI1 & !UI0 */
+#define USBAT_UIO_1            0x20 /* I/O 1 */
+#define USBAT_UIO_0            0x10 /* I/O 0 */
+#define USBAT_UIO_EPP_ATA      0x08 /* 1=EPP mode, 0=ATA mode */
+#define USBAT_UIO_UI1          0x04 /* Input 1 */
+#define USBAT_UIO_UI0          0x02 /* Input 0 */
+#define USBAT_UIO_INTR_ACK     0x01 /* Interrupt (ATA/ISA)/Acknowledge (EPP) */
 
 /* USBAT User I/O Enable registers */
-#define USBAT_UIO_DRVRST       0x80 // Reset Peripheral
-#define USBAT_UIO_ACKD         0x40 // Enable Card Detect
-#define USBAT_UIO_OE1          0x20 // I/O 1 set=output/clr=input
-                                    // If ACKD=1, set OE1 to 1 also.
-#define USBAT_UIO_OE0          0x10 // I/O 0 set=output/clr=input
-#define USBAT_UIO_ADPRST       0x01 // Reset SCM chip
+#define USBAT_UIO_DRVRST       0x80 /* Reset Peripheral */
+#define USBAT_UIO_ACKD         0x40 /* Enable Card Detect */
+#define USBAT_UIO_OE1          0x20 /* I/O 1 set=output/clr=input */
+                                    /* If ACKD=1, set OE1 to 1 also. */
+#define USBAT_UIO_OE0          0x10 /* I/O 0 set=output/clr=input */
+#define USBAT_UIO_ADPRST       0x01 /* Reset SCM chip */
 
 /* USBAT Features */
-#define USBAT_FEAT_ETEN        0x80 // External trigger enable
+#define USBAT_FEAT_ETEN        0x80    /* External trigger enable */
 #define USBAT_FEAT_U1  0x08
 #define USBAT_FEAT_U0  0x04
 #define USBAT_FEAT_ET1 0x02
@@ -112,12 +112,12 @@ struct usbat_info {
        int devicetype;
 
        /* Used for Flash readers only */
-       unsigned long sectors;     // total sector count
-       unsigned long ssize;       // sector size in bytes
+       unsigned long sectors;     /* total sector count */
+       unsigned long ssize;       /* sector size in bytes */
 
        unsigned char sense_key;
-       unsigned long sense_asc;   // additional sense code
-       unsigned long sense_ascq;  // additional sense code qualifier
+       unsigned long sense_asc;   /* additional sense code */
+       unsigned long sense_ascq;  /* additional sense code qualifier */
 };
 
 #endif
index c1ba530..7ca896a 100644 (file)
@@ -636,11 +636,11 @@ void usb_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us)
 
                /* use the new buffer we have */
                old_request_buffer = srb->request_buffer;
-               srb->request_buffer = srb->sense_buffer;
+               srb->request_buffer = us->sensebuf;
 
                /* set the buffer length for transfer */
                old_request_bufflen = srb->request_bufflen;
-               srb->request_bufflen = 18;
+               srb->request_bufflen = US_SENSE_SIZE;
 
                /* set up for no scatter-gather use */
                old_sg = srb->use_sg;
@@ -652,6 +652,7 @@ void usb_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us)
                temp_result = us->transport(us->srb, us);
 
                /* let's clean up right away */
+               memcpy(srb->sense_buffer, us->sensebuf, US_SENSE_SIZE);
                srb->resid = old_resid;
                srb->request_buffer = old_request_buffer;
                srb->request_bufflen = old_request_bufflen;
@@ -923,6 +924,7 @@ int usb_stor_Bulk_max_lun(struct us_data *us)
        int result;
 
        /* issue the command */
+       us->iobuf[0] = 0;
        result = usb_stor_control_msg(us, us->recv_ctrl_pipe,
                                 US_BULK_GET_MAX_LUN, 
                                 USB_DIR_IN | USB_TYPE_CLASS | 
index 8d9e066..0a362cc 100644 (file)
@@ -50,7 +50,7 @@
 #define US_PR_CB       0x01            /* Control/Bulk w/o interrupt */
 #define US_PR_BULK     0x50            /* bulk only */
 #ifdef CONFIG_USB_STORAGE_USBAT
-#define US_PR_SCM_ATAPI        0x80            /* SCM-ATAPI bridge */
+#define US_PR_USBAT    0x80            /* SCM-ATAPI bridge */
 #endif
 #ifdef CONFIG_USB_STORAGE_SDDR09
 #define US_PR_EUSB_SDDR09      0x81    /* SCM-SCSI bridge for SDDR-09 */
index b79dad1..9e926a8 100644 (file)
@@ -71,12 +71,12 @@ UNUSUAL_DEV(  0x03f0, 0x0107, 0x0200, 0x0200,
 UNUSUAL_DEV(  0x03f0, 0x0207, 0x0001, 0x0001, 
                "HP",
                "CD-Writer+ 8200e",
-               US_SC_8070, US_PR_SCM_ATAPI, init_usbat, 0), 
+               US_SC_8070, US_PR_USBAT, init_usbat, 0),
 
 UNUSUAL_DEV(  0x03f0, 0x0307, 0x0001, 0x0001, 
                "HP",
                "CD-Writer+ CD-4e",
-               US_SC_8070, US_PR_SCM_ATAPI, init_usbat, 0), 
+               US_SC_8070, US_PR_USBAT, init_usbat, 0),
 #endif
 
 /* Patch submitted by Mihnea-Costin Grigore <mihnea@zulu.ro> */
@@ -106,6 +106,13 @@ UNUSUAL_DEV(  0x0411, 0x001c, 0x0113, 0x0113,
                US_SC_DEVICE, US_PR_DEVICE, NULL,
                US_FL_FIX_INQUIRY ),
 
+/* Reported by Stefan Werner <dustbln@gmx.de> */
+UNUSUAL_DEV(  0x0419, 0xaaf6, 0x0100, 0x0100,
+               "TrekStor",
+               "i.Beat Joy 2.0",
+               US_SC_DEVICE, US_PR_DEVICE, NULL,
+               US_FL_IGNORE_RESIDUE ),
+
 /* Reported by Olaf Hering <olh@suse.de> from novell bug #105878 */
 UNUSUAL_DEV(  0x0424, 0x0fdc, 0x0210, 0x0210,
                "SMSC",
@@ -244,6 +251,13 @@ UNUSUAL_DEV(  0x04da, 0x2372, 0x0000, 0x9999,
                US_SC_DEVICE, US_PR_DEVICE, NULL,
                US_FL_FIX_CAPACITY | US_FL_NOT_LOCKABLE ),
 
+/* Reported by Simeon Simeonov <simeonov_2000@yahoo.com> */
+UNUSUAL_DEV(  0x04da, 0x2373, 0x0000, 0x9999,
+               "LEICA",
+               "D-LUX Camera",
+               US_SC_DEVICE, US_PR_DEVICE, NULL,
+               US_FL_FIX_CAPACITY | US_FL_NOT_LOCKABLE ),
+
 /* Most of the following entries were developed with the help of
  * Shuttle/SCM directly.
  */
@@ -333,9 +347,9 @@ UNUSUAL_DEV(  0x04fc, 0x80c2, 0x0100, 0x0100,
 
 #ifdef CONFIG_USB_STORAGE_USBAT
 UNUSUAL_DEV(  0x04e6, 0x1010, 0x0000, 0x9999,
-               "SCM",
-               "SCM USBAT-02",
-               US_SC_SCSI, US_PR_SCM_ATAPI, init_usbat,
+               "Shuttle/SCM",
+               "USBAT-02",
+               US_SC_SCSI, US_PR_USBAT, init_usbat,
                US_FL_SINGLE_LUN),
 #endif
 
@@ -598,6 +612,16 @@ UNUSUAL_DEV( 0x05ac, 0x1205, 0x0000, 0x9999,
                US_SC_DEVICE, US_PR_DEVICE, NULL,
                US_FL_FIX_CAPACITY ),
 
+/*
+ * Reported by Tyson Vinson <lornoss@gmail.com>
+ * This particular productId is the iPod Nano
+ */
+UNUSUAL_DEV( 0x05ac, 0x120a, 0x0000, 0x9999,
+               "Apple",
+               "iPod",
+               US_SC_DEVICE, US_PR_DEVICE, NULL,
+               US_FL_FIX_CAPACITY ),
+
 #ifdef CONFIG_USB_STORAGE_JUMPSHOT
 UNUSUAL_DEV(  0x05dc, 0x0001, 0x0000, 0x0001,
                "Lexar",
@@ -702,6 +726,14 @@ UNUSUAL_DEV(  0x0781, 0x0001, 0x0200, 0x0200,
                US_SC_SCSI, US_PR_CB, NULL,
                US_FL_SINGLE_LUN ),
 
+#ifdef CONFIG_USB_STORAGE_USBAT
+UNUSUAL_DEV(  0x0781, 0x0005, 0x0005, 0x0005,
+               "Sandisk",
+               "ImageMate SDDR-05b",
+               US_SC_SCSI, US_PR_USBAT, init_usbat,
+               US_FL_SINGLE_LUN ),
+#endif
+
 UNUSUAL_DEV(  0x0781, 0x0100, 0x0100, 0x0100,
                "Sandisk",
                "ImageMate SDDR-12",
@@ -724,7 +756,7 @@ UNUSUAL_DEV(  0x07ab, 0xfc01, 0x0000, 0x9999,
 #endif
 
 /* Reported by Eero Volotinen <eero@ping-viini.org> */
-UNUSUAL_DEV(  0x07ab, 0xfccd, 0x0406, 0x0406,
+UNUSUAL_DEV(  0x07ab, 0xfccd, 0x0000, 0x9999,
                "Freecom Technologies",
                "FHD-Classic",
                US_SC_DEVICE, US_PR_DEVICE, NULL,
index f9a9bfa..3847ebe 100644 (file)
@@ -54,6 +54,7 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/slab.h>
+#include <linux/kthread.h>
 
 #include <scsi/scsi.h>
 #include <scsi/scsi_cmnd.h>
@@ -111,11 +112,6 @@ static atomic_t total_threads = ATOMIC_INIT(0);
 static DECLARE_COMPLETION(threads_gone);
 
 
-static int storage_probe(struct usb_interface *iface,
-                        const struct usb_device_id *id);
-
-static void storage_disconnect(struct usb_interface *iface);
-
 /* The entries in this table, except for final ones here
  * (USB_MASS_STORAGE_CLASS and the empty entry), correspond,
  * line for line with the entries of us_unsuaul_dev_list[].
@@ -233,13 +229,40 @@ static struct us_unusual_dev us_unusual_dev_list[] = {
        { NULL }
 };
 
-static struct usb_driver usb_storage_driver = {
-       .owner =        THIS_MODULE,
-       .name =         "usb-storage",
-       .probe =        storage_probe,
-       .disconnect =   storage_disconnect,
-       .id_table =     storage_usb_ids,
-};
+
+#ifdef CONFIG_PM       /* Minimal support for suspend and resume */
+
+static int storage_suspend(struct usb_interface *iface, pm_message_t message)
+{
+       struct us_data *us = usb_get_intfdata(iface);
+
+       /* Wait until no command is running */
+       down(&us->dev_semaphore);
+
+       US_DEBUGP("%s\n", __FUNCTION__);
+       iface->dev.power.power_state.event = message.event;
+
+       /* When runtime PM is working, we'll set a flag to indicate
+        * whether we should autoresume when a SCSI request arrives. */
+
+       up(&us->dev_semaphore);
+       return 0;
+}
+
+static int storage_resume(struct usb_interface *iface)
+{
+       struct us_data *us = usb_get_intfdata(iface);
+
+       down(&us->dev_semaphore);
+
+       US_DEBUGP("%s\n", __FUNCTION__);
+       iface->dev.power.power_state.event = PM_EVENT_ON;
+
+       up(&us->dev_semaphore);
+       return 0;
+}
+
+#endif /* CONFIG_PM */
 
 /*
  * fill_inquiry_response takes an unsigned char array (which must
@@ -288,22 +311,7 @@ static int usb_stor_control_thread(void * __us)
        struct us_data *us = (struct us_data *)__us;
        struct Scsi_Host *host = us_to_host(us);
 
-       lock_kernel();
-
-       /*
-        * This thread doesn't need any user-level access,
-        * so get rid of all our resources.
-        */
-       daemonize("usb-storage");
        current->flags |= PF_NOFREEZE;
-       unlock_kernel();
-
-       /* acquire a reference to the host, so it won't be deallocated
-        * until we're ready to exit */
-       scsi_host_get(host);
-
-       /* signal that we've started the thread */
-       complete(&(us->notify));
 
        for(;;) {
                US_DEBUGP("*** thread sleeping.\n");
@@ -467,6 +475,12 @@ static int associate_dev(struct us_data *us, struct usb_interface *intf)
                US_DEBUGP("I/O buffer allocation failed\n");
                return -ENOMEM;
        }
+
+       us->sensebuf = kmalloc(US_SENSE_SIZE, GFP_KERNEL);
+       if (!us->sensebuf) {
+               US_DEBUGP("Sense buffer allocation failed\n");
+               return -ENOMEM;
+       }
        return 0;
 }
 
@@ -555,8 +569,8 @@ static int get_transport(struct us_data *us)
                break;
 
 #ifdef CONFIG_USB_STORAGE_USBAT
-       case US_PR_SCM_ATAPI:
-               us->transport_name = "SCM/ATAPI";
+       case US_PR_USBAT:
+               us->transport_name = "Shuttle USBAT";
                us->transport = usbat_transport;
                us->transport_reset = usb_stor_CB_reset;
                us->max_lun = 1;
@@ -740,6 +754,7 @@ static int get_pipes(struct us_data *us)
 static int usb_stor_acquire_resources(struct us_data *us)
 {
        int p;
+       struct task_struct *th;
 
        us->current_urb = usb_alloc_urb(0, GFP_KERNEL);
        if (!us->current_urb) {
@@ -747,38 +762,28 @@ static int usb_stor_acquire_resources(struct us_data *us)
                return -ENOMEM;
        }
 
-       /* Lock the device while we carry out the next two operations */
-       down(&us->dev_semaphore);
-
-       /* For bulk-only devices, determine the max LUN value */
-       if (us->protocol == US_PR_BULK) {
-               p = usb_stor_Bulk_max_lun(us);
-               if (p < 0) {
-                       up(&us->dev_semaphore);
-                       return p;
-               }
-               us->max_lun = p;
-       }
-
        /* Just before we start our control thread, initialize
         * the device if it needs initialization */
-       if (us->unusual_dev->initFunction)
-               us->unusual_dev->initFunction(us);
-
-       up(&us->dev_semaphore);
+       if (us->unusual_dev->initFunction) {
+               p = us->unusual_dev->initFunction(us);
+               if (p)
+                       return p;
+       }
 
        /* Start up our control thread */
-       p = kernel_thread(usb_stor_control_thread, us, CLONE_VM);
-       if (p < 0) {
+       th = kthread_create(usb_stor_control_thread, us, "usb-storage");
+       if (IS_ERR(th)) {
                printk(KERN_WARNING USB_STORAGE 
                       "Unable to start control thread\n");
-               return p;
+               return PTR_ERR(th);
        }
-       us->pid = p;
-       atomic_inc(&total_threads);
 
-       /* Wait for the thread to start */
-       wait_for_completion(&(us->notify));
+       /* Take a reference to the host for the control thread and
+        * count it among all the threads we have launched.  Then
+        * start it up. */
+       scsi_host_get(us_to_host(us));
+       atomic_inc(&total_threads);
+       wake_up_process(th);
 
        return 0;
 }
@@ -812,6 +817,8 @@ static void dissociate_dev(struct us_data *us)
 {
        US_DEBUGP("-- %s\n", __FUNCTION__);
 
+       kfree(us->sensebuf);
+
        /* Free the device-related DMA-mapped buffers */
        if (us->cr)
                usb_buffer_free(us->pusb_dev, sizeof(*us->cr), us->cr,
@@ -872,21 +879,6 @@ static int usb_stor_scan_thread(void * __us)
 {
        struct us_data *us = (struct us_data *)__us;
 
-       /*
-        * This thread doesn't need any user-level access,
-        * so get rid of all our resources.
-        */
-       lock_kernel();
-       daemonize("usb-stor-scan");
-       unlock_kernel();
-
-       /* Acquire a reference to the host, so it won't be deallocated
-        * until we're ready to exit */
-       scsi_host_get(us_to_host(us));
-
-       /* Signal that we've started the thread */
-       complete(&(us->notify));
-
        printk(KERN_DEBUG
                "usb-storage: device found at %d\n", us->pusb_dev->devnum);
 
@@ -904,6 +896,14 @@ retry:
 
        /* If the device is still connected, perform the scanning */
        if (!test_bit(US_FLIDX_DISCONNECTING, &us->flags)) {
+
+               /* For bulk-only devices, determine the max LUN value */
+               if (us->protocol == US_PR_BULK &&
+                               !(us->flags & US_FL_SINGLE_LUN)) {
+                       down(&us->dev_semaphore);
+                       us->max_lun = usb_stor_Bulk_max_lun(us);
+                       up(&us->dev_semaphore);
+               }
                scsi_scan_host(us_to_host(us));
                printk(KERN_DEBUG "usb-storage: device scan complete\n");
 
@@ -923,6 +923,7 @@ static int storage_probe(struct usb_interface *intf,
        struct us_data *us;
        const int id_index = id - storage_usb_ids; 
        int result;
+       struct task_struct *th;
 
        US_DEBUGP("USB Mass Storage device detected\n");
 
@@ -1003,17 +1004,21 @@ static int storage_probe(struct usb_interface *intf,
        }
 
        /* Start up the thread for delayed SCSI-device scanning */
-       result = kernel_thread(usb_stor_scan_thread, us, CLONE_VM);
-       if (result < 0) {
+       th = kthread_create(usb_stor_scan_thread, us, "usb-stor-scan");
+       if (IS_ERR(th)) {
                printk(KERN_WARNING USB_STORAGE 
                       "Unable to start the device-scanning thread\n");
                quiesce_and_remove_host(us);
+               result = PTR_ERR(th);
                goto BadDevice;
        }
-       atomic_inc(&total_threads);
 
-       /* Wait for the thread to start */
-       wait_for_completion(&(us->notify));
+       /* Take a reference to the host for the scanning thread and
+        * count it among all the threads we have launched.  Then
+        * start it up. */
+       scsi_host_get(us_to_host(us));
+       atomic_inc(&total_threads);
+       wake_up_process(th);
 
        return 0;
 
@@ -1038,6 +1043,18 @@ static void storage_disconnect(struct usb_interface *intf)
  * Initialization and registration
  ***********************************************************************/
 
+static struct usb_driver usb_storage_driver = {
+       .owner =        THIS_MODULE,
+       .name =         "usb-storage",
+       .probe =        storage_probe,
+       .disconnect =   storage_disconnect,
+#ifdef CONFIG_PM
+       .suspend =      storage_suspend,
+       .resume =       storage_resume,
+#endif
+       .id_table =     storage_usb_ids,
+};
+
 static int __init usb_stor_init(void)
 {
        int retval;
index a195ada..98b0971 100644 (file)
@@ -117,6 +117,7 @@ enum { US_DO_ALL_FLAGS };
  */
 
 #define US_IOBUF_SIZE          64      /* Size of the DMA-mapped I/O buffer */
+#define US_SENSE_SIZE          18      /* Size of the autosense data buffer */
 
 typedef int (*trans_cmnd)(struct scsi_cmnd *, struct us_data*);
 typedef int (*trans_reset)(struct us_data*);
@@ -160,14 +161,12 @@ struct us_data {
        struct scsi_cmnd        *srb;            /* current srb         */
        unsigned int            tag;             /* current dCBWTag     */
 
-       /* thread information */
-       int                     pid;             /* control thread       */
-
        /* control and bulk communications data */
        struct urb              *current_urb;    /* USB requests         */
        struct usb_ctrlrequest  *cr;             /* control requests     */
        struct usb_sg_request   current_sg;      /* scatter-gather req.  */
        unsigned char           *iobuf;          /* I/O buffer           */
+       unsigned char           *sensebuf;       /* sense data buffer    */
        dma_addr_t              cr_dma;          /* buffer DMA addresses */
        dma_addr_t              iobuf_dma;
 
index 353f24d..6c3a53f 100644 (file)
@@ -223,9 +223,8 @@ static struct file_operations skel_fops = {
  * and to have the device registered with devfs and the driver core
  */
 static struct usb_class_driver skel_class = {
-       .name =         "usb/skel%d",
+       .name =         "skel%d",
        .fops =         &skel_fops,
-       .mode =         S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH,
        .minor_base =   USB_SKEL_MINOR_BASE,
 };
 
index a304042..3a26f9c 100644 (file)
@@ -275,20 +275,20 @@ static const struct cirrusfb_board_info_rec {
 
 #ifdef CONFIG_PCI
 #define CHIP(id, btype) \
-       { PCI_VENDOR_ID_CIRRUS, PCI_DEVICE_ID_##id, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (btype) }
+       { PCI_VENDOR_ID_CIRRUS, id, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (btype) }
 
 static struct pci_device_id cirrusfb_pci_table[] = {
-       CHIP( CIRRUS_5436,      BT_ALPINE ),
-       CHIP( CIRRUS_5434_8,    BT_ALPINE ),
-       CHIP( CIRRUS_5434_4,    BT_ALPINE ),
-       CHIP( CIRRUS_5430,      BT_ALPINE ), /* GD-5440 has identical id */
-       CHIP( CIRRUS_7543,      BT_ALPINE ),
-       CHIP( CIRRUS_7548,      BT_ALPINE ),
-       CHIP( CIRRUS_5480,      BT_GD5480 ), /* MacPicasso probably */
-       CHIP( CIRRUS_5446,      BT_PICASSO4 ), /* Picasso 4 is a GD5446 */
-       CHIP( CIRRUS_5462,      BT_LAGUNA ), /* CL Laguna */
-       CHIP( CIRRUS_5464,      BT_LAGUNA ), /* CL Laguna 3D */
-       CHIP( CIRRUS_5465,      BT_LAGUNA ), /* CL Laguna 3DA*/
+       CHIP( PCI_DEVICE_ID_CIRRUS_5436, BT_ALPINE ),
+       CHIP( PCI_DEVICE_ID_CIRRUS_5434_8, BT_ALPINE ),
+       CHIP( PCI_DEVICE_ID_CIRRUS_5434_4, BT_ALPINE ),
+       CHIP( PCI_DEVICE_ID_CIRRUS_5430, BT_ALPINE ), /* GD-5440 is same id */
+       CHIP( PCI_DEVICE_ID_CIRRUS_7543, BT_ALPINE ),
+       CHIP( PCI_DEVICE_ID_CIRRUS_7548, BT_ALPINE ),
+       CHIP( PCI_DEVICE_ID_CIRRUS_5480, BT_GD5480 ), /* MacPicasso likely */
+       CHIP( PCI_DEVICE_ID_CIRRUS_5446, BT_PICASSO4 ), /* Picasso 4 is 5446 */
+       CHIP( PCI_DEVICE_ID_CIRRUS_5462, BT_LAGUNA ), /* CL Laguna */
+       CHIP( PCI_DEVICE_ID_CIRRUS_5464, BT_LAGUNA ), /* CL Laguna 3D */
+       CHIP( PCI_DEVICE_ID_CIRRUS_5465, BT_LAGUNA ), /* CL Laguna 3DA*/
        { 0, }
 };
 MODULE_DEVICE_TABLE(pci, cirrusfb_pci_table);
index e28a742..a327e03 100644 (file)
@@ -3050,6 +3050,7 @@ HANDLE_IOCTL(TIOCSSERIAL, serial_struct_ioctl)
 HANDLE_IOCTL(USBDEVFS_CONTROL32, do_usbdevfs_control)
 HANDLE_IOCTL(USBDEVFS_BULK32, do_usbdevfs_bulk)
 HANDLE_IOCTL(USBDEVFS_DISCSIGNAL32, do_usbdevfs_discsignal)
+COMPATIBLE_IOCTL(USBDEVFS_IOCTL32)
 /* i2c */
 HANDLE_IOCTL(I2C_FUNCS, w_long)
 HANDLE_IOCTL(I2C_RDWR, do_i2c_rdwr_ioctl)
index 2b9e6d5..1cce2b9 100644 (file)
@@ -22,7 +22,6 @@ static inline void mpc_oem_pci_bus(struct mpc_config_bus *m,
 {
 }
 
-extern int usb_early_handoff;
 static inline int mps_oem_check(struct mp_config_table *mpc, char *oem, 
                char *productid)
 {
@@ -32,7 +31,6 @@ static inline int mps_oem_check(struct mp_config_table *mpc, char *oem,
                         || !strncmp(productid, "RUTHLESS SMP", 12))){
                use_cyclone = 1; /*enable cyclone-timer*/
                setup_summit();
-               usb_early_handoff = 1;
                return 1;
        }
        return 0;
@@ -46,7 +44,6 @@ static inline int acpi_madt_oem_check(char *oem_id, char *oem_table_id)
             || !strncmp(oem_table_id, "EXA", 3))){
                use_cyclone = 1; /*enable cyclone-timer*/
                setup_summit();
-               usb_early_handoff = 1;
                return 1;
        }
        return 0;
index a2f6ac5..ca5ea99 100644 (file)
@@ -26,7 +26,7 @@ typedef void ia64_mv_cpu_init_t (void);
 typedef void ia64_mv_irq_init_t (void);
 typedef void ia64_mv_send_ipi_t (int, int, int, int);
 typedef void ia64_mv_timer_interrupt_t (int, void *, struct pt_regs *);
-typedef void ia64_mv_global_tlb_purge_t (unsigned long, unsigned long, unsigned long);
+typedef void ia64_mv_global_tlb_purge_t (struct mm_struct *, unsigned long, unsigned long, unsigned long);
 typedef void ia64_mv_tlb_migrate_finish_t (struct mm_struct *);
 typedef unsigned int ia64_mv_local_vector_to_irq (u8);
 typedef char *ia64_mv_pci_get_legacy_mem_t (struct pci_bus *);
index daafe50..e90daf9 100644 (file)
@@ -1,8 +1,7 @@
 #ifndef _ASM_IA64_MACHVEC_HPZX1_h
 #define _ASM_IA64_MACHVEC_HPZX1_h
 
-extern ia64_mv_setup_t dig_setup;
-extern ia64_mv_setup_t                 sba_setup;
+extern ia64_mv_setup_t                 dig_setup;
 extern ia64_mv_dma_alloc_coherent      sba_alloc_coherent;
 extern ia64_mv_dma_free_coherent       sba_free_coherent;
 extern ia64_mv_dma_map_single          sba_map_single;
@@ -19,15 +18,15 @@ extern ia64_mv_dma_mapping_error    sba_dma_mapping_error;
  * platform's machvec structure.  When compiling a non-generic kernel,
  * the macros are used directly.
  */
-#define platform_name                  "hpzx1"
-#define platform_setup                 sba_setup
-#define platform_dma_init              machvec_noop
-#define platform_dma_alloc_coherent    sba_alloc_coherent
-#define platform_dma_free_coherent     sba_free_coherent
-#define platform_dma_map_single                sba_map_single
-#define platform_dma_unmap_single      sba_unmap_single
-#define platform_dma_map_sg            sba_map_sg
-#define platform_dma_unmap_sg          sba_unmap_sg
+#define platform_name                          "hpzx1"
+#define platform_setup                         dig_setup
+#define platform_dma_init                      machvec_noop
+#define platform_dma_alloc_coherent            sba_alloc_coherent
+#define platform_dma_free_coherent             sba_free_coherent
+#define platform_dma_map_single                        sba_map_single
+#define platform_dma_unmap_single              sba_unmap_single
+#define platform_dma_map_sg                    sba_map_sg
+#define platform_dma_unmap_sg                  sba_unmap_sg
 #define platform_dma_sync_single_for_cpu       machvec_dma_sync_single
 #define platform_dma_sync_sg_for_cpu           machvec_dma_sync_sg
 #define platform_dma_sync_single_for_device    machvec_dma_sync_single
index 9924b1b..f00a34a 100644 (file)
@@ -2,7 +2,6 @@
 #define _ASM_IA64_MACHVEC_HPZX1_SWIOTLB_h
 
 extern ia64_mv_setup_t                         dig_setup;
-extern ia64_mv_dma_init                                hwsw_init;
 extern ia64_mv_dma_alloc_coherent              hwsw_alloc_coherent;
 extern ia64_mv_dma_free_coherent               hwsw_free_coherent;
 extern ia64_mv_dma_map_single                  hwsw_map_single;
@@ -26,7 +25,7 @@ extern ia64_mv_dma_sync_sg_for_device         hwsw_sync_sg_for_device;
 #define platform_name                          "hpzx1_swiotlb"
 
 #define platform_setup                         dig_setup
-#define platform_dma_init                      hwsw_init
+#define platform_dma_init                      machvec_noop
 #define platform_dma_alloc_coherent            hwsw_alloc_coherent
 #define platform_dma_free_coherent             hwsw_free_coherent
 #define platform_dma_map_single                        hwsw_map_single
index 1590dc6..46501b0 100644 (file)
  *     - initrd (optional)
  *     - command line string
  *     - kernel code & data
+ *     - Kernel memory map built from EFI memory map
  *
  * More could be added if necessary
  */
-#define IA64_MAX_RSVD_REGIONS 5
+#define IA64_MAX_RSVD_REGIONS 6
 
 struct rsvd_region {
        unsigned long start;    /* virtual address of beginning of element */
@@ -33,6 +34,7 @@ extern void find_memory (void);
 extern void reserve_memory (void);
 extern void find_initrd (void);
 extern int filter_rsvd_memory (unsigned long start, unsigned long end, void *arg);
+extern void efi_memmap_init(unsigned long *, unsigned long *);
 
 /*
  * For rounding an address to the next IA64_GRANULE_SIZE or order
@@ -41,7 +43,7 @@ extern int filter_rsvd_memory (unsigned long start, unsigned long end, void *arg
 #define GRANULEROUNDUP(n)      (((n)+IA64_GRANULE_SIZE-1) & ~(IA64_GRANULE_SIZE-1))
 #define ORDERROUNDDOWN(n)      ((n) & ~((PAGE_SIZE<<MAX_ORDER)-1))
 
-#ifdef CONFIG_DISCONTIGMEM
+#ifdef CONFIG_NUMA
   extern void call_pernode_memory (unsigned long start, unsigned long len, void *func);
 #else
 # define call_pernode_memory(start, len, func) (*func)(start, len, 0)
index d32f51e..34efe88 100644 (file)
@@ -15,7 +15,7 @@
 #include <asm/page.h>
 #include <asm/meminit.h>
 
-#ifdef CONFIG_DISCONTIGMEM
+#ifdef CONFIG_NUMA
 
 static inline int pfn_to_nid(unsigned long pfn)
 {
@@ -31,6 +31,10 @@ static inline int pfn_to_nid(unsigned long pfn)
 #endif
 }
 
+#ifdef CONFIG_HAVE_ARCH_EARLY_PFN_TO_NID
+extern int early_pfn_to_nid(unsigned long pfn);
+#endif
+
 #ifdef CONFIG_IA64_DIG /* DIG systems are small */
 # define MAX_PHYSNODE_ID       8
 # define NR_NODE_MEMBLKS       (MAX_NUMNODES * 8)
@@ -39,8 +43,8 @@ static inline int pfn_to_nid(unsigned long pfn)
 # define NR_NODE_MEMBLKS       (MAX_NUMNODES * 4)
 #endif
 
-#else /* CONFIG_DISCONTIGMEM */
+#else /* CONFIG_NUMA */
 # define NR_NODE_MEMBLKS       (MAX_NUMNODES * 4)
-#endif /* CONFIG_DISCONTIGMEM */
+#endif /* CONFIG_NUMA */
 
 #endif /* _ASM_IA64_MMZONE_H */
index 6b0f3ed..9978c7c 100644 (file)
@@ -17,7 +17,7 @@
 #include <asm/percpu.h>
 #include <asm/mmzone.h>
 
-#ifdef CONFIG_DISCONTIGMEM
+#ifdef CONFIG_NUMA
 
 /*
  * Node Data. One of these structures is located on each node of a NUMA system.
@@ -47,6 +47,6 @@ struct ia64_node_data {
  */
 #define NODE_DATA(nid)         (local_node_data->pg_data_ptrs[nid])
 
-#endif /* CONFIG_DISCONTIGMEM */
+#endif /* CONFIG_NUMA */
 
 #endif /* _ASM_IA64_NODEDATA_H */
index 9edffad..ef436b9 100644 (file)
@@ -102,15 +102,15 @@ do {                                              \
 
 #ifdef CONFIG_VIRTUAL_MEM_MAP
 extern int ia64_pfn_valid (unsigned long pfn);
-#else
+#elif defined(CONFIG_FLATMEM)
 # define ia64_pfn_valid(pfn) 1
 #endif
 
-#ifndef CONFIG_DISCONTIGMEM
+#ifdef CONFIG_FLATMEM
 # define pfn_valid(pfn)                (((pfn) < max_mapnr) && ia64_pfn_valid(pfn))
 # define page_to_pfn(page)     ((unsigned long) (page - mem_map))
 # define pfn_to_page(pfn)      (mem_map + (pfn))
-#else
+#elif defined(CONFIG_DISCONTIGMEM)
 extern struct page *vmem_map;
 extern unsigned long max_low_pfn;
 # define pfn_valid(pfn)                (((pfn) < max_low_pfn) && ia64_pfn_valid(pfn))
index ab827d2..1a3831c 100644 (file)
 #include <asm/sn/types.h>
 #include <asm/sn/sn_cpuid.h>
 
+/*
+ * This is the maximum number of NUMALINK nodes that can be part of a single
+ * SSI kernel. This number includes C-brick, M-bricks, and TIOs. Nodes in
+ * remote partitions are NOT included in this number.
+ * The number of compact nodes cannot exceed size of a coherency domain.
+ * The purpose of this define is to specify a node count that includes
+ * all C/M/TIO nodes in an SSI system.
+ *
+ * SGI system can currently support up to 256 C/M nodes plus additional TIO nodes.
+ *
+ *     Note: ACPI20 has an architectural limit of 256 nodes. When we upgrade
+ *     to ACPI3.0, this limit will be removed. The notion of "compact nodes"
+ *     should be deleted and TIOs should be included in MAX_NUMNODES.
+ */
+#define MAX_COMPACT_NODES      512
+
+/*
+ * Maximum number of nodes in all partitions and in all coherency domains.
+ * This is the total number of nodes accessible in the numalink fabric. It
+ * includes all C & M bricks, plus all TIOs.
+ *
+ * This value is also the value of the maximum number of NASIDs in the numalink
+ * fabric.
+ */
+#define MAX_NUMALINK_NODES     16384
+
 /*
  * The following defines attributes of the HUB chip. These attributes are
  * frequently referenced. They are kept in the per-cpu data areas of each cpu.
@@ -40,15 +66,6 @@ DECLARE_PER_CPU(struct sn_hub_info_s, __sn_hub_info);
 #define enable_shub_wars_1_1() (sn_hub_info->shub_1_1_found)
 
 
-/*
- * This is the maximum number of nodes that can be part of a kernel.
- * Effectively, it's the maximum number of compact node ids (cnodeid_t).
- * This is not necessarily the same as MAX_NASIDS.
- */
-#define MAX_COMPACT_NODES      2048
-#define CPUS_PER_NODE          4
-
-
 /*
  * Compact node ID to nasid mappings kept in the per-cpu data areas of each
  * cpu.
@@ -57,7 +74,6 @@ DECLARE_PER_CPU(short, __sn_cnodeid_to_nasid[MAX_NUMNODES]);
 #define sn_cnodeid_to_nasid    (&__get_cpu_var(__sn_cnodeid_to_nasid[0]))
 
 
-
 extern u8 sn_partition_id;
 extern u8 sn_system_size;
 extern u8 sn_sharing_domain_size;
index 4220973..41c73a7 100644 (file)
@@ -14,7 +14,7 @@
 extern void * sn_io_addr(unsigned long port) __attribute_const__; /* Forward definition */
 extern void __sn_mmiowb(void); /* Forward definition */
 
-extern int numionodes;
+extern int num_cnodes;
 
 #define __sn_mf_a()   ia64_mfa()
 
@@ -35,6 +35,15 @@ extern void sn_dma_flush(unsigned long);
 #define __sn_readl_relaxed ___sn_readl_relaxed
 #define __sn_readq_relaxed ___sn_readq_relaxed
 
+/*
+ * Convenience macros for setting/clearing bits using the above accessors
+ */
+
+#define __sn_setq_relaxed(addr, val) \
+       writeq((__sn_readq_relaxed(addr) | (val)), (addr))
+#define __sn_clrq_relaxed(addr, val) \
+       writeq((__sn_readq_relaxed(addr) & ~(val)), (addr))
+
 /*
  * The following routines are SN Platform specific, called when
  * a reference is made to inX/outX set macros.  SN Platform
index 9f920c7..bcbf209 100644 (file)
@@ -208,19 +208,6 @@ typedef struct lboard_s {
        klconf_off_t    brd_next_same;    /* Next BOARD with same nasid */
 } lboard_t;
 
-#define KLCF_NUM_COMPS(_brd)   ((_brd)->brd_numcompts)
-#define NODE_OFFSET_TO_KLINFO(n,off)    ((klinfo_t*) TO_NODE_CAC(n,off))
-#define KLCF_NEXT(_brd)         \
-        ((_brd)->brd_next_same ?     \
-         (NODE_OFFSET_TO_LBOARD((_brd)->brd_next_same_host, (_brd)->brd_next_same)): NULL)
-#define KLCF_NEXT_ANY(_brd)         \
-        ((_brd)->brd_next_any ?     \
-         (NODE_OFFSET_TO_LBOARD(NASID_GET(_brd), (_brd)->brd_next_any)): NULL)
-#define KLCF_COMP(_brd, _ndx)   \
-                ((((_brd)->brd_compts[(_ndx)]) == 0) ? 0 : \
-                       (NODE_OFFSET_TO_KLINFO(NASID_GET(_brd), (_brd)->brd_compts[(_ndx)])))
-
-
 /*
  * Generic info structure. This stores common info about a 
  * component.
@@ -249,24 +236,11 @@ typedef struct klinfo_s {                  /* Generic info */
 } klinfo_t ;
 
 
-static inline lboard_t *find_lboard_any(lboard_t * start, unsigned char brd_type)
+static inline lboard_t *find_lboard_next(lboard_t * brd)
 {
-        /* Search all boards stored on this node. */
-
-        while (start) {
-                if (start->brd_type == brd_type)
-                        return start;
-                start = KLCF_NEXT_ANY(start);
-        }
-        /* Didn't find it. */
-        return (lboard_t *) NULL;
+       if (brd && brd->brd_next_any)
+               return NODE_OFFSET_TO_LBOARD(NASID_GET(brd), brd->brd_next_any);
+        return NULL;
 }
 
-
-/* external declarations of Linux kernel functions. */
-
-extern lboard_t *root_lboard[];
-extern klinfo_t *find_component(lboard_t *brd, klinfo_t *kli, unsigned char type);
-extern klinfo_t *find_first_component(lboard_t *brd, unsigned char type);
-
 #endif /* _ASM_IA64_SN_KLCONFIG_H */
index 2e5f0aa..e3b8191 100644 (file)
 #define L1_BRICKTYPE_ATHENA    0x2b            /* + */
 #define L1_BRICKTYPE_DAYTONA   0x7a            /* z */
 
+/* board type response codes */
+#define L1_BOARDTYPE_IP69       0x0100          /* CA */
+#define L1_BOARDTYPE_IP63       0x0200          /* CB */
+#define L1_BOARDTYPE_BASEIO     0x0300          /* IB */
+#define L1_BOARDTYPE_PCIE2SLOT  0x0400          /* IC */
+#define L1_BOARDTYPE_PCIX3SLOT  0x0500          /* ID */
+#define L1_BOARDTYPE_PCIXPCIE4SLOT 0x0600       /* IE */
+#define L1_BOARDTYPE_ABACUS     0x0700          /* AB */
+#define L1_BOARDTYPE_DAYTONA    0x0800          /* AD */
+#define L1_BOARDTYPE_INVAL      (-1)            /* invalid brick type */
+
+
 #endif /* _ASM_IA64_SN_L1_H */
index 47bb810..6f6d69e 100644 (file)
@@ -55,7 +55,6 @@ struct nodepda_s {
         */
        struct phys_cpuid       phys_cpuid[NR_CPUS];
        spinlock_t              ptc_lock ____cacheline_aligned_in_smp;
-       spinlock_t              bist_lock;
 };
 
 typedef struct nodepda_s nodepda_t;
index d2c1d34..749deb2 100644 (file)
@@ -105,7 +105,6 @@ extern short physical_node_map[];   /* indexed by nasid to get cnode */
 #define cpuid_to_nasid(cpuid)          (sn_nodepda->phys_cpuid[cpuid].nasid)
 #define cpuid_to_subnode(cpuid)                (sn_nodepda->phys_cpuid[cpuid].subnode)
 #define cpuid_to_slice(cpuid)          (sn_nodepda->phys_cpuid[cpuid].slice)
-#define cpuid_to_cnodeid(cpuid)                (physical_node_map[cpuid_to_nasid(cpuid)])
 
 
 /*
@@ -113,8 +112,6 @@ extern short physical_node_map[];   /* indexed by nasid to get cnode */
  * of potentially large tables.
  */
 extern int nasid_slice_to_cpuid(int, int);
-#define nasid_slice_to_cpu_physical_id(nasid, slice)                   \
-       cpu_physical_id(nasid_slice_to_cpuid(nasid, slice))
 
 /*
  * cnodeid_to_nasid - convert a cnodeid to a NASID
index fea35b3..3f7564d 100644 (file)
@@ -47,6 +47,7 @@
 #define  SN_SAL_CONSOLE_PUTB                      0x02000028
 #define  SN_SAL_CONSOLE_XMIT_CHARS                0x0200002a
 #define  SN_SAL_CONSOLE_READC                     0x0200002b
+#define  SN_SAL_SYSCTL_OP                         0x02000030
 #define  SN_SAL_SYSCTL_MODID_GET                  0x02000031
 #define  SN_SAL_SYSCTL_GET                         0x02000032
 #define  SN_SAL_SYSCTL_IOBRICK_MODULE_GET          0x02000033
@@ -67,7 +68,7 @@
 #define  SN_SAL_IOIF_INTERRUPT                    0x0200004a
 #define  SN_SAL_HWPERF_OP                         0x02000050   // lock
 #define  SN_SAL_IOIF_ERROR_INTERRUPT              0x02000051
-
+#define  SN_SAL_IOIF_PCI_SAFE                     0x02000052
 #define  SN_SAL_IOIF_SLOT_ENABLE                  0x02000053
 #define  SN_SAL_IOIF_SLOT_DISABLE                 0x02000054
 #define  SN_SAL_IOIF_GET_HUBDEV_INFO              0x02000055
 #define SAL_INTR_ALLOC         1
 #define SAL_INTR_FREE          2
 
+/*
+ * operations available on the generic SN_SAL_SYSCTL_OP
+ * runtime service
+ */
+#define SAL_SYSCTL_OP_IOBOARD          0x0001  /*  retrieve board type */
+#define SAL_SYSCTL_OP_TIO_JLCK_RST      0x0002  /* issue TIO clock reset */
+
 /*
  * IRouter (i.e. generalized system controller) operations
  */
@@ -198,26 +206,16 @@ ia64_sn_get_master_baseio_nasid(void)
        return ret_stuff.v0;
 }
 
-static inline char *
+static inline void *
 ia64_sn_get_klconfig_addr(nasid_t nasid)
 {
        struct ia64_sal_retval ret_stuff;
-       int cnodeid;
 
-       cnodeid = nasid_to_cnodeid(nasid);
        ret_stuff.status = 0;
        ret_stuff.v0 = 0;
        ret_stuff.v1 = 0;
        ret_stuff.v2 = 0;
        SAL_CALL(ret_stuff, SN_SAL_GET_KLCONFIG_ADDR, (u64)nasid, 0, 0, 0, 0, 0, 0);
-
-       /*
-        * We should panic if a valid cnode nasid does not produce
-        * a klconfig address.
-        */
-       if (ret_stuff.status != 0) {
-               panic("ia64_sn_get_klconfig_addr: Returned error %lx\n", ret_stuff.status);
-       }
        return ret_stuff.v0 ? __va(ret_stuff.v0) : NULL;
 }
 
@@ -694,12 +692,10 @@ sn_change_memprotect(u64 paddr, u64 len, u64 perms, u64 *nasid_array)
        unsigned long irq_flags;
 
        cnodeid = nasid_to_cnodeid(get_node_number(paddr));
-       // spin_lock(&NODEPDA(cnodeid)->bist_lock);
        local_irq_save(irq_flags);
        ia64_sal_oemcall_nolock(&ret_stuff, SN_SAL_MEMPROTECT, paddr, len,
                                (u64)nasid_array, perms, 0, 0, 0);
        local_irq_restore(irq_flags);
-       // spin_unlock(&NODEPDA(cnodeid)->bist_lock);
        return ret_stuff.status;
 }
 #define SN_MEMPROT_ACCESS_CLASS_0              0x14a080
@@ -873,6 +869,41 @@ ia64_sn_sysctl_event_init(nasid_t nasid)
         return (int) rv.v0;
 }
 
+/*
+ * Ask the system controller on the specified nasid to reset
+ * the CX corelet clock.  Only valid on TIO nodes.
+ */
+static inline int
+ia64_sn_sysctl_tio_clock_reset(nasid_t nasid)
+{
+       struct ia64_sal_retval rv;
+       SAL_CALL_REENTRANT(rv, SN_SAL_SYSCTL_OP, SAL_SYSCTL_OP_TIO_JLCK_RST,
+                       nasid, 0, 0, 0, 0, 0);
+       if (rv.status != 0)
+               return (int)rv.status;
+       if (rv.v0 != 0)
+               return (int)rv.v0;
+
+       return 0;
+}
+
+/*
+ * Get the associated ioboard type for a given nasid.
+ */
+static inline int
+ia64_sn_sysctl_ioboard_get(nasid_t nasid)
+{
+        struct ia64_sal_retval rv;
+        SAL_CALL_REENTRANT(rv, SN_SAL_SYSCTL_OP, SAL_SYSCTL_OP_IOBOARD,
+                        nasid, 0, 0, 0, 0, 0);
+        if (rv.v0 != 0)
+                return (int)rv.v0;
+        if (rv.v1 != 0)
+                return (int)rv.v1;
+
+        return 0;
+}
+
 /**
  * ia64_sn_get_fit_compt - read a FIT entry from the PROM header
  * @nasid: NASID of node to read
index 5ccec60..b532ef6 100644 (file)
@@ -182,11 +182,11 @@ tioca_tlbflush(struct tioca_kernel *tioca_kernel)
                         * touch every CL aligned GART entry.
                         */
 
-                       ca_base->ca_control2 &= ~(CA_GART_MEM_PARAM);
-                       ca_base->ca_control2 |= CA_GART_FLUSH_TLB;
-                       ca_base->ca_control2 |=
-                           (0x2ull << CA_GART_MEM_PARAM_SHFT);
-                       tmp = ca_base->ca_control2;
+                       __sn_clrq_relaxed(&ca_base->ca_control2, CA_GART_MEM_PARAM);
+                       __sn_setq_relaxed(&ca_base->ca_control2, CA_GART_FLUSH_TLB);
+                       __sn_setq_relaxed(&ca_base->ca_control2,
+                           (0x2ull << CA_GART_MEM_PARAM_SHFT));
+                       tmp = __sn_readq_relaxed(&ca_base->ca_control2);
                }
 
                return;
@@ -196,8 +196,8 @@ tioca_tlbflush(struct tioca_kernel *tioca_kernel)
         * Gart in uncached mode ... need an explicit flush.
         */
 
-       ca_base->ca_control2 |= CA_GART_FLUSH_TLB;
-       tmp = ca_base->ca_control2;
+       __sn_setq_relaxed(&ca_base->ca_control2, CA_GART_FLUSH_TLB);
+       tmp = __sn_readq_relaxed(&ca_base->ca_control2);
 }
 
 extern uint32_t        tioca_gart_found;
index c5447a5..5699e75 100644 (file)
@@ -19,6 +19,7 @@ struct cx_id_s {
 
 struct cx_dev {
        struct cx_id_s cx_id;
+       int bt;                         /* board/blade type */
        void *soft;                     /* driver specific */
        struct hubdev_info *hubdev;
        struct device dev;
@@ -59,7 +60,7 @@ struct cx_drv {
 extern struct sn_irq_info *tiocx_irq_alloc(nasid_t, int, int, nasid_t, int);
 extern void tiocx_irq_free(struct sn_irq_info *);
 extern int cx_device_unregister(struct cx_dev *);
-extern int cx_device_register(nasid_t, int, int, struct hubdev_info *);
+extern int cx_device_register(nasid_t, int, int, struct hubdev_info *, int);
 extern int cx_driver_unregister(struct cx_drv *);
 extern int cx_driver_register(struct cx_drv *);
 extern uint64_t tiocx_dma_addr(uint64_t addr);
index 1df1c9f..49faf8f 100644 (file)
@@ -49,7 +49,7 @@
  * C-brick nasids, thus the need for bitmaps which don't account for
  * odd-numbered (non C-brick) nasids.
  */
-#define XP_MAX_PHYSNODE_ID     (MAX_PHYSNODE_ID / 2)
+#define XP_MAX_PHYSNODE_ID     (MAX_NUMALINK_NODES / 2)
 #define XP_NASID_MASK_BYTES    ((XP_MAX_PHYSNODE_ID + 7) / 8)
 #define XP_NASID_MASK_WORDS    ((XP_MAX_PHYSNODE_ID + 63) / 64)
 
@@ -217,7 +217,17 @@ enum xpc_retval {
        xpcInvalidPartid,       /* 42: invalid partition ID */
        xpcLocalPartid,         /* 43: local partition ID */
 
-       xpcUnknownReason        /* 44: unknown reason -- must be last in list */
+       xpcOtherGoingDown,      /* 44: other side going down, reason unknown */
+       xpcSystemGoingDown,     /* 45: system is going down, reason unknown */
+       xpcSystemHalt,          /* 46: system is being halted */
+       xpcSystemReboot,        /* 47: system is being rebooted */
+       xpcSystemPoweroff,      /* 48: system is being powered off */
+
+       xpcDisconnecting,       /* 49: channel disconnecting (closing) */
+
+       xpcOpenCloseError,      /* 50: channel open/close protocol error */
+
+       xpcUnknownReason        /* 51: unknown reason -- must be last in list */
 };
 
 
@@ -342,7 +352,7 @@ typedef void (*xpc_notify_func)(enum xpc_retval reason, partid_t partid,
  *
  * The 'func' field points to the function to call when aynchronous
  * notification is required for such events as: a connection established/lost,
- * or an incomming message received, or an error condition encountered. A
+ * or an incoming message received, or an error condition encountered. A
  * non-NULL 'func' field indicates that there is an active registration for
  * the channel.
  */
diff --git a/include/asm-ia64/sparsemem.h b/include/asm-ia64/sparsemem.h
new file mode 100644 (file)
index 0000000..67a7c40
--- /dev/null
@@ -0,0 +1,20 @@
+#ifndef _ASM_IA64_SPARSEMEM_H
+#define _ASM_IA64_SPARSEMEM_H
+
+#ifdef CONFIG_SPARSEMEM
+/*
+ * SECTION_SIZE_BITS            2^N: how big each section will be
+ * MAX_PHYSMEM_BITS             2^N: how much memory we can have in that space
+ */
+
+#define SECTION_SIZE_BITS      (30)
+#define MAX_PHYSMEM_BITS       (50)
+#ifdef CONFIG_FORCE_MAX_ZONEORDER
+#if ((CONFIG_FORCE_MAX_ZONEORDER - 1 + PAGE_SHIFT) > SECTION_SIZE_BITS)
+#undef SECTION_SIZE_BITS
+#define SECTION_SIZE_BITS (CONFIG_FORCE_MAX_ZONEORDER - 1 + PAGE_SHIFT)
+#endif
+#endif
+
+#endif /* CONFIG_SPARSEMEM */
+#endif /* _ASM_IA64_SPARSEMEM_H */
index 4522c71..cc84934 100644 (file)
@@ -104,6 +104,22 @@ static inline void random_ether_addr(u8 *addr)
        addr [0] &= 0xfe;       /* clear multicast bit */
        addr [0] |= 0x02;       /* set local assignment bit (IEEE802) */
 }
+
+/**
+ * compare_ether_addr - Compare two Ethernet addresses
+ * @addr1: Pointer to a six-byte array containing the Ethernet address
+ * @addr2 Pointer other six-byte array containing the Ethernet address
+ *
+ * Compare two ethernet addresses, returns 0 if equal
+ */
+static inline unsigned compare_ether_addr(const u8 *_a, const u8 *_b)
+{
+       const u16 *a = (const u16 *) _a;
+       const u16 *b = (const u16 *) _b;
+
+       BUILD_BUG_ON(ETH_ALEN != 6);
+       return ((a[0] ^ b[0]) | (a[1] ^ b[1]) | (a[2] ^ b[2])) != 0;
+}
 #endif /* __KERNEL__ */
 
 #endif /* _LINUX_ETHERDEVICE_H */
index 7349058..3596ac9 100644 (file)
@@ -132,6 +132,7 @@ struct pci_dev {
        unsigned int    is_enabled:1;   /* pci_enable_device has been called */
        unsigned int    is_busmaster:1; /* device is busmaster */
        unsigned int    no_msi:1;       /* device may not use msi */
+       unsigned int    block_ucfg_access:1;    /* userspace config space access is blocked */
 
        u32             saved_config_space[16]; /* config space saved at suspend time */
        struct bin_attribute *rom_attr; /* attribute descriptor for sysfs ROM entry */
@@ -490,6 +491,9 @@ extern void pci_disable_msix(struct pci_dev *dev);
 extern void msi_remove_pci_irq_vectors(struct pci_dev *dev);
 #endif
 
+extern void pci_block_user_cfg_access(struct pci_dev *dev);
+extern void pci_unblock_user_cfg_access(struct pci_dev *dev);
+
 /*
  * PCI domain support.  Sometimes called PCI segment (eg by ACPI),
  * a PCI domain is defined to be a set of PCI busses which share
@@ -560,6 +564,9 @@ static inline int pci_enable_wake(struct pci_dev *dev, pci_power_t state, int en
 
 #define pci_dma_burst_advice(pdev, strat, strategy_parameter) do { } while (0)
 
+static inline void pci_block_user_cfg_access(struct pci_dev *dev) { }
+static inline void pci_unblock_user_cfg_access(struct pci_dev *dev) { }
+
 #endif /* CONFIG_PCI */
 
 /* Include architecture-dependent settings and functions */
index d6865bb..5619200 100644 (file)
@@ -96,6 +96,9 @@
 #define PCI_CLASS_SERIAL_ACCESS                0x0c01
 #define PCI_CLASS_SERIAL_SSA           0x0c02
 #define PCI_CLASS_SERIAL_USB           0x0c03
+#define PCI_CLASS_SERIAL_USB_UHCI      0x0c0300
+#define PCI_CLASS_SERIAL_USB_OHCI      0x0c0310
+#define PCI_CLASS_SERIAL_USB_EHCI      0x0c0320
 #define PCI_CLASS_SERIAL_FIBER         0x0c04
 #define PCI_CLASS_SERIAL_SMBUS         0x0c05
 
 
 #define PCI_VENDOR_ID_COMPAQ           0x0e11
 #define PCI_DEVICE_ID_COMPAQ_TOKENRING 0x0508
-#define PCI_DEVICE_ID_COMPAQ_1280      0x3033
-#define PCI_DEVICE_ID_COMPAQ_TRIFLEX   0x4000
-#define PCI_DEVICE_ID_COMPAQ_6010      0x6010
 #define PCI_DEVICE_ID_COMPAQ_TACHYON   0xa0fc
 #define PCI_DEVICE_ID_COMPAQ_SMART2P   0xae10
 #define PCI_DEVICE_ID_COMPAQ_NETEL100  0xae32
 #define PCI_DEVICE_ID_ATI_RAGE128_PP   0x5050
 #define PCI_DEVICE_ID_ATI_RAGE128_PQ   0x5051
 #define PCI_DEVICE_ID_ATI_RAGE128_PR   0x5052
-#define PCI_DEVICE_ID_ATI_RAGE128_TR   0x5452
 #define PCI_DEVICE_ID_ATI_RAGE128_PS   0x5053
 #define PCI_DEVICE_ID_ATI_RAGE128_PT   0x5054
 #define PCI_DEVICE_ID_ATI_RAGE128_PU   0x5055
 #define PCI_DEVICE_ID_ATI_RAGE128_PW   0x5057
 #define PCI_DEVICE_ID_ATI_RAGE128_PX   0x5058
 /* Rage128 M4 */
-#define PCI_DEVICE_ID_ATI_RADEON_LE    0x4d45
-#define PCI_DEVICE_ID_ATI_RADEON_LF    0x4d46
 /* Radeon R100 */
 #define PCI_DEVICE_ID_ATI_RADEON_QD    0x5144
 #define PCI_DEVICE_ID_ATI_RADEON_QE    0x5145
 #define PCI_DEVICE_ID_ATI_RADEON_QW    0x5157
 #define PCI_DEVICE_ID_ATI_RADEON_QX    0x5158
 /* Radeon NV-100 */
-#define PCI_DEVICE_ID_ATI_RADEON_N1    0x5159
-#define PCI_DEVICE_ID_ATI_RADEON_N2    0x515a
 /* Radeon RV250 (9000) */
 #define PCI_DEVICE_ID_ATI_RADEON_Id    0x4964
 #define PCI_DEVICE_ID_ATI_RADEON_Ie    0x4965
 #define PCI_DEVICE_ID_ATI_RADEON_If    0x4966
 #define PCI_DEVICE_ID_ATI_RADEON_Ig    0x4967
 /* Radeon RV280 (9200) */
-#define PCI_DEVICE_ID_ATI_RADEON_Y_    0x5960
 #define PCI_DEVICE_ID_ATI_RADEON_Ya    0x5961
 #define PCI_DEVICE_ID_ATI_RADEON_Yd    0x5964
 /* Radeon R300 (9500) */
-#define PCI_DEVICE_ID_ATI_RADEON_AD    0x4144
 /* Radeon R300 (9700) */
 #define PCI_DEVICE_ID_ATI_RADEON_ND    0x4e44
 #define PCI_DEVICE_ID_ATI_RADEON_NE    0x4e45
 #define PCI_DEVICE_ID_ATI_RADEON_NF    0x4e46
 #define PCI_DEVICE_ID_ATI_RADEON_NG    0x4e47
-#define PCI_DEVICE_ID_ATI_RADEON_AE    0x4145
-#define PCI_DEVICE_ID_ATI_RADEON_AF    0x4146
 /* Radeon R350 (9800) */
-#define PCI_DEVICE_ID_ATI_RADEON_NH    0x4e48
-#define PCI_DEVICE_ID_ATI_RADEON_NI    0x4e49
 /* Radeon RV350 (9600) */
-#define PCI_DEVICE_ID_ATI_RADEON_AP    0x4150
-#define PCI_DEVICE_ID_ATI_RADEON_AR    0x4152
 /* Radeon M6 */
 #define PCI_DEVICE_ID_ATI_RADEON_LY    0x4c59
 #define PCI_DEVICE_ID_ATI_RADEON_LZ    0x4c5a
 #define PCI_DEVICE_ID_ATI_RADEON_Lf    0x4c66
 #define PCI_DEVICE_ID_ATI_RADEON_Lg    0x4c67
 /* Radeon */
-#define PCI_DEVICE_ID_ATI_RADEON_RA    0x5144
-#define PCI_DEVICE_ID_ATI_RADEON_RB    0x5145
-#define PCI_DEVICE_ID_ATI_RADEON_RC    0x5146
-#define PCI_DEVICE_ID_ATI_RADEON_RD    0x5147
 /* RadeonIGP */
 #define PCI_DEVICE_ID_ATI_RS100                0xcab0
 #define PCI_DEVICE_ID_ATI_RS200                0xcab2
 #define PCI_DEVICE_ID_CIRRUS_5465      0x00d6
 #define PCI_DEVICE_ID_CIRRUS_6729      0x1100
 #define PCI_DEVICE_ID_CIRRUS_6832      0x1110
-#define PCI_DEVICE_ID_CIRRUS_7542      0x1200
 #define PCI_DEVICE_ID_CIRRUS_7543      0x1202
-#define PCI_DEVICE_ID_CIRRUS_7541      0x1204
 #define PCI_DEVICE_ID_CIRRUS_4610      0x6001
 #define PCI_DEVICE_ID_CIRRUS_4612      0x6003
 #define PCI_DEVICE_ID_CIRRUS_4615      0x6004
-#define PCI_DEVICE_ID_CIRRUS_4281      0x6005
 
 #define PCI_VENDOR_ID_IBM              0x1014
-#define PCI_DEVICE_ID_IBM_FIRE_CORAL   0x000a
 #define PCI_DEVICE_ID_IBM_TR           0x0018
-#define PCI_DEVICE_ID_IBM_82G2675      0x001d
-#define PCI_DEVICE_ID_IBM_MCA          0x0020
-#define PCI_DEVICE_ID_IBM_82351                0x0022
-#define PCI_DEVICE_ID_IBM_PYTHON       0x002d
-#define PCI_DEVICE_ID_IBM_SERVERAID    0x002e
 #define PCI_DEVICE_ID_IBM_TR_WAKE      0x003e
-#define PCI_DEVICE_ID_IBM_MPIC         0x0046
-#define PCI_DEVICE_ID_IBM_3780IDSP     0x007d
-#define PCI_DEVICE_ID_IBM_CHUKAR       0x0096
 #define PCI_DEVICE_ID_IBM_CPC710_PCI64 0x00fc
-#define PCI_DEVICE_ID_IBM_CPC710_PCI32 0x0105
-#define        PCI_DEVICE_ID_IBM_405GP         0x0156
 #define PCI_DEVICE_ID_IBM_SNIPE                0x0180
-#define PCI_DEVICE_ID_IBM_SERVERAIDI960        0x01bd
 #define PCI_DEVICE_ID_IBM_CITRINE              0x028C
 #define PCI_DEVICE_ID_IBM_GEMSTONE             0xB166
-#define PCI_DEVICE_ID_IBM_MPIC_2       0xffff
 #define PCI_DEVICE_ID_IBM_ICOM_DEV_ID_1        0x0031
 #define PCI_DEVICE_ID_IBM_ICOM_DEV_ID_2        0x0219
 #define PCI_DEVICE_ID_IBM_ICOM_V2_TWO_PORTS_RVX                0x021A
 #define PCI_DEVICE_ID_IBM_ICOM_V2_ONE_PORT_RVX_ONE_PORT_MDM    0x0251
 #define PCI_DEVICE_ID_IBM_ICOM_FOUR_PORT_MODEL 0x252
 
-#define PCI_VENDOR_ID_COMPEX2          0x101a // pci.ids says "AT&T GIS (NCR)"
+#define PCI_VENDOR_ID_COMPEX2          0x101a /* pci.ids says "AT&T GIS (NCR)" */
 #define PCI_DEVICE_ID_COMPEX2_100VG    0x0005
 
 #define PCI_VENDOR_ID_WD               0x101c
-#define PCI_DEVICE_ID_WD_7197          0x3296
 #define PCI_DEVICE_ID_WD_90C           0xc24a
 
 #define PCI_VENDOR_ID_AMI              0x101e
 #define PCI_DEVICE_ID_AMD_FE_GATE_7006 0x7006
 #define PCI_DEVICE_ID_AMD_FE_GATE_7007 0x7007
 #define PCI_DEVICE_ID_AMD_FE_GATE_700C 0x700C
-#define PCI_DEVICE_ID_AMD_FE_GATE_700D 0x700D
 #define PCI_DEVICE_ID_AMD_FE_GATE_700E 0x700E
-#define PCI_DEVICE_ID_AMD_FE_GATE_700F 0x700F
-#define PCI_DEVICE_ID_AMD_COBRA_7400   0x7400
 #define PCI_DEVICE_ID_AMD_COBRA_7401   0x7401
-#define PCI_DEVICE_ID_AMD_COBRA_7403   0x7403
-#define PCI_DEVICE_ID_AMD_COBRA_7404   0x7404
-#define PCI_DEVICE_ID_AMD_VIPER_7408   0x7408
 #define PCI_DEVICE_ID_AMD_VIPER_7409   0x7409
 #define PCI_DEVICE_ID_AMD_VIPER_740B   0x740B
-#define PCI_DEVICE_ID_AMD_VIPER_740C   0x740C
 #define PCI_DEVICE_ID_AMD_VIPER_7410   0x7410
 #define PCI_DEVICE_ID_AMD_VIPER_7411   0x7411
 #define PCI_DEVICE_ID_AMD_VIPER_7413   0x7413
-#define PCI_DEVICE_ID_AMD_VIPER_7414   0x7414
-#define PCI_DEVICE_ID_AMD_OPUS_7440    0x7440
-#      define PCI_DEVICE_ID_AMD_VIPER_7440     PCI_DEVICE_ID_AMD_OPUS_7440
+#define PCI_DEVICE_ID_AMD_VIPER_7440   0x7440
 #define PCI_DEVICE_ID_AMD_OPUS_7441    0x7441
-#      define PCI_DEVICE_ID_AMD_VIPER_7441     PCI_DEVICE_ID_AMD_OPUS_7441
 #define PCI_DEVICE_ID_AMD_OPUS_7443    0x7443
-#      define PCI_DEVICE_ID_AMD_VIPER_7443     PCI_DEVICE_ID_AMD_OPUS_7443
+#define PCI_DEVICE_ID_AMD_VIPER_7443   0x7443
 #define PCI_DEVICE_ID_AMD_OPUS_7445    0x7445
-#define PCI_DEVICE_ID_AMD_OPUS_7448    0x7448
-# define       PCI_DEVICE_ID_AMD_VIPER_7448    PCI_DEVICE_ID_AMD_OPUS_7448
-#define PCI_DEVICE_ID_AMD_OPUS_7449    0x7449
-#      define PCI_DEVICE_ID_AMD_VIPER_7449     PCI_DEVICE_ID_AMD_OPUS_7449
-#define PCI_DEVICE_ID_AMD_8111_LAN     0x7462
 #define PCI_DEVICE_ID_AMD_8111_LPC     0x7468
 #define PCI_DEVICE_ID_AMD_8111_IDE     0x7469
 #define PCI_DEVICE_ID_AMD_8111_SMBUS2  0x746a
 #define PCI_DEVICE_ID_CT_65550         0x00e0
 #define PCI_DEVICE_ID_CT_65554         0x00e4
 #define PCI_DEVICE_ID_CT_65555         0x00e5
-#define PCI_DEVICE_ID_CT_69000         0x00c0
 
 #define PCI_VENDOR_ID_MIRO             0x1031
 #define PCI_DEVICE_ID_MIRO_36050       0x5601
 #define PCI_DEVICE_ID_SI_550           0x0550
 #define PCI_DEVICE_ID_SI_540_VGA       0x5300
 #define PCI_DEVICE_ID_SI_550_VGA       0x5315
-#define PCI_DEVICE_ID_SI_601           0x0601
 #define PCI_DEVICE_ID_SI_620           0x0620
 #define PCI_DEVICE_ID_SI_630           0x0630
 #define PCI_DEVICE_ID_SI_633           0x0633
 #define PCI_DEVICE_ID_SI_648           0x0648
 #define PCI_DEVICE_ID_SI_650           0x0650
 #define PCI_DEVICE_ID_SI_651           0x0651
-#define PCI_DEVICE_ID_SI_652           0x0652
 #define PCI_DEVICE_ID_SI_655           0x0655
 #define PCI_DEVICE_ID_SI_661           0x0661
 #define PCI_DEVICE_ID_SI_730           0x0730
 #define PCI_DEVICE_ID_SI_733           0x0733
 #define PCI_DEVICE_ID_SI_630_VGA       0x6300
-#define PCI_DEVICE_ID_SI_730_VGA       0x7300
 #define PCI_DEVICE_ID_SI_735           0x0735
 #define PCI_DEVICE_ID_SI_740           0x0740
 #define PCI_DEVICE_ID_SI_741           0x0741
 #define PCI_DEVICE_ID_SI_745           0x0745
 #define PCI_DEVICE_ID_SI_746           0x0746
-#define PCI_DEVICE_ID_SI_748           0x0748
-#define PCI_DEVICE_ID_SI_750           0x0750
-#define PCI_DEVICE_ID_SI_751           0x0751
-#define PCI_DEVICE_ID_SI_752           0x0752
 #define PCI_DEVICE_ID_SI_755           0x0755
 #define PCI_DEVICE_ID_SI_760           0x0760
 #define PCI_DEVICE_ID_SI_900           0x0900
 #define PCI_DEVICE_ID_SI_961           0x0961
 #define PCI_DEVICE_ID_SI_962           0x0962
 #define PCI_DEVICE_ID_SI_963           0x0963
-#define PCI_DEVICE_ID_SI_5107          0x5107
-#define PCI_DEVICE_ID_SI_5300          0x5300
 #define PCI_DEVICE_ID_SI_5511          0x5511
 #define PCI_DEVICE_ID_SI_5513          0x5513
 #define PCI_DEVICE_ID_SI_5518          0x5518
 #define PCI_DEVICE_ID_SI_5597          0x5597
 #define PCI_DEVICE_ID_SI_5598          0x5598
 #define PCI_DEVICE_ID_SI_5600          0x5600
-#define PCI_DEVICE_ID_SI_6300          0x6300
-#define PCI_DEVICE_ID_SI_6306          0x6306
-#define PCI_DEVICE_ID_SI_6326          0x6326
-#define PCI_DEVICE_ID_SI_7001          0x7001
 #define PCI_DEVICE_ID_SI_7012          0x7012
 #define PCI_DEVICE_ID_SI_7013          0x7013
 #define PCI_DEVICE_ID_SI_7016          0x7016
 #define PCI_DEVICE_ID_HP_DIVA_TOSCA1   0x1049
 #define PCI_DEVICE_ID_HP_DIVA_TOSCA2   0x104A
 #define PCI_DEVICE_ID_HP_DIVA_MAESTRO  0x104B
-#define PCI_DEVICE_ID_HP_PCI_LBA       0x1054
-#define PCI_DEVICE_ID_HP_REO_SBA       0x10f0
 #define PCI_DEVICE_ID_HP_REO_IOC       0x10f1
 #define PCI_DEVICE_ID_HP_VISUALIZE_FXE 0x108b
 #define PCI_DEVICE_ID_HP_DIVA_HALFDOME 0x1223
 #define PCI_DEVICE_ID_HP_DIVA_KEYSTONE 0x1226
 #define PCI_DEVICE_ID_HP_DIVA_POWERBAR 0x1227
-#define PCI_DEVICE_ID_HP_ZX1_SBA       0x1229
 #define PCI_DEVICE_ID_HP_ZX1_IOC       0x122a
 #define PCI_DEVICE_ID_HP_PCIX_LBA      0x122e
 #define PCI_DEVICE_ID_HP_SX1000_IOC    0x127c
 #define PCI_DEVICE_ID_HP_DIVA_AUX      0x1290
 #define PCI_DEVICE_ID_HP_DIVA_RMP3     0x1301
 #define PCI_DEVICE_ID_HP_DIVA_HURRICANE        0x132a
-#define PCI_DEVICE_ID_HP_CISS          0x3210
 #define PCI_DEVICE_ID_HP_CISSA         0x3220
-#define PCI_DEVICE_ID_HP_CISSB         0x3222
 #define PCI_DEVICE_ID_HP_CISSC         0x3230
 #define PCI_DEVICE_ID_HP_CISSD         0x3238
 #define PCI_DEVICE_ID_HP_ZX2_IOC       0x4031
 #define PCI_VENDOR_ID_PCTECH           0x1042
 #define PCI_DEVICE_ID_PCTECH_RZ1000    0x1000
 #define PCI_DEVICE_ID_PCTECH_RZ1001    0x1001
-#define PCI_DEVICE_ID_PCTECH_SAMURAI_0 0x3000
-#define PCI_DEVICE_ID_PCTECH_SAMURAI_1 0x3010
 #define PCI_DEVICE_ID_PCTECH_SAMURAI_IDE 0x3020
 
 #define PCI_VENDOR_ID_ASUSTEK          0x1043
 #define PCI_DEVICE_ID_DPT              0xa400
 
 #define PCI_VENDOR_ID_OPTI             0x1045
-#define PCI_DEVICE_ID_OPTI_92C178      0xc178
-#define PCI_DEVICE_ID_OPTI_82C557      0xc557
 #define PCI_DEVICE_ID_OPTI_82C558      0xc558
 #define PCI_DEVICE_ID_OPTI_82C621      0xc621
 #define PCI_DEVICE_ID_OPTI_82C700      0xc700
-#define PCI_DEVICE_ID_OPTI_82C701      0xc701
-#define PCI_DEVICE_ID_OPTI_82C814      0xc814
-#define PCI_DEVICE_ID_OPTI_82C822      0xc822
-#define PCI_DEVICE_ID_OPTI_82C861      0xc861
 #define PCI_DEVICE_ID_OPTI_82C825      0xd568
 
 #define PCI_VENDOR_ID_ELSA             0x1048
 #define PCI_DEVICE_ID_ELSA_MICROLINK   0x1000
 #define PCI_DEVICE_ID_ELSA_QS3000      0x3000
 
-#define PCI_VENDOR_ID_SGS              0x104a
-#define PCI_DEVICE_ID_SGS_2000         0x0008
-#define PCI_DEVICE_ID_SGS_1764         0x0009
 
 #define PCI_VENDOR_ID_BUSLOGIC               0x104B
 #define PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER_NC 0x0140
 #define PCI_DEVICE_ID_BUSLOGIC_FLASHPOINT     0x8130
 
 #define PCI_VENDOR_ID_TI               0x104c
-#define PCI_DEVICE_ID_TI_TVP4010       0x3d04
 #define PCI_DEVICE_ID_TI_TVP4020       0x3d07
 #define PCI_DEVICE_ID_TI_4450          0x8011
 #define PCI_DEVICE_ID_TI_XX21_XX11     0x8031
 #define PCI_DEVICE_ID_TI_X420          0xac8e
 
 #define PCI_VENDOR_ID_SONY             0x104d
-#define PCI_DEVICE_ID_SONY_CXD3222     0x8039
 
-#define PCI_VENDOR_ID_OAK              0x104e
-#define PCI_DEVICE_ID_OAK_OTI107       0x0107
 
 /* Winbond have two vendor IDs! See 0x10ad as well */
 #define PCI_VENDOR_ID_WINBOND2         0x1050
-#define PCI_DEVICE_ID_WINBOND2_89C940  0x0940
 #define PCI_DEVICE_ID_WINBOND2_89C940F 0x5a5a
 #define PCI_DEVICE_ID_WINBOND2_6692    0x6692
 
   
 #define PCI_VENDOR_ID_EFAR             0x1055
 #define PCI_DEVICE_ID_EFAR_SLC90E66_1  0x9130
-#define PCI_DEVICE_ID_EFAR_SLC90E66_0  0x9460
-#define PCI_DEVICE_ID_EFAR_SLC90E66_2  0x9462
 #define PCI_DEVICE_ID_EFAR_SLC90E66_3  0x9463
 
 #define PCI_VENDOR_ID_MOTOROLA         0x1057
-#define PCI_VENDOR_ID_MOTOROLA_OOPS    0x1507
 #define PCI_DEVICE_ID_MOTOROLA_MPC105  0x0001
 #define PCI_DEVICE_ID_MOTOROLA_MPC106  0x0002
 #define PCI_DEVICE_ID_MOTOROLA_MPC107  0x0004
 #define PCI_DEVICE_ID_MOTOROLA_RAVEN   0x4801
 #define PCI_DEVICE_ID_MOTOROLA_FALCON  0x4802
 #define PCI_DEVICE_ID_MOTOROLA_HAWK    0x4803
-#define PCI_DEVICE_ID_MOTOROLA_CPX8216 0x4806
 #define PCI_DEVICE_ID_MOTOROLA_HARRIER 0x480b
 #define PCI_DEVICE_ID_MOTOROLA_MPC5200 0x5803
 
 #define PCI_DEVICE_ID_PROMISE_20262    0x4d38
 #define PCI_DEVICE_ID_PROMISE_20263    0x0D38
 #define PCI_DEVICE_ID_PROMISE_20268    0x4d68
-#define PCI_DEVICE_ID_PROMISE_20268R   0x6268
 #define PCI_DEVICE_ID_PROMISE_20269    0x4d69
 #define PCI_DEVICE_ID_PROMISE_20270    0x6268
 #define PCI_DEVICE_ID_PROMISE_20271    0x6269
 #define PCI_DEVICE_ID_PROMISE_20275    0x1275
 #define PCI_DEVICE_ID_PROMISE_20276    0x5275
 #define PCI_DEVICE_ID_PROMISE_20277    0x7275
-#define PCI_DEVICE_ID_PROMISE_5300     0x5300
 
-#define PCI_VENDOR_ID_N9               0x105d
-#define PCI_DEVICE_ID_N9_I128          0x2309
-#define PCI_DEVICE_ID_N9_I128_2                0x2339
-#define PCI_DEVICE_ID_N9_I128_T2R      0x493d
 
 #define PCI_VENDOR_ID_UMC              0x1060
 #define PCI_DEVICE_ID_UMC_UM8673F      0x0101
-#define PCI_DEVICE_ID_UMC_UM8891A      0x0891
 #define PCI_DEVICE_ID_UMC_UM8886BF     0x673a
 #define PCI_DEVICE_ID_UMC_UM8886A      0x886a
-#define PCI_DEVICE_ID_UMC_UM8881F      0x8881
-#define PCI_DEVICE_ID_UMC_UM8886F      0x8886
-#define PCI_DEVICE_ID_UMC_UM9017F      0x9017
-#define PCI_DEVICE_ID_UMC_UM8886N      0xe886
-#define PCI_DEVICE_ID_UMC_UM8891N      0xe891
 
-#define PCI_VENDOR_ID_X                        0x1061
-#define PCI_DEVICE_ID_X_AGX016         0x0001
 
 #define PCI_VENDOR_ID_MYLEX            0x1069
 #define PCI_DEVICE_ID_MYLEX_DAC960_P   0x0001
 #define PCI_DEVICE_ID_MYLEX_DAC960_BA  0xBA56
 #define PCI_DEVICE_ID_MYLEX_DAC960_GEM 0xB166
 
-#define PCI_VENDOR_ID_PICOP            0x1066
-#define PCI_DEVICE_ID_PICOP_PT86C52X   0x0001
-#define PCI_DEVICE_ID_PICOP_PT80C524   0x8002
 
 #define PCI_VENDOR_ID_APPLE            0x106b
 #define PCI_DEVICE_ID_APPLE_BANDIT     0x0001
-#define PCI_DEVICE_ID_APPLE_GC         0x0002
 #define PCI_DEVICE_ID_APPLE_HYDRA      0x000e
 #define PCI_DEVICE_ID_APPLE_UNI_N_FW   0x0018
-#define PCI_DEVICE_ID_APPLE_KL_USB     0x0019
 #define PCI_DEVICE_ID_APPLE_UNI_N_AGP  0x0020
 #define PCI_DEVICE_ID_APPLE_UNI_N_GMAC 0x0021
-#define PCI_DEVICE_ID_APPLE_KEYLARGO   0x0022
 #define PCI_DEVICE_ID_APPLE_UNI_N_GMACP        0x0024
-#define PCI_DEVICE_ID_APPLE_KEYLARGO_P 0x0025
-#define PCI_DEVICE_ID_APPLE_KL_USB_P   0x0026
 #define PCI_DEVICE_ID_APPLE_UNI_N_AGP_P        0x0027
 #define PCI_DEVICE_ID_APPLE_UNI_N_AGP15        0x002d
 #define PCI_DEVICE_ID_APPLE_UNI_N_PCI15        0x002e
-#define PCI_DEVICE_ID_APPLE_UNI_N_FW2  0x0030
 #define PCI_DEVICE_ID_APPLE_UNI_N_GMAC2        0x0032
 #define PCI_DEVICE_ID_APPLE_UNI_N_ATA  0x0033
 #define PCI_DEVICE_ID_APPLE_UNI_N_AGP2 0x0034
 #define PCI_DEVICE_ID_APPLE_IPID_ATA100        0x003b
-#define PCI_DEVICE_ID_APPLE_KEYLARGO_I 0x003e
 #define PCI_DEVICE_ID_APPLE_K2_ATA100  0x0043
 #define PCI_DEVICE_ID_APPLE_U3_AGP     0x004b
 #define PCI_DEVICE_ID_APPLE_K2_GMAC    0x004c
 #define PCI_DEVICE_ID_APPLE_SH_ATA      0x0050
 #define PCI_DEVICE_ID_APPLE_SH_SUNGEM   0x0051
-#define PCI_DEVICE_ID_APPLE_SH_FW       0x0052
 #define PCI_DEVICE_ID_APPLE_U3L_AGP    0x0058
 #define PCI_DEVICE_ID_APPLE_U3H_AGP    0x0059
 #define PCI_DEVICE_ID_APPLE_TIGON3     0x1645
 #define PCI_DEVICE_ID_YAMAHA_744       0x0010
 #define PCI_DEVICE_ID_YAMAHA_754       0x0012
 
-#define PCI_VENDOR_ID_NEXGEN           0x1074
-#define PCI_DEVICE_ID_NEXGEN_82C501    0x4e78
 
 #define PCI_VENDOR_ID_QLOGIC           0x1077
 #define PCI_DEVICE_ID_QLOGIC_ISP1020   0x1020
-#define PCI_DEVICE_ID_QLOGIC_ISP1022   0x1022
 #define PCI_DEVICE_ID_QLOGIC_ISP2100   0x2100
 #define PCI_DEVICE_ID_QLOGIC_ISP2200   0x2200
 #define PCI_DEVICE_ID_QLOGIC_ISP2300   0x2300
 #define PCI_DEVICE_ID_CYRIX_PCI_MASTER 0x0001
 #define PCI_DEVICE_ID_CYRIX_5520       0x0002
 #define PCI_DEVICE_ID_CYRIX_5530_LEGACY        0x0100
-#define PCI_DEVICE_ID_CYRIX_5530_SMI   0x0101
 #define PCI_DEVICE_ID_CYRIX_5530_IDE   0x0102
 #define PCI_DEVICE_ID_CYRIX_5530_AUDIO 0x0103
 #define PCI_DEVICE_ID_CYRIX_5530_VIDEO 0x0104
 
-#define PCI_VENDOR_ID_LEADTEK          0x107d
-#define PCI_DEVICE_ID_LEADTEK_805      0x0000
 
-#define PCI_VENDOR_ID_INTERPHASE       0x107e
-#define PCI_DEVICE_ID_INTERPHASE_5526  0x0004
-#define PCI_DEVICE_ID_INTERPHASE_55x6  0x0005
-#define PCI_DEVICE_ID_INTERPHASE_5575  0x0008
 
 #define PCI_VENDOR_ID_CONTAQ           0x1080
-#define PCI_DEVICE_ID_CONTAQ_82C599    0x0600
 #define PCI_DEVICE_ID_CONTAQ_82C693    0xc693
 
-#define PCI_VENDOR_ID_FOREX            0x1083
 
 #define PCI_VENDOR_ID_OLICOM           0x108d
-#define PCI_DEVICE_ID_OLICOM_OC3136    0x0001
-#define PCI_DEVICE_ID_OLICOM_OC2315    0x0011
 #define PCI_DEVICE_ID_OLICOM_OC2325    0x0012
 #define PCI_DEVICE_ID_OLICOM_OC2183    0x0013
 #define PCI_DEVICE_ID_OLICOM_OC2326    0x0014
-#define PCI_DEVICE_ID_OLICOM_OC6151    0x0021
 
 #define PCI_VENDOR_ID_SUN              0x108e
 #define PCI_DEVICE_ID_SUN_EBUS         0x1000
 #define PCI_DEVICE_ID_SUN_CASSINI      0xabba
 
 #define PCI_VENDOR_ID_CMD              0x1095
-#define PCI_DEVICE_ID_CMD_640          0x0640
 #define PCI_DEVICE_ID_CMD_643          0x0643
 #define PCI_DEVICE_ID_CMD_646          0x0646
-#define PCI_DEVICE_ID_CMD_647          0x0647
 #define PCI_DEVICE_ID_CMD_648          0x0648
 #define PCI_DEVICE_ID_CMD_649          0x0649
-#define PCI_DEVICE_ID_CMD_670          0x0670
-#define PCI_DEVICE_ID_CMD_680          0x0680
 
 #define PCI_DEVICE_ID_SII_680          0x0680
 #define PCI_DEVICE_ID_SII_3112         0x3112
 #define PCI_DEVICE_ID_SII_1210SA       0x0240
 
-#define PCI_VENDOR_ID_VISION           0x1098
-#define PCI_DEVICE_ID_VISION_QD8500    0x0001
-#define PCI_DEVICE_ID_VISION_QD8580    0x0002
 
 #define PCI_VENDOR_ID_BROOKTREE                0x109e
-#define PCI_DEVICE_ID_BROOKTREE_848    0x0350
-#define PCI_DEVICE_ID_BROOKTREE_849A   0x0351
-#define PCI_DEVICE_ID_BROOKTREE_878_1  0x036e
 #define PCI_DEVICE_ID_BROOKTREE_878    0x0878
 #define PCI_DEVICE_ID_BROOKTREE_879    0x0879
-#define PCI_DEVICE_ID_BROOKTREE_8474   0x8474
 
-#define PCI_VENDOR_ID_SIERRA           0x10a8
-#define PCI_DEVICE_ID_SIERRA_STB       0x0000
 
 #define PCI_VENDOR_ID_SGI              0x10a9
 #define PCI_DEVICE_ID_SGI_IOC3         0x0003
 #define PCI_DEVICE_ID_SGI_IOC4         0x100a
 #define PCI_VENDOR_ID_SGI_LITHIUM      0x1002
 
-#define PCI_VENDOR_ID_ACC              0x10aa
-#define PCI_DEVICE_ID_ACC_2056         0x0000
 
 #define PCI_VENDOR_ID_WINBOND          0x10ad
-#define PCI_DEVICE_ID_WINBOND_83769    0x0001
 #define PCI_DEVICE_ID_WINBOND_82C105   0x0105
 #define PCI_DEVICE_ID_WINBOND_83C553   0x0565
 
-#define PCI_VENDOR_ID_DATABOOK         0x10b3
-#define PCI_DEVICE_ID_DATABOOK_87144   0xb106
 
 #define PCI_VENDOR_ID_PLX              0x10b5
 #define PCI_DEVICE_ID_PLX_R685         0x1030
 #define PCI_DEVICE_ID_PLX_DJINN_ITOO   0x1151
 #define PCI_DEVICE_ID_PLX_R753         0x1152
 #define PCI_DEVICE_ID_PLX_OLITEC       0x1187
-#define PCI_DEVICE_ID_PLX_9030         0x9030
 #define PCI_DEVICE_ID_PLX_9050         0x9050
-#define PCI_DEVICE_ID_PLX_9060         0x9060
-#define PCI_DEVICE_ID_PLX_9060ES       0x906E
-#define PCI_DEVICE_ID_PLX_9060SD       0x906D
 #define PCI_DEVICE_ID_PLX_9080         0x9080
 #define PCI_DEVICE_ID_PLX_GTEK_SERIAL2 0xa001
 
 #define PCI_VENDOR_ID_MADGE            0x10b6
 #define PCI_DEVICE_ID_MADGE_MK2                0x0002
-#define PCI_DEVICE_ID_MADGE_C155S      0x1001
 
 #define PCI_VENDOR_ID_3COM             0x10b7
 #define PCI_DEVICE_ID_3COM_3C985       0x0001
 #define PCI_DEVICE_ID_3COM_3C940       0x1700
 #define PCI_DEVICE_ID_3COM_3C339       0x3390
 #define PCI_DEVICE_ID_3COM_3C359       0x3590
-#define PCI_DEVICE_ID_3COM_3C590       0x5900
-#define PCI_DEVICE_ID_3COM_3C595TX     0x5950
-#define PCI_DEVICE_ID_3COM_3C595T4     0x5951
-#define PCI_DEVICE_ID_3COM_3C595MII    0x5952
 #define PCI_DEVICE_ID_3COM_3C940B      0x80eb
-#define PCI_DEVICE_ID_3COM_3C900TPO    0x9000
-#define PCI_DEVICE_ID_3COM_3C900COMBO  0x9001
-#define PCI_DEVICE_ID_3COM_3C905TX     0x9050
-#define PCI_DEVICE_ID_3COM_3C905T4     0x9051
-#define PCI_DEVICE_ID_3COM_3C905B_TX   0x9055
 #define PCI_DEVICE_ID_3COM_3CR990      0x9900
 #define PCI_DEVICE_ID_3COM_3CR990_TX_95        0x9902
 #define PCI_DEVICE_ID_3COM_3CR990_TX_97        0x9903
 #define PCI_DEVICE_ID_3COM_3CR990SVR97 0x9909
 #define PCI_DEVICE_ID_3COM_3CR990SVR   0x990a
 
-#define PCI_VENDOR_ID_SMC              0x10b8
-#define PCI_DEVICE_ID_SMC_EPIC100      0x0005
 
 #define PCI_VENDOR_ID_AL               0x10b9
-#define PCI_DEVICE_ID_AL_M1445         0x1445
-#define PCI_DEVICE_ID_AL_M1449         0x1449
-#define PCI_DEVICE_ID_AL_M1451         0x1451
-#define PCI_DEVICE_ID_AL_M1461         0x1461
-#define PCI_DEVICE_ID_AL_M1489         0x1489
-#define PCI_DEVICE_ID_AL_M1511         0x1511
-#define PCI_DEVICE_ID_AL_M1513         0x1513
-#define PCI_DEVICE_ID_AL_M1521         0x1521
-#define PCI_DEVICE_ID_AL_M1523         0x1523
-#define PCI_DEVICE_ID_AL_M1531         0x1531
 #define PCI_DEVICE_ID_AL_M1533         0x1533
 #define PCI_DEVICE_ID_AL_M1535                 0x1535
 #define PCI_DEVICE_ID_AL_M1541         0x1541
-#define PCI_DEVICE_ID_AL_M1543         0x1543
 #define PCI_DEVICE_ID_AL_M1563         0x1563
 #define PCI_DEVICE_ID_AL_M1621         0x1621
 #define PCI_DEVICE_ID_AL_M1631         0x1631
 #define PCI_DEVICE_ID_AL_M1681         0x1681
 #define PCI_DEVICE_ID_AL_M1683         0x1683
 #define PCI_DEVICE_ID_AL_M1689         0x1689
-#define PCI_DEVICE_ID_AL_M3307         0x3307
-#define PCI_DEVICE_ID_AL_M4803         0x5215
 #define PCI_DEVICE_ID_AL_M5219         0x5219
 #define PCI_DEVICE_ID_AL_M5228         0x5228
 #define PCI_DEVICE_ID_AL_M5229         0x5229
-#define PCI_DEVICE_ID_AL_M5237         0x5237
-#define PCI_DEVICE_ID_AL_M5243         0x5243
 #define PCI_DEVICE_ID_AL_M5451         0x5451
 #define PCI_DEVICE_ID_AL_M7101         0x7101
 
-#define PCI_VENDOR_ID_MITSUBISHI       0x10ba
 
-#define PCI_VENDOR_ID_SURECOM          0x10bd
-#define PCI_DEVICE_ID_SURECOM_NE34     0x0e34
 
 #define PCI_VENDOR_ID_NEOMAGIC         0x10c8
-#define PCI_DEVICE_ID_NEOMAGIC_MAGICGRAPH_NM2070 0x0001
-#define PCI_DEVICE_ID_NEOMAGIC_MAGICGRAPH_128V 0x0002
-#define PCI_DEVICE_ID_NEOMAGIC_MAGICGRAPH_128ZV 0x0003
-#define PCI_DEVICE_ID_NEOMAGIC_MAGICGRAPH_NM2160 0x0004
-#define PCI_DEVICE_ID_NEOMAGIC_MAGICMEDIA_256AV       0x0005
-#define PCI_DEVICE_ID_NEOMAGIC_MAGICGRAPH_128ZVPLUS   0x0083
 #define PCI_DEVICE_ID_NEOMAGIC_NM256AV_AUDIO 0x8005
 #define PCI_DEVICE_ID_NEOMAGIC_NM256ZX_AUDIO 0x8006
 #define PCI_DEVICE_ID_NEOMAGIC_NM256XL_PLUS_AUDIO 0x8016
 
-#define PCI_VENDOR_ID_ASP              0x10cd
-#define PCI_DEVICE_ID_ASP_ABP940       0x1200
-#define PCI_DEVICE_ID_ASP_ABP940U      0x1300
-#define PCI_DEVICE_ID_ASP_ABP940UW     0x2300
-
-#define PCI_VENDOR_ID_MACRONIX         0x10d9
-#define PCI_DEVICE_ID_MACRONIX_MX98713 0x0512
-#define PCI_DEVICE_ID_MACRONIX_MX987x5 0x0531
 
 #define PCI_VENDOR_ID_TCONRAD          0x10da
 #define PCI_DEVICE_ID_TCONRAD_TOKENRING        0x0508
 
-#define PCI_VENDOR_ID_CERN             0x10dc
-#define PCI_DEVICE_ID_CERN_SPSB_PMC    0x0001
-#define PCI_DEVICE_ID_CERN_SPSB_PCI    0x0002
-#define PCI_DEVICE_ID_CERN_HIPPI_DST   0x0021
-#define PCI_DEVICE_ID_CERN_HIPPI_SRC   0x0022
 
 #define PCI_VENDOR_ID_NVIDIA                   0x10de
 #define PCI_DEVICE_ID_NVIDIA_TNT               0x0020
 #define PCI_DEVICE_ID_QUADRO_FX_GO1400          0x00cc
 #define PCI_DEVICE_ID_QUADRO_FX_1400            0x00ce
 #define PCI_DEVICE_ID_NVIDIA_NFORCE3           0x00d1
-#define PCI_DEVICE_ID_NVIDIA_MCP3_AUDIO                0x00da
 #define PCI_DEVICE_ID_NVIDIA_NFORCE3_SMBUS     0x00d4
 #define PCI_DEVICE_ID_NVIDIA_NFORCE3_IDE       0x00d5
 #define PCI_DEVICE_ID_NVIDIA_NVENET_3          0x00d6
 #define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_SATA2        0x037F
 #define PCI_DEVICE_ID_NVIDIA_NVENET_12         0x0268
 #define PCI_DEVICE_ID_NVIDIA_NVENET_13         0x0269
-#define PCI_DEVICE_ID_NVIDIA_MCP51_AUDIO       0x026B
 #define PCI_DEVICE_ID_NVIDIA_GEFORCE4_TI_4800  0x0280
 #define PCI_DEVICE_ID_NVIDIA_GEFORCE4_TI_4800_8X    0x0281
 #define PCI_DEVICE_ID_NVIDIA_GEFORCE4_TI_4800SE     0x0282
 #define PCI_DEVICE_ID_NVIDIA_NVENET_15              0x0373
 
 #define PCI_VENDOR_ID_IMS              0x10e0
-#define PCI_DEVICE_ID_IMS_8849         0x8849
 #define PCI_DEVICE_ID_IMS_TT128                0x9128
 #define PCI_DEVICE_ID_IMS_TT3D         0x9135
 
-#define PCI_VENDOR_ID_TEKRAM2          0x10e1
-#define PCI_DEVICE_ID_TEKRAM2_690c     0x690c
 
-#define PCI_VENDOR_ID_TUNDRA           0x10e3
-#define PCI_DEVICE_ID_TUNDRA_CA91C042  0x0000
 
-#define PCI_VENDOR_ID_AMCC             0x10e8
-#define PCI_DEVICE_ID_AMCC_MYRINET     0x8043
-#define PCI_DEVICE_ID_AMCC_PARASTATION 0x8062
-#define PCI_DEVICE_ID_AMCC_S5933       0x807d
-#define PCI_DEVICE_ID_AMCC_S5933_HEPC3 0x809c
 
 #define PCI_VENDOR_ID_INTERG           0x10ea
-#define PCI_DEVICE_ID_INTERG_1680      0x1680
 #define PCI_DEVICE_ID_INTERG_1682      0x1682
 #define PCI_DEVICE_ID_INTERG_2000      0x2000
 #define PCI_DEVICE_ID_INTERG_2010      0x2010
 #define PCI_DEVICE_ID_INTERG_5050      0x5050
 
 #define PCI_VENDOR_ID_REALTEK          0x10ec
-#define PCI_DEVICE_ID_REALTEK_8029     0x8029
-#define PCI_DEVICE_ID_REALTEK_8129     0x8129
 #define PCI_DEVICE_ID_REALTEK_8139     0x8139
-#define PCI_DEVICE_ID_REALTEK_8169     0x8169
 
 #define PCI_VENDOR_ID_XILINX           0x10ee
 #define PCI_DEVICE_ID_RME_DIGI96       0x3fc0
 #define PCI_DEVICE_ID_RME_DIGI96_8     0x3fc1
 #define PCI_DEVICE_ID_RME_DIGI96_8_PRO 0x3fc2
 #define PCI_DEVICE_ID_RME_DIGI96_8_PAD_OR_PST 0x3fc3
-#define PCI_DEVICE_ID_XILINX_HAMMERFALL        0x3fc4
 #define PCI_DEVICE_ID_XILINX_HAMMERFALL_DSP 0x3fc5
 #define PCI_DEVICE_ID_XILINX_HAMMERFALL_DSP_MADI 0x3fc6
-#define PCI_DEVICE_ID_TURBOPAM         0x4020
 
-#define PCI_VENDOR_ID_TRUEVISION       0x10fa
-#define PCI_DEVICE_ID_TRUEVISION_T1000 0x000c
 
 #define PCI_VENDOR_ID_INIT             0x1101
-#define PCI_DEVICE_ID_INIT_320P                0x9100
-#define PCI_DEVICE_ID_INIT_360P                0x9500
 
-#define PCI_VENDOR_ID_CREATIVE         0x1102 // duplicate: ECTIVA
+#define PCI_VENDOR_ID_CREATIVE         0x1102 /* duplicate: ECTIVA */
 #define PCI_DEVICE_ID_CREATIVE_EMU10K1 0x0002
 
-#define PCI_VENDOR_ID_ECTIVA           0x1102 // duplicate: CREATIVE
+#define PCI_VENDOR_ID_ECTIVA           0x1102 /* duplicate: CREATIVE */
 #define PCI_DEVICE_ID_ECTIVA_EV1938    0x8938
 
 #define PCI_VENDOR_ID_TTI              0x1103
 #define PCI_DEVICE_ID_TTI_HPT302       0x0006
 #define PCI_DEVICE_ID_TTI_HPT371       0x0007
 #define PCI_DEVICE_ID_TTI_HPT374       0x0008
-#define PCI_DEVICE_ID_TTI_HPT372N      0x0009  // apparently a 372N variant?
+#define PCI_DEVICE_ID_TTI_HPT372N      0x0009  /* apparently a 372N variant? */
 
 #define PCI_VENDOR_ID_VIA              0x1106
 #define PCI_DEVICE_ID_VIA_8763_0       0x0198
 #define PCI_DEVICE_ID_VIA_8363_0       0x0305
 #define PCI_DEVICE_ID_VIA_8371_0       0x0391
 #define PCI_DEVICE_ID_VIA_8501_0       0x0501
-#define PCI_DEVICE_ID_VIA_82C505       0x0505
 #define PCI_DEVICE_ID_VIA_82C561       0x0561
 #define PCI_DEVICE_ID_VIA_82C586_1     0x0571
 #define PCI_DEVICE_ID_VIA_82C576       0x0576
-#define PCI_DEVICE_ID_VIA_82C585       0x0585
 #define PCI_DEVICE_ID_VIA_82C586_0     0x0586
-#define PCI_DEVICE_ID_VIA_82C595       0x0595
 #define PCI_DEVICE_ID_VIA_82C596       0x0596
 #define PCI_DEVICE_ID_VIA_82C597_0     0x0597
 #define PCI_DEVICE_ID_VIA_82C598_0     0x0598
 #define PCI_DEVICE_ID_VIA_8601_0       0x0601
 #define PCI_DEVICE_ID_VIA_8605_0       0x0605
-#define PCI_DEVICE_ID_VIA_82C680       0x0680
 #define PCI_DEVICE_ID_VIA_82C686       0x0686
 #define PCI_DEVICE_ID_VIA_82C691_0     0x0691
-#define PCI_DEVICE_ID_VIA_82C693       0x0693
-#define PCI_DEVICE_ID_VIA_82C693_1     0x0698
-#define PCI_DEVICE_ID_VIA_82C926       0x0926
 #define PCI_DEVICE_ID_VIA_82C576_1     0x1571
-#define PCI_DEVICE_ID_VIA_82C595_97    0x1595
 #define PCI_DEVICE_ID_VIA_82C586_2     0x3038
 #define PCI_DEVICE_ID_VIA_82C586_3     0x3040
-#define PCI_DEVICE_ID_VIA_6305         0x3044
 #define PCI_DEVICE_ID_VIA_82C596_3     0x3050
 #define PCI_DEVICE_ID_VIA_82C596B_3    0x3051
 #define PCI_DEVICE_ID_VIA_82C686_4     0x3057
 #define PCI_DEVICE_ID_VIA_82C686_5     0x3058
 #define PCI_DEVICE_ID_VIA_8233_5       0x3059
-#define PCI_DEVICE_ID_VIA_8233_7       0x3065
-#define PCI_DEVICE_ID_VIA_82C686_6     0x3068
 #define PCI_DEVICE_ID_VIA_8233_0       0x3074
 #define PCI_DEVICE_ID_VIA_8633_0       0x3091
 #define PCI_DEVICE_ID_VIA_8367_0       0x3099
 #define PCI_DEVICE_ID_VIA_XN266                0x3156
 #define PCI_DEVICE_ID_VIA_8754C_0      0x3168
 #define PCI_DEVICE_ID_VIA_8235         0x3177
-#define PCI_DEVICE_ID_VIA_P4N333       0x3178
 #define PCI_DEVICE_ID_VIA_8385_0       0x3188
 #define PCI_DEVICE_ID_VIA_8377_0       0x3189
 #define PCI_DEVICE_ID_VIA_8378_0       0x3205
 #define PCI_DEVICE_ID_VIA_8783_0       0x3208
-#define PCI_DEVICE_ID_VIA_P4M400       0x3209
 #define PCI_DEVICE_ID_VIA_8237         0x3227
 #define PCI_DEVICE_ID_VIA_3296_0       0x0296
-#define PCI_DEVICE_ID_VIA_86C100A      0x6100
 #define PCI_DEVICE_ID_VIA_8231         0x8231
 #define PCI_DEVICE_ID_VIA_8231_4       0x8235
 #define PCI_DEVICE_ID_VIA_8365_1       0x8305
 #define PCI_DEVICE_ID_VIA_8371_1       0x8391
-#define PCI_DEVICE_ID_VIA_8501_1       0x8501
-#define PCI_DEVICE_ID_VIA_82C597_1     0x8597
 #define PCI_DEVICE_ID_VIA_82C598_1     0x8598
-#define PCI_DEVICE_ID_VIA_8601_1       0x8601
-#define PCI_DEVICE_ID_VIA_8505_1       0x8605
-#define PCI_DEVICE_ID_VIA_8633_1       0xB091
-#define PCI_DEVICE_ID_VIA_8367_1       0xB099
-#define PCI_DEVICE_ID_VIA_P4X266_1     0xB101
-#define PCI_DEVICE_ID_VIA_8615_1       0xB103
-#define PCI_DEVICE_ID_VIA_8361_1       0xB112
-#define PCI_DEVICE_ID_VIA_8235_1       0xB168
 #define PCI_DEVICE_ID_VIA_838X_1       0xB188
 #define PCI_DEVICE_ID_VIA_83_87XX_1    0xB198
 
 #define PCI_VENDOR_ID_SIEMENS           0x110A
 #define PCI_DEVICE_ID_SIEMENS_DSCC4     0x2102
 
-#define PCI_VENDOR_ID_SMC2             0x1113
-#define PCI_DEVICE_ID_SMC2_1211TX      0x1211
 
 #define PCI_VENDOR_ID_VORTEX           0x1119
 #define PCI_DEVICE_ID_VORTEX_GDT60x0   0x0000
 #define PCI_DEVICE_ID_VORTEX_GDT6557RP 0x0103
 #define PCI_DEVICE_ID_VORTEX_GDT6x11RP 0x0104
 #define PCI_DEVICE_ID_VORTEX_GDT6x21RP 0x0105
-#define PCI_DEVICE_ID_VORTEX_GDT6x17RP1        0x0110
-#define PCI_DEVICE_ID_VORTEX_GDT6x27RP1        0x0111
-#define PCI_DEVICE_ID_VORTEX_GDT6537RP1        0x0112
-#define PCI_DEVICE_ID_VORTEX_GDT6557RP1        0x0113
-#define PCI_DEVICE_ID_VORTEX_GDT6x11RP1        0x0114
-#define PCI_DEVICE_ID_VORTEX_GDT6x21RP1        0x0115
-#define PCI_DEVICE_ID_VORTEX_GDT6x17RP2        0x0120
-#define PCI_DEVICE_ID_VORTEX_GDT6x27RP2        0x0121
-#define PCI_DEVICE_ID_VORTEX_GDT6537RP2        0x0122
-#define PCI_DEVICE_ID_VORTEX_GDT6557RP2        0x0123
-#define PCI_DEVICE_ID_VORTEX_GDT6x11RP2        0x0124
-#define PCI_DEVICE_ID_VORTEX_GDT6x21RP2        0x0125
 
 #define PCI_VENDOR_ID_EF               0x111a
 #define PCI_DEVICE_ID_EF_ATM_FPGA      0x0000
 #define PCI_DEVICE_ID_IDT_IDT77201     0x0001
 
 #define PCI_VENDOR_ID_FORE             0x1127
-#define PCI_DEVICE_ID_FORE_PCA200PC    0x0210
 #define PCI_DEVICE_ID_FORE_PCA200E     0x0300
 
-#define PCI_VENDOR_ID_IMAGINGTECH      0x112f
-#define PCI_DEVICE_ID_IMAGINGTECH_ICPCI        0x0000
 
 #define PCI_VENDOR_ID_PHILIPS          0x1131
-#define PCI_DEVICE_ID_PHILIPS_SAA7145  0x7145
 #define PCI_DEVICE_ID_PHILIPS_SAA7146  0x7146
 #define PCI_DEVICE_ID_PHILIPS_SAA9730  0x9730
 
 #define PCI_VENDOR_ID_EICON            0x1133
-#define PCI_DEVICE_ID_EICON_DIVA20PRO  0xe001
 #define PCI_DEVICE_ID_EICON_DIVA20     0xe002
-#define PCI_DEVICE_ID_EICON_DIVA20PRO_U        0xe003
 #define PCI_DEVICE_ID_EICON_DIVA20_U   0xe004
 #define PCI_DEVICE_ID_EICON_DIVA201    0xe005
 #define PCI_DEVICE_ID_EICON_DIVA202    0xe00b
 #define PCI_VENDOR_ID_ZIATECH          0x1138
 #define PCI_DEVICE_ID_ZIATECH_5550_HC  0x5550
  
-#define PCI_VENDOR_ID_CYCLONE          0x113c
-#define PCI_DEVICE_ID_CYCLONE_SDK      0x0001
 
-#define PCI_VENDOR_ID_ALLIANCE         0x1142
-#define PCI_DEVICE_ID_ALLIANCE_PROMOTIO        0x3210
-#define PCI_DEVICE_ID_ALLIANCE_PROVIDEO        0x6422
-#define PCI_DEVICE_ID_ALLIANCE_AT24    0x6424
-#define PCI_DEVICE_ID_ALLIANCE_AT3D    0x643d
 
 #define PCI_VENDOR_ID_SYSKONNECT       0x1148
-#define PCI_DEVICE_ID_SYSKONNECT_FP    0x4000
 #define PCI_DEVICE_ID_SYSKONNECT_TR    0x4200
 #define PCI_DEVICE_ID_SYSKONNECT_GE    0x4300
 #define PCI_DEVICE_ID_SYSKONNECT_YU    0x4320
 #define PCI_DEVICE_ID_SYSKONNECT_9DXX  0x4400
 #define PCI_DEVICE_ID_SYSKONNECT_9MXX  0x4500
 
-#define PCI_VENDOR_ID_VMIC             0x114a
-#define PCI_DEVICE_ID_VMIC_VME         0x7587
 
 #define PCI_VENDOR_ID_DIGI             0x114f
-#define PCI_DEVICE_ID_DIGI_EPC         0x0002
-#define PCI_DEVICE_ID_DIGI_RIGHTSWITCH 0x0003
-#define PCI_DEVICE_ID_DIGI_XEM         0x0004
-#define PCI_DEVICE_ID_DIGI_XR          0x0005
-#define PCI_DEVICE_ID_DIGI_CX          0x0006
-#define PCI_DEVICE_ID_DIGI_XRJ         0x0009
-#define PCI_DEVICE_ID_DIGI_EPCJ                0x000a
-#define PCI_DEVICE_ID_DIGI_XR_920      0x0027
 #define PCI_DEVICE_ID_DIGI_DF_M_IOM2_E 0x0070
 #define PCI_DEVICE_ID_DIGI_DF_M_E      0x0071
 #define PCI_DEVICE_ID_DIGI_DF_M_IOM2_A 0x0072
 #define PCI_DEVICE_ID_NEO_2RJ45         0x00CA
 #define PCI_DEVICE_ID_NEO_2RJ45PRI      0x00CB
 
-#define PCI_VENDOR_ID_MUTECH           0x1159
-#define PCI_DEVICE_ID_MUTECH_MV1000    0x0001
 
 #define PCI_VENDOR_ID_XIRCOM           0x115d
-#define PCI_DEVICE_ID_XIRCOM_X3201_ETH 0x0003
 #define PCI_DEVICE_ID_XIRCOM_RBM56G    0x0101
 #define PCI_DEVICE_ID_XIRCOM_X3201_MDM 0x0103
 
-#define PCI_VENDOR_ID_RENDITION                0x1163
-#define PCI_DEVICE_ID_RENDITION_VERITE 0x0001
-#define PCI_DEVICE_ID_RENDITION_VERITE2100 0x2000
 
 #define PCI_VENDOR_ID_SERVERWORKS        0x1166
 #define PCI_DEVICE_ID_SERVERWORKS_HE     0x0008
 #define PCI_DEVICE_ID_SERVERWORKS_LE     0x0009
-#define PCI_DEVICE_ID_SERVERWORKS_CIOB30  0x0010
-#define PCI_DEVICE_ID_SERVERWORKS_CMIC_HE 0x0011
 #define PCI_DEVICE_ID_SERVERWORKS_GCNB_LE 0x0017
 #define PCI_DEVICE_ID_SERVERWORKS_OSB4   0x0200
 #define PCI_DEVICE_ID_SERVERWORKS_CSB5   0x0201
 #define PCI_DEVICE_ID_SERVERWORKS_CSB6IDE 0x0213
 #define PCI_DEVICE_ID_SERVERWORKS_HT1000IDE 0x0214
 #define PCI_DEVICE_ID_SERVERWORKS_CSB6IDE2 0x0217
-#define PCI_DEVICE_ID_SERVERWORKS_OSB4USB 0x0220
-#define PCI_DEVICE_ID_SERVERWORKS_CSB5USB PCI_DEVICE_ID_SERVERWORKS_OSB4USB
-#define PCI_DEVICE_ID_SERVERWORKS_CSB6USB 0x0221
 #define PCI_DEVICE_ID_SERVERWORKS_CSB6LPC 0x0227
-#define PCI_DEVICE_ID_SERVERWORKS_GCLE    0x0225
-#define PCI_DEVICE_ID_SERVERWORKS_GCLE2   0x0227
-#define PCI_DEVICE_ID_SERVERWORKS_CSB5ISA 0x0230
 
 #define PCI_VENDOR_ID_SBE              0x1176
 #define PCI_DEVICE_ID_SBE_WANXL100     0x0301
 #define PCI_DEVICE_ID_TOSHIBA_PICCOLO  0x0102
 #define PCI_DEVICE_ID_TOSHIBA_PICCOLO_1        0x0103
 #define PCI_DEVICE_ID_TOSHIBA_PICCOLO_2        0x0105
-#define PCI_DEVICE_ID_TOSHIBA_601      0x0601
 #define PCI_DEVICE_ID_TOSHIBA_TOPIC95  0x060a
-#define PCI_DEVICE_ID_TOSHIBA_TOPIC95_A 0x0603
-#define PCI_DEVICE_ID_TOSHIBA_TOPIC95_B 0x060a
 #define PCI_DEVICE_ID_TOSHIBA_TOPIC97  0x060f
 #define PCI_DEVICE_ID_TOSHIBA_TOPIC100 0x0617
 
 #define PCI_VENDOR_ID_TOSHIBA_2                0x102f
-#define PCI_DEVICE_ID_TOSHIBA_TX3927   0x000a
 #define PCI_DEVICE_ID_TOSHIBA_TC35815CF        0x0030
-#define PCI_DEVICE_ID_TOSHIBA_TX4927   0x0180
 #define PCI_DEVICE_ID_TOSHIBA_TC86C001_MISC    0x0108
 #define PCI_DEVICE_ID_TOSHIBA_SPIDER_NET 0x01b3
 
 #define PCI_DEVICE_ID_DLINK_DGE510T    0x4c00
 
 #define PCI_VENDOR_ID_ARTOP            0x1191
-#define PCI_DEVICE_ID_ARTOP_ATP8400    0x0004
 #define PCI_DEVICE_ID_ARTOP_ATP850UF   0x0005
 #define PCI_DEVICE_ID_ARTOP_ATP860     0x0006
 #define PCI_DEVICE_ID_ARTOP_ATP860R    0x0007
 #define PCI_DEVICE_ID_ARTOP_AEC7612D   0x8040
 #define PCI_DEVICE_ID_ARTOP_AEC7612SUW 0x8050
 #define PCI_DEVICE_ID_ARTOP_8060       0x8060
-#define PCI_DEVICE_ID_ARTOP_AEC67160   0x8080
-#define PCI_DEVICE_ID_ARTOP_AEC67160_2 0x8081
-#define PCI_DEVICE_ID_ARTOP_AEC67162   0x808a
 
 #define PCI_VENDOR_ID_ZEITNET          0x1193
 #define PCI_DEVICE_ID_ZEITNET_1221     0x0001
 #define PCI_DEVICE_ID_ZEITNET_1225     0x0002
 
-#define PCI_VENDOR_ID_OMEGA            0x119b
-#define PCI_DEVICE_ID_OMEGA_82C092G    0x1221
 
 #define PCI_VENDOR_ID_FUJITSU_ME       0x119e
 #define PCI_DEVICE_ID_FUJITSU_FS155    0x0001
 #define PCI_SUBDEVICE_ID_KEYSPAN_SX2   0x5334
 
 #define PCI_VENDOR_ID_MARVELL          0x11ab
-#define PCI_DEVICE_ID_MARVELL_GT64011  0x4146
-#define PCI_DEVICE_ID_MARVELL_GT64111  0x4146
 #define PCI_DEVICE_ID_MARVELL_GT64260  0x6430
 #define PCI_DEVICE_ID_MARVELL_MV64360  0x6460
 #define PCI_DEVICE_ID_MARVELL_MV64460  0x6480
 #define PCI_DEVICE_ID_MARVELL_GT96100  0x9652
 #define PCI_DEVICE_ID_MARVELL_GT96100A 0x9653
 
-#define PCI_VENDOR_ID_LITEON           0x11ad
-#define PCI_DEVICE_ID_LITEON_LNE100TX  0x0002
 
 #define PCI_VENDOR_ID_V3               0x11b0
 #define PCI_DEVICE_ID_V3_V960          0x0001
-#define PCI_DEVICE_ID_V3_V350          0x0001
-#define PCI_DEVICE_ID_V3_V961          0x0002
 #define PCI_DEVICE_ID_V3_V351          0x0002
 
-#define PCI_VENDOR_ID_NP               0x11bc
-#define PCI_DEVICE_ID_NP_PCI_FDDI      0x0001
 
 #define PCI_VENDOR_ID_ATT              0x11c1
-#define PCI_DEVICE_ID_ATT_L56XMF       0x0440
 #define PCI_DEVICE_ID_ATT_VENUS_MODEM  0x480
 
-#define PCI_VENDOR_ID_NEC2             0x11c3 /* NEC (2nd) */
 
 #define PCI_VENDOR_ID_SPECIALIX                0x11cb
 #define PCI_DEVICE_ID_SPECIALIX_IO8    0x2000
-#define PCI_DEVICE_ID_SPECIALIX_XIO    0x4000
 #define PCI_DEVICE_ID_SPECIALIX_RIO    0x8000
 #define PCI_SUBDEVICE_ID_SPECIALIX_SPEED4 0xa004
 
-#define PCI_VENDOR_ID_AURAVISION       0x11d1
-#define PCI_DEVICE_ID_AURAVISION_VXP524        0x01f7
 
 #define PCI_VENDOR_ID_ANALOG_DEVICES   0x11d4
 #define PCI_DEVICE_ID_AD1889JS         0x1889
 
-#define PCI_VENDOR_ID_IKON             0x11d5
-#define PCI_DEVICE_ID_IKON_10115       0x0115
-#define PCI_DEVICE_ID_IKON_10117       0x0117
 
-#define PCI_VENDOR_ID_SEGA             0x11db
 #define PCI_DEVICE_ID_SEGA_BBA         0x1234
 
 #define PCI_VENDOR_ID_ZORAN            0x11de
 #define PCI_DEVICE_ID_ZORAN_36057      0x6057
 #define PCI_DEVICE_ID_ZORAN_36120      0x6120
 
-#define PCI_VENDOR_ID_KINETIC          0x11f4
-#define PCI_DEVICE_ID_KINETIC_2915     0x2915
 
 #define PCI_VENDOR_ID_COMPEX           0x11f6
 #define PCI_DEVICE_ID_COMPEX_ENET100VG4        0x0112
-#define PCI_DEVICE_ID_COMPEX_RL2000    0x1401
 
 #define PCI_VENDOR_ID_RP               0x11fe
 #define PCI_DEVICE_ID_RP32INTF         0x0001
 #define PCI_DEVICE_ID_RP16SNI          0x0009  
 #define PCI_DEVICE_ID_RPP4             0x000A
 #define PCI_DEVICE_ID_RPP8             0x000B
-#define PCI_DEVICE_ID_RP8M             0x000C
 #define PCI_DEVICE_ID_RP4M             0x000D
 #define PCI_DEVICE_ID_RP2_232          0x000E
 #define PCI_DEVICE_ID_RP2_422          0x000F
 #define PCI_DEVICE_ID_PC300_TE_M_2     0x0320
 #define PCI_DEVICE_ID_PC300_TE_M_1     0x0321
 
-/* Allied Telesyn */
-#define PCI_VENDOR_ID_AT               0x1259
-#define PCI_SUBDEVICE_ID_AT_2701FX     0x2703
-
 #define PCI_VENDOR_ID_ESSENTIAL                0x120f
 #define PCI_DEVICE_ID_ESSENTIAL_ROADRUNNER     0x0001
 
 #define PCI_DEVICE_ID_3DFX_VOODOO3     0x0005
 #define PCI_DEVICE_ID_3DFX_VOODOO5     0x0009
 
-#define PCI_VENDOR_ID_SIGMADES         0x1236
-#define PCI_DEVICE_ID_SIGMADES_6425    0x6401
 
-#define PCI_VENDOR_ID_CCUBE            0x123f
 
 #define PCI_VENDOR_ID_AVM              0x1244
 #define PCI_DEVICE_ID_AVM_B1           0x0700
 #define PCI_DEVICE_ID_AVM_C2           0x1100
 #define PCI_DEVICE_ID_AVM_T1           0x1200
 
-#define PCI_VENDOR_ID_DIPIX            0x1246
 
 #define PCI_VENDOR_ID_STALLION         0x124d
-#define PCI_DEVICE_ID_STALLION_ECHPCI832 0x0000
-#define PCI_DEVICE_ID_STALLION_ECHPCI864 0x0002
-#define PCI_DEVICE_ID_STALLION_EIOPCI  0x0003
-
-#define PCI_VENDOR_ID_OPTIBASE         0x1255
-#define PCI_DEVICE_ID_OPTIBASE_FORGE   0x1110
-#define PCI_DEVICE_ID_OPTIBASE_FUSION  0x1210
-#define PCI_DEVICE_ID_OPTIBASE_VPLEX   0x2110
-#define PCI_DEVICE_ID_OPTIBASE_VPLEXCC 0x2120
-#define PCI_DEVICE_ID_OPTIBASE_VQUEST  0x2130
 
 /* Allied Telesyn */
 #define PCI_VENDOR_ID_AT               0x1259
 
 #define PCI_VENDOR_ID_ESS              0x125d
 #define PCI_DEVICE_ID_ESS_ESS1968      0x1968
-#define PCI_DEVICE_ID_ESS_AUDIOPCI     0x1969
 #define PCI_DEVICE_ID_ESS_ESS1978      0x1978
 #define PCI_DEVICE_ID_ESS_ALLEGRO_1    0x1988
 #define PCI_DEVICE_ID_ESS_ALLEGRO      0x1989
 
 #define PCI_VENDOR_ID_SATSAGEM         0x1267
 #define PCI_DEVICE_ID_SATSAGEM_NICCY   0x1016
-#define PCI_DEVICE_ID_SATSAGEM_PCR2101 0x5352
-#define PCI_DEVICE_ID_SATSAGEM_TELSATTURBO 0x5a4b
 
-#define PCI_VENDOR_ID_HUGHES           0x1273
-#define PCI_DEVICE_ID_HUGHES_DIRECPC   0x0002
 
 #define PCI_VENDOR_ID_ENSONIQ          0x1274
 #define PCI_DEVICE_ID_ENSONIQ_CT5880   0x5880
 #define PCI_DEVICE_ID_ITE_IT8330G_0    0xe886
 
 /* formerly Platform Tech */
-#define PCI_VENDOR_ID_ESS_OLD          0x1285
 #define PCI_DEVICE_ID_ESS_ESS0100      0x0100
 
 #define PCI_VENDOR_ID_ALTEON           0x12ae
-#define PCI_DEVICE_ID_ALTEON_ACENIC    0x0001
 
-#define PCI_VENDOR_ID_USR              0x12B9
 
 #define PCI_SUBVENDOR_ID_CONNECT_TECH                  0x12c4
 #define PCI_SUBDEVICE_ID_CONNECT_TECH_BH8_232          0x0001
 #define PCI_SUBDEVICE_ID_CONNECT_TECH_BH081101V1       0x000A
 #define PCI_SUBDEVICE_ID_CONNECT_TECH_BH041101V1       0x000B
 
-#define PCI_VENDOR_ID_PICTUREL         0x12c5
-#define PCI_DEVICE_ID_PICTUREL_PCIVST  0x0081
 
 #define PCI_VENDOR_ID_NVIDIA_SGS       0x12d2
 #define PCI_DEVICE_ID_NVIDIA_SGS_RIVA128 0x0018
 #define PCI_VENDOR_ID_ELECTRONICDESIGNGMBH 0x12f8
 #define PCI_DEVICE_ID_LML_33R10                0x8a02
 
-#define PCI_VENDOR_ID_CBOARDS          0x1307
-#define PCI_DEVICE_ID_CBOARDS_DAS1602_16 0x0001
 
 #define PCI_VENDOR_ID_SIIG             0x131f
 #define PCI_SUBVENDOR_ID_SIIG          0x131f
 #define PCI_SUBDEVICE_ID_SIIG_QUARTET_SERIAL   0x2050
 
 #define PCI_VENDOR_ID_RADISYS          0x1331
-#define PCI_DEVICE_ID_RADISYS_ENP2611  0x0030
 
 #define PCI_VENDOR_ID_DOMEX            0x134a
 #define PCI_DEVICE_ID_DOMEX_DMX3191D   0x0001
 #define PCI_VENDOR_ID_QUATECH          0x135C
 #define PCI_DEVICE_ID_QUATECH_QSC100   0x0010
 #define PCI_DEVICE_ID_QUATECH_DSC100   0x0020
-#define PCI_DEVICE_ID_QUATECH_DSC200   0x0030
-#define PCI_DEVICE_ID_QUATECH_QSC200   0x0040
 #define PCI_DEVICE_ID_QUATECH_ESC100D  0x0050
 #define PCI_DEVICE_ID_QUATECH_ESC100M  0x0060
 
 #define PCI_SUBDEVICE_ID_HYPERCOPE_ERGO                0x0106
 #define PCI_SUBDEVICE_ID_HYPERCOPE_METRO       0x0107
 #define PCI_SUBDEVICE_ID_HYPERCOPE_CHAMP2      0x0108
-#define PCI_SUBDEVICE_ID_HYPERCOPE_PLEXUS      0x0109
 
 #define PCI_VENDOR_ID_KAWASAKI         0x136b
 #define PCI_DEVICE_ID_MCHIP_KL5A72002  0xff01
 #define PCI_DEVICE_ID_LMC_SSI          0x0005
 #define PCI_DEVICE_ID_LMC_T1           0x0006
 
-#define PCI_VENDOR_ID_MARIAN           0x1382
-#define PCI_DEVICE_ID_MARIAN_PRODIF_PLUS 0x2048
 
 #define PCI_VENDOR_ID_NETGEAR          0x1385
 #define PCI_DEVICE_ID_NETGEAR_GA620    0x620a
-#define PCI_DEVICE_ID_NETGEAR_GA622    0x622a
 
 #define PCI_VENDOR_ID_APPLICOM         0x1389
 #define PCI_DEVICE_ID_APPLICOM_PCIGENERIC 0x0001
 #define PCI_DEVICE_ID_MOXA_CP134U      0x1340
 #define PCI_DEVICE_ID_MOXA_C168                0x1680
 #define PCI_DEVICE_ID_MOXA_CP168U      0x1681
-#define PCI_DEVICE_ID_MOXA_CP204J      0x2040
-#define PCI_DEVICE_ID_MOXA_C218                0x2180
-#define PCI_DEVICE_ID_MOXA_C320                0x3200
 
 #define PCI_VENDOR_ID_CCD              0x1397
 #define PCI_DEVICE_ID_CCD_2BD0         0x2bd0
 
 #define PCI_VENDOR_ID_MICROGATE                0x13c0
 #define PCI_DEVICE_ID_MICROGATE_USC    0x0010
-#define PCI_DEVICE_ID_MICROGATE_SCC    0x0020
 #define PCI_DEVICE_ID_MICROGATE_SCA    0x0030
-#define PCI_DEVICE_ID_MICROGATE_USC2   0x0210
 
 #define PCI_VENDOR_ID_3WARE            0x13C1
 #define PCI_DEVICE_ID_3WARE_1000       0x1000
 
 #define PCI_VENDOR_ID_SAMSUNG          0x144d
 
-#define PCI_VENDOR_ID_AIRONET          0x14b9
-#define PCI_DEVICE_ID_AIRONET_4800_1   0x0001
-#define PCI_DEVICE_ID_AIRONET_4800     0x4500 // values switched?  see
-#define PCI_DEVICE_ID_AIRONET_4500     0x4800 // drivers/net/aironet4500_card.c
 
 #define PCI_VENDOR_ID_TITAN            0x14D2
 #define PCI_DEVICE_ID_TITAN_010L       0x8001
 #define PCI_DEVICE_ID_PANACOM_QUADMODEM        0x0400
 #define PCI_DEVICE_ID_PANACOM_DUALMODEM        0x0402
 
-#define PCI_VENDOR_ID_SIPACKETS                0x14d9
-#define PCI_DEVICE_ID_SP_HT            0x0010
 
 #define PCI_VENDOR_ID_AFAVLAB          0x14db
 #define PCI_DEVICE_ID_AFAVLAB_P028     0x2180
 
 #define PCI_VENDOR_ID_CHELSIO          0x1425
 
-#define PCI_VENDOR_ID_MIPS             0x153f
-#define PCI_DEVICE_ID_SOC_IT           0x0001
 
 #define PCI_VENDOR_ID_SYBA             0x1592
 #define PCI_DEVICE_ID_SYBA_2P_EPP      0x0782
 #define PCI_DEVICE_ID_MELLANOX_SINAI   0x6274
 
 #define PCI_VENDOR_ID_PDC              0x15e9
-#define PCI_DEVICE_ID_PDC_1841         0x1841
 
-#define PCI_VENDOR_ID_MACROLINK                0x15ed
-#define PCI_DEVICE_ID_MACROLINK_MCCS8  0x1000
-#define PCI_DEVICE_ID_MACROLINK_MCCS   0x1001
-#define PCI_DEVICE_ID_MACROLINK_MCCS8H 0x1002
-#define PCI_DEVICE_ID_MACROLINK_MCCSH  0x1003
-#define PCI_DEVICE_ID_MACROLINK_MCCR8  0x2000
-#define PCI_DEVICE_ID_MACROLINK_MCCR   0x2001
 
 #define PCI_VENDOR_ID_FARSITE           0x1619
 #define PCI_DEVICE_ID_FARSITE_T2P       0x0400
 #define PCI_DEVICE_ID_REVOLUTION       0x0044
 
 #define PCI_VENDOR_ID_LINKSYS          0x1737
-#define PCI_DEVICE_ID_LINKSYS_EG1032   0x1032
 #define PCI_DEVICE_ID_LINKSYS_EG1064   0x1064
 
 #define PCI_VENDOR_ID_ALTIMA           0x173b
 #define PCI_DEVICE_ID_HERC_WIN         0x5732
 #define PCI_DEVICE_ID_HERC_UNI         0x5832
 
-#define PCI_VENDOR_ID_INFINICON                0x1820
 
 #define PCI_VENDOR_ID_SITECOM          0x182d
 #define PCI_DEVICE_ID_SITECOM_DC105V2  0x3069
 #define PCI_VENDOR_ID_TDI               0x192E
 #define PCI_DEVICE_ID_TDI_EHCI          0x0101
 
-#define PCI_VENDOR_ID_SYMPHONY         0x1c1c
-#define PCI_DEVICE_ID_SYMPHONY_101     0x0001
 
 #define PCI_VENDOR_ID_TEKRAM           0x1de1
 #define PCI_DEVICE_ID_TEKRAM_DC290     0xdc29
 #define PCI_DEVICE_ID_HINT_VXPROII_IDE 0x8013
 
 #define PCI_VENDOR_ID_3DLABS           0x3d3d
-#define PCI_DEVICE_ID_3DLABS_300SX     0x0001
-#define PCI_DEVICE_ID_3DLABS_500TX     0x0002
-#define PCI_DEVICE_ID_3DLABS_DELTA     0x0003
-#define PCI_DEVICE_ID_3DLABS_PERMEDIA  0x0004
-#define PCI_DEVICE_ID_3DLABS_MX                0x0006
 #define PCI_DEVICE_ID_3DLABS_PERMEDIA2 0x0007
-#define PCI_DEVICE_ID_3DLABS_GAMMA     0x0008
 #define PCI_DEVICE_ID_3DLABS_PERMEDIA2V        0x0009
 
-#define PCI_VENDOR_ID_AVANCE           0x4005
-#define PCI_DEVICE_ID_AVANCE_ALG2064   0x2064
-#define PCI_DEVICE_ID_AVANCE_2302      0x2302
 
 #define PCI_VENDOR_ID_AKS              0x416c
 #define PCI_DEVICE_ID_AKS_ALADDINCARD  0x0100
-#define PCI_DEVICE_ID_AKS_CPC          0x0200
 
-#define PCI_VENDOR_ID_REDCREEK         0x4916
-#define PCI_DEVICE_ID_RC45             0x1960
 
-#define PCI_VENDOR_ID_NETVIN           0x4a14
-#define PCI_DEVICE_ID_NETVIN_NV5000SC  0x5000
 
 #define PCI_VENDOR_ID_S3               0x5333
-#define PCI_DEVICE_ID_S3_PLATO_PXS     0x0551
-#define PCI_DEVICE_ID_S3_ViRGE         0x5631
 #define PCI_DEVICE_ID_S3_TRIO          0x8811
-#define PCI_DEVICE_ID_S3_AURORA64VP    0x8812
-#define PCI_DEVICE_ID_S3_TRIO64UVP     0x8814
-#define PCI_DEVICE_ID_S3_ViRGE_VX      0x883d
 #define PCI_DEVICE_ID_S3_868           0x8880
-#define PCI_DEVICE_ID_S3_928           0x88b0
-#define PCI_DEVICE_ID_S3_864_1         0x88c0
-#define PCI_DEVICE_ID_S3_864_2         0x88c1
-#define PCI_DEVICE_ID_S3_964_1         0x88d0
-#define PCI_DEVICE_ID_S3_964_2         0x88d1
 #define PCI_DEVICE_ID_S3_968           0x88f0
-#define PCI_DEVICE_ID_S3_TRIO64V2      0x8901
-#define PCI_DEVICE_ID_S3_PLATO_PXG     0x8902
-#define PCI_DEVICE_ID_S3_ViRGE_DXGX    0x8a01
-#define PCI_DEVICE_ID_S3_ViRGE_GX2     0x8a10
 #define PCI_DEVICE_ID_S3_SAVAGE4       0x8a25
-#define PCI_DEVICE_ID_S3_ViRGE_MX      0x8c01
-#define PCI_DEVICE_ID_S3_ViRGE_MXP     0x8c02
-#define PCI_DEVICE_ID_S3_ViRGE_MXPMV   0x8c03
 #define PCI_DEVICE_ID_S3_PROSAVAGE8    0x8d04
 #define PCI_DEVICE_ID_S3_SONICVIBES    0xca00
 
 #define PCI_VENDOR_ID_DUNORD           0x5544
 #define PCI_DEVICE_ID_DUNORD_I3000     0x0001
 
+
 #define PCI_VENDOR_ID_DCI              0x6666
 #define PCI_DEVICE_ID_DCI_PCCOM4       0x0001
 #define PCI_DEVICE_ID_DCI_PCCOM8       0x0002
 
-#define PCI_VENDOR_ID_DUNORD           0x5544
-#define PCI_DEVICE_ID_DUNORD_I3000     0x0001
-
-#define PCI_VENDOR_ID_GENROCO          0x5555
-#define PCI_DEVICE_ID_GENROCO_HFP832   0x0003
-
 #define PCI_VENDOR_ID_INTEL            0x8086
 #define PCI_DEVICE_ID_INTEL_EESSC      0x0008
-#define PCI_DEVICE_ID_INTEL_21145      0x0039
 #define PCI_DEVICE_ID_INTEL_PXHD_0     0x0320
 #define PCI_DEVICE_ID_INTEL_PXHD_1     0x0321
 #define PCI_DEVICE_ID_INTEL_PXH_0      0x0329
 #define PCI_DEVICE_ID_INTEL_82375      0x0482
 #define PCI_DEVICE_ID_INTEL_82424      0x0483
 #define PCI_DEVICE_ID_INTEL_82378      0x0484
-#define PCI_DEVICE_ID_INTEL_82430      0x0486
-#define PCI_DEVICE_ID_INTEL_82434      0x04a3
 #define PCI_DEVICE_ID_INTEL_I960       0x0960
 #define PCI_DEVICE_ID_INTEL_I960RM     0x0962
-#define PCI_DEVICE_ID_INTEL_82562ET    0x1031
-#define PCI_DEVICE_ID_INTEL_82801CAM   0x1038
 #define PCI_DEVICE_ID_INTEL_82815_MC   0x1130
-#define PCI_DEVICE_ID_INTEL_82815_AB   0x1131
 #define PCI_DEVICE_ID_INTEL_82815_CGC  0x1132
-#define PCI_DEVICE_ID_INTEL_82559ER    0x1209
 #define PCI_DEVICE_ID_INTEL_82092AA_0  0x1221
-#define PCI_DEVICE_ID_INTEL_82092AA_1  0x1222
-#define PCI_DEVICE_ID_INTEL_7116       0x1223
 #define PCI_DEVICE_ID_INTEL_7505_0     0x2550  
-#define PCI_DEVICE_ID_INTEL_7505_1     0x2552  
 #define PCI_DEVICE_ID_INTEL_7205_0     0x255d
-#define PCI_DEVICE_ID_INTEL_82596      0x1226
-#define PCI_DEVICE_ID_INTEL_82865      0x1227
-#define PCI_DEVICE_ID_INTEL_82557      0x1229
 #define PCI_DEVICE_ID_INTEL_82437      0x122d
 #define PCI_DEVICE_ID_INTEL_82371FB_0  0x122e
 #define PCI_DEVICE_ID_INTEL_82371FB_1  0x1230
 #define PCI_DEVICE_ID_INTEL_82371MX    0x1234
-#define PCI_DEVICE_ID_INTEL_82437MX    0x1235
 #define PCI_DEVICE_ID_INTEL_82441      0x1237
 #define PCI_DEVICE_ID_INTEL_82380FB    0x124b
 #define PCI_DEVICE_ID_INTEL_82439      0x1250
 #define PCI_DEVICE_ID_INTEL_82845_HB   0x1a30
 #define PCI_DEVICE_ID_INTEL_82801AA_0  0x2410
 #define PCI_DEVICE_ID_INTEL_82801AA_1  0x2411
-#define PCI_DEVICE_ID_INTEL_82801AA_2  0x2412
 #define PCI_DEVICE_ID_INTEL_82801AA_3  0x2413
 #define PCI_DEVICE_ID_INTEL_82801AA_5  0x2415
 #define PCI_DEVICE_ID_INTEL_82801AA_6  0x2416
 #define PCI_DEVICE_ID_INTEL_82801AA_8  0x2418
 #define PCI_DEVICE_ID_INTEL_82801AB_0  0x2420
 #define PCI_DEVICE_ID_INTEL_82801AB_1  0x2421
-#define PCI_DEVICE_ID_INTEL_82801AB_2  0x2422
 #define PCI_DEVICE_ID_INTEL_82801AB_3  0x2423
 #define PCI_DEVICE_ID_INTEL_82801AB_5  0x2425
 #define PCI_DEVICE_ID_INTEL_82801AB_6  0x2426
 #define PCI_DEVICE_ID_INTEL_82801AB_8  0x2428
 #define PCI_DEVICE_ID_INTEL_82801BA_0  0x2440
-#define PCI_DEVICE_ID_INTEL_82801BA_1  0x2442
 #define PCI_DEVICE_ID_INTEL_82801BA_2  0x2443
-#define PCI_DEVICE_ID_INTEL_82801BA_3  0x2444
 #define PCI_DEVICE_ID_INTEL_82801BA_4  0x2445
-#define PCI_DEVICE_ID_INTEL_82801BA_5  0x2446
 #define PCI_DEVICE_ID_INTEL_82801BA_6  0x2448
-#define PCI_DEVICE_ID_INTEL_82801BA_7  0x2449
 #define PCI_DEVICE_ID_INTEL_82801BA_8  0x244a
 #define PCI_DEVICE_ID_INTEL_82801BA_9  0x244b
 #define PCI_DEVICE_ID_INTEL_82801BA_10 0x244c
 #define PCI_DEVICE_ID_INTEL_82801BA_11 0x244e
 #define PCI_DEVICE_ID_INTEL_82801E_0   0x2450
-#define PCI_DEVICE_ID_INTEL_82801E_2   0x2452
-#define PCI_DEVICE_ID_INTEL_82801E_3   0x2453
-#define PCI_DEVICE_ID_INTEL_82801E_9   0x2459
 #define PCI_DEVICE_ID_INTEL_82801E_11  0x245b
-#define PCI_DEVICE_ID_INTEL_82801E_13  0x245d
-#define PCI_DEVICE_ID_INTEL_82801E_14  0x245e
 #define PCI_DEVICE_ID_INTEL_82801CA_0  0x2480
-#define PCI_DEVICE_ID_INTEL_82801CA_2  0x2482
 #define PCI_DEVICE_ID_INTEL_82801CA_3  0x2483
-#define PCI_DEVICE_ID_INTEL_82801CA_4  0x2484
 #define PCI_DEVICE_ID_INTEL_82801CA_5  0x2485
 #define PCI_DEVICE_ID_INTEL_82801CA_6  0x2486
-#define PCI_DEVICE_ID_INTEL_82801CA_7  0x2487
 #define PCI_DEVICE_ID_INTEL_82801CA_10 0x248a
 #define PCI_DEVICE_ID_INTEL_82801CA_11 0x248b
 #define PCI_DEVICE_ID_INTEL_82801CA_12 0x248c
 #define PCI_DEVICE_ID_INTEL_82801DB_0  0x24c0
 #define PCI_DEVICE_ID_INTEL_82801DB_1  0x24c1
-#define PCI_DEVICE_ID_INTEL_82801DB_2  0x24c2
 #define PCI_DEVICE_ID_INTEL_82801DB_3  0x24c3
-#define PCI_DEVICE_ID_INTEL_82801DB_4  0x24c4
 #define PCI_DEVICE_ID_INTEL_82801DB_5  0x24c5
 #define PCI_DEVICE_ID_INTEL_82801DB_6  0x24c6
-#define PCI_DEVICE_ID_INTEL_82801DB_7  0x24c7
 #define PCI_DEVICE_ID_INTEL_82801DB_9  0x24c9
 #define PCI_DEVICE_ID_INTEL_82801DB_10 0x24ca
 #define PCI_DEVICE_ID_INTEL_82801DB_11 0x24cb
 #define PCI_DEVICE_ID_INTEL_82801DB_12  0x24cc
-#define PCI_DEVICE_ID_INTEL_82801DB_13 0x24cd
 #define PCI_DEVICE_ID_INTEL_82801EB_0  0x24d0
 #define PCI_DEVICE_ID_INTEL_82801EB_1  0x24d1
-#define PCI_DEVICE_ID_INTEL_82801EB_2  0x24d2
 #define PCI_DEVICE_ID_INTEL_82801EB_3  0x24d3
-#define PCI_DEVICE_ID_INTEL_82801EB_4  0x24d4
 #define PCI_DEVICE_ID_INTEL_82801EB_5  0x24d5
 #define PCI_DEVICE_ID_INTEL_82801EB_6  0x24d6
-#define PCI_DEVICE_ID_INTEL_82801EB_7  0x24d7
 #define PCI_DEVICE_ID_INTEL_82801EB_11 0x24db
-#define PCI_DEVICE_ID_INTEL_82801EB_13 0x24dd
 #define PCI_DEVICE_ID_INTEL_ESB_1      0x25a1
 #define PCI_DEVICE_ID_INTEL_ESB_2      0x25a2
-#define PCI_DEVICE_ID_INTEL_ESB_3      0x25a3
-#define PCI_DEVICE_ID_INTEL_ESB_31     0x25b0
 #define PCI_DEVICE_ID_INTEL_ESB_4      0x25a4
 #define PCI_DEVICE_ID_INTEL_ESB_5      0x25a6
-#define PCI_DEVICE_ID_INTEL_ESB_6      0x25a7
-#define PCI_DEVICE_ID_INTEL_ESB_7      0x25a9
-#define PCI_DEVICE_ID_INTEL_ESB_8      0x25aa
 #define PCI_DEVICE_ID_INTEL_ESB_9      0x25ab
-#define PCI_DEVICE_ID_INTEL_ESB_11     0x25ac
-#define PCI_DEVICE_ID_INTEL_ESB_12     0x25ad
-#define PCI_DEVICE_ID_INTEL_ESB_13     0x25ae
 #define PCI_DEVICE_ID_INTEL_82820_HB   0x2500
 #define PCI_DEVICE_ID_INTEL_82820_UP_HB        0x2501
 #define PCI_DEVICE_ID_INTEL_82850_HB   0x2530
 #define PCI_DEVICE_ID_INTEL_82865_HB   0x2570
 #define PCI_DEVICE_ID_INTEL_82865_IG   0x2572
 #define PCI_DEVICE_ID_INTEL_82875_HB   0x2578
-#define PCI_DEVICE_ID_INTEL_82875_IG   0x257b
 #define PCI_DEVICE_ID_INTEL_82915G_HB  0x2580
 #define PCI_DEVICE_ID_INTEL_82915G_IG  0x2582
 #define PCI_DEVICE_ID_INTEL_82915GM_HB 0x2590
 #define PCI_DEVICE_ID_INTEL_ICH6_0     0x2640
 #define PCI_DEVICE_ID_INTEL_ICH6_1     0x2641
 #define PCI_DEVICE_ID_INTEL_ICH6_2     0x2642
-#define PCI_DEVICE_ID_INTEL_ICH6_3     0x2651
-#define PCI_DEVICE_ID_INTEL_ICH6_4     0x2652
-#define PCI_DEVICE_ID_INTEL_ICH6_5     0x2653
-#define PCI_DEVICE_ID_INTEL_ICH6_6     0x2658
-#define PCI_DEVICE_ID_INTEL_ICH6_7     0x2659
-#define PCI_DEVICE_ID_INTEL_ICH6_8     0x265a
-#define PCI_DEVICE_ID_INTEL_ICH6_9     0x265b
-#define PCI_DEVICE_ID_INTEL_ICH6_10    0x265c
-#define PCI_DEVICE_ID_INTEL_ICH6_11    0x2660
-#define PCI_DEVICE_ID_INTEL_ICH6_12    0x2662
-#define PCI_DEVICE_ID_INTEL_ICH6_13    0x2664
-#define PCI_DEVICE_ID_INTEL_ICH6_14    0x2666
-#define PCI_DEVICE_ID_INTEL_ICH6_15    0x2668
 #define PCI_DEVICE_ID_INTEL_ICH6_16    0x266a
 #define PCI_DEVICE_ID_INTEL_ICH6_17    0x266d
 #define PCI_DEVICE_ID_INTEL_ICH6_18    0x266e
 #define PCI_DEVICE_ID_INTEL_ICH6_19    0x266f
 #define PCI_DEVICE_ID_INTEL_ESB2_0     0x2670
-#define PCI_DEVICE_ID_INTEL_ESB2_1     0x2680
-#define PCI_DEVICE_ID_INTEL_ESB2_2     0x2681
-#define PCI_DEVICE_ID_INTEL_ESB2_3     0x2682
-#define PCI_DEVICE_ID_INTEL_ESB2_4     0x2683
-#define PCI_DEVICE_ID_INTEL_ESB2_5     0x2688
-#define PCI_DEVICE_ID_INTEL_ESB2_6     0x2689
-#define PCI_DEVICE_ID_INTEL_ESB2_7     0x268a
-#define PCI_DEVICE_ID_INTEL_ESB2_8     0x268b
-#define PCI_DEVICE_ID_INTEL_ESB2_9     0x268c
-#define PCI_DEVICE_ID_INTEL_ESB2_10    0x2690
-#define PCI_DEVICE_ID_INTEL_ESB2_11    0x2692
-#define PCI_DEVICE_ID_INTEL_ESB2_12    0x2694
-#define PCI_DEVICE_ID_INTEL_ESB2_13    0x2696
 #define PCI_DEVICE_ID_INTEL_ESB2_14    0x2698
-#define PCI_DEVICE_ID_INTEL_ESB2_15    0x2699
-#define PCI_DEVICE_ID_INTEL_ESB2_16    0x269a
 #define PCI_DEVICE_ID_INTEL_ESB2_17    0x269b
 #define PCI_DEVICE_ID_INTEL_ESB2_18    0x269e
 #define PCI_DEVICE_ID_INTEL_ICH7_0     0x27b8
 #define PCI_DEVICE_ID_INTEL_ICH7_1     0x27b9
-#define PCI_DEVICE_ID_INTEL_ICH7_2     0x27c0
-#define PCI_DEVICE_ID_INTEL_ICH7_3     0x27c1
 #define PCI_DEVICE_ID_INTEL_ICH7_30    0x27b0
 #define PCI_DEVICE_ID_INTEL_ICH7_31    0x27bd
-#define PCI_DEVICE_ID_INTEL_ICH7_5     0x27c4
-#define PCI_DEVICE_ID_INTEL_ICH7_6     0x27c5
-#define PCI_DEVICE_ID_INTEL_ICH7_7     0x27c8
-#define PCI_DEVICE_ID_INTEL_ICH7_8     0x27c9
-#define PCI_DEVICE_ID_INTEL_ICH7_9     0x27ca
-#define PCI_DEVICE_ID_INTEL_ICH7_10    0x27cb
-#define PCI_DEVICE_ID_INTEL_ICH7_11    0x27cc
-#define PCI_DEVICE_ID_INTEL_ICH7_12    0x27d0
-#define PCI_DEVICE_ID_INTEL_ICH7_13    0x27d2
-#define PCI_DEVICE_ID_INTEL_ICH7_14    0x27d4
-#define PCI_DEVICE_ID_INTEL_ICH7_15    0x27d6
-#define PCI_DEVICE_ID_INTEL_ICH7_16    0x27d8
 #define PCI_DEVICE_ID_INTEL_ICH7_17    0x27da
-#define PCI_DEVICE_ID_INTEL_ICH7_18    0x27dc
 #define PCI_DEVICE_ID_INTEL_ICH7_19    0x27dd
 #define PCI_DEVICE_ID_INTEL_ICH7_20    0x27de
 #define PCI_DEVICE_ID_INTEL_ICH7_21    0x27df
-#define PCI_DEVICE_ID_INTEL_ICH7_22    0x27e0
-#define PCI_DEVICE_ID_INTEL_ICH7_23    0x27e2
 #define PCI_DEVICE_ID_INTEL_82855PM_HB 0x3340
-#define PCI_DEVICE_ID_INTEL_ESB2_19    0x3500
-#define PCI_DEVICE_ID_INTEL_ESB2_20    0x3501
-#define PCI_DEVICE_ID_INTEL_ESB2_21    0x3504
-#define PCI_DEVICE_ID_INTEL_ESB2_22    0x3505
-#define PCI_DEVICE_ID_INTEL_ESB2_23    0x350c
-#define PCI_DEVICE_ID_INTEL_ESB2_24    0x350d
-#define PCI_DEVICE_ID_INTEL_ESB2_25    0x3510
-#define PCI_DEVICE_ID_INTEL_ESB2_26    0x3511
-#define PCI_DEVICE_ID_INTEL_ESB2_27    0x3514
-#define PCI_DEVICE_ID_INTEL_ESB2_28    0x3515
-#define PCI_DEVICE_ID_INTEL_ESB2_29    0x3518
-#define PCI_DEVICE_ID_INTEL_ESB2_30    0x3519
 #define PCI_DEVICE_ID_INTEL_82830_HB   0x3575
 #define PCI_DEVICE_ID_INTEL_82830_CGC  0x3577
 #define PCI_DEVICE_ID_INTEL_82855GM_HB 0x3580
 #define PCI_DEVICE_ID_INTEL_MCH_PC     0x3599
 #define PCI_DEVICE_ID_INTEL_MCH_PC1    0x359a
 #define PCI_DEVICE_ID_INTEL_E7525_MCH  0x359e
-#define PCI_DEVICE_ID_INTEL_80310      0x530d
 #define PCI_DEVICE_ID_INTEL_82371SB_0  0x7000
 #define PCI_DEVICE_ID_INTEL_82371SB_1  0x7010
 #define PCI_DEVICE_ID_INTEL_82371SB_2  0x7020
 #define PCI_DEVICE_ID_INTEL_440MX_6    0x7196
 #define PCI_DEVICE_ID_INTEL_82443MX_0  0x7198
 #define PCI_DEVICE_ID_INTEL_82443MX_1  0x7199
-#define PCI_DEVICE_ID_INTEL_82443MX_2  0x719a
 #define PCI_DEVICE_ID_INTEL_82443MX_3  0x719b
 #define PCI_DEVICE_ID_INTEL_82443GX_0  0x71a0
-#define PCI_DEVICE_ID_INTEL_82443GX_1  0x71a1
 #define PCI_DEVICE_ID_INTEL_82443GX_2  0x71a2
-#define PCI_DEVICE_ID_INTEL_82372FB_0  0x7600
 #define PCI_DEVICE_ID_INTEL_82372FB_1  0x7601
-#define PCI_DEVICE_ID_INTEL_82372FB_2  0x7602
-#define PCI_DEVICE_ID_INTEL_82372FB_3  0x7603
 #define PCI_DEVICE_ID_INTEL_82454GX    0x84c4
-#define PCI_DEVICE_ID_INTEL_82450GX    0x84c5
 #define PCI_DEVICE_ID_INTEL_82451NX    0x84ca
 #define PCI_DEVICE_ID_INTEL_82454NX     0x84cb
 #define PCI_DEVICE_ID_INTEL_84460GX    0x84ea
 #define PCI_DEVICE_ID_INTEL_IXP4XX     0x8500
-#define PCI_DEVICE_ID_INTEL_IXP2400    0x9001
 #define PCI_DEVICE_ID_INTEL_IXP2800    0x9004
 #define PCI_DEVICE_ID_INTEL_S21152BB   0xb152
 
 #define PCI_SUBDEVICE_ID_COMPUTONE_PG6 0x0003
 
 #define PCI_VENDOR_ID_KTI              0x8e2e
-#define PCI_DEVICE_ID_KTI_ET32P2       0x3000
 
 #define PCI_VENDOR_ID_ADAPTEC          0x9004
 #define PCI_DEVICE_ID_ADAPTEC_7810     0x1078
 #define PCI_DEVICE_ID_ADAPTEC_38602    0x3860
 #define PCI_DEVICE_ID_ADAPTEC_7850     0x5078
 #define PCI_DEVICE_ID_ADAPTEC_7855     0x5578
-#define PCI_DEVICE_ID_ADAPTEC_5800     0x5800
 #define PCI_DEVICE_ID_ADAPTEC_3860     0x6038
 #define PCI_DEVICE_ID_ADAPTEC_1480A    0x6075
 #define PCI_DEVICE_ID_ADAPTEC_7860     0x6078
 #define PCI_DEVICE_ID_ADAPTEC_7886     0x8678
 #define PCI_DEVICE_ID_ADAPTEC_7887     0x8778
 #define PCI_DEVICE_ID_ADAPTEC_7888     0x8878
-#define PCI_DEVICE_ID_ADAPTEC_1030     0x8b78
 
 #define PCI_VENDOR_ID_ADAPTEC2         0x9005
 #define PCI_DEVICE_ID_ADAPTEC2_2940U2  0x0010
 #define PCI_DEVICE_ID_ADAPTEC2_7899P   0x00cf
 #define PCI_DEVICE_ID_ADAPTEC2_SCAMP   0x0503
 
-#define PCI_VENDOR_ID_ATRONICS         0x907f
-#define PCI_DEVICE_ID_ATRONICS_2015    0x2015
 
 #define PCI_VENDOR_ID_HOLTEK           0x9412
 #define PCI_DEVICE_ID_HOLTEK_6565      0x6565
 #define PCI_DEVICE_ID_RME_DIGI32_PRO   0x9897
 #define PCI_DEVICE_ID_RME_DIGI32_8     0x9898
 
-#define PCI_VENDOR_ID_ARK              0xedd8
-#define PCI_DEVICE_ID_ARK_STING                0xa091
-#define PCI_DEVICE_ID_ARK_STINGARK     0xa099
-#define PCI_DEVICE_ID_ARK_2000MT       0xa0a1
index 7897cf5..c61d5de 100644 (file)
@@ -224,7 +224,6 @@ struct dev_pm_info {
        unsigned                should_wakeup:1;
        pm_message_t            prev_state;
        void                    * saved_state;
-       atomic_t                pm_users;
        struct device           * pm_parent;
        struct list_head        entry;
 #endif
@@ -244,6 +243,9 @@ extern int device_suspend(pm_message_t state);
 #define device_may_wakeup(dev) \
        (device_can_wakeup(dev) && (dev)->power.should_wakeup)
 
+extern int dpm_runtime_suspend(struct device *, pm_message_t);
+extern void dpm_runtime_resume(struct device *);
+
 #else /* !CONFIG_PM */
 
 static inline int device_suspend(pm_message_t state)
@@ -254,6 +256,16 @@ static inline int device_suspend(pm_message_t state)
 #define device_set_wakeup_enable(dev,val)      do{}while(0)
 #define device_may_wakeup(dev)                 (0)
 
+static inline int dpm_runtime_suspend(struct device * dev, pm_message_t state)
+{
+       return 0;
+}
+
+static inline void dpm_runtime_resume(struct device * dev)
+{
+
+}
+
 #endif
 
 /* changes to device_may_wakeup take effect on the next pm state change.
index 8f731e8..748d043 100644 (file)
@@ -57,6 +57,7 @@ struct usb_host_endpoint {
        struct usb_endpoint_descriptor  desc;
        struct list_head                urb_list;
        void                            *hcpriv;
+       struct kobject                  *kobj;  /* For sysfs info */
 
        unsigned char *extra;   /* Extra descriptors */
        int extralen;
@@ -136,7 +137,8 @@ struct usb_interface {
                                         * active alternate setting */
        unsigned num_altsetting;        /* number of alternate settings */
 
-       int minor;                      /* minor number this interface is bound to */
+       int minor;                      /* minor number this interface is
+                                        * bound to */
        enum usb_interface_condition condition;         /* state of binding */
        struct device dev;              /* interface specific device info */
        struct class_device *class_dev;
@@ -229,7 +231,7 @@ struct usb_interface_cache {
 struct usb_host_config {
        struct usb_config_descriptor    desc;
 
-       char *string;
+       char *string;           /* iConfiguration string, if present */
        /* the interfaces associated with this configuration,
         * stored in no particular order */
        struct usb_interface *interface[USB_MAXINTERFACES];
@@ -248,7 +250,7 @@ int __usb_get_extra_descriptor(char *buffer, unsigned size,
        __usb_get_extra_descriptor((ifpoint)->extra,(ifpoint)->extralen,\
                type,(void**)ptr)
 
-/* -------------------------------------------------------------------------- */
+/* ----------------------------------------------------------------------- */
 
 struct usb_operations;
 
@@ -268,7 +270,8 @@ struct usb_bus {
        unsigned is_b_host:1;           /* true during some HNP roleswitches */
        unsigned b_hnp_enable:1;        /* OTG: did A-Host enable HNP? */
 
-       int devnum_next;                /* Next open device number in round-robin allocation */
+       int devnum_next;                /* Next open device number in
+                                        * round-robin allocation */
 
        struct usb_devmap devmap;       /* device address allocation map */
        struct usb_operations *op;      /* Operations (specific to the HC) */
@@ -289,15 +292,16 @@ struct usb_bus {
        struct dentry *usbfs_dentry;    /* usbfs dentry entry for the bus */
 
        struct class_device *class_dev; /* class device for this bus */
-       struct kref kref;               /* handles reference counting this bus */
-       void (*release)(struct usb_bus *bus);   /* function to destroy this bus's memory */
+       struct kref kref;               /* reference counting for this bus */
+       void (*release)(struct usb_bus *bus);
+
 #if defined(CONFIG_USB_MON)
        struct mon_bus *mon_bus;        /* non-null when associated */
        int monitored;                  /* non-zero when monitored */
 #endif
 };
 
-/* -------------------------------------------------------------------------- */
+/* ----------------------------------------------------------------------- */
 
 /* This is arbitrary.
  * From USB 2.0 spec Table 11-13, offset 7, a hub can
@@ -326,7 +330,8 @@ struct usb_device {
 
        struct semaphore serialize;
 
-       unsigned int toggle[2];         /* one bit for each endpoint ([0] = IN, [1] = OUT) */
+       unsigned int toggle[2];         /* one bit for each endpoint
+                                        * ([0] = IN, [1] = OUT) */
 
        struct usb_device *parent;      /* our hub, unless we're the root */
        struct usb_bus *bus;            /* Bus we're part of */
@@ -343,12 +348,14 @@ struct usb_device {
 
        char **rawdescriptors;          /* Raw descriptors for each config */
 
-       int have_langid;                /* whether string_langid is valid yet */
+       int have_langid;                /* whether string_langid is valid */
        int string_langid;              /* language ID for strings */
 
-       char *product;
-       char *manufacturer;
-       char *serial;                   /* static strings from the device */
+       /* static strings from the device */
+       char *product;                  /* iProduct string, if present */
+       char *manufacturer;             /* iManufacturer string, if present */
+       char *serial;                   /* iSerialNumber string, if present */
+
        struct list_head filelist;
        struct class_device *class_dev;
        struct dentry *usbfs_dentry;    /* usbfs dentry entry for the device */
@@ -440,22 +447,31 @@ extern struct usb_host_interface *usb_altnum_to_altsetting(
  * USB 2.0 root hubs (EHCI host controllers) will get one path ID if they are
  * high speed, and a different one if they are full or low speed.
  */
-static inline int usb_make_path (struct usb_device *dev, char *buf, size_t size)
+static inline int usb_make_path (struct usb_device *dev, char *buf,
+               size_t size)
 {
        int actual;
-       actual = snprintf (buf, size, "usb-%s-%s", dev->bus->bus_name, dev->devpath);
+       actual = snprintf (buf, size, "usb-%s-%s", dev->bus->bus_name,
+                       dev->devpath);
        return (actual >= (int)size) ? -1 : actual;
 }
 
 /*-------------------------------------------------------------------------*/
 
-#define USB_DEVICE_ID_MATCH_DEVICE             (USB_DEVICE_ID_MATCH_VENDOR | USB_DEVICE_ID_MATCH_PRODUCT)
-#define USB_DEVICE_ID_MATCH_DEV_RANGE          (USB_DEVICE_ID_MATCH_DEV_LO | USB_DEVICE_ID_MATCH_DEV_HI)
-#define USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION (USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_DEV_RANGE)
+#define USB_DEVICE_ID_MATCH_DEVICE \
+               (USB_DEVICE_ID_MATCH_VENDOR | USB_DEVICE_ID_MATCH_PRODUCT)
+#define USB_DEVICE_ID_MATCH_DEV_RANGE \
+               (USB_DEVICE_ID_MATCH_DEV_LO | USB_DEVICE_ID_MATCH_DEV_HI)
+#define USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION \
+               (USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_DEV_RANGE)
 #define USB_DEVICE_ID_MATCH_DEV_INFO \
-       (USB_DEVICE_ID_MATCH_DEV_CLASS | USB_DEVICE_ID_MATCH_DEV_SUBCLASS | USB_DEVICE_ID_MATCH_DEV_PROTOCOL)
+               (USB_DEVICE_ID_MATCH_DEV_CLASS | \
+               USB_DEVICE_ID_MATCH_DEV_SUBCLASS | \
+               USB_DEVICE_ID_MATCH_DEV_PROTOCOL)
 #define USB_DEVICE_ID_MATCH_INT_INFO \
-       (USB_DEVICE_ID_MATCH_INT_CLASS | USB_DEVICE_ID_MATCH_INT_SUBCLASS | USB_DEVICE_ID_MATCH_INT_PROTOCOL)
+               (USB_DEVICE_ID_MATCH_INT_CLASS | \
+               USB_DEVICE_ID_MATCH_INT_SUBCLASS | \
+               USB_DEVICE_ID_MATCH_INT_PROTOCOL)
 
 /**
  * USB_DEVICE - macro used to describe a specific usb device
@@ -466,9 +482,11 @@ static inline int usb_make_path (struct usb_device *dev, char *buf, size_t size)
  * specific device.
  */
 #define USB_DEVICE(vend,prod) \
-       .match_flags = USB_DEVICE_ID_MATCH_DEVICE, .idVendor = (vend), .idProduct = (prod)
+       .match_flags = USB_DEVICE_ID_MATCH_DEVICE, .idVendor = (vend), \
+                       .idProduct = (prod)
 /**
- * USB_DEVICE_VER - macro used to describe a specific usb device with a version range
+ * USB_DEVICE_VER - macro used to describe a specific usb device with a
+ *             version range
  * @vend: the 16 bit USB Vendor ID
  * @prod: the 16 bit USB Product ID
  * @lo: the bcdDevice_lo value
@@ -478,7 +496,9 @@ static inline int usb_make_path (struct usb_device *dev, char *buf, size_t size)
  * specific device, with a version range.
  */
 #define USB_DEVICE_VER(vend,prod,lo,hi) \
-       .match_flags = USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION, .idVendor = (vend), .idProduct = (prod), .bcdDevice_lo = (lo), .bcdDevice_hi = (hi)
+       .match_flags = USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION, \
+       .idVendor = (vend), .idProduct = (prod), \
+       .bcdDevice_lo = (lo), .bcdDevice_hi = (hi)
 
 /**
  * USB_DEVICE_INFO - macro used to describe a class of usb devices
@@ -490,7 +510,8 @@ static inline int usb_make_path (struct usb_device *dev, char *buf, size_t size)
  * specific class of devices.
  */
 #define USB_DEVICE_INFO(cl,sc,pr) \
-       .match_flags = USB_DEVICE_ID_MATCH_DEV_INFO, .bDeviceClass = (cl), .bDeviceSubClass = (sc), .bDeviceProtocol = (pr)
+       .match_flags = USB_DEVICE_ID_MATCH_DEV_INFO, .bDeviceClass = (cl), \
+       .bDeviceSubClass = (sc), .bDeviceProtocol = (pr)
 
 /**
  * USB_INTERFACE_INFO - macro used to describe a class of usb interfaces 
@@ -502,9 +523,10 @@ static inline int usb_make_path (struct usb_device *dev, char *buf, size_t size)
  * specific class of interfaces.
  */
 #define USB_INTERFACE_INFO(cl,sc,pr) \
-       .match_flags = USB_DEVICE_ID_MATCH_INT_INFO, .bInterfaceClass = (cl), .bInterfaceSubClass = (sc), .bInterfaceProtocol = (pr)
+       .match_flags = USB_DEVICE_ID_MATCH_INT_INFO, .bInterfaceClass = (cl), \
+       .bInterfaceSubClass = (sc), .bInterfaceProtocol = (pr)
 
-/* -------------------------------------------------------------------------- */
+/* ----------------------------------------------------------------------- */
 
 /**
  * struct usb_driver - identifies USB driver to usbcore
@@ -557,7 +579,8 @@ struct usb_driver {
 
        void (*disconnect) (struct usb_interface *intf);
 
-       int (*ioctl) (struct usb_interface *intf, unsigned int code, void *buf);
+       int (*ioctl) (struct usb_interface *intf, unsigned int code,
+                       void *buf);
 
        int (*suspend) (struct usb_interface *intf, pm_message_t message);
        int (*resume) (struct usb_interface *intf);
@@ -572,10 +595,8 @@ extern struct bus_type usb_bus_type;
 
 /**
  * struct usb_class_driver - identifies a USB driver that wants to use the USB major number
- * @name: devfs name for this driver.  Will also be used by the driver
- *     class code to create a usb class device.
+ * @name: the usb class device name for this driver.  Will show up in sysfs.
  * @fops: pointer to the struct file_operations of this driver.
- * @mode: the mode for the devfs file to be created for this driver.
  * @minor_base: the start of the minor range for this driver.
  *
  * This structure is used for the usb_register_dev() and
@@ -585,8 +606,7 @@ extern struct bus_type usb_bus_type;
 struct usb_class_driver {
        char *name;
        struct file_operations *fops;
-       mode_t mode;
-       int minor_base; 
+       int minor_base;
 };
 
 /*
@@ -603,7 +623,7 @@ extern void usb_deregister_dev(struct usb_interface *intf,
 
 extern int usb_disabled(void);
 
-/* -------------------------------------------------------------------------- */
+/* ----------------------------------------------------------------------- */
 
 /*
  * URB support, for asynchronous request completions
@@ -613,12 +633,14 @@ extern int usb_disabled(void);
  * urb->transfer_flags:
  */
 #define URB_SHORT_NOT_OK       0x0001  /* report short reads as errors */
-#define URB_ISO_ASAP           0x0002  /* iso-only, urb->start_frame ignored */
+#define URB_ISO_ASAP           0x0002  /* iso-only, urb->start_frame
+                                        * ignored */
 #define URB_NO_TRANSFER_DMA_MAP        0x0004  /* urb->transfer_dma valid on submit */
 #define URB_NO_SETUP_DMA_MAP   0x0008  /* urb->setup_dma valid on submit */
 #define URB_NO_FSBR            0x0020  /* UHCI-specific */
-#define URB_ZERO_PACKET                0x0040  /* Finish bulk OUTs with short packet */
-#define URB_NO_INTERRUPT       0x0080  /* HINT: no non-error interrupt needed */
+#define URB_ZERO_PACKET                0x0040  /* Finish bulk OUT with short packet */
+#define URB_NO_INTERRUPT       0x0080  /* HINT: no non-error interrupt
+                                        * needed */
 
 struct usb_iso_packet_descriptor {
        unsigned int offset;
@@ -806,7 +828,8 @@ struct urb
        u8 reject;                      /* submissions will fail */
 
        /* public, documented fields in the urb that can be used by drivers */
-       struct list_head urb_list;      /* list head for use by the urb owner */
+       struct list_head urb_list;      /* list head for use by the urb's
+                                        * current owner */
        struct usb_device *dev;         /* (in) pointer to associated device */
        unsigned int pipe;              /* (in) pipe information */
        int status;                     /* (return) non-ISO status */
@@ -819,14 +842,16 @@ struct urb
        dma_addr_t setup_dma;           /* (in) dma addr for setup_packet */
        int start_frame;                /* (modify) start frame (ISO) */
        int number_of_packets;          /* (in) number of ISO packets */
-       int interval;                   /* (modify) transfer interval (INT/ISO) */
+       int interval;                   /* (modify) transfer interval
+                                        * (INT/ISO) */
        int error_count;                /* (return) number of ISO errors */
        void *context;                  /* (in) context for completion */
        usb_complete_t complete;        /* (in) completion routine */
-       struct usb_iso_packet_descriptor iso_frame_desc[0];     /* (in) ISO ONLY */
+       struct usb_iso_packet_descriptor iso_frame_desc[0];
+                                       /* (in) ISO ONLY */
 };
 
-/* -------------------------------------------------------------------------- */
+/* ----------------------------------------------------------------------- */
 
 /**
  * usb_fill_control_urb - initializes a control urb
@@ -974,11 +999,6 @@ extern int usb_bulk_msg(struct usb_device *usb_dev, unsigned int pipe,
        void *data, int len, int *actual_length,
        int timeout);
 
-/* selective suspend/resume */
-extern int usb_suspend_device(struct usb_device *dev, pm_message_t message);
-extern int usb_resume_device(struct usb_device *dev);
-
-
 /* wrappers around usb_control_msg() for the most common standard requests */
 extern int usb_get_descriptor(struct usb_device *dev, unsigned char desctype,
        unsigned char descindex, void *buf, int size);
@@ -1056,7 +1076,7 @@ void usb_sg_cancel (struct usb_sg_request *io);
 void usb_sg_wait (struct usb_sg_request *io);
 
 
-/* -------------------------------------------------------------------------- */
+/* ----------------------------------------------------------------------- */
 
 /*
  * For various legacy reasons, Linux has a small cookie that's paired with
@@ -1097,23 +1117,34 @@ void usb_sg_wait (struct usb_sg_request *io);
 /* The D0/D1 toggle bits ... USE WITH CAUTION (they're almost hcd-internal) */
 #define usb_gettoggle(dev, ep, out) (((dev)->toggle[out] >> (ep)) & 1)
 #define        usb_dotoggle(dev, ep, out)  ((dev)->toggle[out] ^= (1 << (ep)))
-#define usb_settoggle(dev, ep, out, bit) ((dev)->toggle[out] = ((dev)->toggle[out] & ~(1 << (ep))) | ((bit) << (ep)))
+#define usb_settoggle(dev, ep, out, bit) \
+               ((dev)->toggle[out] = ((dev)->toggle[out] & ~(1 << (ep))) | \
+                ((bit) << (ep)))
 
 
-static inline unsigned int __create_pipe(struct usb_device *dev, unsigned int endpoint)
+static inline unsigned int __create_pipe(struct usb_device *dev,
+               unsigned int endpoint)
 {
        return (dev->devnum << 8) | (endpoint << 15);
 }
 
 /* Create various pipes... */
-#define usb_sndctrlpipe(dev,endpoint)  ((PIPE_CONTROL << 30) | __create_pipe(dev,endpoint))
-#define usb_rcvctrlpipe(dev,endpoint)  ((PIPE_CONTROL << 30) | __create_pipe(dev,endpoint) | USB_DIR_IN)
-#define usb_sndisocpipe(dev,endpoint)  ((PIPE_ISOCHRONOUS << 30) | __create_pipe(dev,endpoint))
-#define usb_rcvisocpipe(dev,endpoint)  ((PIPE_ISOCHRONOUS << 30) | __create_pipe(dev,endpoint) | USB_DIR_IN)
-#define usb_sndbulkpipe(dev,endpoint)  ((PIPE_BULK << 30) | __create_pipe(dev,endpoint))
-#define usb_rcvbulkpipe(dev,endpoint)  ((PIPE_BULK << 30) | __create_pipe(dev,endpoint) | USB_DIR_IN)
-#define usb_sndintpipe(dev,endpoint)   ((PIPE_INTERRUPT << 30) | __create_pipe(dev,endpoint))
-#define usb_rcvintpipe(dev,endpoint)   ((PIPE_INTERRUPT << 30) | __create_pipe(dev,endpoint) | USB_DIR_IN)
+#define usb_sndctrlpipe(dev,endpoint)  \
+       ((PIPE_CONTROL << 30) | __create_pipe(dev,endpoint))
+#define usb_rcvctrlpipe(dev,endpoint)  \
+       ((PIPE_CONTROL << 30) | __create_pipe(dev,endpoint) | USB_DIR_IN)
+#define usb_sndisocpipe(dev,endpoint)  \
+       ((PIPE_ISOCHRONOUS << 30) | __create_pipe(dev,endpoint))
+#define usb_rcvisocpipe(dev,endpoint)  \
+       ((PIPE_ISOCHRONOUS << 30) | __create_pipe(dev,endpoint) | USB_DIR_IN)
+#define usb_sndbulkpipe(dev,endpoint)  \
+       ((PIPE_BULK << 30) | __create_pipe(dev,endpoint))
+#define usb_rcvbulkpipe(dev,endpoint)  \
+       ((PIPE_BULK << 30) | __create_pipe(dev,endpoint) | USB_DIR_IN)
+#define usb_sndintpipe(dev,endpoint)   \
+       ((PIPE_INTERRUPT << 30) | __create_pipe(dev,endpoint))
+#define usb_rcvintpipe(dev,endpoint)   \
+       ((PIPE_INTERRUPT << 30) | __create_pipe(dev,endpoint) | USB_DIR_IN)
 
 /*-------------------------------------------------------------------------*/
 
@@ -1137,17 +1168,29 @@ usb_maxpacket(struct usb_device *udev, int pipe, int is_out)
        return le16_to_cpu(ep->desc.wMaxPacketSize);
 }
 
-/* -------------------------------------------------------------------------- */
+/* ----------------------------------------------------------------------- */
+
+/* Events from the usb core */
+#define USB_DEVICE_ADD         0x0001
+#define USB_DEVICE_REMOVE      0x0002
+#define USB_BUS_ADD            0x0003
+#define USB_BUS_REMOVE         0x0004
+extern void usb_register_notify(struct notifier_block *nb);
+extern void usb_unregister_notify(struct notifier_block *nb);
 
 #ifdef DEBUG
-#define dbg(format, arg...) printk(KERN_DEBUG "%s: " format "\n" , __FILE__ , ## arg)
+#define dbg(format, arg...) printk(KERN_DEBUG "%s: " format "\n" , \
+       __FILE__ , ## arg)
 #else
 #define dbg(format, arg...) do {} while (0)
 #endif
 
-#define err(format, arg...) printk(KERN_ERR "%s: " format "\n" , __FILE__ , ## arg)
-#define info(format, arg...) printk(KERN_INFO "%s: " format "\n" , __FILE__ , ## arg)
-#define warn(format, arg...) printk(KERN_WARNING "%s: " format "\n" , __FILE__ , ## arg)
+#define err(format, arg...) printk(KERN_ERR "%s: " format "\n" , \
+       __FILE__ , ## arg)
+#define info(format, arg...) printk(KERN_INFO "%s: " format "\n" , \
+       __FILE__ , ## arg)
+#define warn(format, arg...) printk(KERN_WARNING "%s: " format "\n" , \
+       __FILE__ , ## arg)
 
 
 #endif  /* __KERNEL__ */
index c668314..f827f6e 100644 (file)
@@ -63,6 +63,10 @@ struct otg_transceiver {
        int     (*set_power)(struct otg_transceiver *otg,
                                unsigned mA);
 
+       /* for non-OTG B devices: set transceiver into suspend mode */
+       int     (*set_suspend)(struct otg_transceiver *otg,
+                               int suspend);
+
        /* for B devices only:  start session with A-Host */
        int     (*start_srp)(struct otg_transceiver *otg);
 
@@ -107,6 +111,15 @@ otg_set_power(struct otg_transceiver *otg, unsigned mA)
        return otg->set_power(otg, mA);
 }
 
+static inline int
+otg_set_suspend(struct otg_transceiver *otg, int suspend)
+{
+       if (otg->set_suspend != NULL)
+               return otg->set_suspend(otg, suspend);
+       else
+               return 0;
+}
+
 static inline int
 otg_start_srp(struct otg_transceiver *otg)
 {
index 9facf73..8859f0b 100644 (file)
@@ -140,6 +140,12 @@ struct usbdevfs_urb32 {
        compat_caddr_t usercontext; /* unused */
        struct usbdevfs_iso_packet_desc iso_frame_desc[0];
 };
+
+struct usbdevfs_ioctl32 {
+       s32 ifno;
+       s32 ioctl_code;
+       compat_caddr_t data;
+};
 #endif
 
 #define USBDEVFS_CONTROL           _IOWR('U', 0, struct usbdevfs_ctrltransfer)
@@ -160,6 +166,7 @@ struct usbdevfs_urb32 {
 #define USBDEVFS_RELEASEINTERFACE  _IOR('U', 16, unsigned int)
 #define USBDEVFS_CONNECTINFO       _IOW('U', 17, struct usbdevfs_connectinfo)
 #define USBDEVFS_IOCTL             _IOWR('U', 18, struct usbdevfs_ioctl)
+#define USBDEVFS_IOCTL32           _IOWR('U', 18, struct usbdevfs_ioctl32)
 #define USBDEVFS_HUB_PORTINFO      _IOR('U', 19, struct usbdevfs_hub_portinfo)
 #define USBDEVFS_RESET             _IO('U', 20)
 #define USBDEVFS_CLEAR_HALT        _IOR('U', 21, unsigned int)
index 1c5f19f..f1c3bc5 100644 (file)
@@ -171,10 +171,10 @@ struct sctp_sndrcvinfo {
  */
 
 enum sctp_sinfo_flags {
-       MSG_UNORDERED = 1,  /* Send/receive message unordered. */
-       MSG_ADDR_OVER = 2,  /* Override the primary destination. */
-       MSG_ABORT=4,        /* Send an ABORT message to the peer. */
-       /* MSG_EOF is already defined per socket.h */
+       SCTP_UNORDERED = 1,  /* Send/receive message unordered. */
+       SCTP_ADDR_OVER = 2,  /* Override the primary destination. */
+       SCTP_ABORT=4,        /* Send an ABORT message to the peer. */
+       SCTP_EOF=MSG_FIN,    /* Initiate graceful shutdown process. */  
 };
 
 
index 5308683..0a9fcd5 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2004 Intel Corporation.  All rights reserved.
+ * Copyright (c) 2004, 2005 Intel Corporation.  All rights reserved.
  * Copyright (c) 2004 Topspin Corporation.  All rights reserved.
  * Copyright (c) 2004 Voltaire Corporation.  All rights reserved.
  * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved.
@@ -109,7 +109,6 @@ struct ib_cm_id;
 
 struct ib_cm_req_event_param {
        struct ib_cm_id         *listen_id;
-       struct ib_device        *device;
        u8                      port;
 
        struct ib_sa_path_rec   *primary_path;
@@ -220,7 +219,6 @@ struct ib_cm_apr_event_param {
 
 struct ib_cm_sidr_req_event_param {
        struct ib_cm_id         *listen_id;
-       struct ib_device        *device;
        u8                      port;
        u16                     pkey;
 };
@@ -284,6 +282,7 @@ typedef int (*ib_cm_handler)(struct ib_cm_id *cm_id,
 struct ib_cm_id {
        ib_cm_handler           cm_handler;
        void                    *context;
+       struct ib_device        *device;
        __be64                  service_id;
        __be64                  service_mask;
        enum ib_cm_state        state;          /* internal CM/debug use */
@@ -295,6 +294,8 @@ struct ib_cm_id {
 
 /**
  * ib_create_cm_id - Allocate a communication identifier.
+ * @device: Device associated with the cm_id.  All related communication will
+ * be associated with the specified device.
  * @cm_handler: Callback invoked to notify the user of CM events.
  * @context: User specified context associated with the communication
  *   identifier.
@@ -302,7 +303,8 @@ struct ib_cm_id {
  * Communication identifiers are used to track connection states, service
  * ID resolution requests, and listen requests.
  */
-struct ib_cm_id *ib_create_cm_id(ib_cm_handler cm_handler,
+struct ib_cm_id *ib_create_cm_id(struct ib_device *device,
+                                ib_cm_handler cm_handler,
                                 void *context);
 
 /**
index 4172e68..2c13350 100644 (file)
 #define IB_QP_SET_QKEY 0x80000000
 
 enum {
+       IB_MGMT_MAD_HDR = 24,
        IB_MGMT_MAD_DATA = 232,
+       IB_MGMT_RMPP_HDR = 36,
        IB_MGMT_RMPP_DATA = 220,
+       IB_MGMT_VENDOR_HDR = 40,
        IB_MGMT_VENDOR_DATA = 216,
-       IB_MGMT_SA_DATA = 200
+       IB_MGMT_SA_HDR = 56,
+       IB_MGMT_SA_DATA = 200,
 };
 
 struct ib_mad_hdr {
@@ -203,26 +207,25 @@ struct ib_class_port_info
 
 /**
  * ib_mad_send_buf - MAD data buffer and work request for sends.
- * @mad: References an allocated MAD data buffer.  The size of the data
- *   buffer is specified in the @send_wr.length field.
- * @mapping: DMA mapping information.
+ * @next: A pointer used to chain together MADs for posting.
+ * @mad: References an allocated MAD data buffer.
  * @mad_agent: MAD agent that allocated the buffer.
+ * @ah: The address handle to use when sending the MAD.
  * @context: User-controlled context fields.
- * @send_wr: An initialized work request structure used when sending the MAD.
- *   The wr_id field of the work request is initialized to reference this
- *   data structure.
- * @sge: A scatter-gather list referenced by the work request.
+ * @timeout_ms: Time to wait for a response.
+ * @retries: Number of times to retry a request for a response.
  *
  * Users are responsible for initializing the MAD buffer itself, with the
  * exception of specifying the payload length field in any RMPP MAD.
  */
 struct ib_mad_send_buf {
-       struct ib_mad           *mad;
-       DECLARE_PCI_UNMAP_ADDR(mapping)
+       struct ib_mad_send_buf  *next;
+       void                    *mad;
        struct ib_mad_agent     *mad_agent;
+       struct ib_ah            *ah;
        void                    *context[2];
-       struct ib_send_wr       send_wr;
-       struct ib_sge           sge;
+       int                     timeout_ms;
+       int                     retries;
 };
 
 /**
@@ -287,7 +290,7 @@ typedef void (*ib_mad_send_handler)(struct ib_mad_agent *mad_agent,
  * or @mad_send_wc.
  */
 typedef void (*ib_mad_snoop_handler)(struct ib_mad_agent *mad_agent,
-                                    struct ib_send_wr *send_wr,
+                                    struct ib_mad_send_buf *send_buf,
                                     struct ib_mad_send_wc *mad_send_wc);
 
 /**
@@ -334,13 +337,13 @@ struct ib_mad_agent {
 
 /**
  * ib_mad_send_wc - MAD send completion information.
- * @wr_id: Work request identifier associated with the send MAD request.
+ * @send_buf: Send MAD data buffer associated with the send MAD request.
  * @status: Completion status.
  * @vendor_err: Optional vendor error information returned with a failed
  *   request.
  */
 struct ib_mad_send_wc {
-       u64                     wr_id;
+       struct ib_mad_send_buf  *send_buf;
        enum ib_wc_status       status;
        u32                     vendor_err;
 };
@@ -366,7 +369,7 @@ struct ib_mad_recv_buf {
  * @rmpp_list: Specifies a list of RMPP reassembled received MAD buffers.
  * @mad_len: The length of the received MAD, without duplicated headers.
  *
- * For received response, the wr_id field of the wc is set to the wr_id
+ * For received response, the wr_id contains a pointer to the ib_mad_send_buf
  *   for the corresponding send request.
  */
 struct ib_mad_recv_wc {
@@ -463,9 +466,9 @@ int ib_unregister_mad_agent(struct ib_mad_agent *mad_agent);
 /**
  * ib_post_send_mad - Posts MAD(s) to the send queue of the QP associated
  *   with the registered client.
- * @mad_agent: Specifies the associated registration to post the send to.
- * @send_wr: Specifies the information needed to send the MAD(s).
- * @bad_send_wr: Specifies the MAD on which an error was encountered.
+ * @send_buf: Specifies the information needed to send the MAD(s).
+ * @bad_send_buf: Specifies the MAD on which an error was encountered.  This
+ *   parameter is optional if only a single MAD is posted.
  *
  * Sent MADs are not guaranteed to complete in the order that they were posted.
  *
@@ -479,9 +482,8 @@ int ib_unregister_mad_agent(struct ib_mad_agent *mad_agent);
  * defined data being transferred.  The paylen_newwin field should be
  * specified in network-byte order.
  */
-int ib_post_send_mad(struct ib_mad_agent *mad_agent,
-                    struct ib_send_wr *send_wr,
-                    struct ib_send_wr **bad_send_wr);
+int ib_post_send_mad(struct ib_mad_send_buf *send_buf,
+                    struct ib_mad_send_buf **bad_send_buf);
 
 /**
  * ib_coalesce_recv_mad - Coalesces received MAD data into a single buffer.
@@ -507,23 +509,25 @@ void ib_free_recv_mad(struct ib_mad_recv_wc *mad_recv_wc);
 /**
  * ib_cancel_mad - Cancels an outstanding send MAD operation.
  * @mad_agent: Specifies the registration associated with sent MAD.
- * @wr_id: Indicates the work request identifier of the MAD to cancel.
+ * @send_buf: Indicates the MAD to cancel.
  *
  * MADs will be returned to the user through the corresponding
  * ib_mad_send_handler.
  */
-void ib_cancel_mad(struct ib_mad_agent *mad_agent, u64 wr_id);
+void ib_cancel_mad(struct ib_mad_agent *mad_agent,
+                  struct ib_mad_send_buf *send_buf);
 
 /**
  * ib_modify_mad - Modifies an outstanding send MAD operation.
  * @mad_agent: Specifies the registration associated with sent MAD.
- * @wr_id: Indicates the work request identifier of the MAD to modify.
+ * @send_buf: Indicates the MAD to modify.
  * @timeout_ms: New timeout value for sent MAD.
  *
  * This call will reset the timeout value for a sent MAD to the specified
  * value.
  */
-int ib_modify_mad(struct ib_mad_agent *mad_agent, u64 wr_id, u32 timeout_ms);
+int ib_modify_mad(struct ib_mad_agent *mad_agent,
+                 struct ib_mad_send_buf *send_buf, u32 timeout_ms);
 
 /**
  * ib_redirect_mad_qp - Registers a QP for MAD services.
@@ -572,7 +576,6 @@ int ib_process_mad_wc(struct ib_mad_agent *mad_agent,
  * @remote_qpn: Specifies the QPN of the receiving node.
  * @pkey_index: Specifies which PKey the MAD will be sent using.  This field
  *   is valid only if the remote_qpn is QP 1.
- * @ah: References the address handle used to transfer to the remote node.
  * @rmpp_active: Indicates if the send will enable RMPP.
  * @hdr_len: Indicates the size of the data header of the MAD.  This length
  *   should include the common MAD header, RMPP header, plus any class
@@ -582,11 +585,10 @@ int ib_process_mad_wc(struct ib_mad_agent *mad_agent,
  *   additional padding that may be necessary.
  * @gfp_mask: GFP mask used for the memory allocation.
  *
- * This is a helper routine that may be used to allocate a MAD.  Users are
- * not required to allocate outbound MADs using this call.  The returned
- * MAD send buffer will reference a data buffer usable for sending a MAD, along
+ * This routine allocates a MAD for sending.  The returned MAD send buffer
+ * will reference a data buffer usable for sending a MAD, along
  * with an initialized work request structure.  Users may modify the returned
- * MAD data buffer or work request before posting the send.
+ * MAD data buffer before posting the send.
  *
  * The returned data buffer will be cleared.  Users are responsible for
  * initializing the common MAD and any class specific headers.  If @rmpp_active
@@ -594,7 +596,7 @@ int ib_process_mad_wc(struct ib_mad_agent *mad_agent,
  */
 struct ib_mad_send_buf * ib_create_send_mad(struct ib_mad_agent *mad_agent,
                                            u32 remote_qpn, u16 pkey_index,
-                                           struct ib_ah *ah, int rmpp_active,
+                                           int rmpp_active,
                                            int hdr_len, int data_len,
                                            gfp_t gfp_mask);
 
index e4d1654..3037588 100644 (file)
@@ -38,7 +38,7 @@
 
 #include <linux/types.h>
 
-#define IB_USER_CM_ABI_VERSION 2
+#define IB_USER_CM_ABI_VERSION 3
 
 enum {
        IB_USER_CM_CMD_CREATE_ID,
@@ -299,8 +299,6 @@ struct ib_ucm_event_get {
 };
 
 struct ib_ucm_req_event_resp {
-       /* device */
-       /* port */
        struct ib_ucm_path_rec primary_path;
        struct ib_ucm_path_rec alternate_path;
        __be64                 remote_ca_guid;
@@ -316,6 +314,7 @@ struct ib_ucm_req_event_resp {
        __u8  retry_count;
        __u8  rnr_retry_count;
        __u8  srq;
+       __u8  port;
 };
 
 struct ib_ucm_rep_event_resp {
@@ -353,10 +352,9 @@ struct ib_ucm_apr_event_resp {
 };
 
 struct ib_ucm_sidr_req_event_resp {
-       /* device */
-       /* port */
        __u16 pkey;
-       __u8  reserved[2];
+       __u8  port;
+       __u8  reserved;
 };
 
 struct ib_ucm_sidr_rep_event_resp {
index fd85725..072f3a2 100644 (file)
@@ -1,6 +1,7 @@
 /*
  * Copyright (c) 2005 Topspin Communications.  All rights reserved.
  * Copyright (c) 2005 Cisco Systems.  All rights reserved.
+ * Copyright (c) 2005 PathScale, Inc.  All rights reserved.
  *
  * This software is available to you under a choice of one of two
  * licenses.  You may choose to be licensed under the terms of the GNU
  * Increment this value if any changes that break userspace ABI
  * compatibility are made.
  */
-#define IB_USER_VERBS_ABI_VERSION      2
+#define IB_USER_VERBS_ABI_VERSION      3
 
 enum {
-       IB_USER_VERBS_CMD_QUERY_PARAMS,
        IB_USER_VERBS_CMD_GET_CONTEXT,
        IB_USER_VERBS_CMD_QUERY_DEVICE,
        IB_USER_VERBS_CMD_QUERY_PORT,
-       IB_USER_VERBS_CMD_QUERY_GID,
-       IB_USER_VERBS_CMD_QUERY_PKEY,
        IB_USER_VERBS_CMD_ALLOC_PD,
        IB_USER_VERBS_CMD_DEALLOC_PD,
        IB_USER_VERBS_CMD_CREATE_AH,
@@ -65,6 +63,7 @@ enum {
        IB_USER_VERBS_CMD_ALLOC_MW,
        IB_USER_VERBS_CMD_BIND_MW,
        IB_USER_VERBS_CMD_DEALLOC_MW,
+       IB_USER_VERBS_CMD_CREATE_COMP_CHANNEL,
        IB_USER_VERBS_CMD_CREATE_CQ,
        IB_USER_VERBS_CMD_RESIZE_CQ,
        IB_USER_VERBS_CMD_DESTROY_CQ,
@@ -90,8 +89,11 @@ enum {
  * Make sure that all structs defined in this file remain laid out so
  * that they pack the same way on 32-bit and 64-bit architectures (to
  * avoid incompatibility between 32-bit userspace and 64-bit kernels).
- * In particular do not use pointer types -- pass pointers in __u64
- * instead.
+ * Specifically:
+ *  - Do not use pointer types -- pass pointers in __u64 instead.
+ *  - Make sure that any structure larger than 4 bytes is padded to a
+ *    multiple of 8 bytes.  Otherwise the structure size will be
+ *    different between 32-bit and 64-bit architectures.
  */
 
 struct ib_uverbs_async_event_desc {
@@ -118,27 +120,14 @@ struct ib_uverbs_cmd_hdr {
        __u16 out_words;
 };
 
-/*
- * No driver_data for "query params" command, since this is intended
- * to be a core function with no possible device dependence.
- */
-struct ib_uverbs_query_params {
-       __u64 response;
-};
-
-struct ib_uverbs_query_params_resp {
-       __u32 num_cq_events;
-};
-
 struct ib_uverbs_get_context {
        __u64 response;
-       __u64 cq_fd_tab;
        __u64 driver_data[0];
 };
 
 struct ib_uverbs_get_context_resp {
        __u32 async_fd;
-       __u32 reserved;
+       __u32 num_comp_vectors;
 };
 
 struct ib_uverbs_query_device {
@@ -220,31 +209,6 @@ struct ib_uverbs_query_port_resp {
        __u8  reserved[3];
 };
 
-struct ib_uverbs_query_gid {
-       __u64 response;
-       __u8  port_num;
-       __u8  index;
-       __u8  reserved[6];
-       __u64 driver_data[0];
-};
-
-struct ib_uverbs_query_gid_resp {
-       __u8  gid[16];
-};
-
-struct ib_uverbs_query_pkey {
-       __u64 response;
-       __u8  port_num;
-       __u8  index;
-       __u8  reserved[6];
-       __u64 driver_data[0];
-};
-
-struct ib_uverbs_query_pkey_resp {
-       __u16 pkey;
-       __u16 reserved;
-};
-
 struct ib_uverbs_alloc_pd {
        __u64 response;
        __u64 driver_data[0];
@@ -278,11 +242,21 @@ struct ib_uverbs_dereg_mr {
        __u32 mr_handle;
 };
 
+struct ib_uverbs_create_comp_channel {
+       __u64 response;
+};
+
+struct ib_uverbs_create_comp_channel_resp {
+       __u32 fd;
+};
+
 struct ib_uverbs_create_cq {
        __u64 response;
        __u64 user_handle;
        __u32 cqe;
-       __u32 event_handler;
+       __u32 comp_vector;
+       __s32 comp_channel;
+       __u32 reserved;
        __u64 driver_data[0];
 };
 
@@ -291,6 +265,41 @@ struct ib_uverbs_create_cq_resp {
        __u32 cqe;
 };
 
+struct ib_uverbs_poll_cq {
+       __u64 response;
+       __u32 cq_handle;
+       __u32 ne;
+};
+
+struct ib_uverbs_wc {
+       __u64 wr_id;
+       __u32 status;
+       __u32 opcode;
+       __u32 vendor_err;
+       __u32 byte_len;
+       __u32 imm_data;
+       __u32 qp_num;
+       __u32 src_qp;
+       __u32 wc_flags;
+       __u16 pkey_index;
+       __u16 slid;
+       __u8 sl;
+       __u8 dlid_path_bits;
+       __u8 port_num;
+       __u8 reserved;
+};
+
+struct ib_uverbs_poll_cq_resp {
+       __u32 count;
+       __u32 reserved;
+       struct ib_uverbs_wc wc[0];
+};
+
+struct ib_uverbs_req_notify_cq {
+       __u32 cq_handle;
+       __u32 solicited_only;
+};
+
 struct ib_uverbs_destroy_cq {
        __u64 response;
        __u32 cq_handle;
@@ -388,6 +397,127 @@ struct ib_uverbs_destroy_qp_resp {
        __u32 events_reported;
 };
 
+/*
+ * The ib_uverbs_sge structure isn't used anywhere, since we assume
+ * the ib_sge structure is packed the same way on 32-bit and 64-bit
+ * architectures in both kernel and user space.  It's just here to
+ * document the ABI.
+ */
+struct ib_uverbs_sge {
+       __u64 addr;
+       __u32 length;
+       __u32 lkey;
+};
+
+struct ib_uverbs_send_wr {
+       __u64 wr_id; 
+       __u32 num_sge;
+       __u32 opcode;
+       __u32 send_flags;
+       __u32 imm_data;
+       union {
+               struct {
+                       __u64 remote_addr;
+                       __u32 rkey;
+                       __u32 reserved;
+               } rdma;
+               struct {
+                       __u64 remote_addr;
+                       __u64 compare_add;
+                       __u64 swap;
+                       __u32 rkey;
+                       __u32 reserved;
+               } atomic;
+               struct {
+                       __u32 ah;
+                       __u32 remote_qpn;
+                       __u32 remote_qkey;
+                       __u32 reserved;
+               } ud;
+       } wr;
+};
+
+struct ib_uverbs_post_send {
+       __u64 response;
+       __u32 qp_handle;
+       __u32 wr_count;
+       __u32 sge_count;
+       __u32 wqe_size;
+       struct ib_uverbs_send_wr send_wr[0];
+};
+
+struct ib_uverbs_post_send_resp {
+       __u32 bad_wr;
+};
+
+struct ib_uverbs_recv_wr {
+       __u64 wr_id;
+       __u32 num_sge;
+       __u32 reserved;
+};
+
+struct ib_uverbs_post_recv {
+       __u64 response;
+       __u32 qp_handle;
+       __u32 wr_count;
+       __u32 sge_count;
+       __u32 wqe_size;
+       struct ib_uverbs_recv_wr recv_wr[0];
+};
+
+struct ib_uverbs_post_recv_resp {
+       __u32 bad_wr;
+};
+
+struct ib_uverbs_post_srq_recv {
+       __u64 response;
+       __u32 srq_handle;
+       __u32 wr_count;
+       __u32 sge_count;
+       __u32 wqe_size;
+       struct ib_uverbs_recv_wr recv[0];
+};
+
+struct ib_uverbs_post_srq_recv_resp {
+       __u32 bad_wr;
+};
+
+struct ib_uverbs_global_route {
+       __u8  dgid[16];
+       __u32 flow_label;    
+       __u8  sgid_index;
+       __u8  hop_limit;
+       __u8  traffic_class;
+       __u8  reserved;
+};
+
+struct ib_uverbs_ah_attr {
+       struct ib_uverbs_global_route grh;
+       __u16 dlid;
+       __u8  sl;
+       __u8  src_path_bits;
+       __u8  static_rate;
+       __u8  is_global;
+       __u8  port_num;
+       __u8  reserved;
+};
+
+struct ib_uverbs_create_ah {
+       __u64 response;
+       __u64 user_handle;
+       __u32 pd_handle;
+       __u32 reserved;
+       struct ib_uverbs_ah_attr attr;
+};
+
+struct ib_uverbs_create_ah_resp {
+       __u32 ah_handle;
+};
+
+struct ib_uverbs_destroy_ah {
+       __u32 ah_handle;
+};
+
 struct ib_uverbs_attach_mcast {
        __u8  gid[16];
        __u32 qp_handle;
index e6f4c9e..f72d46d 100644 (file)
@@ -595,11 +595,8 @@ struct ib_send_wr {
                } atomic;
                struct {
                        struct ib_ah *ah;
-                       struct ib_mad_hdr *mad_hdr;
                        u32     remote_qpn;
                        u32     remote_qkey;
-                       int     timeout_ms; /* valid for MADs only */
-                       int     retries;    /* valid for MADs only */
                        u16     pkey_index; /* valid for GSI only */
                        u8      port_num;   /* valid for DR SMPs on switch only */
                } ud;
@@ -951,6 +948,9 @@ struct ib_device {
                IB_DEV_UNREGISTERED
        }                            reg_state;
 
+       u64                          uverbs_cmd_mask;
+       int                          uverbs_abi_ver;
+
        u8                           node_type;
        u8                           phys_port_cnt;
 };
index f2b96b0..6904bbb 100644 (file)
@@ -406,6 +406,8 @@ void __exit_signal(struct task_struct *tsk)
 
 void exit_signal(struct task_struct *tsk)
 {
+       atomic_dec(&tsk->signal->live);
+
        write_lock_irq(&tasklist_lock);
        __exit_signal(tsk);
        write_unlock_irq(&tasklist_lock);
index 40c2410..a3c2100 100644 (file)
@@ -532,6 +532,7 @@ int do_settimeofday (struct timespec *tv)
        clock_was_set();
        return 0;
 }
+EXPORT_SYMBOL(do_settimeofday);
 
 void do_gettimeofday (struct timeval *tv)
 {
index 4e958f7..edfea77 100644 (file)
@@ -1,6 +1,6 @@
 config BT_HIDP
        tristate "HIDP protocol support"
-       depends on BT && BT_L2CAP
+       depends on BT && BT_L2CAP && (BROKEN || !S390)
        select INPUT
        help
          HIDP (Human Interface Device Protocol) is a transport layer
index 68a5ca8..e245773 100644 (file)
@@ -146,19 +146,6 @@ int eth_rebuild_header(struct sk_buff *skb)
        return 0;
 }
 
-static inline unsigned int compare_eth_addr(const unsigned char *__a, const unsigned char *__b)
-{
-       const unsigned short *dest = (unsigned short *) __a;
-       const unsigned short *devaddr = (unsigned short *) __b;
-       unsigned int res;
-
-       BUILD_BUG_ON(ETH_ALEN != 6);
-       res = ((dest[0] ^ devaddr[0]) |
-              (dest[1] ^ devaddr[1]) |
-              (dest[2] ^ devaddr[2])) != 0;
-
-       return res;
-}
 
 /*
  *     Determine the packet's protocol ID. The rule here is that we 
@@ -176,7 +163,7 @@ __be16 eth_type_trans(struct sk_buff *skb, struct net_device *dev)
        eth = eth_hdr(skb);
        
        if (*eth->h_dest&1) {
-               if (!compare_eth_addr(eth->h_dest, dev->broadcast))
+               if (!compare_ether_addr(eth->h_dest, dev->broadcast))
                        skb->pkt_type = PACKET_BROADCAST;
                else
                        skb->pkt_type = PACKET_MULTICAST;
@@ -191,7 +178,7 @@ __be16 eth_type_trans(struct sk_buff *skb, struct net_device *dev)
         */
         
        else if(1 /*dev->flags&IFF_PROMISC*/) {
-               if (unlikely(compare_eth_addr(eth->h_dest, dev->dev_addr)))
+               if (unlikely(compare_ether_addr(eth->h_dest, dev->dev_addr)))
                        skb->pkt_type = PACKET_OTHERHOST;
        }
        
index e61bc71..990633c 100644 (file)
@@ -591,7 +591,7 @@ static int fib_inetaddr_event(struct notifier_block *this, unsigned long event,
                break;
        case NETDEV_DOWN:
                fib_del_ifaddr(ifa);
-               if (ifa->ifa_dev && ifa->ifa_dev->ifa_list == NULL) {
+               if (ifa->ifa_dev->ifa_list == NULL) {
                        /* Last address was deleted from this interface.
                           Disable IP.
                         */
index 10e82ec..660c61b 100644 (file)
@@ -554,7 +554,7 @@ struct sctp_chunk *sctp_make_datafrag_empty(struct sctp_association *asoc,
        dp.ppid   = sinfo->sinfo_ppid;
 
        /* Set the flags for an unordered send.  */
-       if (sinfo->sinfo_flags & MSG_UNORDERED) {
+       if (sinfo->sinfo_flags & SCTP_UNORDERED) {
                flags |= SCTP_DATA_UNORDERED;
                dp.ssn = 0;
        } else
index 02e068d..b529af5 100644 (file)
@@ -1010,6 +1010,19 @@ static int __sctp_connect(struct sock* sk,
                                        err = -EAGAIN;
                                        goto out_free;
                                }
+                       } else {
+                               /*
+                                * If an unprivileged user inherits a 1-many 
+                                * style socket with open associations on a 
+                                * privileged port, it MAY be permitted to 
+                                * accept new associations, but it SHOULD NOT 
+                                * be permitted to open new associations.
+                                */
+                               if (ep->base.bind_addr.port < PROT_SOCK &&
+                                   !capable(CAP_NET_BIND_SERVICE)) {
+                                       err = -EACCES;
+                                       goto out_free;
+                               }
                        }
 
                        scope = sctp_scope(&to);
@@ -1389,27 +1402,27 @@ SCTP_STATIC int sctp_sendmsg(struct kiocb *iocb, struct sock *sk,
        SCTP_DEBUG_PRINTK("msg_len: %zu, sinfo_flags: 0x%x\n",
                          msg_len, sinfo_flags);
 
-       /* MSG_EOF or MSG_ABORT cannot be set on a TCP-style socket. */
-       if (sctp_style(sk, TCP) && (sinfo_flags & (MSG_EOF | MSG_ABORT))) {
+       /* SCTP_EOF or SCTP_ABORT cannot be set on a TCP-style socket. */
+       if (sctp_style(sk, TCP) && (sinfo_flags & (SCTP_EOF | SCTP_ABORT))) {
                err = -EINVAL;
                goto out_nounlock;
        }
 
-       /* If MSG_EOF is set, no data can be sent. Disallow sending zero
-        * length messages when MSG_EOF|MSG_ABORT is not set.
-        * If MSG_ABORT is set, the message length could be non zero with
+       /* If SCTP_EOF is set, no data can be sent. Disallow sending zero
+        * length messages when SCTP_EOF|SCTP_ABORT is not set.
+        * If SCTP_ABORT is set, the message length could be non zero with
         * the msg_iov set to the user abort reason.
         */
-       if (((sinfo_flags & MSG_EOF) && (msg_len > 0)) ||
-           (!(sinfo_flags & (MSG_EOF|MSG_ABORT)) && (msg_len == 0))) {
+       if (((sinfo_flags & SCTP_EOF) && (msg_len > 0)) ||
+           (!(sinfo_flags & (SCTP_EOF|SCTP_ABORT)) && (msg_len == 0))) {
                err = -EINVAL;
                goto out_nounlock;
        }
 
-       /* If MSG_ADDR_OVER is set, there must be an address
+       /* If SCTP_ADDR_OVER is set, there must be an address
         * specified in msg_name.
         */
-       if ((sinfo_flags & MSG_ADDR_OVER) && (!msg->msg_name)) {
+       if ((sinfo_flags & SCTP_ADDR_OVER) && (!msg->msg_name)) {
                err = -EINVAL;
                goto out_nounlock;
        }
@@ -1458,14 +1471,14 @@ SCTP_STATIC int sctp_sendmsg(struct kiocb *iocb, struct sock *sk,
                        goto out_unlock;
                }
 
-               if (sinfo_flags & MSG_EOF) {
+               if (sinfo_flags & SCTP_EOF) {
                        SCTP_DEBUG_PRINTK("Shutting down association: %p\n",
                                          asoc);
                        sctp_primitive_SHUTDOWN(asoc, NULL);
                        err = 0;
                        goto out_unlock;
                }
-               if (sinfo_flags & MSG_ABORT) {
+               if (sinfo_flags & SCTP_ABORT) {
                        SCTP_DEBUG_PRINTK("Aborting association: %p\n", asoc);
                        sctp_primitive_ABORT(asoc, msg);
                        err = 0;
@@ -1477,7 +1490,7 @@ SCTP_STATIC int sctp_sendmsg(struct kiocb *iocb, struct sock *sk,
        if (!asoc) {
                SCTP_DEBUG_PRINTK("There is no association yet.\n");
 
-               if (sinfo_flags & (MSG_EOF | MSG_ABORT)) {
+               if (sinfo_flags & (SCTP_EOF | SCTP_ABORT)) {
                        err = -EINVAL;
                        goto out_unlock;
                }
@@ -1515,6 +1528,19 @@ SCTP_STATIC int sctp_sendmsg(struct kiocb *iocb, struct sock *sk,
                                err = -EAGAIN;
                                goto out_unlock;
                        }
+               } else {
+                       /*
+                        * If an unprivileged user inherits a one-to-many
+                        * style socket with open associations on a privileged
+                        * port, it MAY be permitted to accept new associations,
+                        * but it SHOULD NOT be permitted to open new
+                        * associations.
+                        */
+                       if (ep->base.bind_addr.port < PROT_SOCK &&
+                           !capable(CAP_NET_BIND_SERVICE)) {
+                               err = -EACCES;
+                               goto out_unlock;
+                       }
                }
 
                scope = sctp_scope(&to);
@@ -1611,10 +1637,10 @@ SCTP_STATIC int sctp_sendmsg(struct kiocb *iocb, struct sock *sk,
 
        /* If an address is passed with the sendto/sendmsg call, it is used
         * to override the primary destination address in the TCP model, or
-        * when MSG_ADDR_OVER flag is set in the UDP model.
+        * when SCTP_ADDR_OVER flag is set in the UDP model.
         */
        if ((sctp_style(sk, TCP) && msg_name) ||
-           (sinfo_flags & MSG_ADDR_OVER)) {
+           (sinfo_flags & SCTP_ADDR_OVER)) {
                chunk_tp = sctp_assoc_lookup_paddr(asoc, &to);
                if (!chunk_tp) {
                        err = -EINVAL;
@@ -2306,16 +2332,14 @@ static int sctp_setsockopt_maxseg(struct sock *sk, char __user *optval, int optl
                return -EINVAL;
        if (get_user(val, (int __user *)optval))
                return -EFAULT;
-       if ((val < 8) || (val > SCTP_MAX_CHUNK_LEN))
+       if ((val != 0) && ((val < 8) || (val > SCTP_MAX_CHUNK_LEN)))
                return -EINVAL;
        sp->user_frag = val;
 
-       if (val) {
-               /* Update the frag_point of the existing associations. */
-               list_for_each(pos, &(sp->ep->asocs)) {
-                       asoc = list_entry(pos, struct sctp_association, asocs);
-                       asoc->frag_point = sctp_frag_point(sp, asoc->pmtu); 
-               }
+       /* Update the frag_point of the existing associations. */
+       list_for_each(pos, &(sp->ep->asocs)) {
+               asoc = list_entry(pos, struct sctp_association, asocs);
+               asoc->frag_point = sctp_frag_point(sp, asoc->pmtu); 
        }
 
        return 0;
@@ -2384,14 +2408,14 @@ static int sctp_setsockopt_peer_primary_addr(struct sock *sk, char __user *optva
 static int sctp_setsockopt_adaption_layer(struct sock *sk, char __user *optval,
                                          int optlen)
 {
-       __u32 val;
+       struct sctp_setadaption adaption;
 
-       if (optlen < sizeof(__u32))
+       if (optlen != sizeof(struct sctp_setadaption))
                return -EINVAL;
-       if (copy_from_user(&val, optval, sizeof(__u32)))
+       if (copy_from_user(&adaption, optval, optlen)) 
                return -EFAULT;
 
-       sctp_sk(sk)->adaption_ind = val;
+       sctp_sk(sk)->adaption_ind = adaption.ssb_adaption_ind;
 
        return 0;
 }
@@ -3672,17 +3696,15 @@ static int sctp_getsockopt_primary_addr(struct sock *sk, int len,
 static int sctp_getsockopt_adaption_layer(struct sock *sk, int len,
                                  char __user *optval, int __user *optlen)
 {
-       __u32 val;
+       struct sctp_setadaption adaption;
 
-       if (len < sizeof(__u32))
+       if (len != sizeof(struct sctp_setadaption))
                return -EINVAL;
 
-       len = sizeof(__u32);
-       val = sctp_sk(sk)->adaption_ind;
-       if (put_user(len, optlen))
-               return -EFAULT;
-       if (copy_to_user(optval, &val, len))
+       adaption.ssb_adaption_ind = sctp_sk(sk)->adaption_ind;
+       if (copy_to_user(optval, &adaption, len))
                return -EFAULT;
+
        return 0;
 }
 
@@ -4640,8 +4662,8 @@ SCTP_STATIC int sctp_msghdr_parse(const struct msghdr *msg,
 
                        /* Minimally, validate the sinfo_flags. */
                        if (cmsgs->info->sinfo_flags &
-                           ~(MSG_UNORDERED | MSG_ADDR_OVER |
-                             MSG_ABORT | MSG_EOF))
+                           ~(SCTP_UNORDERED | SCTP_ADDR_OVER |
+                             SCTP_ABORT | SCTP_EOF))
                                return -EINVAL;
                        break;
 
index 057e7fa..e049f41 100644 (file)
@@ -698,7 +698,7 @@ struct sctp_ulpevent *sctp_ulpevent_make_rcvmsg(struct sctp_association *asoc,
        event->ssn = ntohs(chunk->subh.data_hdr->ssn);
        event->ppid = chunk->subh.data_hdr->ppid;
        if (chunk->chunk_hdr->flags & SCTP_DATA_UNORDERED) {
-               event->flags |= MSG_UNORDERED;
+               event->flags |= SCTP_UNORDERED;
                event->cumtsn = sctp_tsnmap_get_ctsn(&asoc->peer.tsn_map);
        }
        event->tsn = ntohl(chunk->subh.data_hdr->tsn);
@@ -824,7 +824,7 @@ void sctp_ulpevent_read_sndrcvinfo(const struct sctp_ulpevent *event,
         *
         * recvmsg() flags:
         *
-        * MSG_UNORDERED - This flag is present when the message was sent
+        * SCTP_UNORDERED - This flag is present when the message was sent
         *                 non-ordered.
         */
        sinfo.sinfo_flags = event->flags;
@@ -839,7 +839,7 @@ void sctp_ulpevent_read_sndrcvinfo(const struct sctp_ulpevent *event,
         * This field will hold the current cumulative TSN as
         * known by the underlying SCTP layer.  Note this field is
         * ignored when sending and only valid for a receive
-        * operation when sinfo_flags are set to MSG_UNORDERED.
+        * operation when sinfo_flags are set to SCTP_UNORDERED.
         */
        sinfo.sinfo_cumtsn = event->cumtsn;
        /* sinfo_assoc_id: sizeof (sctp_assoc_t)
index 05203ad..8dae59b 100644 (file)
@@ -107,14 +107,15 @@ static LIST_HEAD(ymf_devs);
  */
 
 static struct pci_device_id ymf_id_tbl[] = {
-#define DEV(v, d, data) \
-  { PCI_VENDOR_ID_##v, PCI_DEVICE_ID_##v##_##d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long)data }
-       DEV (YAMAHA, 724,  "YMF724"),
-       DEV (YAMAHA, 724F, "YMF724F"),
-       DEV (YAMAHA, 740,  "YMF740"),
-       DEV (YAMAHA, 740C, "YMF740C"),
-       DEV (YAMAHA, 744,  "YMF744"),
-       DEV (YAMAHA, 754,  "YMF754"),
+#define DEV(dev, data) \
+       { PCI_VENDOR_ID_YAMAHA, dev, PCI_ANY_ID, PCI_ANY_ID, 0, 0, \
+               (unsigned long)data }
+       DEV (PCI_DEVICE_ID_YAMAHA_724,  "YMF724"),
+       DEV (PCI_DEVICE_ID_YAMAHA_724F, "YMF724F"),
+       DEV (PCI_DEVICE_ID_YAMAHA_740,  "YMF740"),
+       DEV (PCI_DEVICE_ID_YAMAHA_740C, "YMF740C"),
+       DEV (PCI_DEVICE_ID_YAMAHA_744,  "YMF744"),
+       DEV (PCI_DEVICE_ID_YAMAHA_754,  "YMF754"),
 #undef DEV
        { }
 };
index 2236c95..01d98ee 100644 (file)
@@ -761,15 +761,18 @@ static int __devinit snd_bt87x_create(snd_card_t *card,
 
 #define BT_DEVICE(chip, subvend, subdev, rate) \
        { .vendor = PCI_VENDOR_ID_BROOKTREE, \
-         .device = PCI_DEVICE_ID_BROOKTREE_##chip, \
+         .device = chip, \
          .subvendor = subvend, .subdevice = subdev, \
          .driver_data = rate }
 
 /* driver_data is the default digital_rate value for that device */
 static struct pci_device_id snd_bt87x_ids[] = {
-       BT_DEVICE(878, 0x0070, 0x13eb, 32000), /* Hauppauge WinTV series */
-       BT_DEVICE(879, 0x0070, 0x13eb, 32000), /* Hauppauge WinTV series */
-       BT_DEVICE(878, 0x0070, 0xff01, 44100), /* Viewcast Osprey 200 */
+       /* Hauppauge WinTV series */
+       BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_878, 0x0070, 0x13eb, 32000),
+       /* Hauppauge WinTV series */
+       BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_879, 0x0070, 0x13eb, 32000),
+       /* Viewcast Osprey 200 */
+       BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_878, 0x0070, 0xff01, 44100),
        { }
 };
 MODULE_DEVICE_TABLE(pci, snd_bt87x_ids);