瀏覽代碼

Merge master.kernel.org:/pub/scm/linux/kernel/git/gregkh/pci-2.6

* master.kernel.org:/pub/scm/linux/kernel/git/gregkh/pci-2.6: (49 commits)
  [PATCH] acpiphp: fix acpi_path_name
  [PATCH] ibmphp: remove TRUE and FALSE
  [PATCH] PCI Hotplug: add common acpi functions to core
  [PATCH] PCI: kzalloc() conversion in drivers/pci
  [PATCH] acpiphp: Scan slots under the nested P2P bridge
  [PATCH] PCI Hotplug: SN: Fix cleanup on hotplug removal of PPB
  [PATCH] shpchp: cleanup bus speed handling
  [PATCH] PCI: fix pci_request_region[s] arg
  [PATCH] PCI: Provide a boot parameter to disable MSI
  [PATCH] PCI: the scheduled removal of PCI_LEGACY_PROC
  [PATCH] PCI: cpqphp_ctrl.c: board_replaced(): remove dead code
  [PATCH] acpiphp: fix bridge handle
  [PATCH] acpiphp - slot management fix - V4
  [PATCH] acpi: remove dock event handling from ibm_acpi
  [PATCH] acpiphp: add dock event handling
  [PATCH] acpi: export acpi_bus_trim
  [PATCH] acpiphp: add new bus to acpi
  [PATCH] PCI: Move pci_dev_put outside a spinlock
  [PATCH] PCI: PCI/Cardbus cards hidden, needs pci=assign-busses to fix
  [PATCH] PCI: fix problems with MSI-X on ia64
  ...
Linus Torvalds 19 年之前
父節點
當前提交
a3ea9b584e
共有 64 個文件被更改,包括 2198 次插入2564 次删除
  1. 0 7
      Documentation/feature-removal-schedule.txt
  2. 4 0
      Documentation/kernel-parameters.txt
  3. 1 1
      arch/i386/kernel/efi.c
  4. 17 5
      arch/i386/kernel/setup.c
  5. 1 1
      arch/i386/pci/Makefile
  6. 32 0
      arch/i386/pci/common.c
  7. 5 10
      arch/i386/pci/direct.c
  8. 25 0
      arch/i386/pci/init.c
  9. 3 8
      arch/i386/pci/mmconfig.c
  10. 1 3
      arch/i386/pci/pcbios.c
  11. 3 0
      arch/i386/pci/pci.h
  12. 2 1
      arch/x86_64/pci/Makefile
  13. 12 0
      drivers/acpi/Kconfig
  14. 10 3
      drivers/acpi/ibm_acpi.c
  15. 3 2
      drivers/acpi/scan.c
  16. 4 17
      drivers/pci/Kconfig
  17. 5 15
      drivers/pci/hotplug/Makefile
  18. 85 60
      drivers/pci/hotplug/acpi_pcihp.c
  19. 42 20
      drivers/pci/hotplug/acpiphp.h
  20. 66 68
      drivers/pci/hotplug/acpiphp_core.c
  21. 438 0
      drivers/pci/hotplug/acpiphp_dock.c
  22. 219 137
      drivers/pci/hotplug/acpiphp_glue.c
  23. 3 6
      drivers/pci/hotplug/cpci_hotplug_core.c
  24. 2 1
      drivers/pci/hotplug/cpqphp.h
  25. 11 16
      drivers/pci/hotplug/cpqphp_core.c
  26. 38 86
      drivers/pci/hotplug/cpqphp_ctrl.c
  27. 3 6
      drivers/pci/hotplug/fakephp.c
  28. 0 2
      drivers/pci/hotplug/ibmphp.h
  29. 4 6
      drivers/pci/hotplug/ibmphp_core.c
  30. 15 44
      drivers/pci/hotplug/ibmphp_ebda.c
  31. 33 31
      drivers/pci/hotplug/ibmphp_hpc.c
  32. 50 71
      drivers/pci/hotplug/ibmphp_pci.c
  33. 35 46
      drivers/pci/hotplug/ibmphp_res.c
  34. 16 0
      drivers/pci/hotplug/pci_hotplug.h
  35. 17 10
      drivers/pci/hotplug/pciehp.h
  36. 7 12
      drivers/pci/hotplug/pciehp_core.c
  37. 34 34
      drivers/pci/hotplug/pciehp_ctrl.c
  38. 75 2
      drivers/pci/hotplug/pciehp_hpc.c
  39. 0 257
      drivers/pci/hotplug/pciehprm_acpi.c
  40. 0 47
      drivers/pci/hotplug/pciehprm_nonacpi.c
  41. 11 22
      drivers/pci/hotplug/pcihp_skeleton.c
  42. 3 6
      drivers/pci/hotplug/rpaphp_slot.c
  43. 8 8
      drivers/pci/hotplug/sgi_hotplug.c
  44. 38 70
      drivers/pci/hotplug/shpchp.h
  45. 137 194
      drivers/pci/hotplug/shpchp_core.c
  46. 287 521
      drivers/pci/hotplug/shpchp_ctrl.c
  47. 189 329
      drivers/pci/hotplug/shpchp_hpc.c
  48. 8 2
      drivers/pci/hotplug/shpchp_pci.c
  49. 0 54
      drivers/pci/hotplug/shpchprm_legacy.c
  50. 0 57
      drivers/pci/hotplug/shpchprm_nonacpi.c
  51. 72 33
      drivers/pci/msi.c
  52. 2 10
      drivers/pci/pci-driver.c
  53. 1 2
      drivers/pci/pci-sysfs.c
  54. 13 9
      drivers/pci/pci.c
  55. 2 0
      drivers/pci/pci.h
  56. 0 1
      drivers/pci/pcie/portdrv.h
  57. 1 2
      drivers/pci/pcie/portdrv_core.c
  58. 4 62
      drivers/pci/pcie/portdrv_pci.c
  59. 20 14
      drivers/pci/probe.c
  60. 0 126
      drivers/pci/proc.c
  61. 69 2
      drivers/pci/quirks.c
  62. 2 2
      drivers/pci/search.c
  63. 1 0
      include/acpi/acpi_bus.h
  64. 9 3
      include/linux/pci.h

+ 0 - 7
Documentation/feature-removal-schedule.txt

@@ -158,13 +158,6 @@ Who:    Adrian Bunk <bunk@stusta.de>
 
 
 ---------------------------
 ---------------------------
 
 
-What:	Legacy /proc/pci interface (PCI_LEGACY_PROC)
-When:	March 2006
-Why:	deprecated since 2.5.53 in favor of lspci(8)
-Who:	Adrian Bunk <bunk@stusta.de>
-
----------------------------
-
 What:	pci_module_init(driver)
 What:	pci_module_init(driver)
 When:	January 2007
 When:	January 2007
 Why:	Is replaced by pci_register_driver(pci_driver).
 Why:	Is replaced by pci_register_driver(pci_driver).

+ 4 - 0
Documentation/kernel-parameters.txt

@@ -49,6 +49,7 @@ restrictions referred to are that the relevant option is valid if:
 	MCA	MCA bus support is enabled.
 	MCA	MCA bus support is enabled.
 	MDA	MDA console support is enabled.
 	MDA	MDA console support is enabled.
 	MOUSE	Appropriate mouse support is enabled.
 	MOUSE	Appropriate mouse support is enabled.
+	MSI	Message Signaled Interrupts (PCI).
 	MTD	MTD support is enabled.
 	MTD	MTD support is enabled.
 	NET	Appropriate network support is enabled.
 	NET	Appropriate network support is enabled.
 	NUMA	NUMA support is enabled.
 	NUMA	NUMA support is enabled.
@@ -1152,6 +1153,9 @@ running once the system is up.
 				Mechanism 2.
 				Mechanism 2.
 		nommconf	[IA-32,X86_64] Disable use of MMCONFIG for PCI
 		nommconf	[IA-32,X86_64] Disable use of MMCONFIG for PCI
 				Configuration
 				Configuration
+		nomsi		[MSI] If the PCI_MSI kernel config parameter is
+				enabled, this kernel boot option can be used to
+				disable the use of MSI interrupts system-wide.
 		nosort		[IA-32] Don't sort PCI devices according to
 		nosort		[IA-32] Don't sort PCI devices according to
 				order given by the PCI BIOS. This sorting is
 				order given by the PCI BIOS. This sorting is
 				done to get a device order compatible with
 				done to get a device order compatible with

+ 1 - 1
arch/i386/kernel/efi.c

@@ -543,7 +543,7 @@ efi_initialize_iomem_resources(struct resource *code_resource,
 		if ((md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT)) >
 		if ((md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT)) >
 		    0x100000000ULL)
 		    0x100000000ULL)
 			continue;
 			continue;
-		res = alloc_bootmem_low(sizeof(struct resource));
+		res = kzalloc(sizeof(struct resource), GFP_ATOMIC);
 		switch (md->type) {
 		switch (md->type) {
 		case EFI_RESERVED_TYPE:
 		case EFI_RESERVED_TYPE:
 			res->name = "Reserved Memory";
 			res->name = "Reserved Memory";

+ 17 - 5
arch/i386/kernel/setup.c

@@ -1288,7 +1288,7 @@ legacy_init_iomem_resources(struct resource *code_resource, struct resource *dat
 		struct resource *res;
 		struct resource *res;
 		if (e820.map[i].addr + e820.map[i].size > 0x100000000ULL)
 		if (e820.map[i].addr + e820.map[i].size > 0x100000000ULL)
 			continue;
 			continue;
-		res = alloc_bootmem_low(sizeof(struct resource));
+		res = kzalloc(sizeof(struct resource), GFP_ATOMIC);
 		switch (e820.map[i].type) {
 		switch (e820.map[i].type) {
 		case E820_RAM:	res->name = "System RAM"; break;
 		case E820_RAM:	res->name = "System RAM"; break;
 		case E820_ACPI:	res->name = "ACPI Tables"; break;
 		case E820_ACPI:	res->name = "ACPI Tables"; break;
@@ -1316,13 +1316,15 @@ legacy_init_iomem_resources(struct resource *code_resource, struct resource *dat
 
 
 /*
 /*
  * Request address space for all standard resources
  * Request address space for all standard resources
+ *
+ * This is called just before pcibios_assign_resources(), which is also
+ * an fs_initcall, but is linked in later (in arch/i386/pci/i386.c).
  */
  */
-static void __init register_memory(void)
+static int __init request_standard_resources(void)
 {
 {
-	unsigned long gapstart, gapsize, round;
-	unsigned long long last;
-	int	      i;
+	int i;
 
 
+	printk("Setting up standard PCI resources\n");
 	if (efi_enabled)
 	if (efi_enabled)
 		efi_initialize_iomem_resources(&code_resource, &data_resource);
 		efi_initialize_iomem_resources(&code_resource, &data_resource);
 	else
 	else
@@ -1334,6 +1336,16 @@ static void __init register_memory(void)
 	/* request I/O space for devices used on all i[345]86 PCs */
 	/* request I/O space for devices used on all i[345]86 PCs */
 	for (i = 0; i < STANDARD_IO_RESOURCES; i++)
 	for (i = 0; i < STANDARD_IO_RESOURCES; i++)
 		request_resource(&ioport_resource, &standard_io_resources[i]);
 		request_resource(&ioport_resource, &standard_io_resources[i]);
+	return 0;
+}
+
+fs_initcall(request_standard_resources);
+
+static void __init register_memory(void)
+{
+	unsigned long gapstart, gapsize, round;
+	unsigned long long last;
+	int i;
 
 
 	/*
 	/*
 	 * Search for the bigest gap in the low 32 bits of the e820
 	 * Search for the bigest gap in the low 32 bits of the e820

+ 1 - 1
arch/i386/pci/Makefile

@@ -1,4 +1,4 @@
-obj-y				:= i386.o
+obj-y				:= i386.o init.o
 
 
 obj-$(CONFIG_PCI_BIOS)		+= pcbios.o
 obj-$(CONFIG_PCI_BIOS)		+= pcbios.o
 obj-$(CONFIG_PCI_MMCONFIG)	+= mmconfig.o direct.o
 obj-$(CONFIG_PCI_MMCONFIG)	+= mmconfig.o direct.o

+ 32 - 0
arch/i386/pci/common.c

@@ -8,6 +8,7 @@
 #include <linux/pci.h>
 #include <linux/pci.h>
 #include <linux/ioport.h>
 #include <linux/ioport.h>
 #include <linux/init.h>
 #include <linux/init.h>
+#include <linux/dmi.h>
 
 
 #include <asm/acpi.h>
 #include <asm/acpi.h>
 #include <asm/segment.h>
 #include <asm/segment.h>
@@ -120,11 +121,42 @@ void __devinit  pcibios_fixup_bus(struct pci_bus *b)
 	pci_read_bridge_bases(b);
 	pci_read_bridge_bases(b);
 }
 }
 
 
+/*
+ * Enable renumbering of PCI bus# ranges to reach all PCI busses (Cardbus)
+ */
+#ifdef __i386__
+static int __devinit assign_all_busses(struct dmi_system_id *d)
+{
+	pci_probe |= PCI_ASSIGN_ALL_BUSSES;
+	printk(KERN_INFO "%s detected: enabling PCI bus# renumbering"
+			" (pci=assign-busses)\n", d->ident);
+	return 0;
+}
+#endif
+
+/*
+ * Laptops which need pci=assign-busses to see Cardbus cards
+ */
+static struct dmi_system_id __devinitdata pciprobe_dmi_table[] = {
+#ifdef __i386__
+	{
+		.callback = assign_all_busses,
+		.ident = "Samsung X20 Laptop",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Samsung Electronics"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "SX20S"),
+		},
+	},
+#endif		/* __i386__ */
+	{}
+};
 
 
 struct pci_bus * __devinit pcibios_scan_root(int busnum)
 struct pci_bus * __devinit pcibios_scan_root(int busnum)
 {
 {
 	struct pci_bus *bus = NULL;
 	struct pci_bus *bus = NULL;
 
 
+	dmi_check_system(pciprobe_dmi_table);
+
 	while ((bus = pci_find_next_bus(bus)) != NULL) {
 	while ((bus = pci_find_next_bus(bus)) != NULL) {
 		if (bus->number == busnum) {
 		if (bus->number == busnum) {
 			/* Already scanned */
 			/* Already scanned */

+ 5 - 10
arch/i386/pci/direct.c

@@ -245,7 +245,7 @@ static int __init pci_check_type2(void)
 	return works;
 	return works;
 }
 }
 
 
-static int __init pci_direct_init(void)
+void __init pci_direct_init(void)
 {
 {
 	struct resource *region, *region2;
 	struct resource *region, *region2;
 
 
@@ -258,16 +258,16 @@ static int __init pci_direct_init(void)
 	if (pci_check_type1()) {
 	if (pci_check_type1()) {
 		printk(KERN_INFO "PCI: Using configuration type 1\n");
 		printk(KERN_INFO "PCI: Using configuration type 1\n");
 		raw_pci_ops = &pci_direct_conf1;
 		raw_pci_ops = &pci_direct_conf1;
-		return 0;
+		return;
 	}
 	}
 	release_resource(region);
 	release_resource(region);
 
 
  type2:
  type2:
 	if ((pci_probe & PCI_PROBE_CONF2) == 0)
 	if ((pci_probe & PCI_PROBE_CONF2) == 0)
-		goto out;
+		return;
 	region = request_region(0xCF8, 4, "PCI conf2");
 	region = request_region(0xCF8, 4, "PCI conf2");
 	if (!region)
 	if (!region)
-		goto out;
+		return;
 	region2 = request_region(0xC000, 0x1000, "PCI conf2");
 	region2 = request_region(0xC000, 0x1000, "PCI conf2");
 	if (!region2)
 	if (!region2)
 		goto fail2;
 		goto fail2;
@@ -275,15 +275,10 @@ static int __init pci_direct_init(void)
 	if (pci_check_type2()) {
 	if (pci_check_type2()) {
 		printk(KERN_INFO "PCI: Using configuration type 2\n");
 		printk(KERN_INFO "PCI: Using configuration type 2\n");
 		raw_pci_ops = &pci_direct_conf2;
 		raw_pci_ops = &pci_direct_conf2;
-		return 0;
+		return;
 	}
 	}
 
 
 	release_resource(region2);
 	release_resource(region2);
  fail2:
  fail2:
 	release_resource(region);
 	release_resource(region);
-
- out:
-	return 0;
 }
 }
-
-arch_initcall(pci_direct_init);

+ 25 - 0
arch/i386/pci/init.c

@@ -0,0 +1,25 @@
+#include <linux/config.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include "pci.h"
+
+/* arch_initcall has too random ordering, so call the initializers
+   in the right sequence from here. */
+static __init int pci_access_init(void)
+{
+#ifdef CONFIG_PCI_MMCONFIG
+	pci_mmcfg_init();
+#endif
+	if (raw_pci_ops)
+		return 0;
+#ifdef CONFIG_PCI_BIOS
+	pci_pcbios_init();
+#endif
+	if (raw_pci_ops)
+		return 0;
+#ifdef CONFIG_PCI_DIRECT
+	pci_direct_init();
+#endif
+	return 0;
+}
+arch_initcall(pci_access_init);

+ 3 - 8
arch/i386/pci/mmconfig.c

@@ -172,25 +172,20 @@ static __init void unreachable_devices(void)
 	}
 	}
 }
 }
 
 
-static int __init pci_mmcfg_init(void)
+void __init pci_mmcfg_init(void)
 {
 {
 	if ((pci_probe & PCI_PROBE_MMCONF) == 0)
 	if ((pci_probe & PCI_PROBE_MMCONF) == 0)
-		goto out;
+		return;
 
 
 	acpi_table_parse(ACPI_MCFG, acpi_parse_mcfg);
 	acpi_table_parse(ACPI_MCFG, acpi_parse_mcfg);
 	if ((pci_mmcfg_config_num == 0) ||
 	if ((pci_mmcfg_config_num == 0) ||
 	    (pci_mmcfg_config == NULL) ||
 	    (pci_mmcfg_config == NULL) ||
 	    (pci_mmcfg_config[0].base_address == 0))
 	    (pci_mmcfg_config[0].base_address == 0))
-		goto out;
+		return;
 
 
 	printk(KERN_INFO "PCI: Using MMCONFIG\n");
 	printk(KERN_INFO "PCI: Using MMCONFIG\n");
 	raw_pci_ops = &pci_mmcfg;
 	raw_pci_ops = &pci_mmcfg;
 	pci_probe = (pci_probe & ~PCI_PROBE_MASK) | PCI_PROBE_MMCONF;
 	pci_probe = (pci_probe & ~PCI_PROBE_MASK) | PCI_PROBE_MMCONF;
 
 
 	unreachable_devices();
 	unreachable_devices();
-
- out:
-	return 0;
 }
 }
-
-arch_initcall(pci_mmcfg_init);

+ 1 - 3
arch/i386/pci/pcbios.c

@@ -476,14 +476,12 @@ int pcibios_set_irq_routing(struct pci_dev *dev, int pin, int irq)
 }
 }
 EXPORT_SYMBOL(pcibios_set_irq_routing);
 EXPORT_SYMBOL(pcibios_set_irq_routing);
 
 
-static int __init pci_pcbios_init(void)
+void __init pci_pcbios_init(void)
 {
 {
 	if ((pci_probe & PCI_PROBE_BIOS) 
 	if ((pci_probe & PCI_PROBE_BIOS) 
 		&& ((raw_pci_ops = pci_find_bios()))) {
 		&& ((raw_pci_ops = pci_find_bios()))) {
 		pci_probe |= PCI_BIOS_SORT;
 		pci_probe |= PCI_BIOS_SORT;
 		pci_bios_present = 1;
 		pci_bios_present = 1;
 	}
 	}
-	return 0;
 }
 }
 
 
-arch_initcall(pci_pcbios_init);

+ 3 - 0
arch/i386/pci/pci.h

@@ -80,4 +80,7 @@ extern int pci_conf1_write(unsigned int seg, unsigned int bus,
 extern int pci_conf1_read(unsigned int seg, unsigned int bus,
 extern int pci_conf1_read(unsigned int seg, unsigned int bus,
 			  unsigned int devfn, int reg, int len, u32 *value);
 			  unsigned int devfn, int reg, int len, u32 *value);
 
 
+extern void pci_direct_init(void);
+extern void pci_pcbios_init(void);
+extern void pci_mmcfg_init(void);
 
 

+ 2 - 1
arch/x86_64/pci/Makefile

@@ -7,7 +7,7 @@ CFLAGS += -Iarch/i386/pci
 
 
 obj-y		:= i386.o
 obj-y		:= i386.o
 obj-$(CONFIG_PCI_DIRECT)+= direct.o
 obj-$(CONFIG_PCI_DIRECT)+= direct.o
-obj-y		+= fixup.o
+obj-y		+= fixup.o init.o
 obj-$(CONFIG_ACPI)	+= acpi.o
 obj-$(CONFIG_ACPI)	+= acpi.o
 obj-y			+= legacy.o irq.o common.o
 obj-y			+= legacy.o irq.o common.o
 # mmconfig has a 64bit special
 # mmconfig has a 64bit special
@@ -22,3 +22,4 @@ irq-y    += ../../i386/pci/irq.o
 common-y += ../../i386/pci/common.o
 common-y += ../../i386/pci/common.o
 fixup-y  += ../../i386/pci/fixup.o
 fixup-y  += ../../i386/pci/fixup.o
 i386-y  += ../../i386/pci/i386.o
 i386-y  += ../../i386/pci/i386.o
+init-y += ../../i386/pci/init.o

+ 12 - 0
drivers/acpi/Kconfig

@@ -205,6 +205,18 @@ config ACPI_IBM
 
 
 	  If you have an IBM ThinkPad laptop, say Y or M here.
 	  If you have an IBM ThinkPad laptop, say Y or M here.
 
 
+config ACPI_IBM_DOCK
+	bool "Legacy Docking Station Support"
+	depends on ACPI_IBM
+	default n
+	---help---
+	  Allows the ibm_acpi driver to handle docking station events.
+	  This support is obsoleted by CONFIG_HOTPLUG_PCI_ACPI.  It will
+	  allow locking and removing the laptop from the docking station,
+	  but will not properly connect PCI devices.
+
+	  If you are not sure, say N here.
+
 config ACPI_TOSHIBA
 config ACPI_TOSHIBA
 	tristate "Toshiba Laptop Extras"
 	tristate "Toshiba Laptop Extras"
 	depends on X86
 	depends on X86

+ 10 - 3
drivers/acpi/ibm_acpi.c

@@ -160,13 +160,13 @@ IBM_HANDLE(cmos, root, "\\UCMS",	/* R50, R50e, R50p, R51, T4x, X31, X40 */
 	   "\\CMOS",		/* A3x, G4x, R32, T23, T30, X22-24, X30 */
 	   "\\CMOS",		/* A3x, G4x, R32, T23, T30, X22-24, X30 */
 	   "\\CMS",		/* R40, R40e */
 	   "\\CMS",		/* R40, R40e */
     );				/* all others */
     );				/* all others */
-
+#ifdef CONFIG_ACPI_IBM_DOCK
 IBM_HANDLE(dock, root, "\\_SB.GDCK",	/* X30, X31, X40 */
 IBM_HANDLE(dock, root, "\\_SB.GDCK",	/* X30, X31, X40 */
 	   "\\_SB.PCI0.DOCK",	/* 600e/x,770e,770x,A2xm/p,T20-22,X20-21 */
 	   "\\_SB.PCI0.DOCK",	/* 600e/x,770e,770x,A2xm/p,T20-22,X20-21 */
 	   "\\_SB.PCI0.PCI1.DOCK",	/* all others */
 	   "\\_SB.PCI0.PCI1.DOCK",	/* all others */
 	   "\\_SB.PCI.ISA.SLCE",	/* 570 */
 	   "\\_SB.PCI.ISA.SLCE",	/* 570 */
     );				/* A21e,G4x,R30,R31,R32,R40,R40e,R50e */
     );				/* A21e,G4x,R30,R31,R32,R40,R40e,R50e */
-
+#endif
 IBM_HANDLE(bay, root, "\\_SB.PCI.IDE.SECN.MAST",	/* 570 */
 IBM_HANDLE(bay, root, "\\_SB.PCI.IDE.SECN.MAST",	/* 570 */
 	   "\\_SB.PCI0.IDE0.IDES.IDSM",	/* 600e/x, 770e, 770x */
 	   "\\_SB.PCI0.IDE0.IDES.IDSM",	/* 600e/x, 770e, 770x */
 	   "\\_SB.PCI0.IDE0.SCND.MSTR",	/* all others */
 	   "\\_SB.PCI0.IDE0.SCND.MSTR",	/* all others */
@@ -844,7 +844,7 @@ static int _sta(acpi_handle handle)
 
 
 	return status;
 	return status;
 }
 }
-
+#ifdef CONFIG_ACPI_IBM_DOCK
 #define dock_docked() (_sta(dock_handle) & 1)
 #define dock_docked() (_sta(dock_handle) & 1)
 
 
 static int dock_read(char *p)
 static int dock_read(char *p)
@@ -907,6 +907,7 @@ static void dock_notify(struct ibm_struct *ibm, u32 event)
 		acpi_bus_generate_event(ibm->device, event, 0);	/* unknown */
 		acpi_bus_generate_event(ibm->device, event, 0);	/* unknown */
 	}
 	}
 }
 }
+#endif
 
 
 static int bay_status_supported;
 static int bay_status_supported;
 static int bay_status2_supported;
 static int bay_status2_supported;
@@ -1574,6 +1575,7 @@ static struct ibm_struct ibms[] = {
 	 .read = light_read,
 	 .read = light_read,
 	 .write = light_write,
 	 .write = light_write,
 	 },
 	 },
+#ifdef CONFIG_ACPI_IBM_DOCK
 	{
 	{
 	 .name = "dock",
 	 .name = "dock",
 	 .read = dock_read,
 	 .read = dock_read,
@@ -1589,6 +1591,7 @@ static struct ibm_struct ibms[] = {
 	 .handle = &pci_handle,
 	 .handle = &pci_handle,
 	 .type = ACPI_SYSTEM_NOTIFY,
 	 .type = ACPI_SYSTEM_NOTIFY,
 	 },
 	 },
+#endif
 	{
 	{
 	 .name = "bay",
 	 .name = "bay",
 	 .init = bay_init,
 	 .init = bay_init,
@@ -1880,7 +1883,9 @@ IBM_PARAM(hotkey);
 IBM_PARAM(bluetooth);
 IBM_PARAM(bluetooth);
 IBM_PARAM(video);
 IBM_PARAM(video);
 IBM_PARAM(light);
 IBM_PARAM(light);
+#ifdef CONFIG_ACPI_IBM_DOCK
 IBM_PARAM(dock);
 IBM_PARAM(dock);
+#endif
 IBM_PARAM(bay);
 IBM_PARAM(bay);
 IBM_PARAM(cmos);
 IBM_PARAM(cmos);
 IBM_PARAM(led);
 IBM_PARAM(led);
@@ -1927,7 +1932,9 @@ static int __init acpi_ibm_init(void)
 	IBM_HANDLE_INIT(hkey);
 	IBM_HANDLE_INIT(hkey);
 	IBM_HANDLE_INIT(lght);
 	IBM_HANDLE_INIT(lght);
 	IBM_HANDLE_INIT(cmos);
 	IBM_HANDLE_INIT(cmos);
+#ifdef CONFIG_ACPI_IBM_DOCK
 	IBM_HANDLE_INIT(dock);
 	IBM_HANDLE_INIT(dock);
+#endif
 	IBM_HANDLE_INIT(pci);
 	IBM_HANDLE_INIT(pci);
 	IBM_HANDLE_INIT(bay);
 	IBM_HANDLE_INIT(bay);
 	if (bay_handle)
 	if (bay_handle)

+ 3 - 2
drivers/acpi/scan.c

@@ -23,7 +23,6 @@ static LIST_HEAD(acpi_device_list);
 DEFINE_SPINLOCK(acpi_device_lock);
 DEFINE_SPINLOCK(acpi_device_lock);
 LIST_HEAD(acpi_wakeup_device_list);
 LIST_HEAD(acpi_wakeup_device_list);
 
 
-static int acpi_bus_trim(struct acpi_device *start, int rmdevice);
 
 
 static void acpi_device_release(struct kobject *kobj)
 static void acpi_device_release(struct kobject *kobj)
 {
 {
@@ -1284,7 +1283,7 @@ int acpi_bus_start(struct acpi_device *device)
 
 
 EXPORT_SYMBOL(acpi_bus_start);
 EXPORT_SYMBOL(acpi_bus_start);
 
 
-static int acpi_bus_trim(struct acpi_device *start, int rmdevice)
+int acpi_bus_trim(struct acpi_device *start, int rmdevice)
 {
 {
 	acpi_status status;
 	acpi_status status;
 	struct acpi_device *parent, *child;
 	struct acpi_device *parent, *child;
@@ -1337,6 +1336,8 @@ static int acpi_bus_trim(struct acpi_device *start, int rmdevice)
 	}
 	}
 	return err;
 	return err;
 }
 }
+EXPORT_SYMBOL_GPL(acpi_bus_trim);
+
 
 
 static int acpi_bus_scan_fixed(struct acpi_device *root)
 static int acpi_bus_scan_fixed(struct acpi_device *root)
 {
 {

+ 4 - 17
drivers/pci/Kconfig

@@ -11,24 +11,11 @@ config PCI_MSI
 	   generate an interrupt using an inbound Memory Write on its
 	   generate an interrupt using an inbound Memory Write on its
 	   PCI bus instead of asserting a device IRQ pin.
 	   PCI bus instead of asserting a device IRQ pin.
 
 
-	   If you don't know what to do here, say N.
-
-config PCI_LEGACY_PROC
-	bool "Legacy /proc/pci interface"
-	depends on PCI
-	---help---
-	  This feature enables a procfs file -- /proc/pci -- that provides a 
-	  summary of PCI devices in the system. 
-
-	  This feature has been deprecated as of v2.5.53, in favor of using the 
-	  tool lspci(8). This feature may be removed at a future date. 
+	   Use of PCI MSI interrupts can be disabled at kernel boot time
+	   by using the 'pci=nomsi' option.  This disables MSI for the
+	   entire system.
 
 
-	  lspci can provide the same data, as well as much more. lspci is a part of
-	  the pci-utils package, which should be installed by your distribution. 
-	  See <file:Documentation/Changes> for information on where to get the latest
-	  version. 
-
-	  When in doubt, say N.
+	   If you don't know what to do here, say N.
 
 
 config PCI_DEBUG
 config PCI_DEBUG
 	bool "PCI Debugging"
 	bool "PCI Debugging"

+ 5 - 15
drivers/pci/hotplug/Makefile

@@ -22,6 +22,9 @@ ifdef CONFIG_HOTPLUG_PCI_CPCI
 pci_hotplug-objs	+=	cpci_hotplug_core.o	\
 pci_hotplug-objs	+=	cpci_hotplug_core.o	\
 				cpci_hotplug_pci.o
 				cpci_hotplug_pci.o
 endif
 endif
+ifdef CONFIG_ACPI
+pci_hotplug-objs 	+= 	acpi_pcihp.o
+endif
 
 
 cpqphp-objs		:=	cpqphp_core.o	\
 cpqphp-objs		:=	cpqphp_core.o	\
 				cpqphp_ctrl.o	\
 				cpqphp_ctrl.o	\
@@ -37,7 +40,8 @@ ibmphp-objs		:=	ibmphp_core.o	\
 				ibmphp_hpc.o
 				ibmphp_hpc.o
 
 
 acpiphp-objs		:=	acpiphp_core.o	\
 acpiphp-objs		:=	acpiphp_core.o	\
-				acpiphp_glue.o
+				acpiphp_glue.o  \
+				acpiphp_dock.o
 
 
 rpaphp-objs		:=	rpaphp_core.o	\
 rpaphp-objs		:=	rpaphp_core.o	\
 				rpaphp_pci.o	\
 				rpaphp_pci.o	\
@@ -50,23 +54,9 @@ pciehp-objs		:=	pciehp_core.o	\
 				pciehp_ctrl.o	\
 				pciehp_ctrl.o	\
 				pciehp_pci.o	\
 				pciehp_pci.o	\
 				pciehp_hpc.o
 				pciehp_hpc.o
-ifdef CONFIG_ACPI
-	pciehp-objs += pciehprm_acpi.o
-else
-	pciehp-objs += pciehprm_nonacpi.o
-endif
 
 
 shpchp-objs		:=	shpchp_core.o	\
 shpchp-objs		:=	shpchp_core.o	\
 				shpchp_ctrl.o	\
 				shpchp_ctrl.o	\
 				shpchp_pci.o	\
 				shpchp_pci.o	\
 				shpchp_sysfs.o	\
 				shpchp_sysfs.o	\
 				shpchp_hpc.o
 				shpchp_hpc.o
-ifdef CONFIG_ACPI
-	shpchp-objs += shpchprm_acpi.o
-else
-	ifdef CONFIG_HOTPLUG_PCI_SHPC_PHPRM_LEGACY
-		shpchp-objs += shpchprm_legacy.o
-	else
-		shpchp-objs += shpchprm_nonacpi.o
-	endif
-endif

+ 85 - 60
drivers/pci/hotplug/shpchprm_acpi.c → drivers/pci/hotplug/acpi_pcihp.c

@@ -1,7 +1,7 @@
 /*
 /*
- * SHPCHPRM ACPI: PHP Resource Manager for ACPI platform
+ * Common ACPI functions for hot plug platforms
  *
  *
- * Copyright (C) 2003-2004 Intel Corporation
+ * Copyright (C) 2006 Intel Corporation
  *
  *
  * All rights reserved.
  * All rights reserved.
  *
  *
@@ -31,26 +31,12 @@
 #include <acpi/acpi.h>
 #include <acpi/acpi.h>
 #include <acpi/acpi_bus.h>
 #include <acpi/acpi_bus.h>
 #include <acpi/actypes.h>
 #include <acpi/actypes.h>
-#include "shpchp.h"
+#include "pci_hotplug.h"
 
 
 #define	METHOD_NAME__SUN	"_SUN"
 #define	METHOD_NAME__SUN	"_SUN"
 #define	METHOD_NAME__HPP	"_HPP"
 #define	METHOD_NAME__HPP	"_HPP"
 #define	METHOD_NAME_OSHP	"OSHP"
 #define	METHOD_NAME_OSHP	"OSHP"
 
 
-static u8 * acpi_path_name( acpi_handle	handle)
-{
-	acpi_status		status;
-	static u8	path_name[ACPI_PATHNAME_MAX];
-	struct acpi_buffer		ret_buf = { ACPI_PATHNAME_MAX, path_name };
-
-	memset(path_name, 0, sizeof (path_name));
-	status = acpi_get_name(handle, ACPI_FULL_PATHNAME, &ret_buf);
-
-	if (ACPI_FAILURE(status))
-		return NULL;
-	else
-		return path_name;	
-}
 
 
 static acpi_status
 static acpi_status
 acpi_run_hpp(acpi_handle handle, struct hotplug_params *hpp)
 acpi_run_hpp(acpi_handle handle, struct hotplug_params *hpp)
@@ -58,18 +44,21 @@ acpi_run_hpp(acpi_handle handle, struct hotplug_params *hpp)
 	acpi_status		status;
 	acpi_status		status;
 	u8			nui[4];
 	u8			nui[4];
 	struct acpi_buffer	ret_buf = { 0, NULL};
 	struct acpi_buffer	ret_buf = { 0, NULL};
+	struct acpi_buffer	string = { ACPI_ALLOCATE_BUFFER, NULL };
 	union acpi_object	*ext_obj, *package;
 	union acpi_object	*ext_obj, *package;
-	u8			*path_name = acpi_path_name(handle);
 	int			i, len = 0;
 	int			i, len = 0;
 
 
+	acpi_get_name(handle, ACPI_FULL_PATHNAME, &string);
+
 	/* get _hpp */
 	/* get _hpp */
 	status = acpi_evaluate_object(handle, METHOD_NAME__HPP, NULL, &ret_buf);
 	status = acpi_evaluate_object(handle, METHOD_NAME__HPP, NULL, &ret_buf);
 	switch (status) {
 	switch (status) {
 	case AE_BUFFER_OVERFLOW:
 	case AE_BUFFER_OVERFLOW:
 		ret_buf.pointer = kmalloc (ret_buf.length, GFP_KERNEL);
 		ret_buf.pointer = kmalloc (ret_buf.length, GFP_KERNEL);
 		if (!ret_buf.pointer) {
 		if (!ret_buf.pointer) {
-			err ("%s:%s alloc for _HPP fail\n", __FUNCTION__,
-					path_name);
+			printk(KERN_ERR "%s:%s alloc for _HPP fail\n",
+				__FUNCTION__, (char *)string.pointer);
+			acpi_os_free(string.pointer);
 			return AE_NO_MEMORY;
 			return AE_NO_MEMORY;
 		}
 		}
 		status = acpi_evaluate_object(handle, METHOD_NAME__HPP,
 		status = acpi_evaluate_object(handle, METHOD_NAME__HPP,
@@ -78,16 +67,17 @@ acpi_run_hpp(acpi_handle handle, struct hotplug_params *hpp)
 			break;
 			break;
 	default:
 	default:
 		if (ACPI_FAILURE(status)) {
 		if (ACPI_FAILURE(status)) {
-			dbg("%s:%s _HPP fail=0x%x\n", __FUNCTION__,
-					path_name, status);
+			pr_debug("%s:%s _HPP fail=0x%x\n", __FUNCTION__,
+				(char *)string.pointer, status);
+			acpi_os_free(string.pointer);
 			return status;
 			return status;
 		}
 		}
 	}
 	}
 
 
 	ext_obj = (union acpi_object *) ret_buf.pointer;
 	ext_obj = (union acpi_object *) ret_buf.pointer;
 	if (ext_obj->type != ACPI_TYPE_PACKAGE) {
 	if (ext_obj->type != ACPI_TYPE_PACKAGE) {
-		err ("%s:%s _HPP obj not a package\n", __FUNCTION__,
-				path_name);
+		printk(KERN_ERR "%s:%s _HPP obj not a package\n", __FUNCTION__,
+				(char *)string.pointer);
 		status = AE_ERROR;
 		status = AE_ERROR;
 		goto free_and_return;
 		goto free_and_return;
 	}
 	}
@@ -101,8 +91,8 @@ acpi_run_hpp(acpi_handle handle, struct hotplug_params *hpp)
 			nui[i] = (u8)ext_obj->integer.value;
 			nui[i] = (u8)ext_obj->integer.value;
 			break;
 			break;
 		default:
 		default:
-			err ("%s:%s _HPP obj type incorrect\n", __FUNCTION__,
-					path_name);
+			printk(KERN_ERR "%s:%s _HPP obj type incorrect\n",
+				__FUNCTION__, (char *)string.pointer);
 			status = AE_ERROR;
 			status = AE_ERROR;
 			goto free_and_return;
 			goto free_and_return;
 		}
 		}
@@ -113,54 +103,52 @@ acpi_run_hpp(acpi_handle handle, struct hotplug_params *hpp)
 	hpp->enable_serr = nui[2];
 	hpp->enable_serr = nui[2];
 	hpp->enable_perr = nui[3];
 	hpp->enable_perr = nui[3];
 
 
-	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);
+	pr_debug("  _HPP: cache_line_size=0x%x\n", hpp->cache_line_size);
+	pr_debug("  _HPP: latency timer  =0x%x\n", hpp->latency_timer);
+	pr_debug("  _HPP: enable SERR    =0x%x\n", hpp->enable_serr);
+	pr_debug("  _HPP: enable PERR    =0x%x\n", hpp->enable_perr);
 
 
 free_and_return:
 free_and_return:
-	kfree(ret_buf.pointer);
+	acpi_os_free(string.pointer);
+	acpi_os_free(ret_buf.pointer);
 	return status;
 	return status;
 }
 }
 
 
-static void acpi_run_oshp(acpi_handle handle)
+
+
+/* acpi_run_oshp - get control of hotplug from the firmware
+ *
+ * @handle - the handle of the hotplug controller.
+ */
+acpi_status acpi_run_oshp(acpi_handle handle)
 {
 {
 	acpi_status		status;
 	acpi_status		status;
-	u8			*path_name = acpi_path_name(handle);
+	struct acpi_buffer	string = { ACPI_ALLOCATE_BUFFER, NULL };
+
+	acpi_get_name(handle, ACPI_FULL_PATHNAME, &string);
 
 
 	/* run OSHP */
 	/* run OSHP */
 	status = acpi_evaluate_object(handle, METHOD_NAME_OSHP, NULL, NULL);
 	status = acpi_evaluate_object(handle, METHOD_NAME_OSHP, NULL, NULL);
-	if (ACPI_FAILURE(status)) {
-		err("%s:%s OSHP fails=0x%x\n", __FUNCTION__, path_name,
-				status);
-	} else {
-		dbg("%s:%s OSHP passes\n", __FUNCTION__, path_name);
-	}
-}
-
-int shpchprm_get_physical_slot_number(struct controller *ctrl, u32 *sun, u8 busnum, u8 devnum)
-{
-	int offset = devnum - ctrl->slot_device_offset;
+	if (ACPI_FAILURE(status))
+		printk(KERN_ERR "%s:%s OSHP fails=0x%x\n", __FUNCTION__,
+			(char *)string.pointer, status);
+	else
+		pr_debug("%s:%s OSHP passes\n", __FUNCTION__,
+			(char *)string.pointer);
 
 
-	dbg("%s: ctrl->slot_num_inc %d, offset %d\n", __FUNCTION__, ctrl->slot_num_inc, offset);
-	*sun = (u8) (ctrl->first_slot + ctrl->slot_num_inc *offset);
-	return 0;
+	acpi_os_free(string.pointer);
+	return status;
 }
 }
+EXPORT_SYMBOL_GPL(acpi_run_oshp);
+
 
 
-void get_hp_hw_control_from_firmware(struct pci_dev *dev)
-{
-	/*
-	 * 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 get_hp_params_from_firmware(struct pci_dev *dev,
+/* acpi_get_hp_params_from_firmware
+ *
+ * @dev - the pci_dev of the newly added device
+ * @hpp - allocated by the caller
+ */
+acpi_status acpi_get_hp_params_from_firmware(struct pci_dev *dev,
 		struct hotplug_params *hpp)
 		struct hotplug_params *hpp)
 {
 {
 	acpi_status status = AE_NOT_FOUND;
 	acpi_status status = AE_NOT_FOUND;
@@ -182,5 +170,42 @@ void get_hp_params_from_firmware(struct pci_dev *dev,
 		/* Check if a parent object supports _HPP */
 		/* Check if a parent object supports _HPP */
 		pdev = pdev->bus->parent->self;
 		pdev = pdev->bus->parent->self;
 	}
 	}
+	return status;
 }
 }
+EXPORT_SYMBOL_GPL(acpi_get_hp_params_from_firmware);
 
 
+
+/* acpi_root_bridge - check to see if this acpi object is a root bridge
+ *
+ * @handle - the acpi object in question.
+ */
+int acpi_root_bridge(acpi_handle handle)
+{
+	acpi_status status;
+	struct acpi_device_info *info;
+	struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
+	int i;
+
+	status = acpi_get_object_info(handle, &buffer);
+	if (ACPI_SUCCESS(status)) {
+		info = buffer.pointer;
+		if ((info->valid & ACPI_VALID_HID) &&
+			!strcmp(PCI_ROOT_HID_STRING,
+					info->hardware_id.value)) {
+			acpi_os_free(buffer.pointer);
+			return 1;
+		}
+		if (info->valid & ACPI_VALID_CID) {
+			for (i=0; i < info->compatibility_id.count; i++) {
+				if (!strcmp(PCI_ROOT_HID_STRING,
+					info->compatibility_id.id[i].value)) {
+					acpi_os_free(buffer.pointer);
+					return 1;
+				}
+			}
+		}
+		acpi_os_free(buffer.pointer);
+	}
+	return 0;
+}
+EXPORT_SYMBOL_GPL(acpi_root_bridge);

+ 42 - 20
drivers/pci/hotplug/acpiphp.h

@@ -37,6 +37,7 @@
 
 
 #include <linux/acpi.h>
 #include <linux/acpi.h>
 #include <linux/kobject.h>	/* for KOBJ_NAME_LEN */
 #include <linux/kobject.h>	/* for KOBJ_NAME_LEN */
+#include <linux/mutex.h>
 #include "pci_hotplug.h"
 #include "pci_hotplug.h"
 
 
 #define dbg(format, arg...)					\
 #define dbg(format, arg...)					\
@@ -59,26 +60,10 @@ struct acpiphp_slot;
  * struct slot - slot information for each *physical* slot
  * struct slot - slot information for each *physical* slot
  */
  */
 struct slot {
 struct slot {
-	u8 number;
 	struct hotplug_slot	*hotplug_slot;
 	struct hotplug_slot	*hotplug_slot;
-	struct list_head	slot_list;
-
 	struct acpiphp_slot	*acpi_slot;
 	struct acpiphp_slot	*acpi_slot;
 };
 };
 
 
-/**
- * struct hpp_param - ACPI 2.0 _HPP Hot Plug Parameters
- * @cache_line_size in DWORD
- * @latency_timer in PCI clock
- * @enable_SERR 0 or 1
- * @enable_PERR 0 or 1
- */
-struct hpp_param {
-	u8 cache_line_size;
-	u8 latency_timer;
-	u8 enable_SERR;
-	u8 enable_PERR;
-};
 
 
 
 
 /**
 /**
@@ -102,7 +87,7 @@ struct acpiphp_bridge {
 	struct pci_dev *pci_dev;
 	struct pci_dev *pci_dev;
 
 
 	/* ACPI 2.0 _HPP parameters */
 	/* ACPI 2.0 _HPP parameters */
-	struct hpp_param hpp;
+	struct hotplug_params hpp;
 
 
 	spinlock_t res_lock;
 	spinlock_t res_lock;
 };
 };
@@ -118,9 +103,9 @@ struct acpiphp_slot {
 	struct acpiphp_bridge *bridge;	/* parent */
 	struct acpiphp_bridge *bridge;	/* parent */
 	struct list_head funcs;		/* one slot may have different
 	struct list_head funcs;		/* one slot may have different
 					   objects (i.e. for each function) */
 					   objects (i.e. for each function) */
-	struct semaphore crit_sect;
+	struct slot *slot;
+	struct mutex crit_sect;
 
 
-	u32		id;		/* slot id (serial #) for hotplug core */
 	u8		device;		/* pci device# */
 	u8		device;		/* pci device# */
 
 
 	u32		sun;		/* ACPI _SUN (slot unique number) */
 	u32		sun;		/* ACPI _SUN (slot unique number) */
@@ -160,6 +145,25 @@ struct acpiphp_attention_info
 	struct module *owner;
 	struct module *owner;
 };
 };
 
 
+
+struct dependent_device {
+	struct list_head device_list;
+	struct list_head pci_list;
+	acpi_handle handle;
+	struct acpiphp_func *func;
+};
+
+
+struct acpiphp_dock_station {
+	acpi_handle handle;
+	u32 last_dock_time;
+	u32 flags;
+	struct acpiphp_func *dock_bridge;
+	struct list_head dependent_devices;
+	struct list_head pci_dependent_devices;
+};
+
+
 /* PCI bus bridge HID */
 /* PCI bus bridge HID */
 #define ACPI_PCI_HOST_HID		"PNP0A03"
 #define ACPI_PCI_HOST_HID		"PNP0A03"
 
 
@@ -197,19 +201,27 @@ struct acpiphp_attention_info
 #define FUNC_HAS_PS1		(0x00000020)
 #define FUNC_HAS_PS1		(0x00000020)
 #define FUNC_HAS_PS2		(0x00000040)
 #define FUNC_HAS_PS2		(0x00000040)
 #define FUNC_HAS_PS3		(0x00000080)
 #define FUNC_HAS_PS3		(0x00000080)
+#define FUNC_HAS_DCK            (0x00000100)
+#define FUNC_IS_DD              (0x00000200)
+
+/* dock station flags */
+#define DOCK_DOCKING            (0x00000001)
+#define DOCK_HAS_BRIDGE         (0x00000002)
 
 
 /* function prototypes */
 /* function prototypes */
 
 
 /* acpiphp_core.c */
 /* acpiphp_core.c */
 extern int acpiphp_register_attention(struct acpiphp_attention_info*info);
 extern int acpiphp_register_attention(struct acpiphp_attention_info*info);
 extern int acpiphp_unregister_attention(struct acpiphp_attention_info *info);
 extern int acpiphp_unregister_attention(struct acpiphp_attention_info *info);
+extern int acpiphp_register_hotplug_slot(struct acpiphp_slot *slot);
+extern void acpiphp_unregister_hotplug_slot(struct acpiphp_slot *slot);
 
 
 /* acpiphp_glue.c */
 /* acpiphp_glue.c */
 extern int acpiphp_glue_init (void);
 extern int acpiphp_glue_init (void);
 extern void acpiphp_glue_exit (void);
 extern void acpiphp_glue_exit (void);
 extern int acpiphp_get_num_slots (void);
 extern int acpiphp_get_num_slots (void);
-extern struct acpiphp_slot *get_slot_from_id (int id);
 typedef int (*acpiphp_callback)(struct acpiphp_slot *slot, void *data);
 typedef int (*acpiphp_callback)(struct acpiphp_slot *slot, void *data);
+void handle_hotplug_event_func(acpi_handle, u32, void*);
 
 
 extern int acpiphp_enable_slot (struct acpiphp_slot *slot);
 extern int acpiphp_enable_slot (struct acpiphp_slot *slot);
 extern int acpiphp_disable_slot (struct acpiphp_slot *slot);
 extern int acpiphp_disable_slot (struct acpiphp_slot *slot);
@@ -219,6 +231,16 @@ extern u8 acpiphp_get_latch_status (struct acpiphp_slot *slot);
 extern u8 acpiphp_get_adapter_status (struct acpiphp_slot *slot);
 extern u8 acpiphp_get_adapter_status (struct acpiphp_slot *slot);
 extern u32 acpiphp_get_address (struct acpiphp_slot *slot);
 extern u32 acpiphp_get_address (struct acpiphp_slot *slot);
 
 
+/* acpiphp_dock.c */
+extern int find_dock_station(void);
+extern void remove_dock_station(void);
+extern void add_dependent_device(struct dependent_device *new_dd);
+extern void add_pci_dependent_device(struct dependent_device *new_dd);
+extern struct dependent_device *get_dependent_device(acpi_handle handle);
+extern int is_dependent_device(acpi_handle handle);
+extern int detect_dependent_devices(acpi_handle *bridge_handle);
+extern struct dependent_device *alloc_dependent_device(acpi_handle handle);
+
 /* variables */
 /* variables */
 extern int acpiphp_debug;
 extern int acpiphp_debug;
 
 

+ 66 - 68
drivers/pci/hotplug/acpiphp_core.c

@@ -44,8 +44,6 @@
 #include "pci_hotplug.h"
 #include "pci_hotplug.h"
 #include "acpiphp.h"
 #include "acpiphp.h"
 
 
-static LIST_HEAD(slot_list);
-
 #define MY_NAME	"acpiphp"
 #define MY_NAME	"acpiphp"
 
 
 static int debug;
 static int debug;
@@ -341,62 +339,53 @@ static void release_slot(struct hotplug_slot *hotplug_slot)
 	kfree(slot);
 	kfree(slot);
 }
 }
 
 
-/**
- * init_slots - initialize 'struct slot' structures for each slot
- *
- */
-static int __init init_slots(void)
+/* callback routine to initialize 'struct slot' for each slot */
+int acpiphp_register_hotplug_slot(struct acpiphp_slot *acpiphp_slot)
 {
 {
 	struct slot *slot;
 	struct slot *slot;
+	struct hotplug_slot *hotplug_slot;
+	struct hotplug_slot_info *hotplug_slot_info;
 	int retval = -ENOMEM;
 	int retval = -ENOMEM;
-	int i;
-
-	for (i = 0; i < num_slots; ++i) {
-		slot = kmalloc(sizeof(struct slot), GFP_KERNEL);
-		if (!slot)
-			goto error;
-		memset(slot, 0, sizeof(struct slot));
-
-		slot->hotplug_slot = kmalloc(sizeof(struct hotplug_slot), GFP_KERNEL);
-		if (!slot->hotplug_slot)
-			goto error_slot;
-		memset(slot->hotplug_slot, 0, sizeof(struct hotplug_slot));
-
-		slot->hotplug_slot->info = kmalloc(sizeof(struct hotplug_slot_info), GFP_KERNEL);
-		if (!slot->hotplug_slot->info)
-			goto error_hpslot;
-		memset(slot->hotplug_slot->info, 0, sizeof(struct hotplug_slot_info));
-
-		slot->hotplug_slot->name = kmalloc(SLOT_NAME_SIZE, GFP_KERNEL);
-		if (!slot->hotplug_slot->name)
-			goto error_info;
-
-		slot->number = i;
-
-		slot->hotplug_slot->private = slot;
-		slot->hotplug_slot->release = &release_slot;
-		slot->hotplug_slot->ops = &acpi_hotplug_slot_ops;
-
-		slot->acpi_slot = get_slot_from_id(i);
-		slot->hotplug_slot->info->power_status = acpiphp_get_power_status(slot->acpi_slot);
-		slot->hotplug_slot->info->attention_status = 0;
-		slot->hotplug_slot->info->latch_status = acpiphp_get_latch_status(slot->acpi_slot);
-		slot->hotplug_slot->info->adapter_status = acpiphp_get_adapter_status(slot->acpi_slot);
-		slot->hotplug_slot->info->max_bus_speed = PCI_SPEED_UNKNOWN;
-		slot->hotplug_slot->info->cur_bus_speed = PCI_SPEED_UNKNOWN;
-
-		make_slot_name(slot);
-
-		retval = pci_hp_register(slot->hotplug_slot);
-		if (retval) {
-			err("pci_hp_register failed with error %d\n", retval);
-			goto error_name;
-		}
-
-		/* add slot to our internal list */
-		list_add(&slot->slot_list, &slot_list);
-		info("Slot [%s] registered\n", slot->hotplug_slot->name);
-	}
+
+	slot = kzalloc(sizeof(*slot), GFP_KERNEL);
+	if (!slot)
+		goto error;
+
+	slot->hotplug_slot = kzalloc(sizeof(*hotplug_slot), GFP_KERNEL);
+	if (!slot->hotplug_slot)
+		goto error_slot;
+
+	slot->hotplug_slot->info = kzalloc(sizeof(*hotplug_slot_info),
+					   GFP_KERNEL);
+	if (!slot->hotplug_slot->info)
+		goto error_hpslot;
+
+	slot->hotplug_slot->name = kzalloc(SLOT_NAME_SIZE, GFP_KERNEL);
+	if (!slot->hotplug_slot->name)
+		goto error_info;
+
+	slot->hotplug_slot->private = slot;
+	slot->hotplug_slot->release = &release_slot;
+	slot->hotplug_slot->ops = &acpi_hotplug_slot_ops;
+
+	slot->acpi_slot = acpiphp_slot;
+	slot->hotplug_slot->info->power_status = acpiphp_get_power_status(slot->acpi_slot);
+	slot->hotplug_slot->info->attention_status = 0;
+	slot->hotplug_slot->info->latch_status = acpiphp_get_latch_status(slot->acpi_slot);
+	slot->hotplug_slot->info->adapter_status = acpiphp_get_adapter_status(slot->acpi_slot);
+	slot->hotplug_slot->info->max_bus_speed = PCI_SPEED_UNKNOWN;
+	slot->hotplug_slot->info->cur_bus_speed = PCI_SPEED_UNKNOWN;
+
+	acpiphp_slot->slot = slot;
+	make_slot_name(slot);
+
+	retval = pci_hp_register(slot->hotplug_slot);
+	if (retval) {
+		err("pci_hp_register failed with error %d\n", retval);
+		goto error_name;
+ 	}
+
+	info("Slot [%s] registered\n", slot->hotplug_slot->name);
 
 
 	return 0;
 	return 0;
 error_name:
 error_name:
@@ -412,42 +401,51 @@ error:
 }
 }
 
 
 
 
-static void __exit cleanup_slots (void)
+void acpiphp_unregister_hotplug_slot(struct acpiphp_slot *acpiphp_slot)
 {
 {
-	struct list_head *tmp, *n;
-	struct slot *slot;
+	struct slot *slot = acpiphp_slot->slot;
+	int retval = 0;
 
 
-	list_for_each_safe (tmp, n, &slot_list) {
-		/* memory will be freed in release_slot callback */
-		slot = list_entry(tmp, struct slot, slot_list);
-		list_del(&slot->slot_list);
-		pci_hp_deregister(slot->hotplug_slot);
-	}
+	info ("Slot [%s] unregistered\n", slot->hotplug_slot->name);
+
+	retval = pci_hp_deregister(slot->hotplug_slot);
+	if (retval)
+		err("pci_hp_deregister failed with error %d\n", retval);
 }
 }
 
 
 
 
 static int __init acpiphp_init(void)
 static int __init acpiphp_init(void)
 {
 {
 	int retval;
 	int retval;
+	int docking_station;
 
 
 	info(DRIVER_DESC " version: " DRIVER_VERSION "\n");
 	info(DRIVER_DESC " version: " DRIVER_VERSION "\n");
 
 
 	acpiphp_debug = debug;
 	acpiphp_debug = debug;
 
 
+	docking_station = find_dock_station();
+
 	/* read all the ACPI info from the system */
 	/* read all the ACPI info from the system */
 	retval = init_acpi();
 	retval = init_acpi();
-	if (retval)
-		return retval;
 
 
-	return init_slots();
+	/* if we have found a docking station, we should
+	 * go ahead and load even if init_acpi has found
+	 * no slots.  This handles the case when the _DCK
+	 * method not defined under the actual dock bridge
+	 */
+	if (docking_station)
+		return 0;
+	else
+		return retval;
 }
 }
 
 
 
 
 static void __exit acpiphp_exit(void)
 static void __exit acpiphp_exit(void)
 {
 {
-	cleanup_slots();
 	/* deallocate internal data structures etc. */
 	/* deallocate internal data structures etc. */
 	acpiphp_glue_exit();
 	acpiphp_glue_exit();
+
+	remove_dock_station();
 }
 }
 
 
 module_init(acpiphp_init);
 module_init(acpiphp_init);

+ 438 - 0
drivers/pci/hotplug/acpiphp_dock.c

@@ -0,0 +1,438 @@
+/*
+ * ACPI PCI HotPlug dock functions to ACPI CA subsystem
+ *
+ * Copyright (C) 2006 Kristen Carlson Accardi (kristen.c.accardi@intel.com)
+ * Copyright (C) 2006 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 <kristen.c.accardi@intel.com>
+ *
+ */
+#include <linux/init.h>
+#include <linux/module.h>
+
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/smp_lock.h>
+#include <linux/mutex.h>
+
+#include "../pci.h"
+#include "pci_hotplug.h"
+#include "acpiphp.h"
+
+static struct acpiphp_dock_station *ds;
+#define MY_NAME "acpiphp_dock"
+
+
+int is_dependent_device(acpi_handle handle)
+{
+	return (get_dependent_device(handle) ? 1 : 0);
+}
+
+
+static acpi_status
+find_dependent_device(acpi_handle handle, u32 lvl, void *context, void **rv)
+{
+	int *count = (int *)context;
+
+	if (is_dependent_device(handle)) {
+		(*count)++;
+		return AE_CTRL_TERMINATE;
+	} else {
+		return AE_OK;
+	}
+}
+
+
+
+
+void add_dependent_device(struct dependent_device *new_dd)
+{
+	list_add_tail(&new_dd->device_list, &ds->dependent_devices);
+}
+
+
+void add_pci_dependent_device(struct dependent_device *new_dd)
+{
+	list_add_tail(&new_dd->pci_list, &ds->pci_dependent_devices);
+}
+
+
+
+struct dependent_device * get_dependent_device(acpi_handle handle)
+{
+	struct dependent_device *dd;
+
+	if (!ds)
+		return NULL;
+
+	list_for_each_entry(dd, &ds->dependent_devices, device_list) {
+		if (handle == dd->handle)
+			return dd;
+	}
+	return NULL;
+}
+
+
+
+struct dependent_device *alloc_dependent_device(acpi_handle handle)
+{
+	struct dependent_device *dd;
+
+	dd = kzalloc(sizeof(*dd), GFP_KERNEL);
+	if (dd) {
+		INIT_LIST_HEAD(&dd->pci_list);
+		INIT_LIST_HEAD(&dd->device_list);
+		dd->handle = handle;
+	}
+	return dd;
+}
+
+
+
+static int is_dock(acpi_handle handle)
+{
+	acpi_status status;
+	acpi_handle tmp;
+
+	status = acpi_get_handle(handle, "_DCK", &tmp);
+	if (ACPI_FAILURE(status)) {
+		return 0;
+	}
+	return 1;
+}
+
+
+
+static int dock_present(void)
+{
+	unsigned long sta;
+	acpi_status status;
+
+	if (ds) {
+		status = acpi_evaluate_integer(ds->handle, "_STA", NULL, &sta);
+		if (ACPI_SUCCESS(status) && sta)
+			return 1;
+	}
+	return 0;
+}
+
+
+
+static void eject_dock(void)
+{
+	struct acpi_object_list arg_list;
+	union acpi_object arg;
+
+	arg_list.count = 1;
+	arg_list.pointer = &arg;
+	arg.type = ACPI_TYPE_INTEGER;
+	arg.integer.value = 1;
+
+	if (ACPI_FAILURE(acpi_evaluate_object(ds->handle, "_EJ0",
+					&arg_list, NULL)) || dock_present())
+		warn("%s: failed to eject dock!\n", __FUNCTION__);
+
+	return;
+}
+
+
+
+
+static acpi_status handle_dock(int dock)
+{
+	acpi_status status;
+	struct acpi_object_list arg_list;
+	union acpi_object arg;
+	struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
+
+	dbg("%s: %s\n", __FUNCTION__, dock ? "docking" : "undocking");
+
+	/* _DCK method has one argument */
+	arg_list.count = 1;
+	arg_list.pointer = &arg;
+	arg.type = ACPI_TYPE_INTEGER;
+	arg.integer.value = dock;
+	status = acpi_evaluate_object(ds->handle, "_DCK",
+					&arg_list, &buffer);
+	if (ACPI_FAILURE(status))
+		err("%s: failed to execute _DCK\n", __FUNCTION__);
+	acpi_os_free(buffer.pointer);
+
+	return status;
+}
+
+
+
+static inline void dock(void)
+{
+	handle_dock(1);
+}
+
+
+
+static inline void undock(void)
+{
+	handle_dock(0);
+}
+
+
+
+/*
+ * the _DCK method can do funny things... and sometimes not
+ * hah-hah funny.
+ *
+ * TBD - figure out a way to only call fixups for
+ * systems that require them.
+ */
+static void post_dock_fixups(void)
+{
+	struct pci_bus *bus;
+	u32 buses;
+	struct dependent_device *dd;
+
+	list_for_each_entry(dd, &ds->pci_dependent_devices, pci_list) {
+		bus = dd->func->slot->bridge->pci_bus;
+
+		/* fixup bad _DCK function that rewrites
+	 	 * secondary bridge on slot
+	 	 */
+		pci_read_config_dword(bus->self,
+				PCI_PRIMARY_BUS,
+				&buses);
+
+		if (((buses >> 8) & 0xff) != bus->secondary) {
+			buses = (buses & 0xff000000)
+	     			| ((unsigned int)(bus->primary)     <<  0)
+	     			| ((unsigned int)(bus->secondary)   <<  8)
+	     			| ((unsigned int)(bus->subordinate) << 16);
+			pci_write_config_dword(bus->self,
+					PCI_PRIMARY_BUS,
+					buses);
+		}
+	}
+}
+
+
+
+static void hotplug_pci(u32 type)
+{
+	struct dependent_device *dd;
+
+	list_for_each_entry(dd, &ds->pci_dependent_devices, pci_list)
+		handle_hotplug_event_func(dd->handle, type, dd->func);
+}
+
+
+
+static inline void begin_dock(void)
+{
+	ds->flags |= DOCK_DOCKING;
+}
+
+
+static inline void complete_dock(void)
+{
+	ds->flags &= ~(DOCK_DOCKING);
+	ds->last_dock_time = jiffies;
+}
+
+
+static int dock_in_progress(void)
+{
+	if (ds->flags & DOCK_DOCKING ||
+		ds->last_dock_time == jiffies) {
+		dbg("dock in progress\n");
+		return 1;
+	}
+	return 0;
+}
+
+
+
+static void
+handle_hotplug_event_dock(acpi_handle handle, u32 type, void *context)
+{
+	dbg("%s: enter\n", __FUNCTION__);
+
+	switch (type) {
+		case ACPI_NOTIFY_BUS_CHECK:
+			dbg("BUS Check\n");
+			if (!dock_in_progress() && dock_present()) {
+				begin_dock();
+				dock();
+				if (!dock_present()) {
+					err("Unable to dock!\n");
+					break;
+				}
+				post_dock_fixups();
+				hotplug_pci(type);
+				complete_dock();
+			}
+			break;
+		case ACPI_NOTIFY_EJECT_REQUEST:
+			dbg("EJECT request\n");
+			if (!dock_in_progress() && dock_present()) {
+				hotplug_pci(type);
+				undock();
+				eject_dock();
+				if (dock_present())
+					err("Unable to undock!\n");
+			}
+			break;
+	}
+}
+
+
+
+
+static acpi_status
+find_dock_ejd(acpi_handle handle, u32 lvl, void *context, void **rv)
+{
+	acpi_status status;
+	acpi_handle tmp;
+	acpi_handle dck_handle = (acpi_handle) context;
+	char objname[64];
+	struct acpi_buffer buffer = { .length = sizeof(objname),
+				      .pointer = objname };
+	struct acpi_buffer ejd_buffer = {ACPI_ALLOCATE_BUFFER, NULL};
+	union acpi_object *ejd_obj;
+
+	status = acpi_get_handle(handle, "_EJD", &tmp);
+	if (ACPI_FAILURE(status))
+		return AE_OK;
+
+	/* make sure we are dependent on the dock device,
+	 * by executing the _EJD method, then getting a handle
+	 * to the device referenced by that name.  If that
+	 * device handle is the same handle as the dock station
+	 * handle, then we are a device dependent on the dock station
+	 */
+	acpi_get_name(dck_handle, ACPI_FULL_PATHNAME, &buffer);
+	status = acpi_evaluate_object(handle, "_EJD", NULL, &ejd_buffer);
+	if (ACPI_FAILURE(status)) {
+		err("Unable to execute _EJD!\n");
+		goto find_ejd_out;
+	}
+	ejd_obj = ejd_buffer.pointer;
+	status = acpi_get_handle(NULL, ejd_obj->string.pointer, &tmp);
+	if (ACPI_FAILURE(status))
+		goto find_ejd_out;
+
+	if (tmp == dck_handle) {
+		struct dependent_device *dd;
+		dbg("%s: found device dependent on dock\n", __FUNCTION__);
+		dd = alloc_dependent_device(handle);
+		if (!dd) {
+			err("Can't allocate memory for dependent device!\n");
+			goto find_ejd_out;
+		}
+		add_dependent_device(dd);
+	}
+
+find_ejd_out:
+	acpi_os_free(ejd_buffer.pointer);
+	return AE_OK;
+}
+
+
+
+int detect_dependent_devices(acpi_handle *bridge_handle)
+{
+	acpi_status status;
+	int count;
+
+	count = 0;
+
+	status = acpi_walk_namespace(ACPI_TYPE_DEVICE, bridge_handle,
+					(u32)1, find_dependent_device,
+					(void *)&count, NULL);
+
+	return count;
+}
+
+
+
+
+
+static acpi_status
+find_dock(acpi_handle handle, u32 lvl, void *context, void **rv)
+{
+	int *count = (int *)context;
+
+	if (is_dock(handle)) {
+		dbg("%s: found dock\n", __FUNCTION__);
+		ds = kzalloc(sizeof(*ds), GFP_KERNEL);
+		ds->handle = handle;
+		INIT_LIST_HEAD(&ds->dependent_devices);
+		INIT_LIST_HEAD(&ds->pci_dependent_devices);
+
+		/* look for devices dependent on dock station */
+		acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
+			ACPI_UINT32_MAX, find_dock_ejd, handle, NULL);
+
+		acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
+			handle_hotplug_event_dock, ds);
+		(*count)++;
+	}
+
+	return AE_OK;
+}
+
+
+
+
+int find_dock_station(void)
+{
+	int num = 0;
+
+	ds = NULL;
+
+	/* start from the root object, because some laptops define
+	 * _DCK methods outside the scope of PCI (IBM x-series laptop)
+	 */
+	acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
+			ACPI_UINT32_MAX, find_dock, &num, NULL);
+
+	return num;
+}
+
+
+
+void remove_dock_station(void)
+{
+	struct dependent_device *dd, *tmp;
+	if (ds) {
+		if (ACPI_FAILURE(acpi_remove_notify_handler(ds->handle,
+			ACPI_SYSTEM_NOTIFY, handle_hotplug_event_dock)))
+			err("failed to remove dock notify handler\n");
+
+		/* free all dependent devices */
+		list_for_each_entry_safe(dd, tmp, &ds->dependent_devices,
+				device_list)
+			kfree(dd);
+
+		/* no need to touch the pci_dependent_device list,
+		 * cause all memory was freed above
+		 */
+		kfree(ds);
+	}
+}
+
+

+ 219 - 137
drivers/pci/hotplug/acpiphp_glue.c

@@ -46,7 +46,7 @@
 #include <linux/kernel.h>
 #include <linux/kernel.h>
 #include <linux/pci.h>
 #include <linux/pci.h>
 #include <linux/smp_lock.h>
 #include <linux/smp_lock.h>
-#include <asm/semaphore.h>
+#include <linux/mutex.h>
 
 
 #include "../pci.h"
 #include "../pci.h"
 #include "pci_hotplug.h"
 #include "pci_hotplug.h"
@@ -57,7 +57,6 @@ static LIST_HEAD(bridge_list);
 #define MY_NAME "acpiphp_glue"
 #define MY_NAME "acpiphp_glue"
 
 
 static void handle_hotplug_event_bridge (acpi_handle, u32, void *);
 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_sanitize_bus(struct pci_bus *bus);
 static void acpiphp_set_hpp_values(acpi_handle handle, struct pci_bus *bus);
 static void acpiphp_set_hpp_values(acpi_handle handle, struct pci_bus *bus);
 
 
@@ -125,11 +124,11 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv)
 	struct acpiphp_bridge *bridge = (struct acpiphp_bridge *)context;
 	struct acpiphp_bridge *bridge = (struct acpiphp_bridge *)context;
 	struct acpiphp_slot *slot;
 	struct acpiphp_slot *slot;
 	struct acpiphp_func *newfunc;
 	struct acpiphp_func *newfunc;
+	struct dependent_device *dd;
 	acpi_handle tmp;
 	acpi_handle tmp;
 	acpi_status status = AE_OK;
 	acpi_status status = AE_OK;
 	unsigned long adr, sun;
 	unsigned long adr, sun;
-	int device, function;
-	static int num_slots = 0;	/* XXX if we support I/O node hotplug... */
+	int device, function, retval;
 
 
 	status = acpi_evaluate_integer(handle, "_ADR", NULL, &adr);
 	status = acpi_evaluate_integer(handle, "_ADR", NULL, &adr);
 
 
@@ -138,21 +137,21 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv)
 
 
 	status = acpi_get_handle(handle, "_EJ0", &tmp);
 	status = acpi_get_handle(handle, "_EJ0", &tmp);
 
 
-	if (ACPI_FAILURE(status))
+	if (ACPI_FAILURE(status) && !(is_dependent_device(handle)))
 		return AE_OK;
 		return AE_OK;
 
 
 	device = (adr >> 16) & 0xffff;
 	device = (adr >> 16) & 0xffff;
 	function = adr & 0xffff;
 	function = adr & 0xffff;
 
 
-	newfunc = kmalloc(sizeof(struct acpiphp_func), GFP_KERNEL);
+	newfunc = kzalloc(sizeof(struct acpiphp_func), GFP_KERNEL);
 	if (!newfunc)
 	if (!newfunc)
 		return AE_NO_MEMORY;
 		return AE_NO_MEMORY;
-	memset(newfunc, 0, sizeof(struct acpiphp_func));
 
 
 	INIT_LIST_HEAD(&newfunc->sibling);
 	INIT_LIST_HEAD(&newfunc->sibling);
 	newfunc->handle = handle;
 	newfunc->handle = handle;
 	newfunc->function = function;
 	newfunc->function = function;
-	newfunc->flags = FUNC_HAS_EJ0;
+	if (ACPI_SUCCESS(status))
+		newfunc->flags = FUNC_HAS_EJ0;
 
 
 	if (ACPI_SUCCESS(acpi_get_handle(handle, "_STA", &tmp)))
 	if (ACPI_SUCCESS(acpi_get_handle(handle, "_STA", &tmp)))
 		newfunc->flags |= FUNC_HAS_STA;
 		newfunc->flags |= FUNC_HAS_STA;
@@ -163,6 +162,19 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv)
 	if (ACPI_SUCCESS(acpi_get_handle(handle, "_PS3", &tmp)))
 	if (ACPI_SUCCESS(acpi_get_handle(handle, "_PS3", &tmp)))
 		newfunc->flags |= FUNC_HAS_PS3;
 		newfunc->flags |= FUNC_HAS_PS3;
 
 
+	if (ACPI_SUCCESS(acpi_get_handle(handle, "_DCK", &tmp))) {
+		newfunc->flags |= FUNC_HAS_DCK;
+		/* add to devices dependent on dock station,
+		 * because this may actually be the dock bridge
+		 */
+		dd = alloc_dependent_device(handle);
+                if (!dd)
+                        err("Can't allocate memory for "
+				"new dependent device!\n");
+		else
+			add_dependent_device(dd);
+	}
+
 	status = acpi_evaluate_integer(handle, "_SUN", NULL, &sun);
 	status = acpi_evaluate_integer(handle, "_SUN", NULL, &sun);
 	if (ACPI_FAILURE(status))
 	if (ACPI_FAILURE(status))
 		sun = -1;
 		sun = -1;
@@ -176,19 +188,17 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv)
 		}
 		}
 
 
 	if (!slot) {
 	if (!slot) {
-		slot = kmalloc(sizeof(struct acpiphp_slot), GFP_KERNEL);
+		slot = kzalloc(sizeof(struct acpiphp_slot), GFP_KERNEL);
 		if (!slot) {
 		if (!slot) {
 			kfree(newfunc);
 			kfree(newfunc);
 			return AE_NO_MEMORY;
 			return AE_NO_MEMORY;
 		}
 		}
 
 
-		memset(slot, 0, sizeof(struct acpiphp_slot));
 		slot->bridge = bridge;
 		slot->bridge = bridge;
-		slot->id = num_slots++;
 		slot->device = device;
 		slot->device = device;
 		slot->sun = sun;
 		slot->sun = sun;
 		INIT_LIST_HEAD(&slot->funcs);
 		INIT_LIST_HEAD(&slot->funcs);
-		init_MUTEX(&slot->crit_sect);
+		mutex_init(&slot->crit_sect);
 
 
 		slot->next = bridge->slots;
 		slot->next = bridge->slots;
 		bridge->slots = slot;
 		bridge->slots = slot;
@@ -198,6 +208,11 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv)
 		dbg("found ACPI PCI Hotplug slot %d at PCI %04x:%02x:%02x\n",
 		dbg("found ACPI PCI Hotplug slot %d at PCI %04x:%02x:%02x\n",
 				slot->sun, pci_domain_nr(bridge->pci_bus),
 				slot->sun, pci_domain_nr(bridge->pci_bus),
 				bridge->pci_bus->number, slot->device);
 				bridge->pci_bus->number, slot->device);
+		retval = acpiphp_register_hotplug_slot(slot);
+		if (retval) {
+			warn("acpiphp_register_hotplug_slot failed(err code = 0x%x)\n", retval);
+			goto err_exit;
+		}
 	}
 	}
 
 
 	newfunc->slot = slot;
 	newfunc->slot = slot;
@@ -210,16 +225,41 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv)
 		slot->flags |= (SLOT_ENABLED | SLOT_POWEREDON);
 		slot->flags |= (SLOT_ENABLED | SLOT_POWEREDON);
 	}
 	}
 
 
+	/* if this is a device dependent on a dock station,
+	 * associate the acpiphp_func to the dependent_device
+ 	 * struct.
+	 */
+	if ((dd = get_dependent_device(handle))) {
+		newfunc->flags |= FUNC_IS_DD;
+		/*
+		 * we don't want any devices which is dependent
+		 * on the dock to have it's _EJ0 method executed.
+		 * because we need to run _DCK first.
+		 */
+		newfunc->flags &= ~FUNC_HAS_EJ0;
+		dd->func = newfunc;
+		add_pci_dependent_device(dd);
+	}
+
 	/* install notify handler */
 	/* install notify handler */
-	status = acpi_install_notify_handler(handle,
+	if (!(newfunc->flags & FUNC_HAS_DCK)) {
+		status = acpi_install_notify_handler(handle,
 					     ACPI_SYSTEM_NOTIFY,
 					     ACPI_SYSTEM_NOTIFY,
 					     handle_hotplug_event_func,
 					     handle_hotplug_event_func,
 					     newfunc);
 					     newfunc);
 
 
-	if (ACPI_FAILURE(status)) {
-		err("failed to register interrupt notify handler\n");
-		return status;
-	}
+		if (ACPI_FAILURE(status))
+			err("failed to register interrupt notify handler\n");
+	} else
+		status = AE_OK;
+
+	return status;
+
+ err_exit:
+	bridge->nr_slots--;
+	bridge->slots = slot->next;
+	kfree(slot);
+	kfree(newfunc);
 
 
 	return AE_OK;
 	return AE_OK;
 }
 }
@@ -245,57 +285,19 @@ static int detect_ejectable_slots(acpi_handle *bridge_handle)
 static void decode_hpp(struct acpiphp_bridge *bridge)
 static void decode_hpp(struct acpiphp_bridge *bridge)
 {
 {
 	acpi_status status;
 	acpi_status status;
-	struct acpi_buffer buffer = { .length = ACPI_ALLOCATE_BUFFER,
-				      .pointer = NULL};
-	union acpi_object *package;
-	int i;
-
-	/* default numbers */
-	bridge->hpp.cache_line_size = 0x10;
-	bridge->hpp.latency_timer = 0x40;
-	bridge->hpp.enable_SERR = 0;
-	bridge->hpp.enable_PERR = 0;
-
-	status = acpi_evaluate_object(bridge->handle, "_HPP", NULL, &buffer);
 
 
+	status = acpi_get_hp_params_from_firmware(bridge->pci_dev, &bridge->hpp);
 	if (ACPI_FAILURE(status)) {
 	if (ACPI_FAILURE(status)) {
-		dbg("_HPP evaluation failed\n");
-		return;
+		/* use default numbers */
+		bridge->hpp.cache_line_size = 0x10;
+		bridge->hpp.latency_timer = 0x40;
+		bridge->hpp.enable_serr = 0;
+		bridge->hpp.enable_perr = 0;
 	}
 	}
-
-	package = (union acpi_object *) buffer.pointer;
-
-	if (!package || package->type != ACPI_TYPE_PACKAGE ||
-	    package->package.count != 4 || !package->package.elements) {
-		err("invalid _HPP object; ignoring\n");
-		goto err_exit;
-	}
-
-	for (i = 0; i < 4; i++) {
-		if (package->package.elements[i].type != ACPI_TYPE_INTEGER) {
-			err("invalid _HPP parameter type; ignoring\n");
-			goto err_exit;
-		}
-	}
-
-	bridge->hpp.cache_line_size = package->package.elements[0].integer.value;
-	bridge->hpp.latency_timer = package->package.elements[1].integer.value;
-	bridge->hpp.enable_SERR = package->package.elements[2].integer.value;
-	bridge->hpp.enable_PERR = package->package.elements[3].integer.value;
-
-	dbg("_HPP parameter = (%02x, %02x, %02x, %02x)\n",
-		bridge->hpp.cache_line_size,
-		bridge->hpp.latency_timer,
-		bridge->hpp.enable_SERR,
-		bridge->hpp.enable_PERR);
-
-	bridge->flags |= BRIDGE_HAS_HPP;
-
- err_exit:
-	kfree(buffer.pointer);
 }
 }
 
 
 
 
+
 /* initialize miscellaneous stuff for both root and PCI-to-PCI bridge */
 /* initialize miscellaneous stuff for both root and PCI-to-PCI bridge */
 static void init_bridge_misc(struct acpiphp_bridge *bridge)
 static void init_bridge_misc(struct acpiphp_bridge *bridge)
 {
 {
@@ -304,9 +306,16 @@ static void init_bridge_misc(struct acpiphp_bridge *bridge)
 	/* decode ACPI 2.0 _HPP (hot plug parameters) */
 	/* decode ACPI 2.0 _HPP (hot plug parameters) */
 	decode_hpp(bridge);
 	decode_hpp(bridge);
 
 
+	/* must be added to the list prior to calling register_slot */
+	list_add(&bridge->list, &bridge_list);
+
 	/* register all slot objects under this bridge */
 	/* register all slot objects under this bridge */
 	status = acpi_walk_namespace(ACPI_TYPE_DEVICE, bridge->handle, (u32)1,
 	status = acpi_walk_namespace(ACPI_TYPE_DEVICE, bridge->handle, (u32)1,
 				     register_slot, bridge, NULL);
 				     register_slot, bridge, NULL);
+	if (ACPI_FAILURE(status)) {
+		list_del(&bridge->list);
+		return;
+	}
 
 
 	/* install notify handler */
 	/* install notify handler */
 	if (bridge->type != BRIDGE_TYPE_HOST) {
 	if (bridge->type != BRIDGE_TYPE_HOST) {
@@ -319,8 +328,6 @@ static void init_bridge_misc(struct acpiphp_bridge *bridge)
 			err("failed to register interrupt notify handler\n");
 			err("failed to register interrupt notify handler\n");
 		}
 		}
 	}
 	}
-
-	list_add(&bridge->list, &bridge_list);
 }
 }
 
 
 
 
@@ -329,12 +336,10 @@ static void add_host_bridge(acpi_handle *handle, struct pci_bus *pci_bus)
 {
 {
 	struct acpiphp_bridge *bridge;
 	struct acpiphp_bridge *bridge;
 
 
-	bridge = kmalloc(sizeof(struct acpiphp_bridge), GFP_KERNEL);
+	bridge = kzalloc(sizeof(struct acpiphp_bridge), GFP_KERNEL);
 	if (bridge == NULL)
 	if (bridge == NULL)
 		return;
 		return;
 
 
-	memset(bridge, 0, sizeof(struct acpiphp_bridge));
-
 	bridge->type = BRIDGE_TYPE_HOST;
 	bridge->type = BRIDGE_TYPE_HOST;
 	bridge->handle = handle;
 	bridge->handle = handle;
 
 
@@ -351,14 +356,12 @@ static void add_p2p_bridge(acpi_handle *handle, struct pci_dev *pci_dev)
 {
 {
 	struct acpiphp_bridge *bridge;
 	struct acpiphp_bridge *bridge;
 
 
-	bridge = kmalloc(sizeof(struct acpiphp_bridge), GFP_KERNEL);
+	bridge = kzalloc(sizeof(struct acpiphp_bridge), GFP_KERNEL);
 	if (bridge == NULL) {
 	if (bridge == NULL) {
 		err("out of memory\n");
 		err("out of memory\n");
 		return;
 		return;
 	}
 	}
 
 
-	memset(bridge, 0, sizeof(struct acpiphp_bridge));
-
 	bridge->type = BRIDGE_TYPE_P2P;
 	bridge->type = BRIDGE_TYPE_P2P;
 	bridge->handle = handle;
 	bridge->handle = handle;
 
 
@@ -410,11 +413,18 @@ find_p2p_bridge(acpi_handle handle, u32 lvl, void *context, void **rv)
 		goto out;
 		goto out;
 
 
 	/* check if this bridge has ejectable slots */
 	/* check if this bridge has ejectable slots */
-	if (detect_ejectable_slots(handle) > 0) {
+	if ((detect_ejectable_slots(handle) > 0) ||
+		(detect_dependent_devices(handle) > 0)) {
 		dbg("found PCI-to-PCI bridge at PCI %s\n", pci_name(dev));
 		dbg("found PCI-to-PCI bridge at PCI %s\n", pci_name(dev));
 		add_p2p_bridge(handle, dev);
 		add_p2p_bridge(handle, dev);
 	}
 	}
 
 
+	/* search P2P bridges under this p2p bridge */
+	status = acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, (u32)1,
+				     find_p2p_bridge, dev->subordinate, NULL);
+	if (ACPI_FAILURE(status))
+		warn("find_p2p_bridge faied (error code = 0x%x)\n", status);
+
  out:
  out:
 	pci_dev_put(dev);
 	pci_dev_put(dev);
 	return AE_OK;
 	return AE_OK;
@@ -512,15 +522,19 @@ static void cleanup_bridge(struct acpiphp_bridge *bridge)
 		list_for_each_safe (list, tmp, &slot->funcs) {
 		list_for_each_safe (list, tmp, &slot->funcs) {
 			struct acpiphp_func *func;
 			struct acpiphp_func *func;
 			func = list_entry(list, struct acpiphp_func, sibling);
 			func = list_entry(list, struct acpiphp_func, sibling);
-			status = acpi_remove_notify_handler(func->handle,
+			if (!(func->flags & FUNC_HAS_DCK)) {
+				status = acpi_remove_notify_handler(func->handle,
 						ACPI_SYSTEM_NOTIFY,
 						ACPI_SYSTEM_NOTIFY,
 						handle_hotplug_event_func);
 						handle_hotplug_event_func);
-			if (ACPI_FAILURE(status))
-				err("failed to remove notify handler\n");
+				if (ACPI_FAILURE(status))
+					err("failed to remove notify handler\n");
+			}
 			pci_dev_put(func->pci_dev);
 			pci_dev_put(func->pci_dev);
 			list_del(list);
 			list_del(list);
 			kfree(func);
 			kfree(func);
 		}
 		}
+		acpiphp_unregister_hotplug_slot(slot);
+		list_del(&slot->funcs);
 		kfree(slot);
 		kfree(slot);
 		slot = next;
 		slot = next;
 	}
 	}
@@ -551,7 +565,8 @@ static void remove_bridge(acpi_handle handle)
 	} else {
 	} else {
 		/* clean-up p2p bridges under this host bridge */
 		/* clean-up p2p bridges under this host bridge */
 		acpi_walk_namespace(ACPI_TYPE_DEVICE, handle,
 		acpi_walk_namespace(ACPI_TYPE_DEVICE, handle,
-				(u32)1, cleanup_p2p_bridge, NULL, NULL);
+				    ACPI_UINT32_MAX, cleanup_p2p_bridge,
+				    NULL, NULL);
 	}
 	}
 }
 }
 
 
@@ -751,6 +766,113 @@ static int power_off_slot(struct acpiphp_slot *slot)
 }
 }
 
 
 
 
+
+/**
+ * acpiphp_max_busnr - return the highest reserved bus number under
+ * the given bus.
+ * @bus: bus to start search with
+ *
+ */
+static unsigned char acpiphp_max_busnr(struct pci_bus *bus)
+{
+	struct list_head *tmp;
+	unsigned char max, n;
+
+	/*
+	 * pci_bus_max_busnr will return the highest
+	 * reserved busnr for all these children.
+	 * that is equivalent to the bus->subordinate
+	 * value.  We don't want to use the parent's
+	 * bus->subordinate value because it could have
+	 * padding in it.
+	 */
+	max = bus->secondary;
+
+	list_for_each(tmp, &bus->children) {
+		n = pci_bus_max_busnr(pci_bus_b(tmp));
+		if (n > max)
+			max = n;
+	}
+	return max;
+}
+
+
+
+/**
+ *  get_func - get a pointer to acpiphp_func given a slot, device
+ *  @slot: slot to search
+ *  @dev:  pci_dev struct to match.
+ *
+ *  This function will increase the reference count of pci_dev,
+ *  so callers should call pci_dev_put when complete.
+ *
+ */
+static struct acpiphp_func *
+get_func(struct acpiphp_slot *slot, struct pci_dev *dev)
+{
+	struct acpiphp_func *func = NULL;
+	struct pci_bus *bus = slot->bridge->pci_bus;
+	struct pci_dev *pdev;
+
+	list_for_each_entry(func, &slot->funcs, sibling) {
+		pdev = pci_get_slot(bus, PCI_DEVFN(slot->device,
+					func->function));
+		if (pdev) {
+			if (pdev == dev)
+				break;
+			pci_dev_put(pdev);
+		}
+	}
+	return func;
+}
+
+
+/**
+ * acpiphp_bus_add - add a new bus to acpi subsystem
+ * @func: acpiphp_func of the bridge
+ *
+ */
+static int acpiphp_bus_add(struct acpiphp_func *func)
+{
+	acpi_handle phandle;
+	struct acpi_device *device, *pdevice;
+	int ret_val;
+
+	acpi_get_parent(func->handle, &phandle);
+	if (acpi_bus_get_device(phandle, &pdevice)) {
+		dbg("no parent device, assuming NULL\n");
+		pdevice = NULL;
+	}
+	if (!acpi_bus_get_device(func->handle, &device)) {
+		dbg("bus exists... trim\n");
+		/* this shouldn't be in here, so remove
+		 * the bus then re-add it...
+		 */
+		ret_val = acpi_bus_trim(device, 1);
+		dbg("acpi_bus_trim return %x\n", ret_val);
+	}
+
+	ret_val = acpi_bus_add(&device, pdevice, func->handle,
+		ACPI_BUS_TYPE_DEVICE);
+	if (ret_val) {
+		dbg("error adding bus, %x\n",
+			-ret_val);
+		goto acpiphp_bus_add_out;
+	}
+	/*
+	 * try to start anyway.  We could have failed to add
+	 * simply because this bus had previously been added
+	 * on another add.  Don't bother with the return value
+	 * we just keep going.
+	 */
+	ret_val = acpi_bus_start(device);
+
+acpiphp_bus_add_out:
+	return ret_val;
+}
+
+
+
 /**
 /**
  * enable_device - enable, configure a slot
  * enable_device - enable, configure a slot
  * @slot: slot to be enabled
  * @slot: slot to be enabled
@@ -788,7 +910,7 @@ static int enable_device(struct acpiphp_slot *slot)
 		goto err_exit;
 		goto err_exit;
 	}
 	}
 
 
-	max = bus->secondary;
+	max = acpiphp_max_busnr(bus);
 	for (pass = 0; pass < 2; pass++) {
 	for (pass = 0; pass < 2; pass++) {
 		list_for_each_entry(dev, &bus->devices, bus_list) {
 		list_for_each_entry(dev, &bus->devices, bus_list) {
 			if (PCI_SLOT(dev->devfn) != slot->device)
 			if (PCI_SLOT(dev->devfn) != slot->device)
@@ -796,8 +918,15 @@ static int enable_device(struct acpiphp_slot *slot)
 			if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE ||
 			if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE ||
 			    dev->hdr_type == PCI_HEADER_TYPE_CARDBUS) {
 			    dev->hdr_type == PCI_HEADER_TYPE_CARDBUS) {
 				max = pci_scan_bridge(bus, dev, max, pass);
 				max = pci_scan_bridge(bus, dev, max, pass);
-				if (pass && dev->subordinate)
+				if (pass && dev->subordinate) {
 					pci_bus_size_bridges(dev->subordinate);
 					pci_bus_size_bridges(dev->subordinate);
+					func = get_func(slot, dev);
+					if (func) {
+						acpiphp_bus_add(func);
+						/* side effect of get_func */
+						pci_dev_put(dev);
+					}
+				}
 			}
 			}
 		}
 		}
 	}
 	}
@@ -806,8 +935,8 @@ static int enable_device(struct acpiphp_slot *slot)
 	acpiphp_sanitize_bus(bus);
 	acpiphp_sanitize_bus(bus);
 	pci_enable_bridges(bus);
 	pci_enable_bridges(bus);
 	pci_bus_add_devices(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));
+	acpiphp_set_hpp_values(slot->bridge->handle, bus);
+	acpiphp_configure_ioapics(slot->bridge->handle);
 
 
 	/* associate pci_dev to our representation */
 	/* associate pci_dev to our representation */
 	list_for_each (l, &slot->funcs) {
 	list_for_each (l, &slot->funcs) {
@@ -987,11 +1116,11 @@ static void program_hpp(struct pci_dev *dev, struct acpiphp_bridge *bridge)
 	pci_write_config_byte(dev, PCI_LATENCY_TIMER,
 	pci_write_config_byte(dev, PCI_LATENCY_TIMER,
 			bridge->hpp.latency_timer);
 			bridge->hpp.latency_timer);
 	pci_read_config_word(dev, PCI_COMMAND, &pci_cmd);
 	pci_read_config_word(dev, PCI_COMMAND, &pci_cmd);
-	if (bridge->hpp.enable_SERR)
+	if (bridge->hpp.enable_serr)
 		pci_cmd |= PCI_COMMAND_SERR;
 		pci_cmd |= PCI_COMMAND_SERR;
 	else
 	else
 		pci_cmd &= ~PCI_COMMAND_SERR;
 		pci_cmd &= ~PCI_COMMAND_SERR;
-	if (bridge->hpp.enable_PERR)
+	if (bridge->hpp.enable_perr)
 		pci_cmd |= PCI_COMMAND_PARITY;
 		pci_cmd |= PCI_COMMAND_PARITY;
 	else
 	else
 		pci_cmd &= ~PCI_COMMAND_PARITY;
 		pci_cmd &= ~PCI_COMMAND_PARITY;
@@ -1002,11 +1131,11 @@ static void program_hpp(struct pci_dev *dev, struct acpiphp_bridge *bridge)
 		pci_write_config_byte(dev, PCI_SEC_LATENCY_TIMER,
 		pci_write_config_byte(dev, PCI_SEC_LATENCY_TIMER,
 				bridge->hpp.latency_timer);
 				bridge->hpp.latency_timer);
 		pci_read_config_word(dev, PCI_BRIDGE_CONTROL, &pci_bctl);
 		pci_read_config_word(dev, PCI_BRIDGE_CONTROL, &pci_bctl);
-		if (bridge->hpp.enable_SERR)
+		if (bridge->hpp.enable_serr)
 			pci_bctl |= PCI_BRIDGE_CTL_SERR;
 			pci_bctl |= PCI_BRIDGE_CTL_SERR;
 		else
 		else
 			pci_bctl &= ~PCI_BRIDGE_CTL_SERR;
 			pci_bctl &= ~PCI_BRIDGE_CTL_SERR;
-		if (bridge->hpp.enable_PERR)
+		if (bridge->hpp.enable_perr)
 			pci_bctl |= PCI_BRIDGE_CTL_PARITY;
 			pci_bctl |= PCI_BRIDGE_CTL_PARITY;
 		else
 		else
 			pci_bctl &= ~PCI_BRIDGE_CTL_PARITY;
 			pci_bctl &= ~PCI_BRIDGE_CTL_PARITY;
@@ -1026,6 +1155,7 @@ static void acpiphp_set_hpp_values(acpi_handle handle, struct pci_bus *bus)
 
 
 	memset(&bridge, 0, sizeof(bridge));
 	memset(&bridge, 0, sizeof(bridge));
 	bridge.handle = handle;
 	bridge.handle = handle;
+	bridge.pci_dev = bus->self;
 	decode_hpp(&bridge);
 	decode_hpp(&bridge);
 	list_for_each_entry(dev, &bus->devices, bus_list)
 	list_for_each_entry(dev, &bus->devices, bus_list)
 		program_hpp(dev, &bridge);
 		program_hpp(dev, &bridge);
@@ -1200,7 +1330,7 @@ static void handle_hotplug_event_bridge(acpi_handle handle, u32 type, void *cont
  * handles ACPI event notification on slots
  * handles ACPI event notification on slots
  *
  *
  */
  */
-static void handle_hotplug_event_func(acpi_handle handle, u32 type, void *context)
+void handle_hotplug_event_func(acpi_handle handle, u32 type, void *context)
 {
 {
 	struct acpiphp_func *func;
 	struct acpiphp_func *func;
 	char objname[64];
 	char objname[64];
@@ -1242,41 +1372,13 @@ static void handle_hotplug_event_func(acpi_handle handle, u32 type, void *contex
 	}
 	}
 }
 }
 
 
-static int is_root_bridge(acpi_handle handle)
-{
-	acpi_status status;
-	struct acpi_device_info *info;
-	struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
-	int i;
-
-	status = acpi_get_object_info(handle, &buffer);
-	if (ACPI_SUCCESS(status)) {
-		info = buffer.pointer;
-		if ((info->valid & ACPI_VALID_HID) &&
-			!strcmp(PCI_ROOT_HID_STRING,
-					info->hardware_id.value)) {
-			acpi_os_free(buffer.pointer);
-			return 1;
-		}
-		if (info->valid & ACPI_VALID_CID) {
-			for (i=0; i < info->compatibility_id.count; i++) {
-				if (!strcmp(PCI_ROOT_HID_STRING,
-					info->compatibility_id.id[i].value)) {
-					acpi_os_free(buffer.pointer);
-					return 1;
-				}
-			}
-		}
-	}
-	return 0;
-}
 
 
 static acpi_status
 static acpi_status
 find_root_bridges(acpi_handle handle, u32 lvl, void *context, void **rv)
 find_root_bridges(acpi_handle handle, u32 lvl, void *context, void **rv)
 {
 {
 	int *count = (int *)context;
 	int *count = (int *)context;
 
 
-	if (is_root_bridge(handle)) {
+	if (acpi_root_bridge(handle)) {
 		acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
 		acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
 				handle_hotplug_event_bridge, NULL);
 				handle_hotplug_event_bridge, NULL);
 			(*count)++;
 			(*count)++;
@@ -1373,26 +1475,6 @@ static int acpiphp_for_each_slot(acpiphp_callback fn, void *data)
 }
 }
 #endif
 #endif
 
 
-/* search matching slot from id  */
-struct acpiphp_slot *get_slot_from_id(int id)
-{
-	struct list_head *node;
-	struct acpiphp_bridge *bridge;
-	struct acpiphp_slot *slot;
-
-	list_for_each (node, &bridge_list) {
-		bridge = (struct acpiphp_bridge *)node;
-		for (slot = bridge->slots; slot; slot = slot->next)
-			if (slot->id == id)
-				return slot;
-	}
-
-	/* should never happen! */
-	err("%s: no object for id %d\n", __FUNCTION__, id);
-	WARN_ON(1);
-	return NULL;
-}
-
 
 
 /**
 /**
  * acpiphp_enable_slot - power on slot
  * acpiphp_enable_slot - power on slot
@@ -1401,7 +1483,7 @@ int acpiphp_enable_slot(struct acpiphp_slot *slot)
 {
 {
 	int retval;
 	int retval;
 
 
-	down(&slot->crit_sect);
+	mutex_lock(&slot->crit_sect);
 
 
 	/* wake up all functions */
 	/* wake up all functions */
 	retval = power_on_slot(slot);
 	retval = power_on_slot(slot);
@@ -1413,7 +1495,7 @@ int acpiphp_enable_slot(struct acpiphp_slot *slot)
 		retval = enable_device(slot);
 		retval = enable_device(slot);
 
 
  err_exit:
  err_exit:
-	up(&slot->crit_sect);
+	mutex_unlock(&slot->crit_sect);
 	return retval;
 	return retval;
 }
 }
 
 
@@ -1424,7 +1506,7 @@ int acpiphp_disable_slot(struct acpiphp_slot *slot)
 {
 {
 	int retval = 0;
 	int retval = 0;
 
 
-	down(&slot->crit_sect);
+	mutex_lock(&slot->crit_sect);
 
 
 	/* unconfigure all functions */
 	/* unconfigure all functions */
 	retval = disable_device(slot);
 	retval = disable_device(slot);
@@ -1437,7 +1519,7 @@ int acpiphp_disable_slot(struct acpiphp_slot *slot)
 		goto err_exit;
 		goto err_exit;
 
 
  err_exit:
  err_exit:
-	up(&slot->crit_sect);
+	mutex_unlock(&slot->crit_sect);
 	return retval;
 	return retval;
 }
 }
 
 

+ 3 - 6
drivers/pci/hotplug/cpci_hotplug_core.c

@@ -248,22 +248,19 @@ cpci_hp_register_bus(struct pci_bus *bus, u8 first, u8 last)
 	 * with the pci_hotplug subsystem.
 	 * with the pci_hotplug subsystem.
 	 */
 	 */
 	for (i = first; i <= last; ++i) {
 	for (i = first; i <= last; ++i) {
-		slot = kmalloc(sizeof (struct slot), GFP_KERNEL);
+		slot = kzalloc(sizeof (struct slot), GFP_KERNEL);
 		if (!slot)
 		if (!slot)
 			goto error;
 			goto error;
-		memset(slot, 0, sizeof (struct slot));
 
 
 		hotplug_slot =
 		hotplug_slot =
-		    kmalloc(sizeof (struct hotplug_slot), GFP_KERNEL);
+			kzalloc(sizeof (struct hotplug_slot), GFP_KERNEL);
 		if (!hotplug_slot)
 		if (!hotplug_slot)
 			goto error_slot;
 			goto error_slot;
-		memset(hotplug_slot, 0, sizeof (struct hotplug_slot));
 		slot->hotplug_slot = hotplug_slot;
 		slot->hotplug_slot = hotplug_slot;
 
 
-		info = kmalloc(sizeof (struct hotplug_slot_info), GFP_KERNEL);
+		info = kzalloc(sizeof (struct hotplug_slot_info), GFP_KERNEL);
 		if (!info)
 		if (!info)
 			goto error_hpslot;
 			goto error_hpslot;
-		memset(info, 0, sizeof (struct hotplug_slot_info));
 		hotplug_slot->info = info;
 		hotplug_slot->info = info;
 
 
 		name = kmalloc(SLOT_NAME_SIZE, GFP_KERNEL);
 		name = kmalloc(SLOT_NAME_SIZE, GFP_KERNEL);

+ 2 - 1
drivers/pci/hotplug/cpqphp.h

@@ -32,6 +32,7 @@
 #include <linux/interrupt.h>
 #include <linux/interrupt.h>
 #include <asm/io.h>		/* for read? and write? functions */
 #include <asm/io.h>		/* for read? and write? functions */
 #include <linux/delay.h>	/* for delays */
 #include <linux/delay.h>	/* for delays */
+#include <linux/mutex.h>
 
 
 #define MY_NAME	"cpqphp"
 #define MY_NAME	"cpqphp"
 
 
@@ -286,7 +287,7 @@ struct event_info {
 struct controller {
 struct controller {
 	struct controller *next;
 	struct controller *next;
 	u32 ctrl_int_comp;
 	u32 ctrl_int_comp;
-	struct semaphore crit_sect;	/* critical section semaphore */
+	struct mutex crit_sect;		/* critical section mutex */
 	void __iomem *hpc_reg;		/* cookie for our pci controller location */
 	void __iomem *hpc_reg;		/* cookie for our pci controller location */
 	struct pci_resource *mem_head;
 	struct pci_resource *mem_head;
 	struct pci_resource *p_mem_head;
 	struct pci_resource *p_mem_head;

+ 11 - 16
drivers/pci/hotplug/cpqphp_core.c

@@ -347,26 +347,22 @@ static int ctrl_slot_setup(struct controller *ctrl,
 	slot_number = ctrl->first_slot;
 	slot_number = ctrl->first_slot;
 
 
 	while (number_of_slots) {
 	while (number_of_slots) {
-		slot = kmalloc(sizeof(*slot), GFP_KERNEL);
+		slot = kzalloc(sizeof(*slot), GFP_KERNEL);
 		if (!slot)
 		if (!slot)
 			goto error;
 			goto error;
 
 
-		memset(slot, 0, sizeof(struct slot));
-		slot->hotplug_slot = kmalloc(sizeof(*(slot->hotplug_slot)),
+		slot->hotplug_slot = kzalloc(sizeof(*(slot->hotplug_slot)),
 						GFP_KERNEL);
 						GFP_KERNEL);
 		if (!slot->hotplug_slot)
 		if (!slot->hotplug_slot)
 			goto error_slot;
 			goto error_slot;
 		hotplug_slot = slot->hotplug_slot;
 		hotplug_slot = slot->hotplug_slot;
-		memset(hotplug_slot, 0, sizeof(struct hotplug_slot));
 
 
 		hotplug_slot->info =
 		hotplug_slot->info =
-				kmalloc(sizeof(*(hotplug_slot->info)),
+				kzalloc(sizeof(*(hotplug_slot->info)),
 							GFP_KERNEL);
 							GFP_KERNEL);
 		if (!hotplug_slot->info)
 		if (!hotplug_slot->info)
 			goto error_hpslot;
 			goto error_hpslot;
 		hotplug_slot_info = hotplug_slot->info;
 		hotplug_slot_info = hotplug_slot->info;
-		memset(hotplug_slot_info, 0,
-				sizeof(struct hotplug_slot_info));
 		hotplug_slot->name = kmalloc(SLOT_NAME_SIZE, GFP_KERNEL);
 		hotplug_slot->name = kmalloc(SLOT_NAME_SIZE, GFP_KERNEL);
 
 
 		if (!hotplug_slot->name)
 		if (!hotplug_slot->name)
@@ -599,7 +595,7 @@ cpqhp_set_attention_status(struct controller *ctrl, struct pci_func *func,
 	hp_slot = func->device - ctrl->slot_device_offset;
 	hp_slot = func->device - ctrl->slot_device_offset;
 
 
 	// Wait for exclusive access to hardware
 	// Wait for exclusive access to hardware
-	down(&ctrl->crit_sect);
+	mutex_lock(&ctrl->crit_sect);
 
 
 	if (status == 1) {
 	if (status == 1) {
 		amber_LED_on (ctrl, hp_slot);
 		amber_LED_on (ctrl, hp_slot);
@@ -607,7 +603,7 @@ cpqhp_set_attention_status(struct controller *ctrl, struct pci_func *func,
 		amber_LED_off (ctrl, hp_slot);
 		amber_LED_off (ctrl, hp_slot);
 	} else {
 	} else {
 		// Done with exclusive hardware access
 		// Done with exclusive hardware access
-		up(&ctrl->crit_sect);
+		mutex_unlock(&ctrl->crit_sect);
 		return(1);
 		return(1);
 	}
 	}
 
 
@@ -617,7 +613,7 @@ cpqhp_set_attention_status(struct controller *ctrl, struct pci_func *func,
 	wait_for_ctrl_irq (ctrl);
 	wait_for_ctrl_irq (ctrl);
 
 
 	// Done with exclusive hardware access
 	// Done with exclusive hardware access
-	up(&ctrl->crit_sect);
+	mutex_unlock(&ctrl->crit_sect);
 
 
 	return(0);
 	return(0);
 }
 }
@@ -854,13 +850,12 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 			goto err_disable_device;
 			goto err_disable_device;
 		}
 		}
 
 
-		ctrl = (struct controller *) kmalloc(sizeof(struct controller), GFP_KERNEL);
+		ctrl = kzalloc(sizeof(struct controller), GFP_KERNEL);
 		if (!ctrl) {
 		if (!ctrl) {
 			err("%s : out of memory\n", __FUNCTION__);
 			err("%s : out of memory\n", __FUNCTION__);
 			rc = -ENOMEM;
 			rc = -ENOMEM;
 			goto err_disable_device;
 			goto err_disable_device;
 		}
 		}
-		memset(ctrl, 0, sizeof(struct controller));
 
 
 		rc = pci_read_config_word(pdev, PCI_SUBSYSTEM_ID, &subsystem_deviceid);
 		rc = pci_read_config_word(pdev, PCI_SUBSYSTEM_ID, &subsystem_deviceid);
 		if (rc) {
 		if (rc) {
@@ -1084,7 +1079,7 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 	dbg("bus device function rev: %d %d %d %d\n", ctrl->bus,
 	dbg("bus device function rev: %d %d %d %d\n", ctrl->bus,
 		PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn), ctrl->rev);
 		PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn), ctrl->rev);
 
 
-	init_MUTEX(&ctrl->crit_sect);
+	mutex_init(&ctrl->crit_sect);
 	init_waitqueue_head(&ctrl->queue);
 	init_waitqueue_head(&ctrl->queue);
 
 
 	/* initialize our threads if they haven't already been started up */
 	/* initialize our threads if they haven't already been started up */
@@ -1223,7 +1218,7 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 
 
 	// turn off empty slots here unless command line option "ON" set
 	// turn off empty slots here unless command line option "ON" set
 	// Wait for exclusive access to hardware
 	// Wait for exclusive access to hardware
-	down(&ctrl->crit_sect);
+	mutex_lock(&ctrl->crit_sect);
 
 
 	num_of_slots = readb(ctrl->hpc_reg + SLOT_MASK) & 0x0F;
 	num_of_slots = readb(ctrl->hpc_reg + SLOT_MASK) & 0x0F;
 
 
@@ -1270,12 +1265,12 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 	rc = init_SERR(ctrl);
 	rc = init_SERR(ctrl);
 	if (rc) {
 	if (rc) {
 		err("init_SERR failed\n");
 		err("init_SERR failed\n");
-		up(&ctrl->crit_sect);
+		mutex_unlock(&ctrl->crit_sect);
 		goto err_free_irq;
 		goto err_free_irq;
 	}
 	}
 
 
 	// Done with exclusive hardware access
 	// Done with exclusive hardware access
-	up(&ctrl->crit_sect);
+	mutex_unlock(&ctrl->crit_sect);
 
 
 	cpqhp_create_debugfs_files(ctrl);
 	cpqhp_create_debugfs_files(ctrl);
 
 

+ 38 - 86
drivers/pci/hotplug/cpqphp_ctrl.c

@@ -1282,9 +1282,7 @@ static u32 board_replaced(struct pci_func *func, struct controller *ctrl)
 	u8 hp_slot;
 	u8 hp_slot;
 	u8 temp_byte;
 	u8 temp_byte;
 	u8 adapter_speed;
 	u8 adapter_speed;
-	u32 index;
 	u32 rc = 0;
 	u32 rc = 0;
-	u32 src = 8;
 
 
 	hp_slot = func->device - ctrl->slot_device_offset;
 	hp_slot = func->device - ctrl->slot_device_offset;
 
 
@@ -1299,7 +1297,7 @@ static u32 board_replaced(struct pci_func *func, struct controller *ctrl)
 		 **********************************/
 		 **********************************/
 		rc = CARD_FUNCTIONING;
 		rc = CARD_FUNCTIONING;
 	} else {
 	} else {
-		down(&ctrl->crit_sect);
+		mutex_lock(&ctrl->crit_sect);
 
 
 		/* turn on board without attaching to the bus */
 		/* turn on board without attaching to the bus */
 		enable_slot_power (ctrl, hp_slot);
 		enable_slot_power (ctrl, hp_slot);
@@ -1333,12 +1331,12 @@ static u32 board_replaced(struct pci_func *func, struct controller *ctrl)
 		/* Wait for SOBS to be unset */
 		/* Wait for SOBS to be unset */
 		wait_for_ctrl_irq (ctrl);
 		wait_for_ctrl_irq (ctrl);
 
 
-		up(&ctrl->crit_sect);
+		mutex_unlock(&ctrl->crit_sect);
 
 
 		if (rc)
 		if (rc)
 			return rc;
 			return rc;
 
 
-		down(&ctrl->crit_sect);
+		mutex_lock(&ctrl->crit_sect);
 
 
 		slot_enable (ctrl, hp_slot);
 		slot_enable (ctrl, hp_slot);
 		green_LED_blink (ctrl, hp_slot);
 		green_LED_blink (ctrl, hp_slot);
@@ -1350,7 +1348,7 @@ static u32 board_replaced(struct pci_func *func, struct controller *ctrl)
 		/* Wait for SOBS to be unset */
 		/* Wait for SOBS to be unset */
 		wait_for_ctrl_irq (ctrl);
 		wait_for_ctrl_irq (ctrl);
 
 
-		up(&ctrl->crit_sect);
+		mutex_unlock(&ctrl->crit_sect);
 
 
 		/* Wait for ~1 second because of hot plug spec */
 		/* Wait for ~1 second because of hot plug spec */
 		long_delay(1*HZ);
 		long_delay(1*HZ);
@@ -1368,76 +1366,30 @@ static u32 board_replaced(struct pci_func *func, struct controller *ctrl)
 
 
 			rc = cpqhp_configure_board(ctrl, func);
 			rc = cpqhp_configure_board(ctrl, func);
 
 
-			if (rc || src) {
-				/* If configuration fails, turn it off
-				 * Get slot won't work for devices behind
-				 * bridges, but in this case it will always be
-				 * called for the "base" bus/dev/func of an
-				 * adapter. */
+			/* If configuration fails, turn it off
+			 * Get slot won't work for devices behind
+			 * bridges, but in this case it will always be
+			 * called for the "base" bus/dev/func of an
+			 * adapter. */
 
 
-				down(&ctrl->crit_sect);
+			mutex_lock(&ctrl->crit_sect);
 
 
-				amber_LED_on (ctrl, hp_slot);
-				green_LED_off (ctrl, hp_slot);
-				slot_disable (ctrl, hp_slot);
-
-				set_SOGO(ctrl);
-
-				/* Wait for SOBS to be unset */
-				wait_for_ctrl_irq (ctrl);
-
-				up(&ctrl->crit_sect);
-
-				if (rc)
-					return rc;
-				else
-					return 1;
-			}
-
-			func->status = 0;
-			func->switch_save = 0x10;
-
-			index = 1;
-			while (((func = cpqhp_slot_find(func->bus, func->device, index)) != NULL) && !rc) {
-				rc |= cpqhp_configure_board(ctrl, func);
-				index++;
-			}
-
-			if (rc) {
-				/* If configuration fails, turn it off
-				 * Get slot won't work for devices behind
-				 * bridges, but in this case it will always be
-				 * called for the "base" bus/dev/func of an
-				 * adapter. */
-
-				down(&ctrl->crit_sect);
-
-				amber_LED_on (ctrl, hp_slot);
-				green_LED_off (ctrl, hp_slot);
-				slot_disable (ctrl, hp_slot);
-
-				set_SOGO(ctrl);
-
-				/* Wait for SOBS to be unset */
-				wait_for_ctrl_irq (ctrl);
-
-				up(&ctrl->crit_sect);
-
-				return rc;
-			}
-			/* Done configuring so turn LED on full time */
-
-			down(&ctrl->crit_sect);
-
-			green_LED_on (ctrl, hp_slot);
+			amber_LED_on (ctrl, hp_slot);
+			green_LED_off (ctrl, hp_slot);
+			slot_disable (ctrl, hp_slot);
 
 
 			set_SOGO(ctrl);
 			set_SOGO(ctrl);
 
 
 			/* Wait for SOBS to be unset */
 			/* Wait for SOBS to be unset */
 			wait_for_ctrl_irq (ctrl);
 			wait_for_ctrl_irq (ctrl);
 
 
-			up(&ctrl->crit_sect);
-			rc = 0;
+			mutex_unlock(&ctrl->crit_sect);
+
+			if (rc)
+				return rc;
+			else
+				return 1;
+
 		} else {
 		} else {
 			/* Something is wrong
 			/* Something is wrong
 
 
@@ -1445,7 +1397,7 @@ static u32 board_replaced(struct pci_func *func, struct controller *ctrl)
 			 * in this case it will always be called for the "base"
 			 * in this case it will always be called for the "base"
 			 * bus/dev/func of an adapter. */
 			 * bus/dev/func of an adapter. */
 
 
-			down(&ctrl->crit_sect);
+			mutex_lock(&ctrl->crit_sect);
 
 
 			amber_LED_on (ctrl, hp_slot);
 			amber_LED_on (ctrl, hp_slot);
 			green_LED_off (ctrl, hp_slot);
 			green_LED_off (ctrl, hp_slot);
@@ -1456,7 +1408,7 @@ static u32 board_replaced(struct pci_func *func, struct controller *ctrl)
 			/* Wait for SOBS to be unset */
 			/* Wait for SOBS to be unset */
 			wait_for_ctrl_irq (ctrl);
 			wait_for_ctrl_irq (ctrl);
 
 
-			up(&ctrl->crit_sect);
+			mutex_unlock(&ctrl->crit_sect);
 		}
 		}
 
 
 	}
 	}
@@ -1488,7 +1440,7 @@ static u32 board_added(struct pci_func *func, struct controller *ctrl)
 	dbg("%s: func->device, slot_offset, hp_slot = %d, %d ,%d\n",
 	dbg("%s: func->device, slot_offset, hp_slot = %d, %d ,%d\n",
 	    __FUNCTION__, func->device, ctrl->slot_device_offset, hp_slot);
 	    __FUNCTION__, func->device, ctrl->slot_device_offset, hp_slot);
 
 
-	down(&ctrl->crit_sect);
+	mutex_lock(&ctrl->crit_sect);
 
 
 	/* turn on board without attaching to the bus */
 	/* turn on board without attaching to the bus */
 	enable_slot_power(ctrl, hp_slot);
 	enable_slot_power(ctrl, hp_slot);
@@ -1522,7 +1474,7 @@ static u32 board_added(struct pci_func *func, struct controller *ctrl)
 	/* Wait for SOBS to be unset */
 	/* Wait for SOBS to be unset */
 	wait_for_ctrl_irq(ctrl);
 	wait_for_ctrl_irq(ctrl);
 
 
-	up(&ctrl->crit_sect);
+	mutex_unlock(&ctrl->crit_sect);
 
 
 	if (rc)
 	if (rc)
 		return rc;
 		return rc;
@@ -1532,7 +1484,7 @@ static u32 board_added(struct pci_func *func, struct controller *ctrl)
 	/* turn on board and blink green LED */
 	/* turn on board and blink green LED */
 
 
 	dbg("%s: before down\n", __FUNCTION__);
 	dbg("%s: before down\n", __FUNCTION__);
-	down(&ctrl->crit_sect);
+	mutex_lock(&ctrl->crit_sect);
 	dbg("%s: after down\n", __FUNCTION__);
 	dbg("%s: after down\n", __FUNCTION__);
 
 
 	dbg("%s: before slot_enable\n", __FUNCTION__);
 	dbg("%s: before slot_enable\n", __FUNCTION__);
@@ -1553,7 +1505,7 @@ static u32 board_added(struct pci_func *func, struct controller *ctrl)
 	dbg("%s: after wait_for_ctrl_irq\n", __FUNCTION__);
 	dbg("%s: after wait_for_ctrl_irq\n", __FUNCTION__);
 
 
 	dbg("%s: before up\n", __FUNCTION__);
 	dbg("%s: before up\n", __FUNCTION__);
-	up(&ctrl->crit_sect);
+	mutex_unlock(&ctrl->crit_sect);
 	dbg("%s: after up\n", __FUNCTION__);
 	dbg("%s: after up\n", __FUNCTION__);
 
 
 	/* Wait for ~1 second because of hot plug spec */
 	/* Wait for ~1 second because of hot plug spec */
@@ -1607,7 +1559,7 @@ static u32 board_added(struct pci_func *func, struct controller *ctrl)
 		cpqhp_resource_sort_and_combine(&(ctrl->bus_head));
 		cpqhp_resource_sort_and_combine(&(ctrl->bus_head));
 
 
 		if (rc) {
 		if (rc) {
-			down(&ctrl->crit_sect);
+			mutex_lock(&ctrl->crit_sect);
 
 
 			amber_LED_on (ctrl, hp_slot);
 			amber_LED_on (ctrl, hp_slot);
 			green_LED_off (ctrl, hp_slot);
 			green_LED_off (ctrl, hp_slot);
@@ -1618,7 +1570,7 @@ static u32 board_added(struct pci_func *func, struct controller *ctrl)
 			/* Wait for SOBS to be unset */
 			/* Wait for SOBS to be unset */
 			wait_for_ctrl_irq (ctrl);
 			wait_for_ctrl_irq (ctrl);
 
 
-			up(&ctrl->crit_sect);
+			mutex_unlock(&ctrl->crit_sect);
 			return rc;
 			return rc;
 		} else {
 		} else {
 			cpqhp_save_slot_config(ctrl, func);
 			cpqhp_save_slot_config(ctrl, func);
@@ -1640,7 +1592,7 @@ static u32 board_added(struct pci_func *func, struct controller *ctrl)
 			}
 			}
 		} while (new_slot);
 		} while (new_slot);
 
 
-		down(&ctrl->crit_sect);
+		mutex_lock(&ctrl->crit_sect);
 
 
 		green_LED_on (ctrl, hp_slot);
 		green_LED_on (ctrl, hp_slot);
 
 
@@ -1649,9 +1601,9 @@ static u32 board_added(struct pci_func *func, struct controller *ctrl)
 		/* Wait for SOBS to be unset */
 		/* Wait for SOBS to be unset */
 		wait_for_ctrl_irq (ctrl);
 		wait_for_ctrl_irq (ctrl);
 
 
-		up(&ctrl->crit_sect);
+		mutex_unlock(&ctrl->crit_sect);
 	} else {
 	} else {
-		down(&ctrl->crit_sect);
+		mutex_lock(&ctrl->crit_sect);
 
 
 		amber_LED_on (ctrl, hp_slot);
 		amber_LED_on (ctrl, hp_slot);
 		green_LED_off (ctrl, hp_slot);
 		green_LED_off (ctrl, hp_slot);
@@ -1662,7 +1614,7 @@ static u32 board_added(struct pci_func *func, struct controller *ctrl)
 		/* Wait for SOBS to be unset */
 		/* Wait for SOBS to be unset */
 		wait_for_ctrl_irq (ctrl);
 		wait_for_ctrl_irq (ctrl);
 
 
-		up(&ctrl->crit_sect);
+		mutex_unlock(&ctrl->crit_sect);
 
 
 		return rc;
 		return rc;
 	}
 	}
@@ -1721,7 +1673,7 @@ static u32 remove_board(struct pci_func * func, u32 replace_flag, struct control
 		func->status = 0x01;
 		func->status = 0x01;
 	func->configured = 0;
 	func->configured = 0;
 
 
-	down(&ctrl->crit_sect);
+	mutex_lock(&ctrl->crit_sect);
 
 
 	green_LED_off (ctrl, hp_slot);
 	green_LED_off (ctrl, hp_slot);
 	slot_disable (ctrl, hp_slot);
 	slot_disable (ctrl, hp_slot);
@@ -1736,7 +1688,7 @@ static u32 remove_board(struct pci_func * func, u32 replace_flag, struct control
 	/* Wait for SOBS to be unset */
 	/* Wait for SOBS to be unset */
 	wait_for_ctrl_irq (ctrl);
 	wait_for_ctrl_irq (ctrl);
 
 
-	up(&ctrl->crit_sect);
+	mutex_unlock(&ctrl->crit_sect);
 
 
 	if (!replace_flag && ctrl->add_support) {
 	if (!replace_flag && ctrl->add_support) {
 		while (func) {
 		while (func) {
@@ -1899,7 +1851,7 @@ static void interrupt_event_handler(struct controller *ctrl)
 					dbg("button cancel\n");
 					dbg("button cancel\n");
 					del_timer(&p_slot->task_event);
 					del_timer(&p_slot->task_event);
 
 
-					down(&ctrl->crit_sect);
+					mutex_lock(&ctrl->crit_sect);
 
 
 					if (p_slot->state == BLINKINGOFF_STATE) {
 					if (p_slot->state == BLINKINGOFF_STATE) {
 						/* slot is on */
 						/* slot is on */
@@ -1922,7 +1874,7 @@ static void interrupt_event_handler(struct controller *ctrl)
 					/* Wait for SOBS to be unset */
 					/* Wait for SOBS to be unset */
 					wait_for_ctrl_irq (ctrl);
 					wait_for_ctrl_irq (ctrl);
 
 
-					up(&ctrl->crit_sect);
+					mutex_unlock(&ctrl->crit_sect);
 				}
 				}
 				/*** button Released (No action on press...) */
 				/*** button Released (No action on press...) */
 				else if (ctrl->event_queue[loop].event_type == INT_BUTTON_RELEASE) {
 				else if (ctrl->event_queue[loop].event_type == INT_BUTTON_RELEASE) {
@@ -1937,7 +1889,7 @@ static void interrupt_event_handler(struct controller *ctrl)
 						p_slot->state = BLINKINGON_STATE;
 						p_slot->state = BLINKINGON_STATE;
 						info(msg_button_on, p_slot->number);
 						info(msg_button_on, p_slot->number);
 					}
 					}
-					down(&ctrl->crit_sect);
+					mutex_lock(&ctrl->crit_sect);
 					
 					
 					dbg("blink green LED and turn off amber\n");
 					dbg("blink green LED and turn off amber\n");
 					
 					
@@ -1949,7 +1901,7 @@ static void interrupt_event_handler(struct controller *ctrl)
 					/* Wait for SOBS to be unset */
 					/* Wait for SOBS to be unset */
 					wait_for_ctrl_irq (ctrl);
 					wait_for_ctrl_irq (ctrl);
 
 
-					up(&ctrl->crit_sect);
+					mutex_unlock(&ctrl->crit_sect);
 					init_timer(&p_slot->task_event);
 					init_timer(&p_slot->task_event);
 					p_slot->hp_slot = hp_slot;
 					p_slot->hp_slot = hp_slot;
 					p_slot->ctrl = ctrl;
 					p_slot->ctrl = ctrl;

+ 3 - 6
drivers/pci/hotplug/fakephp.c

@@ -95,15 +95,13 @@ static int add_slot(struct pci_dev *dev)
 	struct hotplug_slot *slot;
 	struct hotplug_slot *slot;
 	int retval = -ENOMEM;
 	int retval = -ENOMEM;
 
 
-	slot = kmalloc(sizeof(struct hotplug_slot), GFP_KERNEL);
+	slot = kzalloc(sizeof(struct hotplug_slot), GFP_KERNEL);
 	if (!slot)
 	if (!slot)
 		goto error;
 		goto error;
-	memset(slot, 0, sizeof(*slot));
 
 
-	slot->info = kmalloc(sizeof(struct hotplug_slot_info), GFP_KERNEL);
+	slot->info = kzalloc(sizeof(struct hotplug_slot_info), GFP_KERNEL);
 	if (!slot->info)
 	if (!slot->info)
 		goto error_slot;
 		goto error_slot;
-	memset(slot->info, 0, sizeof(struct hotplug_slot_info));
 
 
 	slot->info->power_status = 1;
 	slot->info->power_status = 1;
 	slot->info->max_bus_speed = PCI_SPEED_UNKNOWN;
 	slot->info->max_bus_speed = PCI_SPEED_UNKNOWN;
@@ -227,11 +225,10 @@ static void pci_rescan_bus(const struct pci_bus *bus)
 {
 {
 	unsigned int devfn;
 	unsigned int devfn;
 	struct pci_dev *dev;
 	struct pci_dev *dev;
-	dev = kmalloc(sizeof(struct pci_dev), GFP_KERNEL);
+	dev = kzalloc(sizeof(struct pci_dev), GFP_KERNEL);
 	if (!dev)
 	if (!dev)
 		return;
 		return;
 
 
-	memset(dev, 0, sizeof(dev));
 	dev->bus = (struct pci_bus*)bus;
 	dev->bus = (struct pci_bus*)bus;
 	dev->sysdata = bus->sysdata;
 	dev->sysdata = bus->sysdata;
 	for (devfn = 0; devfn < 0x100; devfn += 8) {
 	for (devfn = 0; devfn < 0x100; devfn += 8) {

+ 0 - 2
drivers/pci/hotplug/ibmphp.h

@@ -406,8 +406,6 @@ extern void ibmphp_hpc_stop_poll_thread (void);
 //----------------------------------------------------------------------------
 //----------------------------------------------------------------------------
 // HPC return codes
 // HPC return codes
 //----------------------------------------------------------------------------
 //----------------------------------------------------------------------------
-#define FALSE				0x00
-#define TRUE				0x01
 #define HPC_ERROR			0xFF
 #define HPC_ERROR			0xFF
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------

+ 4 - 6
drivers/pci/hotplug/ibmphp_core.c

@@ -1141,7 +1141,7 @@ static int enable_slot(struct hotplug_slot *hs)
 		goto error_power;
 		goto error_power;
 	}
 	}
 
 
-	slot_cur->func = kmalloc(sizeof(struct pci_func), GFP_KERNEL);
+	slot_cur->func = kzalloc(sizeof(struct pci_func), GFP_KERNEL);
 	if (!slot_cur->func) {
 	if (!slot_cur->func) {
 		/* We cannot do update_slot_info here, since no memory for
 		/* We cannot do update_slot_info here, since no memory for
 		 * kmalloc n.e.ways, and update_slot_info allocates some */
 		 * kmalloc n.e.ways, and update_slot_info allocates some */
@@ -1149,7 +1149,6 @@ static int enable_slot(struct hotplug_slot *hs)
 		rc = -ENOMEM;
 		rc = -ENOMEM;
 		goto error_power;
 		goto error_power;
 	}
 	}
-	memset(slot_cur->func, 0, sizeof(struct pci_func));
 	slot_cur->func->busno = slot_cur->bus;
 	slot_cur->func->busno = slot_cur->bus;
 	slot_cur->func->device = slot_cur->device;
 	slot_cur->func->device = slot_cur->device;
 	for (i = 0; i < 4; i++)
 	for (i = 0; i < 4; i++)
@@ -1240,9 +1239,9 @@ int ibmphp_do_disable_slot(struct slot *slot_cur)
 	}
 	}
 	
 	
 	flag = slot_cur->flag;
 	flag = slot_cur->flag;
-	slot_cur->flag = TRUE;
+	slot_cur->flag = 1;
 
 
-	if (flag == TRUE) {
+	if (flag == 1) {
 		rc = validate(slot_cur, DISABLE);
 		rc = validate(slot_cur, DISABLE);
 			/* checking if powered off already & valid slot # */
 			/* checking if powered off already & valid slot # */
 		if (rc)
 		if (rc)
@@ -1252,13 +1251,12 @@ int ibmphp_do_disable_slot(struct slot *slot_cur)
 
 
 	if (slot_cur->func == NULL) {
 	if (slot_cur->func == NULL) {
 		/* We need this for fncs's that were there on bootup */
 		/* We need this for fncs's that were there on bootup */
-		slot_cur->func = kmalloc(sizeof(struct pci_func), GFP_KERNEL);
+		slot_cur->func = kzalloc(sizeof(struct pci_func), GFP_KERNEL);
 		if (!slot_cur->func) {
 		if (!slot_cur->func) {
 			err("out of system memory\n");
 			err("out of system memory\n");
 			rc = -ENOMEM;
 			rc = -ENOMEM;
 			goto error;
 			goto error;
 		}
 		}
-		memset(slot_cur->func, 0, sizeof(struct pci_func));
 		slot_cur->func->busno = slot_cur->bus;
 		slot_cur->func->busno = slot_cur->bus;
 		slot_cur->func->device = slot_cur->device;
 		slot_cur->func->device = slot_cur->device;
 	}
 	}

+ 15 - 44
drivers/pci/hotplug/ibmphp_ebda.c

@@ -72,13 +72,7 @@ static int ebda_rio_table (void);
 
 
 static struct ebda_hpc_list * __init alloc_ebda_hpc_list (void)
 static struct ebda_hpc_list * __init alloc_ebda_hpc_list (void)
 {
 {
-	struct ebda_hpc_list *list;
-
-	list = kmalloc (sizeof (struct ebda_hpc_list), GFP_KERNEL);
-	if (!list)
-		return NULL;
-	memset (list, 0, sizeof (*list));
-	return list;
+	return kzalloc(sizeof(struct ebda_hpc_list), GFP_KERNEL);
 }
 }
 
 
 static struct controller *alloc_ebda_hpc (u32 slot_count, u32 bus_count)
 static struct controller *alloc_ebda_hpc (u32 slot_count, u32 bus_count)
@@ -87,21 +81,18 @@ static struct controller *alloc_ebda_hpc (u32 slot_count, u32 bus_count)
 	struct ebda_hpc_slot *slots;
 	struct ebda_hpc_slot *slots;
 	struct ebda_hpc_bus *buses;
 	struct ebda_hpc_bus *buses;
 
 
-	controller = kmalloc (sizeof (struct controller), GFP_KERNEL);
+	controller = kzalloc(sizeof(struct controller), GFP_KERNEL);
 	if (!controller)
 	if (!controller)
 		goto error;
 		goto error;
-	memset (controller, 0, sizeof (*controller));
 
 
-	slots = kmalloc (sizeof (struct ebda_hpc_slot) * slot_count, GFP_KERNEL);
+	slots = kcalloc(slot_count, sizeof(struct ebda_hpc_slot), GFP_KERNEL);
 	if (!slots)
 	if (!slots)
 		goto error_contr;
 		goto error_contr;
-	memset (slots, 0, sizeof (*slots) * slot_count);
 	controller->slots = slots;
 	controller->slots = slots;
 
 
-	buses = kmalloc (sizeof (struct ebda_hpc_bus) * bus_count, GFP_KERNEL);
+	buses = kcalloc(bus_count, sizeof(struct ebda_hpc_bus), GFP_KERNEL);
 	if (!buses)
 	if (!buses)
 		goto error_slots;
 		goto error_slots;
-	memset (buses, 0, sizeof (*buses) * bus_count);
 	controller->buses = buses;
 	controller->buses = buses;
 
 
 	return controller;
 	return controller;
@@ -122,24 +113,12 @@ static void free_ebda_hpc (struct controller *controller)
 
 
 static struct ebda_rsrc_list * __init alloc_ebda_rsrc_list (void)
 static struct ebda_rsrc_list * __init alloc_ebda_rsrc_list (void)
 {
 {
-	struct ebda_rsrc_list *list;
-
-	list = kmalloc (sizeof (struct ebda_rsrc_list), GFP_KERNEL);
-	if (!list)
-		return NULL;
-	memset (list, 0, sizeof (*list));
-	return list;
+	return kzalloc(sizeof(struct ebda_rsrc_list), GFP_KERNEL);
 }
 }
 
 
 static struct ebda_pci_rsrc *alloc_ebda_pci_rsrc (void)
 static struct ebda_pci_rsrc *alloc_ebda_pci_rsrc (void)
 {
 {
-	struct ebda_pci_rsrc *resource;
-
-	resource = kmalloc (sizeof (struct ebda_pci_rsrc), GFP_KERNEL);
-	if (!resource)
-		return NULL;
-	memset (resource, 0, sizeof (*resource));
-	return resource;
+	return kzalloc(sizeof(struct ebda_pci_rsrc), GFP_KERNEL);
 }
 }
 
 
 static void __init print_bus_info (void)
 static void __init print_bus_info (void)
@@ -390,10 +369,9 @@ int __init ibmphp_access_ebda (void)
 			debug ("now enter io table ---\n");
 			debug ("now enter io table ---\n");
 			debug ("rio blk id: %x\n", blk_id);
 			debug ("rio blk id: %x\n", blk_id);
 
 
-			rio_table_ptr = kmalloc (sizeof (struct rio_table_hdr), GFP_KERNEL);
+			rio_table_ptr = kzalloc(sizeof(struct rio_table_hdr), GFP_KERNEL);
 			if (!rio_table_ptr)
 			if (!rio_table_ptr)
 				return -ENOMEM; 
 				return -ENOMEM; 
-			memset (rio_table_ptr, 0, sizeof (struct rio_table_hdr) );
 			rio_table_ptr->ver_num = readb (io_mem + offset);
 			rio_table_ptr->ver_num = readb (io_mem + offset);
 			rio_table_ptr->scal_count = readb (io_mem + offset + 1);
 			rio_table_ptr->scal_count = readb (io_mem + offset + 1);
 			rio_table_ptr->riodev_count = readb (io_mem + offset + 2);
 			rio_table_ptr->riodev_count = readb (io_mem + offset + 2);
@@ -445,10 +423,9 @@ static int __init ebda_rio_table (void)
 
 
 	// we do concern about rio details
 	// we do concern about rio details
 	for (i = 0; i < rio_table_ptr->riodev_count; i++) {
 	for (i = 0; i < rio_table_ptr->riodev_count; i++) {
-		rio_detail_ptr = kmalloc (sizeof (struct rio_detail), GFP_KERNEL);
+		rio_detail_ptr = kzalloc(sizeof(struct rio_detail), GFP_KERNEL);
 		if (!rio_detail_ptr)
 		if (!rio_detail_ptr)
 			return -ENOMEM;
 			return -ENOMEM;
-		memset (rio_detail_ptr, 0, sizeof (struct rio_detail));
 		rio_detail_ptr->rio_node_id = readb (io_mem + offset);
 		rio_detail_ptr->rio_node_id = readb (io_mem + offset);
 		rio_detail_ptr->bbar = readl (io_mem + offset + 1);
 		rio_detail_ptr->bbar = readl (io_mem + offset + 1);
 		rio_detail_ptr->rio_type = readb (io_mem + offset + 5);
 		rio_detail_ptr->rio_type = readb (io_mem + offset + 5);
@@ -503,10 +480,9 @@ static int __init combine_wpg_for_chassis (void)
 		rio_detail_ptr = list_entry (list_head_ptr, struct rio_detail, rio_detail_list);
 		rio_detail_ptr = list_entry (list_head_ptr, struct rio_detail, rio_detail_list);
 		opt_rio_ptr = search_opt_vg (rio_detail_ptr->chassis_num);
 		opt_rio_ptr = search_opt_vg (rio_detail_ptr->chassis_num);
 		if (!opt_rio_ptr) {
 		if (!opt_rio_ptr) {
-			opt_rio_ptr = (struct opt_rio *) kmalloc (sizeof (struct opt_rio), GFP_KERNEL);
+			opt_rio_ptr = kzalloc(sizeof(struct opt_rio), GFP_KERNEL);
 			if (!opt_rio_ptr)
 			if (!opt_rio_ptr)
 				return -ENOMEM;
 				return -ENOMEM;
-			memset (opt_rio_ptr, 0, sizeof (struct opt_rio));
 			opt_rio_ptr->rio_type = rio_detail_ptr->rio_type;
 			opt_rio_ptr->rio_type = rio_detail_ptr->rio_type;
 			opt_rio_ptr->chassis_num = rio_detail_ptr->chassis_num;
 			opt_rio_ptr->chassis_num = rio_detail_ptr->chassis_num;
 			opt_rio_ptr->first_slot_num = rio_detail_ptr->first_slot_num;
 			opt_rio_ptr->first_slot_num = rio_detail_ptr->first_slot_num;
@@ -546,10 +522,9 @@ static int combine_wpg_for_expansion (void)
 		rio_detail_ptr = list_entry (list_head_ptr, struct rio_detail, rio_detail_list);
 		rio_detail_ptr = list_entry (list_head_ptr, struct rio_detail, rio_detail_list);
 		opt_rio_lo_ptr = search_opt_lo (rio_detail_ptr->chassis_num);
 		opt_rio_lo_ptr = search_opt_lo (rio_detail_ptr->chassis_num);
 		if (!opt_rio_lo_ptr) {
 		if (!opt_rio_lo_ptr) {
-			opt_rio_lo_ptr = (struct opt_rio_lo *) kmalloc (sizeof (struct opt_rio_lo), GFP_KERNEL);
+			opt_rio_lo_ptr = kzalloc(sizeof(struct opt_rio_lo), GFP_KERNEL);
 			if (!opt_rio_lo_ptr)
 			if (!opt_rio_lo_ptr)
 				return -ENOMEM;
 				return -ENOMEM;
-			memset (opt_rio_lo_ptr, 0, sizeof (struct opt_rio_lo));
 			opt_rio_lo_ptr->rio_type = rio_detail_ptr->rio_type;
 			opt_rio_lo_ptr->rio_type = rio_detail_ptr->rio_type;
 			opt_rio_lo_ptr->chassis_num = rio_detail_ptr->chassis_num;
 			opt_rio_lo_ptr->chassis_num = rio_detail_ptr->chassis_num;
 			opt_rio_lo_ptr->first_slot_num = rio_detail_ptr->first_slot_num;
 			opt_rio_lo_ptr->first_slot_num = rio_detail_ptr->first_slot_num;
@@ -842,12 +817,11 @@ static int __init ebda_rsrc_controller (void)
 
 
 			bus_info_ptr2 = ibmphp_find_same_bus_num (slot_ptr->slot_bus_num);
 			bus_info_ptr2 = ibmphp_find_same_bus_num (slot_ptr->slot_bus_num);
 			if (!bus_info_ptr2) {
 			if (!bus_info_ptr2) {
-				bus_info_ptr1 = (struct bus_info *) kmalloc (sizeof (struct bus_info), GFP_KERNEL);
+				bus_info_ptr1 = kzalloc(sizeof(struct bus_info), GFP_KERNEL);
 				if (!bus_info_ptr1) {
 				if (!bus_info_ptr1) {
 					rc = -ENOMEM;
 					rc = -ENOMEM;
 					goto error_no_hp_slot;
 					goto error_no_hp_slot;
 				}
 				}
-				memset (bus_info_ptr1, 0, sizeof (struct bus_info));
 				bus_info_ptr1->slot_min = slot_ptr->slot_num;
 				bus_info_ptr1->slot_min = slot_ptr->slot_num;
 				bus_info_ptr1->slot_max = slot_ptr->slot_num;
 				bus_info_ptr1->slot_max = slot_ptr->slot_num;
 				bus_info_ptr1->slot_count += 1;
 				bus_info_ptr1->slot_count += 1;
@@ -946,19 +920,17 @@ static int __init ebda_rsrc_controller (void)
 		// register slots with hpc core as well as create linked list of ibm slot
 		// register slots with hpc core as well as create linked list of ibm slot
 		for (index = 0; index < hpc_ptr->slot_count; index++) {
 		for (index = 0; index < hpc_ptr->slot_count; index++) {
 
 
-			hp_slot_ptr = kmalloc(sizeof(*hp_slot_ptr), GFP_KERNEL);
+			hp_slot_ptr = kzalloc(sizeof(*hp_slot_ptr), GFP_KERNEL);
 			if (!hp_slot_ptr) {
 			if (!hp_slot_ptr) {
 				rc = -ENOMEM;
 				rc = -ENOMEM;
 				goto error_no_hp_slot;
 				goto error_no_hp_slot;
 			}
 			}
-			memset(hp_slot_ptr, 0, sizeof(*hp_slot_ptr));
 
 
-			hp_slot_ptr->info = kmalloc (sizeof(struct hotplug_slot_info), GFP_KERNEL);
+			hp_slot_ptr->info = kzalloc(sizeof(struct hotplug_slot_info), GFP_KERNEL);
 			if (!hp_slot_ptr->info) {
 			if (!hp_slot_ptr->info) {
 				rc = -ENOMEM;
 				rc = -ENOMEM;
 				goto error_no_hp_info;
 				goto error_no_hp_info;
 			}
 			}
-			memset(hp_slot_ptr->info, 0, sizeof(struct hotplug_slot_info));
 
 
 			hp_slot_ptr->name = kmalloc(30, GFP_KERNEL);
 			hp_slot_ptr->name = kmalloc(30, GFP_KERNEL);
 			if (!hp_slot_ptr->name) {
 			if (!hp_slot_ptr->name) {
@@ -966,14 +938,13 @@ static int __init ebda_rsrc_controller (void)
 				goto error_no_hp_name;
 				goto error_no_hp_name;
 			}
 			}
 
 
-			tmp_slot = kmalloc(sizeof(*tmp_slot), GFP_KERNEL);
+			tmp_slot = kzalloc(sizeof(*tmp_slot), GFP_KERNEL);
 			if (!tmp_slot) {
 			if (!tmp_slot) {
 				rc = -ENOMEM;
 				rc = -ENOMEM;
 				goto error_no_slot;
 				goto error_no_slot;
 			}
 			}
-			memset(tmp_slot, 0, sizeof(*tmp_slot));
 
 
-			tmp_slot->flag = TRUE;
+			tmp_slot->flag = 1;
 
 
 			tmp_slot->capabilities = hpc_ptr->slots[index].slot_cap;
 			tmp_slot->capabilities = hpc_ptr->slots[index].slot_cap;
 			if ((hpc_ptr->slots[index].slot_cap & EBDA_SLOT_133_MAX) == EBDA_SLOT_133_MAX)
 			if ((hpc_ptr->slots[index].slot_cap & EBDA_SLOT_133_MAX) == EBDA_SLOT_133_MAX)

+ 33 - 31
drivers/pci/hotplug/ibmphp_hpc.c

@@ -34,9 +34,11 @@
 #include <linux/pci.h>
 #include <linux/pci.h>
 #include <linux/smp_lock.h>
 #include <linux/smp_lock.h>
 #include <linux/init.h>
 #include <linux/init.h>
+#include <linux/mutex.h>
+
 #include "ibmphp.h"
 #include "ibmphp.h"
 
 
-static int to_debug = FALSE;
+static int to_debug = 0;
 #define debug_polling(fmt, arg...)	do { if (to_debug) debug (fmt, arg); } while (0)
 #define debug_polling(fmt, arg...)	do { if (to_debug) debug (fmt, arg); } while (0)
 
 
 //----------------------------------------------------------------------------
 //----------------------------------------------------------------------------
@@ -93,15 +95,15 @@ static int to_debug = FALSE;
 //----------------------------------------------------------------------------
 //----------------------------------------------------------------------------
 // macro utilities
 // macro utilities
 //----------------------------------------------------------------------------
 //----------------------------------------------------------------------------
-// if bits 20,22,25,26,27,29,30 are OFF return TRUE
-#define HPC_I2CSTATUS_CHECK(s)	((u8)((s & 0x00000A76) ? FALSE : TRUE))
+// if bits 20,22,25,26,27,29,30 are OFF return 1
+#define HPC_I2CSTATUS_CHECK(s)	((u8)((s & 0x00000A76) ? 0 : 1))
 
 
 //----------------------------------------------------------------------------
 //----------------------------------------------------------------------------
 // global variables
 // global variables
 //----------------------------------------------------------------------------
 //----------------------------------------------------------------------------
 static int ibmphp_shutdown;
 static int ibmphp_shutdown;
 static int tid_poll;
 static int tid_poll;
-static struct semaphore sem_hpcaccess;	// lock access to HPC
+static struct mutex sem_hpcaccess;	// lock access to HPC
 static struct semaphore semOperations;	// lock all operations and
 static struct semaphore semOperations;	// lock all operations and
 					// access to data structures
 					// access to data structures
 static struct semaphore sem_exit;	// make sure polling thread goes away
 static struct semaphore sem_exit;	// make sure polling thread goes away
@@ -131,11 +133,11 @@ void __init ibmphp_hpc_initvars (void)
 {
 {
 	debug ("%s - Entry\n", __FUNCTION__);
 	debug ("%s - Entry\n", __FUNCTION__);
 
 
-	init_MUTEX (&sem_hpcaccess);
+	mutex_init(&sem_hpcaccess);
 	init_MUTEX (&semOperations);
 	init_MUTEX (&semOperations);
 	init_MUTEX_LOCKED (&sem_exit);
 	init_MUTEX_LOCKED (&sem_exit);
-	to_debug = FALSE;
-	ibmphp_shutdown = FALSE;
+	to_debug = 0;
+	ibmphp_shutdown = 0;
 	tid_poll = 0;
 	tid_poll = 0;
 
 
 	debug ("%s - Exit\n", __FUNCTION__);
 	debug ("%s - Exit\n", __FUNCTION__);
@@ -737,21 +739,21 @@ int ibmphp_hpc_writeslot (struct slot * pslot, u8 cmd)
 		// check controller is still not working on the command
 		// check controller is still not working on the command
 		//--------------------------------------------------------------------
 		//--------------------------------------------------------------------
 		timeout = CMD_COMPLETE_TOUT_SEC;
 		timeout = CMD_COMPLETE_TOUT_SEC;
-		done = FALSE;
+		done = 0;
 		while (!done) {
 		while (!done) {
 			rc = hpc_wait_ctlr_notworking (HPC_CTLR_WORKING_TOUT, ctlr_ptr, wpg_bbar,
 			rc = hpc_wait_ctlr_notworking (HPC_CTLR_WORKING_TOUT, ctlr_ptr, wpg_bbar,
 							&status);
 							&status);
 			if (!rc) {
 			if (!rc) {
 				if (NEEDTOCHECK_CMDSTATUS (cmd)) {
 				if (NEEDTOCHECK_CMDSTATUS (cmd)) {
 					if (CTLR_FINISHED (status) == HPC_CTLR_FINISHED_YES)
 					if (CTLR_FINISHED (status) == HPC_CTLR_FINISHED_YES)
-						done = TRUE;
+						done = 1;
 				} else
 				} else
-					done = TRUE;
+					done = 1;
 			}
 			}
 			if (!done) {
 			if (!done) {
 				msleep(1000);
 				msleep(1000);
 				if (timeout < 1) {
 				if (timeout < 1) {
-					done = TRUE;
+					done = 1;
 					err ("%s - Error command complete timeout\n", __FUNCTION__);
 					err ("%s - Error command complete timeout\n", __FUNCTION__);
 					rc = -EFAULT;
 					rc = -EFAULT;
 				} else
 				} else
@@ -778,7 +780,7 @@ int ibmphp_hpc_writeslot (struct slot * pslot, u8 cmd)
 *---------------------------------------------------------------------*/
 *---------------------------------------------------------------------*/
 static void get_hpc_access (void)
 static void get_hpc_access (void)
 {
 {
-	down (&sem_hpcaccess);
+	mutex_lock(&sem_hpcaccess);
 }
 }
 
 
 /*----------------------------------------------------------------------
 /*----------------------------------------------------------------------
@@ -786,7 +788,7 @@ static void get_hpc_access (void)
 *---------------------------------------------------------------------*/
 *---------------------------------------------------------------------*/
 void free_hpc_access (void)
 void free_hpc_access (void)
 {
 {
-	up (&sem_hpcaccess);
+	mutex_unlock(&sem_hpcaccess);
 }
 }
 
 
 /*----------------------------------------------------------------------
 /*----------------------------------------------------------------------
@@ -797,7 +799,7 @@ void free_hpc_access (void)
 void ibmphp_lock_operations (void)
 void ibmphp_lock_operations (void)
 {
 {
 	down (&semOperations);
 	down (&semOperations);
-	to_debug = TRUE;
+	to_debug = 1;
 }
 }
 
 
 /*----------------------------------------------------------------------
 /*----------------------------------------------------------------------
@@ -807,7 +809,7 @@ void ibmphp_unlock_operations (void)
 {
 {
 	debug ("%s - Entry\n", __FUNCTION__);
 	debug ("%s - Entry\n", __FUNCTION__);
 	up (&semOperations);
 	up (&semOperations);
-	to_debug = FALSE;
+	to_debug = 0;
 	debug ("%s - Exit\n", __FUNCTION__);
 	debug ("%s - Exit\n", __FUNCTION__);
 }
 }
 
 
@@ -935,40 +937,40 @@ static int process_changeinstatus (struct slot *pslot, struct slot *poldslot)
 {
 {
 	u8 status;
 	u8 status;
 	int rc = 0;
 	int rc = 0;
-	u8 disable = FALSE;
-	u8 update = FALSE;
+	u8 disable = 0;
+	u8 update = 0;
 
 
 	debug ("process_changeinstatus - Entry pslot[%p], poldslot[%p]\n", pslot, poldslot);
 	debug ("process_changeinstatus - Entry pslot[%p], poldslot[%p]\n", pslot, poldslot);
 
 
 	// bit 0 - HPC_SLOT_POWER
 	// bit 0 - HPC_SLOT_POWER
 	if ((pslot->status & 0x01) != (poldslot->status & 0x01))
 	if ((pslot->status & 0x01) != (poldslot->status & 0x01))
-		update = TRUE;
+		update = 1;
 
 
 	// bit 1 - HPC_SLOT_CONNECT
 	// bit 1 - HPC_SLOT_CONNECT
 	// ignore
 	// ignore
 
 
 	// bit 2 - HPC_SLOT_ATTN
 	// bit 2 - HPC_SLOT_ATTN
 	if ((pslot->status & 0x04) != (poldslot->status & 0x04))
 	if ((pslot->status & 0x04) != (poldslot->status & 0x04))
-		update = TRUE;
+		update = 1;
 
 
 	// bit 3 - HPC_SLOT_PRSNT2
 	// bit 3 - HPC_SLOT_PRSNT2
 	// bit 4 - HPC_SLOT_PRSNT1
 	// bit 4 - HPC_SLOT_PRSNT1
 	if (((pslot->status & 0x08) != (poldslot->status & 0x08))
 	if (((pslot->status & 0x08) != (poldslot->status & 0x08))
 		|| ((pslot->status & 0x10) != (poldslot->status & 0x10)))
 		|| ((pslot->status & 0x10) != (poldslot->status & 0x10)))
-		update = TRUE;
+		update = 1;
 
 
 	// bit 5 - HPC_SLOT_PWRGD
 	// bit 5 - HPC_SLOT_PWRGD
 	if ((pslot->status & 0x20) != (poldslot->status & 0x20))
 	if ((pslot->status & 0x20) != (poldslot->status & 0x20))
 		// OFF -> ON: ignore, ON -> OFF: disable slot
 		// OFF -> ON: ignore, ON -> OFF: disable slot
 		if ((poldslot->status & 0x20) && (SLOT_CONNECT (poldslot->status) == HPC_SLOT_CONNECTED) && (SLOT_PRESENT (poldslot->status))) 
 		if ((poldslot->status & 0x20) && (SLOT_CONNECT (poldslot->status) == HPC_SLOT_CONNECTED) && (SLOT_PRESENT (poldslot->status))) 
-			disable = TRUE;
+			disable = 1;
 
 
 	// bit 6 - HPC_SLOT_BUS_SPEED
 	// bit 6 - HPC_SLOT_BUS_SPEED
 	// ignore
 	// ignore
 
 
 	// bit 7 - HPC_SLOT_LATCH
 	// bit 7 - HPC_SLOT_LATCH
 	if ((pslot->status & 0x80) != (poldslot->status & 0x80)) {
 	if ((pslot->status & 0x80) != (poldslot->status & 0x80)) {
-		update = TRUE;
+		update = 1;
 		// OPEN -> CLOSE
 		// OPEN -> CLOSE
 		if (pslot->status & 0x80) {
 		if (pslot->status & 0x80) {
 			if (SLOT_PWRGD (pslot->status)) {
 			if (SLOT_PWRGD (pslot->status)) {
@@ -977,7 +979,7 @@ static int process_changeinstatus (struct slot *pslot, struct slot *poldslot)
 				msleep(1000);
 				msleep(1000);
 				rc = ibmphp_hpc_readslot (pslot, READ_SLOTSTATUS, &status);
 				rc = ibmphp_hpc_readslot (pslot, READ_SLOTSTATUS, &status);
 				if (SLOT_PWRGD (status))
 				if (SLOT_PWRGD (status))
-					update = TRUE;
+					update = 1;
 				else	// overwrite power in pslot to OFF
 				else	// overwrite power in pslot to OFF
 					pslot->status &= ~HPC_SLOT_POWER;
 					pslot->status &= ~HPC_SLOT_POWER;
 			}
 			}
@@ -985,17 +987,17 @@ static int process_changeinstatus (struct slot *pslot, struct slot *poldslot)
 		// CLOSE -> OPEN 
 		// CLOSE -> OPEN 
 		else if ((SLOT_PWRGD (poldslot->status) == HPC_SLOT_PWRGD_GOOD)
 		else if ((SLOT_PWRGD (poldslot->status) == HPC_SLOT_PWRGD_GOOD)
 			&& (SLOT_CONNECT (poldslot->status) == HPC_SLOT_CONNECTED) && (SLOT_PRESENT (poldslot->status))) {
 			&& (SLOT_CONNECT (poldslot->status) == HPC_SLOT_CONNECTED) && (SLOT_PRESENT (poldslot->status))) {
-			disable = TRUE;
+			disable = 1;
 		}
 		}
 		// else - ignore
 		// else - ignore
 	}
 	}
 	// bit 4 - HPC_SLOT_BLINK_ATTN
 	// bit 4 - HPC_SLOT_BLINK_ATTN
 	if ((pslot->ext_status & 0x08) != (poldslot->ext_status & 0x08))
 	if ((pslot->ext_status & 0x08) != (poldslot->ext_status & 0x08))
-		update = TRUE;
+		update = 1;
 
 
 	if (disable) {
 	if (disable) {
 		debug ("process_changeinstatus - disable slot\n");
 		debug ("process_changeinstatus - disable slot\n");
-		pslot->flag = FALSE;
+		pslot->flag = 0;
 		rc = ibmphp_do_disable_slot (pslot);
 		rc = ibmphp_do_disable_slot (pslot);
 	}
 	}
 
 
@@ -1100,7 +1102,7 @@ void __exit ibmphp_hpc_stop_poll_thread (void)
 {
 {
 	debug ("%s - Entry\n", __FUNCTION__);
 	debug ("%s - Entry\n", __FUNCTION__);
 
 
-	ibmphp_shutdown = TRUE;
+	ibmphp_shutdown = 1;
 	debug ("before locking operations \n");
 	debug ("before locking operations \n");
 	ibmphp_lock_operations ();
 	ibmphp_lock_operations ();
 	debug ("after locking operations \n");
 	debug ("after locking operations \n");
@@ -1134,7 +1136,7 @@ static int hpc_wait_ctlr_notworking (int timeout, struct controller *ctlr_ptr, v
 				    u8 * pstatus)
 				    u8 * pstatus)
 {
 {
 	int rc = 0;
 	int rc = 0;
-	u8 done = FALSE;
+	u8 done = 0;
 
 
 	debug_polling ("hpc_wait_ctlr_notworking - Entry timeout[%d]\n", timeout);
 	debug_polling ("hpc_wait_ctlr_notworking - Entry timeout[%d]\n", timeout);
 
 
@@ -1142,14 +1144,14 @@ static int hpc_wait_ctlr_notworking (int timeout, struct controller *ctlr_ptr, v
 		*pstatus = ctrl_read (ctlr_ptr, wpg_bbar, WPG_CTLR_INDEX);
 		*pstatus = ctrl_read (ctlr_ptr, wpg_bbar, WPG_CTLR_INDEX);
 		if (*pstatus == HPC_ERROR) {
 		if (*pstatus == HPC_ERROR) {
 			rc = HPC_ERROR;
 			rc = HPC_ERROR;
-			done = TRUE;
+			done = 1;
 		}
 		}
 		if (CTLR_WORKING (*pstatus) == HPC_CTLR_WORKING_NO)
 		if (CTLR_WORKING (*pstatus) == HPC_CTLR_WORKING_NO)
-			done = TRUE;
+			done = 1;
 		if (!done) {
 		if (!done) {
 			msleep(1000);
 			msleep(1000);
 			if (timeout < 1) {
 			if (timeout < 1) {
-				done = TRUE;
+				done = 1;
 				err ("HPCreadslot - Error ctlr timeout\n");
 				err ("HPCreadslot - Error ctlr timeout\n");
 				rc = HPC_ERROR;
 				rc = HPC_ERROR;
 			} else
 			} else

+ 50 - 71
drivers/pci/hotplug/ibmphp_pci.c

@@ -164,12 +164,11 @@ int ibmphp_configure_card (struct pci_func *func, u8 slotno)
 						cleanup_count = 6;
 						cleanup_count = 6;
 						goto error;
 						goto error;
 					}
 					}
-					newfunc = kmalloc(sizeof(*newfunc), GFP_KERNEL);
+					newfunc = kzalloc(sizeof(*newfunc), GFP_KERNEL);
 					if (!newfunc) {
 					if (!newfunc) {
 						err ("out of system memory\n");
 						err ("out of system memory\n");
 						return -ENOMEM;
 						return -ENOMEM;
 					}
 					}
-					memset (newfunc, 0, sizeof (struct pci_func));
 					newfunc->busno = cur_func->busno;
 					newfunc->busno = cur_func->busno;
 					newfunc->device = device;
 					newfunc->device = device;
 					cur_func->next = newfunc;
 					cur_func->next = newfunc;
@@ -200,15 +199,14 @@ int ibmphp_configure_card (struct pci_func *func, u8 slotno)
 					}
 					}
 
 
 					pci_bus_read_config_byte (ibmphp_pci_bus, devfn, PCI_SECONDARY_BUS, &sec_number);
 					pci_bus_read_config_byte (ibmphp_pci_bus, devfn, PCI_SECONDARY_BUS, &sec_number);
-					flag = FALSE;
+					flag = 0;
 					for (i = 0; i < 32; i++) {
 					for (i = 0; i < 32; i++) {
 						if (func->devices[i]) {
 						if (func->devices[i]) {
-							newfunc = kmalloc(sizeof(*newfunc), GFP_KERNEL);
+							newfunc = kzalloc(sizeof(*newfunc), GFP_KERNEL);
 							if (!newfunc) {
 							if (!newfunc) {
 								err ("out of system memory\n");
 								err ("out of system memory\n");
 								return -ENOMEM;
 								return -ENOMEM;
 							}
 							}
-							memset (newfunc, 0, sizeof (struct pci_func));
 							newfunc->busno = sec_number;
 							newfunc->busno = sec_number;
 							newfunc->device = (u8) i;
 							newfunc->device = (u8) i;
 							for (j = 0; j < 4; j++)
 							for (j = 0; j < 4; j++)
@@ -228,16 +226,15 @@ int ibmphp_configure_card (struct pci_func *func, u8 slotno)
 								cleanup_count = 2;
 								cleanup_count = 2;
 								goto error;
 								goto error;
 							}
 							}
-							flag = TRUE;
+							flag = 1;
 						}
 						}
 					}
 					}
 
 
-					newfunc = kmalloc(sizeof(*newfunc), GFP_KERNEL);
+					newfunc = kzalloc(sizeof(*newfunc), GFP_KERNEL);
 					if (!newfunc) {
 					if (!newfunc) {
 						err ("out of system memory\n");
 						err ("out of system memory\n");
 						return -ENOMEM;
 						return -ENOMEM;
 					}
 					}
-					memset (newfunc, 0, sizeof (struct pci_func));
 					newfunc->busno = cur_func->busno;
 					newfunc->busno = cur_func->busno;
 					newfunc->device = device;
 					newfunc->device = device;
 					for (j = 0; j < 4; j++)
 					for (j = 0; j < 4; j++)
@@ -275,16 +272,15 @@ int ibmphp_configure_card (struct pci_func *func, u8 slotno)
 						cur_func->busno, device, function);
 						cur_func->busno, device, function);
 					pci_bus_read_config_byte (ibmphp_pci_bus, devfn, PCI_SECONDARY_BUS, &sec_number);
 					pci_bus_read_config_byte (ibmphp_pci_bus, devfn, PCI_SECONDARY_BUS, &sec_number);
 					debug ("after configuring bridge..., sec_number = %x\n", sec_number);
 					debug ("after configuring bridge..., sec_number = %x\n", sec_number);
-					flag = FALSE;
+					flag = 0;
 					for (i = 0; i < 32; i++) {
 					for (i = 0; i < 32; i++) {
 						if (func->devices[i]) {
 						if (func->devices[i]) {
 							debug ("inside for loop, device is %x\n", i);
 							debug ("inside for loop, device is %x\n", i);
-							newfunc = kmalloc(sizeof(*newfunc), GFP_KERNEL);
+							newfunc = kzalloc(sizeof(*newfunc), GFP_KERNEL);
 							if (!newfunc) {
 							if (!newfunc) {
 								err (" out of system memory\n");
 								err (" out of system memory\n");
 								return -ENOMEM;
 								return -ENOMEM;
 							}
 							}
-							memset (newfunc, 0, sizeof (struct pci_func));
 							newfunc->busno = sec_number;
 							newfunc->busno = sec_number;
 							newfunc->device = (u8) i;
 							newfunc->device = (u8) i;
 							for (j = 0; j < 4; j++)
 							for (j = 0; j < 4; j++)
@@ -305,7 +301,7 @@ int ibmphp_configure_card (struct pci_func *func, u8 slotno)
 								cleanup_count = 2;
 								cleanup_count = 2;
 								goto error;
 								goto error;
 							}
 							}
-							flag = TRUE;
+							flag = 1;
 						}
 						}
 					}
 					}
 
 
@@ -405,13 +401,12 @@ static int configure_device (struct pci_func *func)
 
 
 			debug ("len[count] in IO %x, count %d\n", len[count], count);
 			debug ("len[count] in IO %x, count %d\n", len[count], count);
 
 
-			io[count] = kmalloc (sizeof (struct resource_node), GFP_KERNEL);
+			io[count] = kzalloc(sizeof(struct resource_node), GFP_KERNEL);
 
 
 			if (!io[count]) {
 			if (!io[count]) {
 				err ("out of system memory\n");
 				err ("out of system memory\n");
 				return -ENOMEM;
 				return -ENOMEM;
 			}
 			}
-			memset (io[count], 0, sizeof (struct resource_node));
 			io[count]->type = IO;
 			io[count]->type = IO;
 			io[count]->busno = func->busno;
 			io[count]->busno = func->busno;
 			io[count]->devfunc = PCI_DEVFN(func->device, func->function);
 			io[count]->devfunc = PCI_DEVFN(func->device, func->function);
@@ -444,29 +439,27 @@ static int configure_device (struct pci_func *func)
 
 
 				debug ("len[count] in PFMEM %x, count %d\n", len[count], count);
 				debug ("len[count] in PFMEM %x, count %d\n", len[count], count);
 
 
-				pfmem[count] = kmalloc (sizeof (struct resource_node), GFP_KERNEL);
+				pfmem[count] = kzalloc(sizeof(struct resource_node), GFP_KERNEL);
 				if (!pfmem[count]) {
 				if (!pfmem[count]) {
 					err ("out of system memory\n");
 					err ("out of system memory\n");
 					return -ENOMEM;
 					return -ENOMEM;
 				}
 				}
-				memset (pfmem[count], 0, sizeof (struct resource_node));
 				pfmem[count]->type = PFMEM;
 				pfmem[count]->type = PFMEM;
 				pfmem[count]->busno = func->busno;
 				pfmem[count]->busno = func->busno;
 				pfmem[count]->devfunc = PCI_DEVFN(func->device,
 				pfmem[count]->devfunc = PCI_DEVFN(func->device,
 							func->function);
 							func->function);
 				pfmem[count]->len = len[count];
 				pfmem[count]->len = len[count];
-				pfmem[count]->fromMem = FALSE;
+				pfmem[count]->fromMem = 0;
 				if (ibmphp_check_resource (pfmem[count], 0) == 0) {
 				if (ibmphp_check_resource (pfmem[count], 0) == 0) {
 					ibmphp_add_resource (pfmem[count]);
 					ibmphp_add_resource (pfmem[count]);
 					func->pfmem[count] = pfmem[count];
 					func->pfmem[count] = pfmem[count];
 				} else {
 				} else {
-					mem_tmp = kmalloc(sizeof(*mem_tmp), GFP_KERNEL);
+					mem_tmp = kzalloc(sizeof(*mem_tmp), GFP_KERNEL);
 					if (!mem_tmp) {
 					if (!mem_tmp) {
 						err ("out of system memory\n");
 						err ("out of system memory\n");
 						kfree (pfmem[count]);
 						kfree (pfmem[count]);
 						return -ENOMEM;
 						return -ENOMEM;
 					}
 					}
-					memset (mem_tmp, 0, sizeof (struct resource_node));
 					mem_tmp->type = MEM;
 					mem_tmp->type = MEM;
 					mem_tmp->busno = pfmem[count]->busno;
 					mem_tmp->busno = pfmem[count]->busno;
 					mem_tmp->devfunc = pfmem[count]->devfunc;
 					mem_tmp->devfunc = pfmem[count]->devfunc;
@@ -474,7 +467,7 @@ static int configure_device (struct pci_func *func)
 					debug ("there's no pfmem... going into mem.\n");
 					debug ("there's no pfmem... going into mem.\n");
 					if (ibmphp_check_resource (mem_tmp, 0) == 0) {
 					if (ibmphp_check_resource (mem_tmp, 0) == 0) {
 						ibmphp_add_resource (mem_tmp);
 						ibmphp_add_resource (mem_tmp);
-						pfmem[count]->fromMem = TRUE;
+						pfmem[count]->fromMem = 1;
 						pfmem[count]->rangeno = mem_tmp->rangeno;
 						pfmem[count]->rangeno = mem_tmp->rangeno;
 						pfmem[count]->start = mem_tmp->start;
 						pfmem[count]->start = mem_tmp->start;
 						pfmem[count]->end = mem_tmp->end;
 						pfmem[count]->end = mem_tmp->end;
@@ -512,12 +505,11 @@ static int configure_device (struct pci_func *func)
 
 
 				debug ("len[count] in Mem %x, count %d\n", len[count], count);
 				debug ("len[count] in Mem %x, count %d\n", len[count], count);
 
 
-				mem[count] = kmalloc (sizeof (struct resource_node), GFP_KERNEL);
+				mem[count] = kzalloc(sizeof(struct resource_node), GFP_KERNEL);
 				if (!mem[count]) {
 				if (!mem[count]) {
 					err ("out of system memory\n");
 					err ("out of system memory\n");
 					return -ENOMEM;
 					return -ENOMEM;
 				}
 				}
-				memset (mem[count], 0, sizeof (struct resource_node));
 				mem[count]->type = MEM;
 				mem[count]->type = MEM;
 				mem[count]->busno = func->busno;
 				mem[count]->busno = func->busno;
 				mem[count]->devfunc = PCI_DEVFN(func->device,
 				mem[count]->devfunc = PCI_DEVFN(func->device,
@@ -579,11 +571,11 @@ static int configure_bridge (struct pci_func **func_passed, u8 slotno)
 	u16 pfmem_base;
 	u16 pfmem_base;
 	u32 bar[2];
 	u32 bar[2];
 	u32 len[2];
 	u32 len[2];
-	u8 flag_io = FALSE;
-	u8 flag_mem = FALSE;
-	u8 flag_pfmem = FALSE;
-	u8 need_io_upper = FALSE;
-	u8 need_pfmem_upper = FALSE;
+	u8 flag_io = 0;
+	u8 flag_mem = 0;
+	u8 flag_pfmem = 0;
+	u8 need_io_upper = 0;
+	u8 need_pfmem_upper = 0;
 	struct res_needed *amount_needed = NULL;
 	struct res_needed *amount_needed = NULL;
 	struct resource_node *io = NULL;
 	struct resource_node *io = NULL;
 	struct resource_node *bus_io[2] = {NULL, NULL};
 	struct resource_node *bus_io[2] = {NULL, NULL};
@@ -677,14 +669,13 @@ static int configure_bridge (struct pci_func **func_passed, u8 slotno)
 
 
 			debug ("len[count] in IO = %x\n", len[count]);
 			debug ("len[count] in IO = %x\n", len[count]);
 
 
-			bus_io[count] = kmalloc (sizeof (struct resource_node), GFP_KERNEL);
+			bus_io[count] = kzalloc(sizeof(struct resource_node), GFP_KERNEL);
 		
 		
 			if (!bus_io[count]) {
 			if (!bus_io[count]) {
 				err ("out of system memory\n");
 				err ("out of system memory\n");
 				retval = -ENOMEM;
 				retval = -ENOMEM;
 				goto error;
 				goto error;
 			}
 			}
-			memset (bus_io[count], 0, sizeof (struct resource_node));
 			bus_io[count]->type = IO;
 			bus_io[count]->type = IO;
 			bus_io[count]->busno = func->busno;
 			bus_io[count]->busno = func->busno;
 			bus_io[count]->devfunc = PCI_DEVFN(func->device,
 			bus_io[count]->devfunc = PCI_DEVFN(func->device,
@@ -711,37 +702,35 @@ static int configure_bridge (struct pci_func **func_passed, u8 slotno)
 
 
 				debug ("len[count] in PFMEM = %x\n", len[count]);
 				debug ("len[count] in PFMEM = %x\n", len[count]);
 
 
-				bus_pfmem[count] = kmalloc (sizeof (struct resource_node), GFP_KERNEL);
+				bus_pfmem[count] = kzalloc(sizeof(struct resource_node), GFP_KERNEL);
 				if (!bus_pfmem[count]) {
 				if (!bus_pfmem[count]) {
 					err ("out of system memory\n");
 					err ("out of system memory\n");
 					retval = -ENOMEM;
 					retval = -ENOMEM;
 					goto error;
 					goto error;
 				}
 				}
-				memset (bus_pfmem[count], 0, sizeof (struct resource_node));
 				bus_pfmem[count]->type = PFMEM;
 				bus_pfmem[count]->type = PFMEM;
 				bus_pfmem[count]->busno = func->busno;
 				bus_pfmem[count]->busno = func->busno;
 				bus_pfmem[count]->devfunc = PCI_DEVFN(func->device,
 				bus_pfmem[count]->devfunc = PCI_DEVFN(func->device,
 							func->function);
 							func->function);
 				bus_pfmem[count]->len = len[count];
 				bus_pfmem[count]->len = len[count];
-				bus_pfmem[count]->fromMem = FALSE;
+				bus_pfmem[count]->fromMem = 0;
 				if (ibmphp_check_resource (bus_pfmem[count], 0) == 0) {
 				if (ibmphp_check_resource (bus_pfmem[count], 0) == 0) {
 					ibmphp_add_resource (bus_pfmem[count]);
 					ibmphp_add_resource (bus_pfmem[count]);
 					func->pfmem[count] = bus_pfmem[count];
 					func->pfmem[count] = bus_pfmem[count];
 				} else {
 				} else {
-					mem_tmp = kmalloc(sizeof(*mem_tmp), GFP_KERNEL);
+					mem_tmp = kzalloc(sizeof(*mem_tmp), GFP_KERNEL);
 					if (!mem_tmp) {
 					if (!mem_tmp) {
 						err ("out of system memory\n");
 						err ("out of system memory\n");
 						retval = -ENOMEM;
 						retval = -ENOMEM;
 						goto error;
 						goto error;
 					}
 					}
-					memset (mem_tmp, 0, sizeof (struct resource_node));
 					mem_tmp->type = MEM;
 					mem_tmp->type = MEM;
 					mem_tmp->busno = bus_pfmem[count]->busno;
 					mem_tmp->busno = bus_pfmem[count]->busno;
 					mem_tmp->devfunc = bus_pfmem[count]->devfunc;
 					mem_tmp->devfunc = bus_pfmem[count]->devfunc;
 					mem_tmp->len = bus_pfmem[count]->len;
 					mem_tmp->len = bus_pfmem[count]->len;
 					if (ibmphp_check_resource (mem_tmp, 0) == 0) {
 					if (ibmphp_check_resource (mem_tmp, 0) == 0) {
 						ibmphp_add_resource (mem_tmp);
 						ibmphp_add_resource (mem_tmp);
-						bus_pfmem[count]->fromMem = TRUE;
+						bus_pfmem[count]->fromMem = 1;
 						bus_pfmem[count]->rangeno = mem_tmp->rangeno;
 						bus_pfmem[count]->rangeno = mem_tmp->rangeno;
 						ibmphp_add_pfmem_from_mem (bus_pfmem[count]);
 						ibmphp_add_pfmem_from_mem (bus_pfmem[count]);
 						func->pfmem[count] = bus_pfmem[count];
 						func->pfmem[count] = bus_pfmem[count];
@@ -770,13 +759,12 @@ static int configure_bridge (struct pci_func **func_passed, u8 slotno)
 
 
 				debug ("len[count] in Memory is %x\n", len[count]);
 				debug ("len[count] in Memory is %x\n", len[count]);
 
 
-				bus_mem[count] = kmalloc (sizeof (struct resource_node), GFP_KERNEL);
+				bus_mem[count] = kzalloc(sizeof(struct resource_node), GFP_KERNEL);
 				if (!bus_mem[count]) {
 				if (!bus_mem[count]) {
 					err ("out of system memory\n");
 					err ("out of system memory\n");
 					retval = -ENOMEM;
 					retval = -ENOMEM;
 					goto error;
 					goto error;
 				}
 				}
-				memset (bus_mem[count], 0, sizeof (struct resource_node));
 				bus_mem[count]->type = MEM;
 				bus_mem[count]->type = MEM;
 				bus_mem[count]->busno = func->busno;
 				bus_mem[count]->busno = func->busno;
 				bus_mem[count]->devfunc = PCI_DEVFN(func->device,
 				bus_mem[count]->devfunc = PCI_DEVFN(func->device,
@@ -838,17 +826,16 @@ static int configure_bridge (struct pci_func **func_passed, u8 slotno)
 
 
 	if (!amount_needed->io) {
 	if (!amount_needed->io) {
 		debug ("it doesn't want IO?\n");
 		debug ("it doesn't want IO?\n");
-		flag_io = TRUE;
+		flag_io = 1;
 	} else {
 	} else {
 		debug ("it wants %x IO behind the bridge\n", amount_needed->io);
 		debug ("it wants %x IO behind the bridge\n", amount_needed->io);
-		io = kmalloc(sizeof(*io), GFP_KERNEL);
+		io = kzalloc(sizeof(*io), GFP_KERNEL);
 		
 		
 		if (!io) {
 		if (!io) {
 			err ("out of system memory\n");
 			err ("out of system memory\n");
 			retval = -ENOMEM;
 			retval = -ENOMEM;
 			goto error;
 			goto error;
 		}
 		}
-		memset (io, 0, sizeof (struct resource_node));
 		io->type = IO;
 		io->type = IO;
 		io->busno = func->busno;
 		io->busno = func->busno;
 		io->devfunc = PCI_DEVFN(func->device, func->function);
 		io->devfunc = PCI_DEVFN(func->device, func->function);
@@ -856,71 +843,68 @@ static int configure_bridge (struct pci_func **func_passed, u8 slotno)
 		if (ibmphp_check_resource (io, 1) == 0) {
 		if (ibmphp_check_resource (io, 1) == 0) {
 			debug ("were we able to add io\n");
 			debug ("were we able to add io\n");
 			ibmphp_add_resource (io);
 			ibmphp_add_resource (io);
-			flag_io = TRUE;
+			flag_io = 1;
 		}
 		}
 	}
 	}
 
 
 	if (!amount_needed->mem) {
 	if (!amount_needed->mem) {
 		debug ("it doesn't want n.e.memory?\n");
 		debug ("it doesn't want n.e.memory?\n");
-		flag_mem = TRUE;
+		flag_mem = 1;
 	} else {
 	} else {
 		debug ("it wants %x memory behind the bridge\n", amount_needed->mem);
 		debug ("it wants %x memory behind the bridge\n", amount_needed->mem);
-		mem = kmalloc(sizeof(*mem), GFP_KERNEL);
+		mem = kzalloc(sizeof(*mem), GFP_KERNEL);
 		if (!mem) {
 		if (!mem) {
 			err ("out of system memory\n");
 			err ("out of system memory\n");
 			retval = -ENOMEM;
 			retval = -ENOMEM;
 			goto error;
 			goto error;
 		}
 		}
-		memset (mem, 0, sizeof (struct resource_node));
 		mem->type = MEM;
 		mem->type = MEM;
 		mem->busno = func->busno;
 		mem->busno = func->busno;
 		mem->devfunc = PCI_DEVFN(func->device, func->function);
 		mem->devfunc = PCI_DEVFN(func->device, func->function);
 		mem->len = amount_needed->mem;
 		mem->len = amount_needed->mem;
 		if (ibmphp_check_resource (mem, 1) == 0) {
 		if (ibmphp_check_resource (mem, 1) == 0) {
 			ibmphp_add_resource (mem);
 			ibmphp_add_resource (mem);
-			flag_mem = TRUE;
+			flag_mem = 1;
 			debug ("were we able to add mem\n");
 			debug ("were we able to add mem\n");
 		}
 		}
 	}
 	}
 
 
 	if (!amount_needed->pfmem) {
 	if (!amount_needed->pfmem) {
 		debug ("it doesn't want n.e.pfmem mem?\n");
 		debug ("it doesn't want n.e.pfmem mem?\n");
-		flag_pfmem = TRUE;
+		flag_pfmem = 1;
 	} else {
 	} else {
 		debug ("it wants %x pfmemory behind the bridge\n", amount_needed->pfmem);
 		debug ("it wants %x pfmemory behind the bridge\n", amount_needed->pfmem);
-		pfmem = kmalloc(sizeof(*pfmem), GFP_KERNEL);
+		pfmem = kzalloc(sizeof(*pfmem), GFP_KERNEL);
 		if (!pfmem) {
 		if (!pfmem) {
 			err ("out of system memory\n");
 			err ("out of system memory\n");
 			retval = -ENOMEM;
 			retval = -ENOMEM;
 			goto error;
 			goto error;
 		}
 		}
-		memset (pfmem, 0, sizeof (struct resource_node));
 		pfmem->type = PFMEM;
 		pfmem->type = PFMEM;
 		pfmem->busno = func->busno;
 		pfmem->busno = func->busno;
 		pfmem->devfunc = PCI_DEVFN(func->device, func->function);
 		pfmem->devfunc = PCI_DEVFN(func->device, func->function);
 		pfmem->len = amount_needed->pfmem;
 		pfmem->len = amount_needed->pfmem;
-		pfmem->fromMem = FALSE;
+		pfmem->fromMem = 0;
 		if (ibmphp_check_resource (pfmem, 1) == 0) {
 		if (ibmphp_check_resource (pfmem, 1) == 0) {
 			ibmphp_add_resource (pfmem);
 			ibmphp_add_resource (pfmem);
-			flag_pfmem = TRUE;
+			flag_pfmem = 1;
 		} else {
 		} else {
-			mem_tmp = kmalloc(sizeof(*mem_tmp), GFP_KERNEL);
+			mem_tmp = kzalloc(sizeof(*mem_tmp), GFP_KERNEL);
 			if (!mem_tmp) {
 			if (!mem_tmp) {
 				err ("out of system memory\n");
 				err ("out of system memory\n");
 				retval = -ENOMEM;
 				retval = -ENOMEM;
 				goto error;
 				goto error;
 			}
 			}
-			memset (mem_tmp, 0, sizeof (struct resource_node));
 			mem_tmp->type = MEM;
 			mem_tmp->type = MEM;
 			mem_tmp->busno = pfmem->busno;
 			mem_tmp->busno = pfmem->busno;
 			mem_tmp->devfunc = pfmem->devfunc;
 			mem_tmp->devfunc = pfmem->devfunc;
 			mem_tmp->len = pfmem->len;
 			mem_tmp->len = pfmem->len;
 			if (ibmphp_check_resource (mem_tmp, 1) == 0) {
 			if (ibmphp_check_resource (mem_tmp, 1) == 0) {
 				ibmphp_add_resource (mem_tmp);
 				ibmphp_add_resource (mem_tmp);
-				pfmem->fromMem = TRUE;
+				pfmem->fromMem = 1;
 				pfmem->rangeno = mem_tmp->rangeno;
 				pfmem->rangeno = mem_tmp->rangeno;
 				ibmphp_add_pfmem_from_mem (pfmem);
 				ibmphp_add_pfmem_from_mem (pfmem);
-				flag_pfmem = TRUE;
+				flag_pfmem = 1;
 			}
 			}
 		}
 		}
 	}
 	}
@@ -936,13 +920,12 @@ static int configure_bridge (struct pci_func **func_passed, u8 slotno)
 		 */
 		 */
 		bus = ibmphp_find_res_bus (sec_number);
 		bus = ibmphp_find_res_bus (sec_number);
 		if (!bus) {
 		if (!bus) {
-			bus = kmalloc(sizeof(*bus), GFP_KERNEL);
+			bus = kzalloc(sizeof(*bus), GFP_KERNEL);
 			if (!bus) {
 			if (!bus) {
 				err ("out of system memory\n");
 				err ("out of system memory\n");
 				retval = -ENOMEM;
 				retval = -ENOMEM;
 				goto error;
 				goto error;
 			}
 			}
-			memset (bus, 0, sizeof (struct bus_node));
 			bus->busno = sec_number;
 			bus->busno = sec_number;
 			debug ("b4 adding new bus\n");
 			debug ("b4 adding new bus\n");
 			rc = add_new_bus (bus, io, mem, pfmem, func->busno);
 			rc = add_new_bus (bus, io, mem, pfmem, func->busno);
@@ -967,11 +950,11 @@ static int configure_bridge (struct pci_func **func_passed, u8 slotno)
 
 
 		if ((io_base & PCI_IO_RANGE_TYPE_MASK) == PCI_IO_RANGE_TYPE_32) {
 		if ((io_base & PCI_IO_RANGE_TYPE_MASK) == PCI_IO_RANGE_TYPE_32) {
 			debug ("io 32\n");
 			debug ("io 32\n");
-			need_io_upper = TRUE;
+			need_io_upper = 1;
 		}
 		}
 		if ((pfmem_base & PCI_PREF_RANGE_TYPE_MASK) == PCI_PREF_RANGE_TYPE_64) {
 		if ((pfmem_base & PCI_PREF_RANGE_TYPE_MASK) == PCI_PREF_RANGE_TYPE_64) {
 			debug ("pfmem 64\n");
 			debug ("pfmem 64\n");
-			need_pfmem_upper = TRUE;
+			need_pfmem_upper = 1;
 		}
 		}
 
 
 		if (bus->noIORanges) {
 		if (bus->noIORanges) {
@@ -1111,10 +1094,9 @@ static struct res_needed *scan_behind_bridge (struct pci_func * func, u8 busno)
 	};
 	};
 	struct res_needed *amount;
 	struct res_needed *amount;
 
 
-	amount = kmalloc(sizeof(*amount), GFP_KERNEL);
+	amount = kzalloc(sizeof(*amount), GFP_KERNEL);
 	if (amount == NULL)
 	if (amount == NULL)
 		return NULL;
 		return NULL;
-	memset (amount, 0, sizeof (struct res_needed));
 
 
 	ibmphp_pci_bus->number = busno;
 	ibmphp_pci_bus->number = busno;
 
 
@@ -1137,7 +1119,7 @@ static struct res_needed *scan_behind_bridge (struct pci_func * func, u8 busno)
 				debug ("hdr_type behind the bridge is %x\n", hdr_type);
 				debug ("hdr_type behind the bridge is %x\n", hdr_type);
 				if (hdr_type & PCI_HEADER_TYPE_BRIDGE) {
 				if (hdr_type & PCI_HEADER_TYPE_BRIDGE) {
 					err ("embedded bridges not supported for hot-plugging.\n");
 					err ("embedded bridges not supported for hot-plugging.\n");
-					amount->not_correct = TRUE;
+					amount->not_correct = 1;
 					return amount;
 					return amount;
 				}
 				}
 
 
@@ -1145,12 +1127,12 @@ static struct res_needed *scan_behind_bridge (struct pci_func * func, u8 busno)
 				if (class == PCI_CLASS_NOT_DEFINED_VGA) {
 				if (class == PCI_CLASS_NOT_DEFINED_VGA) {
 					err ("The device %x is VGA compatible and as is not supported for hot plugging. "
 					err ("The device %x is VGA compatible and as is not supported for hot plugging. "
 					     "Please choose another device.\n", device);
 					     "Please choose another device.\n", device);
-					amount->not_correct = TRUE;
+					amount->not_correct = 1;
 					return amount;
 					return amount;
 				} else if (class == PCI_CLASS_DISPLAY_VGA) {
 				} else if (class == PCI_CLASS_DISPLAY_VGA) {
 					err ("The device %x is not supported for hot plugging. "
 					err ("The device %x is not supported for hot plugging. "
 					     "Please choose another device.\n", device);
 					     "Please choose another device.\n", device);
-					amount->not_correct = TRUE;
+					amount->not_correct = 1;
 					return amount;
 					return amount;
 				}
 				}
 
 
@@ -1210,9 +1192,9 @@ static struct res_needed *scan_behind_bridge (struct pci_func * func, u8 busno)
 	}	/* end for */
 	}	/* end for */
 
 
 	if (!howmany)
 	if (!howmany)
-		amount->not_correct = TRUE;
+		amount->not_correct = 1;
 	else
 	else
-		amount->not_correct = FALSE;
+		amount->not_correct = 0;
 	if ((amount->io) && (amount->io < IOBRIDGE))
 	if ((amount->io) && (amount->io < IOBRIDGE))
 		amount->io = IOBRIDGE;
 		amount->io = IOBRIDGE;
 	if ((amount->mem) && (amount->mem < MEMBRIDGE))
 	if ((amount->mem) && (amount->mem < MEMBRIDGE))
@@ -1672,12 +1654,11 @@ static int add_new_bus (struct bus_node *bus, struct resource_node *io, struct r
 		list_add (&bus->bus_list, &cur_bus->bus_list);
 		list_add (&bus->bus_list, &cur_bus->bus_list);
 	}
 	}
 	if (io) {
 	if (io) {
-		io_range = kmalloc(sizeof(*io_range), GFP_KERNEL);
+		io_range = kzalloc(sizeof(*io_range), GFP_KERNEL);
 		if (!io_range) {
 		if (!io_range) {
 			err ("out of system memory\n");
 			err ("out of system memory\n");
 			return -ENOMEM;
 			return -ENOMEM;
 		}
 		}
-		memset (io_range, 0, sizeof (struct range_node));
 		io_range->start = io->start;
 		io_range->start = io->start;
 		io_range->end = io->end;
 		io_range->end = io->end;
 		io_range->rangeno = 1;
 		io_range->rangeno = 1;
@@ -1685,12 +1666,11 @@ static int add_new_bus (struct bus_node *bus, struct resource_node *io, struct r
 		bus->rangeIO = io_range;
 		bus->rangeIO = io_range;
 	}
 	}
 	if (mem) {
 	if (mem) {
-		mem_range = kmalloc(sizeof(*mem_range), GFP_KERNEL);
+		mem_range = kzalloc(sizeof(*mem_range), GFP_KERNEL);
 		if (!mem_range) {
 		if (!mem_range) {
 			err ("out of system memory\n");
 			err ("out of system memory\n");
 			return -ENOMEM;
 			return -ENOMEM;
 		}
 		}
-		memset (mem_range, 0, sizeof (struct range_node));
 		mem_range->start = mem->start;
 		mem_range->start = mem->start;
 		mem_range->end = mem->end;
 		mem_range->end = mem->end;
 		mem_range->rangeno = 1;
 		mem_range->rangeno = 1;
@@ -1698,12 +1678,11 @@ static int add_new_bus (struct bus_node *bus, struct resource_node *io, struct r
 		bus->rangeMem = mem_range;
 		bus->rangeMem = mem_range;
 	}
 	}
 	if (pfmem) {
 	if (pfmem) {
-		pfmem_range = kmalloc(sizeof(*pfmem_range), GFP_KERNEL);
+		pfmem_range = kzalloc(sizeof(*pfmem_range), GFP_KERNEL);
 		if (!pfmem_range) {	
 		if (!pfmem_range) {	
 			err ("out of system memory\n");
 			err ("out of system memory\n");
 			return -ENOMEM;
 			return -ENOMEM;
 		}
 		}
-		memset (pfmem_range, 0, sizeof (struct range_node));
 		pfmem_range->start = pfmem->start;
 		pfmem_range->start = pfmem->start;
 		pfmem_range->end = pfmem->end;
 		pfmem_range->end = pfmem->end;
 		pfmem_range->rangeno = 1;
 		pfmem_range->rangeno = 1;

+ 35 - 46
drivers/pci/hotplug/ibmphp_res.c

@@ -55,13 +55,12 @@ static struct bus_node * __init alloc_error_bus (struct ebda_pci_rsrc * curr, u8
 		return NULL;
 		return NULL;
 	}
 	}
 
 
-	newbus = kmalloc (sizeof (struct bus_node), GFP_KERNEL);
+	newbus = kzalloc(sizeof(struct bus_node), GFP_KERNEL);
 	if (!newbus) {
 	if (!newbus) {
 		err ("out of system memory\n");
 		err ("out of system memory\n");
 		return NULL;
 		return NULL;
 	}
 	}
 
 
-	memset (newbus, 0, sizeof (struct bus_node));
 	if (flag)
 	if (flag)
 		newbus->busno = busno;
 		newbus->busno = busno;
 	else
 	else
@@ -79,12 +78,11 @@ static struct resource_node * __init alloc_resources (struct ebda_pci_rsrc * cur
 		return NULL;
 		return NULL;
 	}
 	}
 
 
-	rs = kmalloc (sizeof (struct resource_node), GFP_KERNEL);
+	rs = kzalloc(sizeof(struct resource_node), GFP_KERNEL);
 	if (!rs) {
 	if (!rs) {
 		err ("out of system memory\n");
 		err ("out of system memory\n");
 		return NULL;
 		return NULL;
 	}
 	}
-	memset (rs, 0, sizeof (struct resource_node));
 	rs->busno = curr->bus_num;
 	rs->busno = curr->bus_num;
 	rs->devfunc = curr->dev_fun;
 	rs->devfunc = curr->dev_fun;
 	rs->start = curr->start_addr;
 	rs->start = curr->start_addr;
@@ -100,12 +98,11 @@ static int __init alloc_bus_range (struct bus_node **new_bus, struct range_node
 	u8 num_ranges = 0;
 	u8 num_ranges = 0;
 
 
 	if (first_bus) {
 	if (first_bus) {
-		newbus = kmalloc (sizeof (struct bus_node), GFP_KERNEL);
+		newbus = kzalloc(sizeof(struct bus_node), GFP_KERNEL);
 		if (!newbus) {
 		if (!newbus) {
 			err ("out of system memory.\n");
 			err ("out of system memory.\n");
 			return -ENOMEM;
 			return -ENOMEM;
 		}
 		}
-		memset (newbus, 0, sizeof (struct bus_node));
 		newbus->busno = curr->bus_num;
 		newbus->busno = curr->bus_num;
 	} else {
 	} else {
 		newbus = *new_bus;
 		newbus = *new_bus;
@@ -122,14 +119,13 @@ static int __init alloc_bus_range (struct bus_node **new_bus, struct range_node
 		}
 		}
 	}
 	}
 
 
-	newrange = kmalloc (sizeof (struct range_node), GFP_KERNEL);
+	newrange = kzalloc(sizeof(struct range_node), GFP_KERNEL);
 	if (!newrange) {
 	if (!newrange) {
 		if (first_bus)
 		if (first_bus)
 			kfree (newbus);
 			kfree (newbus);
 		err ("out of system memory\n");
 		err ("out of system memory\n");
 		return -ENOMEM;
 		return -ENOMEM;
 	}
 	}
-	memset (newrange, 0, sizeof (struct range_node));
 	newrange->start = curr->start_addr;
 	newrange->start = curr->start_addr;
 	newrange->end = curr->end_addr;
 	newrange->end = curr->end_addr;
 		
 		
@@ -329,7 +325,7 @@ int __init ibmphp_rsrc_init (void)
 				if (!new_pfmem)
 				if (!new_pfmem)
 					return -ENOMEM;
 					return -ENOMEM;
 				new_pfmem->type = PFMEM;
 				new_pfmem->type = PFMEM;
-				new_pfmem->fromMem = FALSE;
+				new_pfmem->fromMem = 0;
 				if (ibmphp_add_resource (new_pfmem) < 0) {
 				if (ibmphp_add_resource (new_pfmem) < 0) {
 					newbus = alloc_error_bus (curr, 0, 0);
 					newbus = alloc_error_bus (curr, 0, 0);
 					if (!newbus)
 					if (!newbus)
@@ -466,7 +462,7 @@ static int add_range (int type, struct range_node *range, struct bus_node *bus_c
 static void update_resources (struct bus_node *bus_cur, int type, int rangeno)
 static void update_resources (struct bus_node *bus_cur, int type, int rangeno)
 {
 {
 	struct resource_node *res = NULL;
 	struct resource_node *res = NULL;
-	u8 eol = FALSE;	/* end of list indicator */
+	u8 eol = 0;	/* end of list indicator */
 
 
 	switch (type) {
 	switch (type) {
 		case MEM:
 		case MEM:
@@ -492,7 +488,7 @@ static void update_resources (struct bus_node *bus_cur, int type, int rangeno)
 			else if (res->nextRange)
 			else if (res->nextRange)
 				res = res->nextRange;
 				res = res->nextRange;
 			else {
 			else {
-				eol = TRUE;
+				eol = 1;
 				break;
 				break;
 			}
 			}
 		}
 		}
@@ -983,7 +979,7 @@ int ibmphp_check_resource (struct resource_node *res, u8 bridge)
 	int noranges = 0;
 	int noranges = 0;
 	u32 tmp_start;		/* this is to make sure start address is divisible by the length needed */
 	u32 tmp_start;		/* this is to make sure start address is divisible by the length needed */
 	u32 tmp_divide;
 	u32 tmp_divide;
-	u8 flag = FALSE;
+	u8 flag = 0;
 
 
 	if (!res)
 	if (!res)
 		return -EINVAL;
 		return -EINVAL;
@@ -1050,17 +1046,17 @@ int ibmphp_check_resource (struct resource_node *res, u8 bridge)
 
 
 					if ((range->start % tmp_divide) == 0) {
 					if ((range->start % tmp_divide) == 0) {
 						/* just perfect, starting address is divisible by length */
 						/* just perfect, starting address is divisible by length */
-						flag = TRUE;
+						flag = 1;
 						len_cur = len_tmp;
 						len_cur = len_tmp;
 						start_cur = range->start;
 						start_cur = range->start;
 					} else {
 					} else {
 						/* Needs adjusting */
 						/* Needs adjusting */
 						tmp_start = range->start;
 						tmp_start = range->start;
-						flag = FALSE;
+						flag = 0;
 
 
 						while ((len_tmp = res_cur->start - 1 - tmp_start) >= res->len) {
 						while ((len_tmp = res_cur->start - 1 - tmp_start) >= res->len) {
 							if ((tmp_start % tmp_divide) == 0) {
 							if ((tmp_start % tmp_divide) == 0) {
-								flag = TRUE;
+								flag = 1;
 								len_cur = len_tmp;
 								len_cur = len_tmp;
 								start_cur = tmp_start;
 								start_cur = tmp_start;
 								break;
 								break;
@@ -1089,17 +1085,17 @@ int ibmphp_check_resource (struct resource_node *res, u8 bridge)
 
 
 					if (((res_cur->end + 1) % tmp_divide) == 0) {
 					if (((res_cur->end + 1) % tmp_divide) == 0) {
 						/* just perfect, starting address is divisible by length */
 						/* just perfect, starting address is divisible by length */
-						flag = TRUE;
+						flag = 1;
 						len_cur = len_tmp;
 						len_cur = len_tmp;
 						start_cur = res_cur->end + 1;
 						start_cur = res_cur->end + 1;
 					} else {
 					} else {
 						/* Needs adjusting */
 						/* Needs adjusting */
 						tmp_start = res_cur->end + 1;
 						tmp_start = res_cur->end + 1;
-						flag = FALSE;
+						flag = 0;
 
 
 						while ((len_tmp = range->end - tmp_start) >= res->len) {
 						while ((len_tmp = range->end - tmp_start) >= res->len) {
 							if ((tmp_start % tmp_divide) == 0) {
 							if ((tmp_start % tmp_divide) == 0) {
-								flag = TRUE;
+								flag = 1;
 								len_cur = len_tmp;
 								len_cur = len_tmp;
 								start_cur = tmp_start;
 								start_cur = tmp_start;
 								break;
 								break;
@@ -1127,17 +1123,17 @@ int ibmphp_check_resource (struct resource_node *res, u8 bridge)
 					if ((len_tmp < len_cur) || (len_cur == 0)) {
 					if ((len_tmp < len_cur) || (len_cur == 0)) {
 						if ((range->start % tmp_divide) == 0) {	
 						if ((range->start % tmp_divide) == 0) {	
 							/* just perfect, starting address is divisible by length */
 							/* just perfect, starting address is divisible by length */
-							flag = TRUE;
+							flag = 1;
 							len_cur = len_tmp;
 							len_cur = len_tmp;
 							start_cur = range->start;
 							start_cur = range->start;
 						} else {
 						} else {
 							/* Needs adjusting */
 							/* Needs adjusting */
 							tmp_start = range->start;
 							tmp_start = range->start;
-							flag = FALSE;
+							flag = 0;
 
 
 							while ((len_tmp = res_cur->start - 1 - tmp_start) >= res->len) {
 							while ((len_tmp = res_cur->start - 1 - tmp_start) >= res->len) {
 								if ((tmp_start % tmp_divide) == 0) {
 								if ((tmp_start % tmp_divide) == 0) {
-									flag = TRUE;
+									flag = 1;
 									len_cur = len_tmp;
 									len_cur = len_tmp;
 									start_cur = tmp_start;
 									start_cur = tmp_start;
 									break;
 									break;
@@ -1162,17 +1158,17 @@ int ibmphp_check_resource (struct resource_node *res, u8 bridge)
 					if ((len_tmp < len_cur) || (len_cur == 0)) {
 					if ((len_tmp < len_cur) || (len_cur == 0)) {
 						if (((res_prev->end + 1) % tmp_divide) == 0) {
 						if (((res_prev->end + 1) % tmp_divide) == 0) {
 							/* just perfect, starting address's divisible by length */
 							/* just perfect, starting address's divisible by length */
-							flag = TRUE;
+							flag = 1;
 							len_cur = len_tmp;
 							len_cur = len_tmp;
 							start_cur = res_prev->end + 1;
 							start_cur = res_prev->end + 1;
 						} else {
 						} else {
 							/* Needs adjusting */
 							/* Needs adjusting */
 							tmp_start = res_prev->end + 1;
 							tmp_start = res_prev->end + 1;
-							flag = FALSE;
+							flag = 0;
 
 
 							while ((len_tmp = res_cur->start - 1 - tmp_start) >= res->len) {
 							while ((len_tmp = res_cur->start - 1 - tmp_start) >= res->len) {
 								if ((tmp_start % tmp_divide) == 0) {
 								if ((tmp_start % tmp_divide) == 0) {
-									flag = TRUE;
+									flag = 1;
 									len_cur = len_tmp;
 									len_cur = len_tmp;
 									start_cur = tmp_start;
 									start_cur = tmp_start;
 									break;
 									break;
@@ -1221,17 +1217,17 @@ int ibmphp_check_resource (struct resource_node *res, u8 bridge)
 				if ((len_tmp < len_cur) || (len_cur == 0)) {
 				if ((len_tmp < len_cur) || (len_cur == 0)) {
 					if ((range->start % tmp_divide) == 0) {
 					if ((range->start % tmp_divide) == 0) {
 						/* just perfect, starting address's divisible by length */
 						/* just perfect, starting address's divisible by length */
-						flag = TRUE;
+						flag = 1;
 						len_cur = len_tmp;
 						len_cur = len_tmp;
 						start_cur = range->start;
 						start_cur = range->start;
 					} else {
 					} else {
 						/* Needs adjusting */
 						/* Needs adjusting */
 						tmp_start = range->start;
 						tmp_start = range->start;
-						flag = FALSE;
+						flag = 0;
 
 
 						while ((len_tmp = range->end - tmp_start) >= res->len) {
 						while ((len_tmp = range->end - tmp_start) >= res->len) {
 							if ((tmp_start % tmp_divide) == 0) {
 							if ((tmp_start % tmp_divide) == 0) {
-								flag = TRUE;
+								flag = 1;
 								len_cur = len_tmp;
 								len_cur = len_tmp;
 								start_cur = tmp_start;
 								start_cur = tmp_start;
 								break;
 								break;
@@ -1285,17 +1281,17 @@ int ibmphp_check_resource (struct resource_node *res, u8 bridge)
 					if ((len_tmp < len_cur) || (len_cur == 0)) {
 					if ((len_tmp < len_cur) || (len_cur == 0)) {
 						if ((range->start % tmp_divide) == 0) {
 						if ((range->start % tmp_divide) == 0) {
 							/* just perfect, starting address's divisible by length */
 							/* just perfect, starting address's divisible by length */
-							flag = TRUE;
+							flag = 1;
 							len_cur = len_tmp;
 							len_cur = len_tmp;
 							start_cur = range->start;
 							start_cur = range->start;
 						} else {
 						} else {
 							/* Needs adjusting */
 							/* Needs adjusting */
 							tmp_start = range->start;
 							tmp_start = range->start;
-							flag = FALSE;
+							flag = 0;
 
 
 							while ((len_tmp = range->end - tmp_start) >= res->len) {
 							while ((len_tmp = range->end - tmp_start) >= res->len) {
 								if ((tmp_start % tmp_divide) == 0) {
 								if ((tmp_start % tmp_divide) == 0) {
-									flag = TRUE;
+									flag = 1;
 									len_cur = len_tmp;
 									len_cur = len_tmp;
 									start_cur = tmp_start;
 									start_cur = tmp_start;
 									break;
 									break;
@@ -1688,7 +1684,7 @@ static int __init once_over (void)
 		bus_cur = list_entry (tmp, struct bus_node, bus_list);
 		bus_cur = list_entry (tmp, struct bus_node, bus_list);
 		if ((!bus_cur->rangePFMem) && (bus_cur->firstPFMem)) {
 		if ((!bus_cur->rangePFMem) && (bus_cur->firstPFMem)) {
 			for (pfmem_cur = bus_cur->firstPFMem, pfmem_prev = NULL; pfmem_cur; pfmem_prev = pfmem_cur, pfmem_cur = pfmem_cur->next) {
 			for (pfmem_cur = bus_cur->firstPFMem, pfmem_prev = NULL; pfmem_cur; pfmem_prev = pfmem_cur, pfmem_cur = pfmem_cur->next) {
-				pfmem_cur->fromMem = TRUE;
+				pfmem_cur->fromMem = 1;
 				if (pfmem_prev)
 				if (pfmem_prev)
 					pfmem_prev->next = pfmem_cur->next;
 					pfmem_prev->next = pfmem_cur->next;
 				else
 				else
@@ -1705,12 +1701,11 @@ static int __init once_over (void)
 
 
 				bus_cur->firstPFMemFromMem = pfmem_cur;
 				bus_cur->firstPFMemFromMem = pfmem_cur;
 
 
-				mem = kmalloc (sizeof (struct resource_node), GFP_KERNEL);		
+				mem = kzalloc(sizeof(struct resource_node), GFP_KERNEL);
 				if (!mem) {
 				if (!mem) {
 					err ("out of system memory\n");
 					err ("out of system memory\n");
 					return -ENOMEM;
 					return -ENOMEM;
 				}
 				}
-				memset (mem, 0, sizeof (struct resource_node));
 				mem->type = MEM;
 				mem->type = MEM;
 				mem->busno = pfmem_cur->busno;
 				mem->busno = pfmem_cur->busno;
 				mem->devfunc = pfmem_cur->devfunc;
 				mem->devfunc = pfmem_cur->devfunc;
@@ -1994,12 +1989,11 @@ static int __init update_bridge_ranges (struct bus_node **bus)
 						end_address |= (upper_io_end << 16);
 						end_address |= (upper_io_end << 16);
 
 
 						if ((start_address) && (start_address <= end_address)) {
 						if ((start_address) && (start_address <= end_address)) {
-							range = kmalloc (sizeof (struct range_node), GFP_KERNEL);
+							range = kzalloc(sizeof(struct range_node), GFP_KERNEL);
 							if (!range) {
 							if (!range) {
 								err ("out of system memory\n");
 								err ("out of system memory\n");
 								return -ENOMEM;
 								return -ENOMEM;
 							}
 							}
-							memset (range, 0, sizeof (struct range_node));
 							range->start = start_address;
 							range->start = start_address;
 							range->end = end_address + 0xfff;
 							range->end = end_address + 0xfff;
 
 
@@ -2020,13 +2014,12 @@ static int __init update_bridge_ranges (struct bus_node **bus)
 							fix_resources (bus_sec);
 							fix_resources (bus_sec);
 
 
 							if (ibmphp_find_resource (bus_cur, start_address, &io, IO)) {
 							if (ibmphp_find_resource (bus_cur, start_address, &io, IO)) {
-								io = kmalloc (sizeof (struct resource_node), GFP_KERNEL);							
+								io = kzalloc(sizeof(struct resource_node), GFP_KERNEL);
 								if (!io) {
 								if (!io) {
 									kfree (range);
 									kfree (range);
 									err ("out of system memory\n");
 									err ("out of system memory\n");
 									return -ENOMEM;
 									return -ENOMEM;
 								}
 								}
-								memset (io, 0, sizeof (struct resource_node));
 								io->type = IO;
 								io->type = IO;
 								io->busno = bus_cur->busno;
 								io->busno = bus_cur->busno;
 								io->devfunc = ((device << 3) | (function & 0x7));
 								io->devfunc = ((device << 3) | (function & 0x7));
@@ -2045,12 +2038,11 @@ static int __init update_bridge_ranges (struct bus_node **bus)
 
 
 						if ((start_address) && (start_address <= end_address)) {
 						if ((start_address) && (start_address <= end_address)) {
 
 
-							range = kmalloc (sizeof (struct range_node), GFP_KERNEL);
+							range = kzalloc(sizeof(struct range_node), GFP_KERNEL);
 							if (!range) {
 							if (!range) {
 								err ("out of system memory\n");
 								err ("out of system memory\n");
 								return -ENOMEM;
 								return -ENOMEM;
 							}
 							}
-							memset (range, 0, sizeof (struct range_node));
 							range->start = start_address;
 							range->start = start_address;
 							range->end = end_address + 0xfffff;
 							range->end = end_address + 0xfffff;
 
 
@@ -2072,13 +2064,12 @@ static int __init update_bridge_ranges (struct bus_node **bus)
 							fix_resources (bus_sec);
 							fix_resources (bus_sec);
 
 
 							if (ibmphp_find_resource (bus_cur, start_address, &mem, MEM)) {
 							if (ibmphp_find_resource (bus_cur, start_address, &mem, MEM)) {
-								mem = kmalloc (sizeof (struct resource_node), GFP_KERNEL);
+								mem = kzalloc(sizeof(struct resource_node), GFP_KERNEL);
 								if (!mem) {
 								if (!mem) {
 									kfree (range);
 									kfree (range);
 									err ("out of system memory\n");
 									err ("out of system memory\n");
 									return -ENOMEM;
 									return -ENOMEM;
 								}
 								}
-								memset (mem, 0, sizeof (struct resource_node));
 								mem->type = MEM;
 								mem->type = MEM;
 								mem->busno = bus_cur->busno;
 								mem->busno = bus_cur->busno;
 								mem->devfunc = ((device << 3) | (function & 0x7));
 								mem->devfunc = ((device << 3) | (function & 0x7));
@@ -2101,12 +2092,11 @@ static int __init update_bridge_ranges (struct bus_node **bus)
 
 
 						if ((start_address) && (start_address <= end_address)) {
 						if ((start_address) && (start_address <= end_address)) {
 
 
-							range = kmalloc (sizeof (struct range_node), GFP_KERNEL);
+							range = kzalloc(sizeof(struct range_node), GFP_KERNEL);
 							if (!range) {
 							if (!range) {
 								err ("out of system memory\n");
 								err ("out of system memory\n");
 								return -ENOMEM;
 								return -ENOMEM;
 							}
 							}
-							memset (range, 0, sizeof (struct range_node));
 							range->start = start_address;
 							range->start = start_address;
 							range->end = end_address + 0xfffff;
 							range->end = end_address + 0xfffff;
 
 
@@ -2127,20 +2117,19 @@ static int __init update_bridge_ranges (struct bus_node **bus)
 
 
 							fix_resources (bus_sec);
 							fix_resources (bus_sec);
 							if (ibmphp_find_resource (bus_cur, start_address, &pfmem, PFMEM)) {
 							if (ibmphp_find_resource (bus_cur, start_address, &pfmem, PFMEM)) {
-								pfmem = kmalloc (sizeof (struct resource_node), GFP_KERNEL);
+								pfmem = kzalloc(sizeof(struct resource_node), GFP_KERNEL);
 								if (!pfmem) {
 								if (!pfmem) {
 									kfree (range);
 									kfree (range);
 									err ("out of system memory\n");
 									err ("out of system memory\n");
 									return -ENOMEM;
 									return -ENOMEM;
 								}
 								}
-								memset (pfmem, 0, sizeof (struct resource_node));
 								pfmem->type = PFMEM;
 								pfmem->type = PFMEM;
 								pfmem->busno = bus_cur->busno;
 								pfmem->busno = bus_cur->busno;
 								pfmem->devfunc = ((device << 3) | (function & 0x7));
 								pfmem->devfunc = ((device << 3) | (function & 0x7));
 								pfmem->start = start_address;
 								pfmem->start = start_address;
 								pfmem->end = end_address + 0xfffff;
 								pfmem->end = end_address + 0xfffff;
 								pfmem->len = pfmem->end - pfmem->start + 1;
 								pfmem->len = pfmem->end - pfmem->start + 1;
-								pfmem->fromMem = FALSE;
+								pfmem->fromMem = 0;
 
 
 								ibmphp_add_resource (pfmem);
 								ibmphp_add_resource (pfmem);
 							}
 							}

+ 16 - 0
drivers/pci/hotplug/pci_hotplug.h

@@ -176,5 +176,21 @@ extern int pci_hp_change_slot_info	(struct hotplug_slot *slot,
 					 struct hotplug_slot_info *info);
 					 struct hotplug_slot_info *info);
 extern struct subsystem pci_hotplug_slots_subsys;
 extern struct subsystem pci_hotplug_slots_subsys;
 
 
+struct hotplug_params {
+	u8 cache_line_size;
+	u8 latency_timer;
+	u8 enable_serr;
+	u8 enable_perr;
+};
+
+#ifdef CONFIG_ACPI
+#include <acpi/acpi.h>
+#include <acpi/acpi_bus.h>
+#include <acpi/actypes.h>
+extern acpi_status acpi_run_oshp(acpi_handle handle);
+extern acpi_status acpi_get_hp_params_from_firmware(struct pci_dev *dev,
+				struct hotplug_params *hpp);
+int acpi_root_bridge(acpi_handle handle);
+#endif
 #endif
 #endif
 
 

+ 17 - 10
drivers/pci/hotplug/pciehp.h

@@ -34,6 +34,7 @@
 #include <linux/delay.h>
 #include <linux/delay.h>
 #include <linux/sched.h>		/* signal_pending() */
 #include <linux/sched.h>		/* signal_pending() */
 #include <linux/pcieport_if.h>
 #include <linux/pcieport_if.h>
+#include <linux/mutex.h>
 #include "pci_hotplug.h"
 #include "pci_hotplug.h"
 
 
 #define MY_NAME	"pciehp"
 #define MY_NAME	"pciehp"
@@ -49,12 +50,6 @@ extern int pciehp_force;
 #define info(format, arg...) printk(KERN_INFO "%s: " format, MY_NAME , ## arg)
 #define info(format, arg...) printk(KERN_INFO "%s: " format, MY_NAME , ## arg)
 #define warn(format, arg...) printk(KERN_WARNING "%s: " format, MY_NAME , ## arg)
 #define warn(format, arg...) printk(KERN_WARNING "%s: " format, MY_NAME , ## arg)
 
 
-struct hotplug_params {
-	u8 cache_line_size;
-	u8 latency_timer;
-	u8 enable_serr;
-	u8 enable_perr;
-};
 
 
 struct slot {
 struct slot {
 	struct slot *next;
 	struct slot *next;
@@ -96,7 +91,7 @@ struct php_ctlr_state_s {
 #define MAX_EVENTS		10
 #define MAX_EVENTS		10
 struct controller {
 struct controller {
 	struct controller *next;
 	struct controller *next;
-	struct semaphore crit_sect;	/* critical section semaphore */
+	struct mutex crit_sect;		/* critical section mutex */
 	struct php_ctlr_state_s *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 num_slots;			/* Number of slots on ctlr */
 	int slot_num_inc;		/* 1 or -1 */
 	int slot_num_inc;		/* 1 or -1 */
@@ -191,9 +186,6 @@ extern u8	pciehp_handle_power_fault	(u8 hp_slot, void *inst_id);
 /* pci functions */
 /* pci functions */
 extern int	pciehp_configure_device		(struct slot *p_slot);
 extern int	pciehp_configure_device		(struct slot *p_slot);
 extern int	pciehp_unconfigure_device	(struct slot *p_slot);
 extern int	pciehp_unconfigure_device	(struct slot *p_slot);
-extern int	pciehp_get_hp_hw_control_from_firmware(struct pci_dev *dev);
-extern void	pciehp_get_hp_params_from_firmware(struct pci_dev *dev,
-	       	struct hotplug_params *hpp);
 
 
 
 
 
 
@@ -285,4 +277,19 @@ struct hpc_ops {
 	int	(*check_lnk_status)	(struct controller *ctrl);
 	int	(*check_lnk_status)	(struct controller *ctrl);
 };
 };
 
 
+
+#ifdef CONFIG_ACPI
+#define pciehp_get_hp_hw_control_from_firmware(dev) \
+	pciehp_acpi_get_hp_hw_control_from_firmware(dev)
+static inline int pciehp_get_hp_params_from_firmware(struct pci_dev *dev,
+			struct hotplug_params *hpp)
+{
+	if (ACPI_FAILURE(acpi_get_hp_params_from_firmware(dev, hpp)))
+		return -ENODEV;
+	return 0;
+}
+#else
+#define pciehp_get_hp_hw_control_from_firmware(dev) 	0
+#define pciehp_get_hp_params_from_firmware(dev, hpp)    (-ENODEV)
+#endif 				/* CONFIG_ACPI */
 #endif				/* _PCIEHP_H */
 #endif				/* _PCIEHP_H */

+ 7 - 12
drivers/pci/hotplug/pciehp_core.c

@@ -117,27 +117,23 @@ static int init_slots(struct controller *ctrl)
 	slot_number = ctrl->first_slot;
 	slot_number = ctrl->first_slot;
 
 
 	while (number_of_slots) {
 	while (number_of_slots) {
-		slot = kmalloc(sizeof(*slot), GFP_KERNEL);
+		slot = kzalloc(sizeof(*slot), GFP_KERNEL);
 		if (!slot)
 		if (!slot)
 			goto error;
 			goto error;
 
 
-		memset(slot, 0, sizeof(struct slot));
 		slot->hotplug_slot =
 		slot->hotplug_slot =
-				kmalloc(sizeof(*(slot->hotplug_slot)),
+				kzalloc(sizeof(*(slot->hotplug_slot)),
 						GFP_KERNEL);
 						GFP_KERNEL);
 		if (!slot->hotplug_slot)
 		if (!slot->hotplug_slot)
 			goto error_slot;
 			goto error_slot;
 		hotplug_slot = slot->hotplug_slot;
 		hotplug_slot = slot->hotplug_slot;
-		memset(hotplug_slot, 0, sizeof(struct hotplug_slot));
 
 
 		hotplug_slot->info =
 		hotplug_slot->info =
-			kmalloc(sizeof(*(hotplug_slot->info)),
+			kzalloc(sizeof(*(hotplug_slot->info)),
 						GFP_KERNEL);
 						GFP_KERNEL);
 		if (!hotplug_slot->info)
 		if (!hotplug_slot->info)
 			goto error_hpslot;
 			goto error_hpslot;
 		hotplug_slot_info = hotplug_slot->info;
 		hotplug_slot_info = hotplug_slot->info;
-		memset(hotplug_slot_info, 0,
-					sizeof(struct hotplug_slot_info));
 		hotplug_slot->name = kmalloc(SLOT_NAME_SIZE, GFP_KERNEL);
 		hotplug_slot->name = kmalloc(SLOT_NAME_SIZE, GFP_KERNEL);
 		if (!hotplug_slot->name)
 		if (!hotplug_slot->name)
 			goto error_info;
 			goto error_info;
@@ -373,12 +369,11 @@ static int pciehp_probe(struct pcie_device *dev, const struct pcie_port_service_
 	u8 value;
 	u8 value;
 	struct pci_dev *pdev;
 	struct pci_dev *pdev;
 	
 	
-	ctrl = kmalloc(sizeof(*ctrl), GFP_KERNEL);
+	ctrl = kzalloc(sizeof(*ctrl), GFP_KERNEL);
 	if (!ctrl) {
 	if (!ctrl) {
 		err("%s : out of memory\n", __FUNCTION__);
 		err("%s : out of memory\n", __FUNCTION__);
 		goto err_out_none;
 		goto err_out_none;
 	}
 	}
-	memset(ctrl, 0, sizeof(struct controller));
 
 
 	pdev = dev->port;
 	pdev = dev->port;
 	ctrl->pci_dev = pdev;
 	ctrl->pci_dev = pdev;
@@ -439,7 +434,7 @@ static int pciehp_probe(struct pcie_device *dev, const struct pcie_port_service_
 	}
 	}
 
 
 	/* Wait for exclusive access to hardware */
 	/* Wait for exclusive access to hardware */
-	down(&ctrl->crit_sect);
+	mutex_lock(&ctrl->crit_sect);
 
 
 	t_slot->hpc_ops->get_adapter_status(t_slot, &value); /* Check if slot is occupied */
 	t_slot->hpc_ops->get_adapter_status(t_slot, &value); /* Check if slot is occupied */
 	
 	
@@ -447,7 +442,7 @@ static int pciehp_probe(struct pcie_device *dev, const struct pcie_port_service_
 		rc = t_slot->hpc_ops->power_off_slot(t_slot); /* Power off slot if not occupied*/
 		rc = t_slot->hpc_ops->power_off_slot(t_slot); /* Power off slot if not occupied*/
 		if (rc) {
 		if (rc) {
 			/* Done with exclusive hardware access */
 			/* Done with exclusive hardware access */
-			up(&ctrl->crit_sect);
+			mutex_unlock(&ctrl->crit_sect);
 			goto err_out_free_ctrl_slot;
 			goto err_out_free_ctrl_slot;
 		} else
 		} else
 			/* Wait for the command to complete */
 			/* Wait for the command to complete */
@@ -455,7 +450,7 @@ static int pciehp_probe(struct pcie_device *dev, const struct pcie_port_service_
 	}
 	}
 
 
 	/* Done with exclusive hardware access */
 	/* Done with exclusive hardware access */
-	up(&ctrl->crit_sect);
+	mutex_unlock(&ctrl->crit_sect);
 
 
 	return 0;
 	return 0;
 
 

+ 34 - 34
drivers/pci/hotplug/pciehp_ctrl.c

@@ -229,13 +229,13 @@ u8 pciehp_handle_power_fault(u8 hp_slot, void *inst_id)
 static void set_slot_off(struct controller *ctrl, struct slot * pslot)
 static void set_slot_off(struct controller *ctrl, struct slot * pslot)
 {
 {
 	/* Wait for exclusive access to hardware */
 	/* Wait for exclusive access to hardware */
-	down(&ctrl->crit_sect);
+	mutex_lock(&ctrl->crit_sect);
 
 
 	/* turn off slot, turn on Amber LED, turn off Green LED if supported*/
 	/* turn off slot, turn on Amber LED, turn off Green LED if supported*/
 	if (POWER_CTRL(ctrl->ctrlcap)) {
 	if (POWER_CTRL(ctrl->ctrlcap)) {
 		if (pslot->hpc_ops->power_off_slot(pslot)) {   
 		if (pslot->hpc_ops->power_off_slot(pslot)) {   
 			err("%s: Issue of Slot Power Off command failed\n", __FUNCTION__);
 			err("%s: Issue of Slot Power Off command failed\n", __FUNCTION__);
-			up(&ctrl->crit_sect);
+			mutex_unlock(&ctrl->crit_sect);
 			return;
 			return;
 		}
 		}
 		wait_for_ctrl_irq (ctrl);
 		wait_for_ctrl_irq (ctrl);
@@ -249,14 +249,14 @@ static void set_slot_off(struct controller *ctrl, struct slot * pslot)
 	if (ATTN_LED(ctrl->ctrlcap)) { 
 	if (ATTN_LED(ctrl->ctrlcap)) { 
 		if (pslot->hpc_ops->set_attention_status(pslot, 1)) {   
 		if (pslot->hpc_ops->set_attention_status(pslot, 1)) {   
 			err("%s: Issue of Set Attention Led command failed\n", __FUNCTION__);
 			err("%s: Issue of Set Attention Led command failed\n", __FUNCTION__);
-			up(&ctrl->crit_sect);
+			mutex_unlock(&ctrl->crit_sect);
 			return;
 			return;
 		}
 		}
 		wait_for_ctrl_irq (ctrl);
 		wait_for_ctrl_irq (ctrl);
 	}
 	}
 
 
 	/* Done with exclusive hardware access */
 	/* Done with exclusive hardware access */
-	up(&ctrl->crit_sect);
+	mutex_unlock(&ctrl->crit_sect);
 }
 }
 
 
 /**
 /**
@@ -279,13 +279,13 @@ static int board_added(struct slot *p_slot)
 			ctrl->slot_device_offset, hp_slot);
 			ctrl->slot_device_offset, hp_slot);
 
 
 	/* Wait for exclusive access to hardware */
 	/* Wait for exclusive access to hardware */
-	down(&ctrl->crit_sect);
+	mutex_lock(&ctrl->crit_sect);
 
 
 	if (POWER_CTRL(ctrl->ctrlcap)) {
 	if (POWER_CTRL(ctrl->ctrlcap)) {
 		/* Power on slot */
 		/* Power on slot */
 		rc = p_slot->hpc_ops->power_on_slot(p_slot);
 		rc = p_slot->hpc_ops->power_on_slot(p_slot);
 		if (rc) {
 		if (rc) {
-			up(&ctrl->crit_sect);
+			mutex_unlock(&ctrl->crit_sect);
 			return -1;
 			return -1;
 		}
 		}
 
 
@@ -301,7 +301,7 @@ static int board_added(struct slot *p_slot)
 	}
 	}
 
 
 	/* Done with exclusive hardware access */
 	/* Done with exclusive hardware access */
-	up(&ctrl->crit_sect);
+	mutex_unlock(&ctrl->crit_sect);
 
 
 	/* Wait for ~1 second */
 	/* Wait for ~1 second */
 	wait_for_ctrl_irq (ctrl);
 	wait_for_ctrl_irq (ctrl);
@@ -335,7 +335,7 @@ static int board_added(struct slot *p_slot)
 		pci_fixup_device(pci_fixup_final, ctrl->pci_dev);
 		pci_fixup_device(pci_fixup_final, ctrl->pci_dev);
 	if (PWR_LED(ctrl->ctrlcap)) {
 	if (PWR_LED(ctrl->ctrlcap)) {
 		/* Wait for exclusive access to hardware */
 		/* Wait for exclusive access to hardware */
-  		down(&ctrl->crit_sect);
+  		mutex_lock(&ctrl->crit_sect);
 
 
   		p_slot->hpc_ops->green_led_on(p_slot);
   		p_slot->hpc_ops->green_led_on(p_slot);
   
   
@@ -343,7 +343,7 @@ static int board_added(struct slot *p_slot)
   		wait_for_ctrl_irq (ctrl);
   		wait_for_ctrl_irq (ctrl);
   	
   	
   		/* Done with exclusive hardware access */
   		/* Done with exclusive hardware access */
-  		up(&ctrl->crit_sect);
+  		mutex_unlock(&ctrl->crit_sect);
   	}
   	}
 	return 0;
 	return 0;
 
 
@@ -375,14 +375,14 @@ static int remove_board(struct slot *p_slot)
 	dbg("In %s, hp_slot = %d\n", __FUNCTION__, hp_slot);
 	dbg("In %s, hp_slot = %d\n", __FUNCTION__, hp_slot);
 
 
 	/* Wait for exclusive access to hardware */
 	/* Wait for exclusive access to hardware */
-	down(&ctrl->crit_sect);
+	mutex_lock(&ctrl->crit_sect);
 
 
 	if (POWER_CTRL(ctrl->ctrlcap)) {
 	if (POWER_CTRL(ctrl->ctrlcap)) {
 		/* power off slot */
 		/* power off slot */
 		rc = p_slot->hpc_ops->power_off_slot(p_slot);
 		rc = p_slot->hpc_ops->power_off_slot(p_slot);
 		if (rc) {
 		if (rc) {
 			err("%s: Issue of Slot Disable command failed\n", __FUNCTION__);
 			err("%s: Issue of Slot Disable command failed\n", __FUNCTION__);
-			up(&ctrl->crit_sect);
+			mutex_unlock(&ctrl->crit_sect);
 			return rc;
 			return rc;
 		}
 		}
 		/* Wait for the command to complete */
 		/* Wait for the command to complete */
@@ -398,7 +398,7 @@ static int remove_board(struct slot *p_slot)
 	}
 	}
 
 
 	/* Done with exclusive hardware access */
 	/* Done with exclusive hardware access */
-	up(&ctrl->crit_sect);
+	mutex_unlock(&ctrl->crit_sect);
 
 
 	return 0;
 	return 0;
 }
 }
@@ -445,7 +445,7 @@ static void pciehp_pushbutton_thread(unsigned long slot)
 
 
 		if (pciehp_enable_slot(p_slot) && PWR_LED(p_slot->ctrl->ctrlcap)) {
 		if (pciehp_enable_slot(p_slot) && PWR_LED(p_slot->ctrl->ctrlcap)) {
 			/* Wait for exclusive access to hardware */
 			/* Wait for exclusive access to hardware */
-			down(&p_slot->ctrl->crit_sect);
+			mutex_lock(&p_slot->ctrl->crit_sect);
 
 
 			p_slot->hpc_ops->green_led_off(p_slot);
 			p_slot->hpc_ops->green_led_off(p_slot);
 
 
@@ -453,7 +453,7 @@ static void pciehp_pushbutton_thread(unsigned long slot)
 			wait_for_ctrl_irq (p_slot->ctrl);
 			wait_for_ctrl_irq (p_slot->ctrl);
 
 
 			/* Done with exclusive hardware access */
 			/* Done with exclusive hardware access */
-			up(&p_slot->ctrl->crit_sect);
+			mutex_unlock(&p_slot->ctrl->crit_sect);
 		}
 		}
 		p_slot->state = STATIC_STATE;
 		p_slot->state = STATIC_STATE;
 	}
 	}
@@ -495,7 +495,7 @@ static void pciehp_surprise_rm_thread(unsigned long slot)
 
 
 		if (pciehp_enable_slot(p_slot) && PWR_LED(p_slot->ctrl->ctrlcap)) {
 		if (pciehp_enable_slot(p_slot) && PWR_LED(p_slot->ctrl->ctrlcap)) {
 			/* Wait for exclusive access to hardware */
 			/* Wait for exclusive access to hardware */
-			down(&p_slot->ctrl->crit_sect);
+			mutex_lock(&p_slot->ctrl->crit_sect);
 
 
 			p_slot->hpc_ops->green_led_off(p_slot);
 			p_slot->hpc_ops->green_led_off(p_slot);
 
 
@@ -503,7 +503,7 @@ static void pciehp_surprise_rm_thread(unsigned long slot)
 			wait_for_ctrl_irq (p_slot->ctrl);
 			wait_for_ctrl_irq (p_slot->ctrl);
 
 
 			/* Done with exclusive hardware access */
 			/* Done with exclusive hardware access */
-			up(&p_slot->ctrl->crit_sect);
+			mutex_unlock(&p_slot->ctrl->crit_sect);
 		}
 		}
 		p_slot->state = STATIC_STATE;
 		p_slot->state = STATIC_STATE;
 	}
 	}
@@ -616,7 +616,7 @@ static void interrupt_event_handler(struct controller *ctrl)
 					switch (p_slot->state) {
 					switch (p_slot->state) {
 					case BLINKINGOFF_STATE:
 					case BLINKINGOFF_STATE:
 						/* Wait for exclusive access to hardware */
 						/* Wait for exclusive access to hardware */
-						down(&ctrl->crit_sect);
+						mutex_lock(&ctrl->crit_sect);
 						
 						
 						if (PWR_LED(ctrl->ctrlcap)) {
 						if (PWR_LED(ctrl->ctrlcap)) {
 							p_slot->hpc_ops->green_led_on(p_slot);
 							p_slot->hpc_ops->green_led_on(p_slot);
@@ -630,11 +630,11 @@ static void interrupt_event_handler(struct controller *ctrl)
 							wait_for_ctrl_irq (ctrl);
 							wait_for_ctrl_irq (ctrl);
 						}
 						}
 						/* Done with exclusive hardware access */
 						/* Done with exclusive hardware access */
-						up(&ctrl->crit_sect);
+						mutex_unlock(&ctrl->crit_sect);
 						break;
 						break;
 					case BLINKINGON_STATE:
 					case BLINKINGON_STATE:
 						/* Wait for exclusive access to hardware */
 						/* Wait for exclusive access to hardware */
-						down(&ctrl->crit_sect);
+						mutex_lock(&ctrl->crit_sect);
 
 
 						if (PWR_LED(ctrl->ctrlcap)) {
 						if (PWR_LED(ctrl->ctrlcap)) {
 							p_slot->hpc_ops->green_led_off(p_slot);
 							p_slot->hpc_ops->green_led_off(p_slot);
@@ -647,7 +647,7 @@ static void interrupt_event_handler(struct controller *ctrl)
 							wait_for_ctrl_irq (ctrl);
 							wait_for_ctrl_irq (ctrl);
 						}
 						}
 						/* Done with exclusive hardware access */
 						/* Done with exclusive hardware access */
-						up(&ctrl->crit_sect);
+						mutex_unlock(&ctrl->crit_sect);
 
 
 						break;
 						break;
 					default:
 					default:
@@ -676,7 +676,7 @@ static void interrupt_event_handler(struct controller *ctrl)
 						}
 						}
 
 
 						/* Wait for exclusive access to hardware */
 						/* Wait for exclusive access to hardware */
-						down(&ctrl->crit_sect);
+						mutex_lock(&ctrl->crit_sect);
 
 
 						/* blink green LED and turn off amber */
 						/* blink green LED and turn off amber */
 						if (PWR_LED(ctrl->ctrlcap)) {
 						if (PWR_LED(ctrl->ctrlcap)) {
@@ -693,7 +693,7 @@ static void interrupt_event_handler(struct controller *ctrl)
 						}
 						}
 
 
 						/* Done with exclusive hardware access */
 						/* Done with exclusive hardware access */
-						up(&ctrl->crit_sect);
+						mutex_unlock(&ctrl->crit_sect);
 
 
 						init_timer(&p_slot->task_event);
 						init_timer(&p_slot->task_event);
 						p_slot->task_event.expires = jiffies + 5 * HZ;   /* 5 second delay */
 						p_slot->task_event.expires = jiffies + 5 * HZ;   /* 5 second delay */
@@ -708,7 +708,7 @@ static void interrupt_event_handler(struct controller *ctrl)
 					if (POWER_CTRL(ctrl->ctrlcap)) {
 					if (POWER_CTRL(ctrl->ctrlcap)) {
 						dbg("power fault\n");
 						dbg("power fault\n");
 						/* Wait for exclusive access to hardware */
 						/* Wait for exclusive access to hardware */
-						down(&ctrl->crit_sect);
+						mutex_lock(&ctrl->crit_sect);
 
 
 						if (ATTN_LED(ctrl->ctrlcap)) {
 						if (ATTN_LED(ctrl->ctrlcap)) {
 							p_slot->hpc_ops->set_attention_status(p_slot, 1);
 							p_slot->hpc_ops->set_attention_status(p_slot, 1);
@@ -721,7 +721,7 @@ static void interrupt_event_handler(struct controller *ctrl)
 						}
 						}
 
 
 						/* Done with exclusive hardware access */
 						/* Done with exclusive hardware access */
-						up(&ctrl->crit_sect);
+						mutex_unlock(&ctrl->crit_sect);
 					}
 					}
 				}
 				}
 				/***********SURPRISE REMOVAL********************/
 				/***********SURPRISE REMOVAL********************/
@@ -756,19 +756,19 @@ int pciehp_enable_slot(struct slot *p_slot)
 	int rc;
 	int rc;
 
 
 	/* Check to see if (latch closed, card present, power off) */
 	/* Check to see if (latch closed, card present, power off) */
-	down(&p_slot->ctrl->crit_sect);
+	mutex_lock(&p_slot->ctrl->crit_sect);
 
 
 	rc = p_slot->hpc_ops->get_adapter_status(p_slot, &getstatus);
 	rc = p_slot->hpc_ops->get_adapter_status(p_slot, &getstatus);
 	if (rc || !getstatus) {
 	if (rc || !getstatus) {
 		info("%s: no adapter on slot(%x)\n", __FUNCTION__, p_slot->number);
 		info("%s: no adapter on slot(%x)\n", __FUNCTION__, p_slot->number);
-		up(&p_slot->ctrl->crit_sect);
+		mutex_unlock(&p_slot->ctrl->crit_sect);
 		return 1;
 		return 1;
 	}
 	}
 	if (MRL_SENS(p_slot->ctrl->ctrlcap)) {	
 	if (MRL_SENS(p_slot->ctrl->ctrlcap)) {	
 		rc = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
 		rc = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
 		if (rc || getstatus) {
 		if (rc || getstatus) {
 			info("%s: latch open on slot(%x)\n", __FUNCTION__, p_slot->number);
 			info("%s: latch open on slot(%x)\n", __FUNCTION__, p_slot->number);
-			up(&p_slot->ctrl->crit_sect);
+			mutex_unlock(&p_slot->ctrl->crit_sect);
 			return 1;
 			return 1;
 		}
 		}
 	}
 	}
@@ -777,11 +777,11 @@ int pciehp_enable_slot(struct slot *p_slot)
 		rc = p_slot->hpc_ops->get_power_status(p_slot, &getstatus);
 		rc = p_slot->hpc_ops->get_power_status(p_slot, &getstatus);
 		if (rc || getstatus) {
 		if (rc || getstatus) {
 			info("%s: already enabled on slot(%x)\n", __FUNCTION__, p_slot->number);
 			info("%s: already enabled on slot(%x)\n", __FUNCTION__, p_slot->number);
-			up(&p_slot->ctrl->crit_sect);
+			mutex_unlock(&p_slot->ctrl->crit_sect);
 			return 1;
 			return 1;
 		}
 		}
 	}
 	}
-	up(&p_slot->ctrl->crit_sect);
+	mutex_unlock(&p_slot->ctrl->crit_sect);
 
 
 	p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
 	p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
 
 
@@ -806,13 +806,13 @@ int pciehp_disable_slot(struct slot *p_slot)
 		return 1;
 		return 1;
 
 
 	/* Check to see if (latch closed, card present, power on) */
 	/* Check to see if (latch closed, card present, power on) */
-	down(&p_slot->ctrl->crit_sect);
+	mutex_lock(&p_slot->ctrl->crit_sect);
 
 
 	if (!HP_SUPR_RM(p_slot->ctrl->ctrlcap)) {	
 	if (!HP_SUPR_RM(p_slot->ctrl->ctrlcap)) {	
 		ret = p_slot->hpc_ops->get_adapter_status(p_slot, &getstatus);
 		ret = p_slot->hpc_ops->get_adapter_status(p_slot, &getstatus);
 		if (ret || !getstatus) {
 		if (ret || !getstatus) {
 			info("%s: no adapter on slot(%x)\n", __FUNCTION__, p_slot->number);
 			info("%s: no adapter on slot(%x)\n", __FUNCTION__, p_slot->number);
-			up(&p_slot->ctrl->crit_sect);
+			mutex_unlock(&p_slot->ctrl->crit_sect);
 			return 1;
 			return 1;
 		}
 		}
 	}
 	}
@@ -821,7 +821,7 @@ int pciehp_disable_slot(struct slot *p_slot)
 		ret = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
 		ret = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
 		if (ret || getstatus) {
 		if (ret || getstatus) {
 			info("%s: latch open on slot(%x)\n", __FUNCTION__, p_slot->number);
 			info("%s: latch open on slot(%x)\n", __FUNCTION__, p_slot->number);
-			up(&p_slot->ctrl->crit_sect);
+			mutex_unlock(&p_slot->ctrl->crit_sect);
 			return 1;
 			return 1;
 		}
 		}
 	}
 	}
@@ -830,12 +830,12 @@ int pciehp_disable_slot(struct slot *p_slot)
 		ret = p_slot->hpc_ops->get_power_status(p_slot, &getstatus);
 		ret = p_slot->hpc_ops->get_power_status(p_slot, &getstatus);
 		if (ret || !getstatus) {
 		if (ret || !getstatus) {
 			info("%s: already disabled slot(%x)\n", __FUNCTION__, p_slot->number);
 			info("%s: already disabled slot(%x)\n", __FUNCTION__, p_slot->number);
-			up(&p_slot->ctrl->crit_sect);
+			mutex_unlock(&p_slot->ctrl->crit_sect);
 			return 1;
 			return 1;
 		}
 		}
 	}
 	}
 
 
-	up(&p_slot->ctrl->crit_sect);
+	mutex_unlock(&p_slot->ctrl->crit_sect);
 
 
 	ret = remove_board(p_slot);
 	ret = remove_board(p_slot);
 	update_slot_info(p_slot);
 	update_slot_info(p_slot);

+ 75 - 2
drivers/pci/hotplug/pciehp_hpc.c

@@ -38,7 +38,10 @@
 
 
 #include "../pci.h"
 #include "../pci.h"
 #include "pciehp.h"
 #include "pciehp.h"
-
+#include <acpi/acpi.h>
+#include <acpi/acpi_bus.h>
+#include <acpi/actypes.h>
+#include <linux/pci-acpi.h>
 #ifdef DEBUG
 #ifdef DEBUG
 #define DBG_K_TRACE_ENTRY      ((unsigned int)0x00000001)	/* On function entry */
 #define DBG_K_TRACE_ENTRY      ((unsigned int)0x00000001)	/* On function entry */
 #define DBG_K_TRACE_EXIT       ((unsigned int)0x00000002)	/* On function exit */
 #define DBG_K_TRACE_EXIT       ((unsigned int)0x00000002)	/* On function exit */
@@ -1236,6 +1239,76 @@ static struct hpc_ops pciehp_hpc_ops = {
 	.check_lnk_status		= hpc_check_lnk_status,
 	.check_lnk_status		= hpc_check_lnk_status,
 };
 };
 
 
+#ifdef CONFIG_ACPI
+int pciehp_acpi_get_hp_hw_control_from_firmware(struct pci_dev *dev)
+{
+	acpi_status status;
+	acpi_handle chandle, handle = DEVICE_ACPI_HANDLE(&(dev->dev));
+	struct pci_dev *pdev = dev;
+	struct pci_bus *parent;
+	struct acpi_buffer string = { ACPI_ALLOCATE_BUFFER, NULL };
+
+	/*
+	 * Per PCI firmware specification, we should run the ACPI _OSC
+	 * method to get control of hotplug hardware before using it.
+	 * If an _OSC is missing, we look for an OSHP to do the same thing.
+	 * To handle different BIOS behavior, we look for _OSC and OSHP
+	 * within the scope of the hotplug controller and its parents, upto
+	 * the host bridge under which this controller exists.
+	 */
+	while (!handle) {
+		/*
+		 * This hotplug controller was not listed in the ACPI name
+		 * space at all. Try to get acpi handle of parent pci bus.
+		 */
+		if (!pdev || !pdev->bus->parent)
+			break;
+		parent = pdev->bus->parent;
+		dbg("Could not find %s in acpi namespace, trying parent\n",
+				pci_name(pdev));
+		if (!parent->self)
+			/* Parent must be a host bridge */
+			handle = acpi_get_pci_rootbridge_handle(
+					pci_domain_nr(parent),
+					parent->number);
+		else
+			handle = DEVICE_ACPI_HANDLE(
+					&(parent->self->dev));
+		pdev = parent->self;
+	}
+
+	while (handle) {
+		acpi_get_name(handle, ACPI_FULL_PATHNAME, &string);
+		dbg("Trying to get hotplug control for %s \n",
+			(char *)string.pointer);
+		status = pci_osc_control_set(handle,
+				OSC_PCI_EXPRESS_NATIVE_HP_CONTROL);
+		if (status == AE_NOT_FOUND)
+			status = acpi_run_oshp(handle);
+		if (ACPI_SUCCESS(status)) {
+			dbg("Gained control for hotplug HW for pci %s (%s)\n",
+				pci_name(dev), (char *)string.pointer);
+			acpi_os_free(string.pointer);
+			return 0;
+		}
+		if (acpi_root_bridge(handle))
+			break;
+		chandle = handle;
+		status = acpi_get_parent(chandle, &handle);
+		if (ACPI_FAILURE(status))
+			break;
+	}
+
+	err("Cannot get control of hotplug hardware for pci %s\n",
+			pci_name(dev));
+
+	acpi_os_free(string.pointer);
+	return -1;
+}
+#endif
+
+
+
 int pcie_init(struct controller * ctrl, struct pcie_device *dev)
 int pcie_init(struct controller * ctrl, struct pcie_device *dev)
 {
 {
 	struct php_ctlr_state_s *php_ctlr, *p;
 	struct php_ctlr_state_s *php_ctlr, *p;
@@ -1334,7 +1407,7 @@ int pcie_init(struct controller * ctrl, struct pcie_device *dev)
 	if (pci_enable_device(pdev))
 	if (pci_enable_device(pdev))
 		goto abort_free_ctlr;
 		goto abort_free_ctlr;
 	
 	
-	init_MUTEX(&ctrl->crit_sect);
+	mutex_init(&ctrl->crit_sect);
 	/* setup wait queue */
 	/* setup wait queue */
 	init_waitqueue_head(&ctrl->queue);
 	init_waitqueue_head(&ctrl->queue);
 
 

+ 0 - 257
drivers/pci/hotplug/pciehprm_acpi.c

@@ -1,257 +0,0 @@
-/*
- * PCIEHPRM ACPI: PHP Resource Manager for ACPI platform
- *
- * 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 <kristen.c.accardi@intel.com>
- *
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/pci.h>
-#include <linux/acpi.h>
-#include <linux/pci-acpi.h>
-#include <acpi/acpi_bus.h>
-#include <acpi/actypes.h>
-#include "pciehp.h"
-
-#define	METHOD_NAME__SUN	"_SUN"
-#define	METHOD_NAME__HPP	"_HPP"
-#define	METHOD_NAME_OSHP	"OSHP"
-
-static u8 * acpi_path_name( acpi_handle	handle)
-{
-	acpi_status		status;
-	static u8		path_name[ACPI_PATHNAME_MAX];
-	struct acpi_buffer	ret_buf = { ACPI_PATHNAME_MAX, path_name };
-
-	memset(path_name, 0, sizeof (path_name));
-	status = acpi_get_name(handle, ACPI_FULL_PATHNAME, &ret_buf);
-
-	if (ACPI_FAILURE(status))
-		return NULL;
-	else
-		return path_name;	
-}
-
-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(handle);
-	int			i, len = 0;
-
-	/* get _hpp */
-	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 ("%s:%s alloc for _HPP fail\n", __FUNCTION__,
-					path_name);
-			return AE_NO_MEMORY;
-		}
-		status = acpi_evaluate_object(handle, METHOD_NAME__HPP,
-				NULL, &ret_buf);
-		if (ACPI_SUCCESS(status))
-			break;
-	default:
-		if (ACPI_FAILURE(status)) {
-			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 ("%s:%s _HPP obj not a package\n", __FUNCTION__,
-				path_name);
-		status = AE_ERROR;
-		goto free_and_return;
-	}
-
-	len = ext_obj->package.count;
-	package = (union acpi_object *) ret_buf.pointer;
-	for ( i = 0; (i < len) || (i < 4); i++) {
-		ext_obj = (union acpi_object *) &package->package.elements[i];
-		switch (ext_obj->type) {
-		case ACPI_TYPE_INTEGER:
-			nui[i] = (u8)ext_obj->integer.value;
-			break;
-		default:
-			err ("%s:%s _HPP obj type incorrect\n", __FUNCTION__,
-					path_name);
-			status = AE_ERROR;
-			goto free_and_return;
-		}
-	}
-
-	hpp->cache_line_size = nui[0];
-	hpp->latency_timer = nui[1];
-	hpp->enable_serr = nui[2];
-	hpp->enable_perr = nui[3];
-
-	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);
-	return status;
-}
-
-static acpi_status acpi_run_oshp(acpi_handle handle)
-{
-	acpi_status		status;
-	u8			*path_name = acpi_path_name(handle);
-
-	/* run OSHP */
-	status = acpi_evaluate_object(handle, METHOD_NAME_OSHP, NULL, NULL);
-	if (ACPI_FAILURE(status)) {
-		dbg("%s:%s OSHP fails=0x%x\n", __FUNCTION__, path_name,
-				status);
-	} else {
-		dbg("%s:%s OSHP passes\n", __FUNCTION__, path_name);
-	}
-	return status;
-}
-
-static int is_root_bridge(acpi_handle handle)
-{
-	acpi_status status;
-	struct acpi_device_info *info;
-	struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
-	int i;
-
-	status = acpi_get_object_info(handle, &buffer);
-	if (ACPI_SUCCESS(status)) {
-		info = buffer.pointer;
-		if ((info->valid & ACPI_VALID_HID) &&
-			!strcmp(PCI_ROOT_HID_STRING,
-					info->hardware_id.value)) {
-			acpi_os_free(buffer.pointer);
-			return 1;
-		}
-		if (info->valid & ACPI_VALID_CID) {
-			for (i=0; i < info->compatibility_id.count; i++) {
-				if (!strcmp(PCI_ROOT_HID_STRING,
-					info->compatibility_id.id[i].value)) {
-					acpi_os_free(buffer.pointer);
-					return 1;
-				}
-			}
-		}
-	}
-	return 0;
-}
-
-int pciehp_get_hp_hw_control_from_firmware(struct pci_dev *dev)
-{
-	acpi_status status;
-	acpi_handle chandle, handle = DEVICE_ACPI_HANDLE(&(dev->dev));
-	struct pci_dev *pdev = dev;
-	struct pci_bus *parent;
-	u8 *path_name;
-
-	/*
-	 * Per PCI firmware specification, we should run the ACPI _OSC
-	 * method to get control of hotplug hardware before using it.
-	 * If an _OSC is missing, we look for an OSHP to do the same thing.
-	 * To handle different BIOS behavior, we look for _OSC and OSHP
-	 * within the scope of the hotplug controller and its parents, upto
-	 * the host bridge under which this controller exists.
-	 */
-	while (!handle) {
-		/*
-		 * This hotplug controller was not listed in the ACPI name
-		 * space at all. Try to get acpi handle of parent pci bus.
-		 */
-		if (!pdev || !pdev->bus->parent)
-			break;
-		parent = pdev->bus->parent;
-		dbg("Could not find %s in acpi namespace, trying parent\n",
-				pci_name(pdev));
-		if (!parent->self)
-			/* Parent must be a host bridge */
-			handle = acpi_get_pci_rootbridge_handle(
-					pci_domain_nr(parent),
-					parent->number);
-		else
-			handle = DEVICE_ACPI_HANDLE(
-					&(parent->self->dev));
-		pdev = parent->self;
-	}
-
-	while (handle) {
-		path_name = acpi_path_name(handle);
-		dbg("Trying to get hotplug control for %s \n", path_name);
-		status = pci_osc_control_set(handle,
-				OSC_PCI_EXPRESS_NATIVE_HP_CONTROL);
-		if (status == AE_NOT_FOUND)
-			status = acpi_run_oshp(handle);
-		if (ACPI_SUCCESS(status)) {
-			dbg("Gained control for hotplug HW for pci %s (%s)\n",
-				pci_name(dev), path_name);
-			return 0;
-		}
-		if (is_root_bridge(handle))
-			break;
-		chandle = handle;
-		status = acpi_get_parent(chandle, &handle);
-		if (ACPI_FAILURE(status))
-			break;
-	}
-
-	err("Cannot get control of hotplug hardware for pci %s\n",
-			pci_name(dev));
-	return -1;
-}
-
-void pciehp_get_hp_params_from_firmware(struct pci_dev *dev,
-		struct hotplug_params *hpp)
-{
-	acpi_status status = AE_NOT_FOUND;
-	struct pci_dev *pdev = dev;
-
-	/*
-	 * _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;
-	}
-}
-

+ 0 - 47
drivers/pci/hotplug/pciehprm_nonacpi.c

@@ -1,47 +0,0 @@
-/*
- * PCIEHPRM 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>
- *
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/sched.h>
-#include <linux/pci.h>
-#include <linux/slab.h>
-#include "pciehp.h"
-
-void pciehp_get_hp_params_from_firmware(struct pci_dev *dev,
-		struct hotplug_params *hpp)
-{
-	return;
-}
-
-int pciehp_get_hp_hw_control_from_firmware(struct pci_dev *dev)
-{
-	return 0;
-}

+ 11 - 22
drivers/pci/hotplug/pcihp_skeleton.c

@@ -37,10 +37,12 @@
 #include <linux/init.h>
 #include <linux/init.h>
 #include "pci_hotplug.h"
 #include "pci_hotplug.h"
 
 
+#define SLOT_NAME_SIZE	10
 struct slot {
 struct slot {
 	u8 number;
 	u8 number;
 	struct hotplug_slot *hotplug_slot;
 	struct hotplug_slot *hotplug_slot;
 	struct list_head slot_list;
 	struct list_head slot_list;
+	char name[SLOT_NAME_SIZE];
 };
 };
 
 
 static LIST_HEAD(slot_list);
 static LIST_HEAD(slot_list);
@@ -233,12 +235,10 @@ static void release_slot(struct hotplug_slot *hotplug_slot)
 
 
 	dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
 	dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
 	kfree(slot->hotplug_slot->info);
 	kfree(slot->hotplug_slot->info);
-	kfree(slot->hotplug_slot->name);
 	kfree(slot->hotplug_slot);
 	kfree(slot->hotplug_slot);
 	kfree(slot);
 	kfree(slot);
 }
 }
 
 
-#define SLOT_NAME_SIZE	10
 static void make_slot_name(struct slot *slot)
 static void make_slot_name(struct slot *slot)
 {
 {
 	/*
 	/*
@@ -257,7 +257,6 @@ static int __init init_slots(void)
 	struct slot *slot;
 	struct slot *slot;
 	struct hotplug_slot *hotplug_slot;
 	struct hotplug_slot *hotplug_slot;
 	struct hotplug_slot_info *info;
 	struct hotplug_slot_info *info;
-	char *name;
 	int retval = -ENOMEM;
 	int retval = -ENOMEM;
 	int i;
 	int i;
 
 
@@ -266,31 +265,23 @@ static int __init init_slots(void)
 	 * with the pci_hotplug subsystem.
 	 * with the pci_hotplug subsystem.
 	 */
 	 */
 	for (i = 0; i < num_slots; ++i) {
 	for (i = 0; i < num_slots; ++i) {
-		slot = kmalloc(sizeof(struct slot), GFP_KERNEL);
+		slot = kzalloc(sizeof(*slot), GFP_KERNEL);
 		if (!slot)
 		if (!slot)
 			goto error;
 			goto error;
-		memset(slot, 0, sizeof(struct slot));
 
 
-		hotplug_slot = kmalloc(sizeof(struct hotplug_slot),
-					GFP_KERNEL);
+		hotplug_slot = kzalloc(sizeof(*hotplug_slot), GFP_KERNEL);
 		if (!hotplug_slot)
 		if (!hotplug_slot)
 			goto error_slot;
 			goto error_slot;
-		memset(hotplug_slot, 0, sizeof (struct hotplug_slot));
 		slot->hotplug_slot = hotplug_slot;
 		slot->hotplug_slot = hotplug_slot;
 
 
-		info = kmalloc(sizeof(struct hotplug_slot_info), GFP_KERNEL);
+		info = kzalloc(sizeof(*info), GFP_KERNEL);
 		if (!info)
 		if (!info)
 			goto error_hpslot;
 			goto error_hpslot;
-		memset(info, 0, sizeof (struct hotplug_slot_info));
 		hotplug_slot->info = info;
 		hotplug_slot->info = info;
 
 
-		name = kmalloc(SLOT_NAME_SIZE, GFP_KERNEL);
-		if (!name)
-			goto error_info;
-		hotplug_slot->name = name;
-
 		slot->number = i;
 		slot->number = i;
 
 
+		hotplug_slot->name = slot->name;
 		hotplug_slot->private = slot;
 		hotplug_slot->private = slot;
 		hotplug_slot->release = &release_slot;
 		hotplug_slot->release = &release_slot;
 		make_slot_name(slot);
 		make_slot_name(slot);
@@ -300,16 +291,16 @@ static int __init init_slots(void)
 		 * Initialize the slot info structure with some known
 		 * Initialize the slot info structure with some known
 		 * good values.
 		 * good values.
 		 */
 		 */
-		info->power_status = get_power_status(slot);
-		info->attention_status = get_attention_status(slot);
-		info->latch_status = get_latch_status(slot);
-		info->adapter_status = get_adapter_status(slot);
+		get_power_status(hotplug_slot, &info->power_status);
+		get_attention_status(hotplug_slot, &info->attention_status);
+		get_latch_status(hotplug_slot, &info->latch_status);
+		get_adapter_status(hotplug_slot, &info->adapter_status);
 		
 		
 		dbg("registering slot %d\n", i);
 		dbg("registering slot %d\n", i);
 		retval = pci_hp_register(slot->hotplug_slot);
 		retval = pci_hp_register(slot->hotplug_slot);
 		if (retval) {
 		if (retval) {
 			err("pci_hp_register failed with error %d\n", retval);
 			err("pci_hp_register failed with error %d\n", retval);
-			goto error_name;
+			goto error_info;
 		}
 		}
 
 
 		/* add slot to our internal list */
 		/* add slot to our internal list */
@@ -317,8 +308,6 @@ static int __init init_slots(void)
 	}
 	}
 
 
 	return 0;
 	return 0;
-error_name:
-	kfree(name);
 error_info:
 error_info:
 	kfree(info);
 	kfree(info);
 error_hpslot:
 error_hpslot:

+ 3 - 6
drivers/pci/hotplug/rpaphp_slot.c

@@ -84,19 +84,16 @@ struct slot *alloc_slot_struct(struct device_node *dn, int drc_index, char *drc_
 {
 {
 	struct slot *slot;
 	struct slot *slot;
 	
 	
-	slot = kmalloc(sizeof (struct slot), GFP_KERNEL);
+	slot = kzalloc(sizeof(struct slot), GFP_KERNEL);
 	if (!slot)
 	if (!slot)
 		goto error_nomem;
 		goto error_nomem;
-	memset(slot, 0, sizeof (struct slot));
-	slot->hotplug_slot = kmalloc(sizeof (struct hotplug_slot), GFP_KERNEL);
+	slot->hotplug_slot = kzalloc(sizeof(struct hotplug_slot), GFP_KERNEL);
 	if (!slot->hotplug_slot)
 	if (!slot->hotplug_slot)
 		goto error_slot;	
 		goto error_slot;	
-	memset(slot->hotplug_slot, 0, sizeof (struct hotplug_slot));
-	slot->hotplug_slot->info = kmalloc(sizeof (struct hotplug_slot_info),
+	slot->hotplug_slot->info = kzalloc(sizeof(struct hotplug_slot_info),
 					   GFP_KERNEL);
 					   GFP_KERNEL);
 	if (!slot->hotplug_slot->info)
 	if (!slot->hotplug_slot->info)
 		goto error_hpslot;
 		goto error_hpslot;
-	memset(slot->hotplug_slot->info, 0, sizeof (struct hotplug_slot_info));
 	slot->hotplug_slot->name = kmalloc(BUS_ID_SIZE + 1, GFP_KERNEL);
 	slot->hotplug_slot->name = kmalloc(BUS_ID_SIZE + 1, GFP_KERNEL);
 	if (!slot->hotplug_slot->name)
 	if (!slot->hotplug_slot->name)
 		goto error_info;	
 		goto error_info;	

+ 8 - 8
drivers/pci/hotplug/sgi_hotplug.c

@@ -3,7 +3,7 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  * for more details.
  *
  *
- * Copyright (C) 2005 Silicon Graphics, Inc. All rights reserved.
+ * Copyright (C) 2005-2006 Silicon Graphics, Inc. All rights reserved.
  *
  *
  * This work was based on the 2.4/2.6 kernel development by Dick Reigner.
  * This work was based on the 2.4/2.6 kernel development by Dick Reigner.
  * Work to add BIOS PROM support was completed by Mike Habeck.
  * Work to add BIOS PROM support was completed by Mike Habeck.
@@ -230,6 +230,13 @@ static void sn_bus_free_data(struct pci_dev *dev)
 		list_for_each_entry(child, &subordinate_bus->devices, bus_list)
 		list_for_each_entry(child, &subordinate_bus->devices, bus_list)
 			sn_bus_free_data(child);
 			sn_bus_free_data(child);
 	}
 	}
+	/*
+	 * Some drivers may use dma accesses during the
+	 * driver remove function. We release the sysdata
+	 * areas after the driver remove functions have
+	 * been called.
+	 */
+	sn_bus_store_sysdata(dev);
 	sn_pci_unfixup_slot(dev);
 	sn_pci_unfixup_slot(dev);
 }
 }
 
 
@@ -429,13 +436,6 @@ static int disable_slot(struct hotplug_slot *bss_hotplug_slot)
 				   PCI_DEVFN(slot->device_num + 1,
 				   PCI_DEVFN(slot->device_num + 1,
 				   	     PCI_FUNC(func)));
 				   	     PCI_FUNC(func)));
 		if (dev) {
 		if (dev) {
-			/*
-			 * Some drivers may use dma accesses during the
-			 * driver remove function. We release the sysdata
-			 * areas after the driver remove functions have
-			 * been called.
-			 */
-			sn_bus_store_sysdata(dev);
 			sn_bus_free_data(dev);
 			sn_bus_free_data(dev);
 			pci_remove_bus_device(dev);
 			pci_remove_bus_device(dev);
 			pci_dev_put(dev);
 			pci_dev_put(dev);

+ 38 - 70
drivers/pci/hotplug/shpchp.h

@@ -33,6 +33,7 @@
 #include <linux/pci.h>
 #include <linux/pci.h>
 #include <linux/delay.h>
 #include <linux/delay.h>
 #include <linux/sched.h>	/* signal_pending(), struct timer_list */
 #include <linux/sched.h>	/* signal_pending(), struct timer_list */
+#include <linux/mutex.h>
 
 
 #include "pci_hotplug.h"
 #include "pci_hotplug.h"
 
 
@@ -45,6 +46,7 @@
 extern int shpchp_poll_mode;
 extern int shpchp_poll_mode;
 extern int shpchp_poll_time;
 extern int shpchp_poll_time;
 extern int shpchp_debug;
 extern int shpchp_debug;
+extern struct workqueue_struct *shpchp_wq;
 
 
 /*#define dbg(format, arg...) do { if (shpchp_debug) printk(KERN_DEBUG "%s: " format, MY_NAME , ## arg); } while (0)*/
 /*#define dbg(format, arg...) do { if (shpchp_debug) printk(KERN_DEBUG "%s: " format, MY_NAME , ## arg); } while (0)*/
 #define dbg(format, arg...) do { if (shpchp_debug) printk("%s: " format, MY_NAME , ## arg); } while (0)
 #define dbg(format, arg...) do { if (shpchp_debug) printk("%s: " format, MY_NAME , ## arg); } while (0)
@@ -52,10 +54,8 @@ extern int shpchp_debug;
 #define info(format, arg...) printk(KERN_INFO "%s: " format, MY_NAME , ## arg)
 #define info(format, arg...) printk(KERN_INFO "%s: " format, MY_NAME , ## arg)
 #define warn(format, arg...) printk(KERN_WARNING "%s: " format, MY_NAME , ## arg)
 #define warn(format, arg...) printk(KERN_WARNING "%s: " format, MY_NAME , ## arg)
 
 
-#define SLOT_MAGIC	0x67267321
+#define SLOT_NAME_SIZE 10
 struct slot {
 struct slot {
-	u32 magic;
-	struct slot *next;
 	u8 bus;
 	u8 bus;
 	u8 device;
 	u8 device;
 	u16 status;
 	u16 status;
@@ -70,26 +70,27 @@ struct slot {
 	struct hpc_ops *hpc_ops;
 	struct hpc_ops *hpc_ops;
 	struct hotplug_slot *hotplug_slot;
 	struct hotplug_slot *hotplug_slot;
 	struct list_head	slot_list;
 	struct list_head	slot_list;
+	char name[SLOT_NAME_SIZE];
+	struct work_struct work;	/* work for button event */
+	struct mutex lock;
 };
 };
 
 
 struct event_info {
 struct event_info {
 	u32 event_type;
 	u32 event_type;
-	u8 hp_slot;
+	struct slot *p_slot;
+	struct work_struct work;
 };
 };
 
 
 struct controller {
 struct controller {
-	struct controller *next;
-	struct semaphore crit_sect;	/* critical section semaphore */
+	struct mutex crit_sect;		/* critical section mutex */
+	struct mutex cmd_lock;		/* command lock */
 	struct php_ctlr_state_s *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 num_slots;			/* Number of slots on ctlr */
 	int slot_num_inc;		/* 1 or -1 */
 	int slot_num_inc;		/* 1 or -1 */
 	struct pci_dev *pci_dev;
 	struct pci_dev *pci_dev;
-	struct pci_bus *pci_bus;
-	struct event_info event_queue[10];
-	struct slot *slot;
+	struct list_head slot_list;
 	struct hpc_ops *hpc_ops;
 	struct hpc_ops *hpc_ops;
 	wait_queue_head_t queue;	/* sleep & wake process */
 	wait_queue_head_t queue;	/* sleep & wake process */
-	u8 next_event;
 	u8 bus;
 	u8 bus;
 	u8 device;
 	u8 device;
 	u8 function;
 	u8 function;
@@ -105,12 +106,6 @@ struct controller {
 	volatile int cmd_busy;
 	volatile int cmd_busy;
 };
 };
 
 
-struct hotplug_params {
-	u8	cache_line_size;
-	u8	latency_timer;
-	u8	enable_serr;
-	u8	enable_perr;
-};
 
 
 /* Define AMD SHPC ID  */
 /* Define AMD SHPC ID  */
 #define PCI_DEVICE_ID_AMD_GOLAM_7450	0x7450 
 #define PCI_DEVICE_ID_AMD_GOLAM_7450	0x7450 
@@ -180,11 +175,8 @@ struct hotplug_params {
 /* sysfs functions for the hotplug controller info */
 /* sysfs functions for the hotplug controller info */
 extern void shpchp_create_ctrl_files	(struct controller *ctrl);
 extern void shpchp_create_ctrl_files	(struct controller *ctrl);
 
 
-/* controller functions */
-extern int	shpchp_event_start_thread(void);
-extern void	shpchp_event_stop_thread(void);
-extern int	shpchp_enable_slot(struct slot *slot);
-extern int	shpchp_disable_slot(struct slot *slot);
+extern int	shpchp_sysfs_enable_slot(struct slot *slot);
+extern int	shpchp_sysfs_disable_slot(struct slot *slot);
 
 
 extern u8	shpchp_handle_attention_button(u8 hp_slot, void *inst_id);
 extern u8	shpchp_handle_attention_button(u8 hp_slot, void *inst_id);
 extern u8	shpchp_handle_switch_change(u8 hp_slot, void *inst_id);
 extern u8	shpchp_handle_switch_change(u8 hp_slot, void *inst_id);
@@ -195,16 +187,28 @@ extern u8	shpchp_handle_power_fault(u8 hp_slot, void *inst_id);
 extern int	shpchp_save_config(struct controller *ctrl, int busnumber, int num_ctlr_slots, int first_device_num);
 extern int	shpchp_save_config(struct controller *ctrl, int busnumber, int num_ctlr_slots, int first_device_num);
 extern int	shpchp_configure_device(struct slot *p_slot);
 extern int	shpchp_configure_device(struct slot *p_slot);
 extern int	shpchp_unconfigure_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);
 extern void	shpchp_remove_ctrl_files(struct controller *ctrl);
+extern void	cleanup_slots(struct controller *ctrl);
+extern void	queue_pushbutton_work(void *data);
 
 
 
 
-/* Global variables */
-extern struct controller *shpchp_ctrl_list;
+#ifdef CONFIG_ACPI
+static inline int get_hp_params_from_firmware(struct pci_dev *dev,
+			struct hotplug_params *hpp)
+{
+	if (ACPI_FAILURE(acpi_get_hp_params_from_firmware(dev, hpp)))
+			return -ENODEV;
+	return 0;
+}
+#define get_hp_hw_control_from_firmware(pdev) \
+	do { \
+		if (DEVICE_ACPI_HANDLE(&(pdev->dev))) \
+			acpi_run_oshp(DEVICE_ACPI_HANDLE(&(pdev->dev))); \
+	} while (0)
+#else
+#define get_hp_params_from_firmware(dev, hpp) (-ENODEV)
+#define get_hp_hw_control_from_firmware(dev) do { } while (0)
+#endif
 
 
 struct ctrl_reg {
 struct ctrl_reg {
 	volatile u32 base_offset;
 	volatile u32 base_offset;
@@ -286,10 +290,6 @@ static inline int slot_paranoia_check (struct slot *slot, const char *function)
 		dbg("%s - slot == NULL", function);
 		dbg("%s - slot == NULL", function);
 		return -1;
 		return -1;
 	}
 	}
-	if (slot->magic != SLOT_MAGIC) {
-		dbg("%s - bad magic number for slot", function);
-		return -1;
-	}
 	if (!slot->hotplug_slot) {
 	if (!slot->hotplug_slot) {
 		dbg("%s - slot->hotplug_slot == NULL!", function);
 		dbg("%s - slot->hotplug_slot == NULL!", function);
 		return -1;
 		return -1;
@@ -314,44 +314,19 @@ static inline struct slot *get_slot (struct hotplug_slot *hotplug_slot, const ch
 
 
 static inline struct slot *shpchp_find_slot (struct controller *ctrl, u8 device)
 static inline struct slot *shpchp_find_slot (struct controller *ctrl, u8 device)
 {
 {
-	struct slot *p_slot, *tmp_slot = NULL;
+	struct slot *slot;
 
 
 	if (!ctrl)
 	if (!ctrl)
 		return NULL;
 		return NULL;
 
 
-	p_slot = ctrl->slot;
-
-	while (p_slot && (p_slot->device != device)) {
-		tmp_slot = p_slot;
-		p_slot = p_slot->next;
+	list_for_each_entry(slot, &ctrl->slot_list, slot_list) {
+		if (slot->device == device)
+			return slot;
 	}
 	}
-	if (p_slot == NULL) {
-		err("ERROR: shpchp_find_slot device=0x%x\n", device);
-		p_slot = tmp_slot;
-	}
-
-	return (p_slot);
-}
-
-static inline int wait_for_ctrl_irq (struct controller *ctrl)
-{
-    DECLARE_WAITQUEUE(wait, current);
-	int retval = 0;
-
-	add_wait_queue(&ctrl->queue, &wait);
 
 
-	if (!shpchp_poll_mode) {
-		/* Sleep for up to 1 second */
-		msleep_interruptible(1000);
-	} else {
-		/* Sleep for up to 2 seconds */
-		msleep_interruptible(2000);
-	}
-	remove_wait_queue(&ctrl->queue, &wait);
-	if (signal_pending(current))
-		retval =  -EINTR;
+	err("%s: slot (device=0x%x) not found\n", __FUNCTION__, device);
 
 
-	return retval;
+	return NULL;
 }
 }
 
 
 static inline void amd_pogo_errata_save_misc_reg(struct slot *p_slot)
 static inline void amd_pogo_errata_save_misc_reg(struct slot *p_slot)
@@ -427,13 +402,6 @@ static inline void amd_pogo_errata_restore_misc_reg(struct slot *p_slot)
 	pci_write_config_dword(p_slot->ctrl->pci_dev, PCIX_MISCII_OFFSET, pcix_misc2_temp);
 	pci_write_config_dword(p_slot->ctrl->pci_dev, PCIX_MISCII_OFFSET, pcix_misc2_temp);
 }
 }
 
 
-#define SLOT_NAME_SIZE 10
-
-static inline void make_slot_name(char *buffer, int buffer_size, struct slot *slot)
-{
-	snprintf(buffer, buffer_size, "%04d_%04d", slot->bus, slot->number);
-}
-
 enum php_ctlr_type {
 enum php_ctlr_type {
 	PCI,
 	PCI,
 	ISA,
 	ISA,

+ 137 - 194
drivers/pci/hotplug/shpchp_core.c

@@ -32,13 +32,14 @@
 #include <linux/kernel.h>
 #include <linux/kernel.h>
 #include <linux/types.h>
 #include <linux/types.h>
 #include <linux/pci.h>
 #include <linux/pci.h>
+#include <linux/workqueue.h>
 #include "shpchp.h"
 #include "shpchp.h"
 
 
 /* Global variables */
 /* Global variables */
 int shpchp_debug;
 int shpchp_debug;
 int shpchp_poll_mode;
 int shpchp_poll_mode;
 int shpchp_poll_time;
 int shpchp_poll_time;
-struct controller *shpchp_ctrl_list;	/* = NULL */
+struct workqueue_struct *shpchp_wq;
 
 
 #define DRIVER_VERSION	"0.4"
 #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>"
 #define DRIVER_AUTHOR	"Dan Zink <dan.zink@compaq.com>, Greg Kroah-Hartman <greg@kroah.com>, Dely Sy <dely.l.sy@intel.com>"
@@ -57,7 +58,6 @@ MODULE_PARM_DESC(shpchp_poll_time, "Polling mechanism frequency, in seconds");
 
 
 #define SHPC_MODULE_NAME "shpchp"
 #define SHPC_MODULE_NAME "shpchp"
 
 
-static int shpc_start_thread (void);
 static int set_attention_status (struct hotplug_slot *slot, u8 value);
 static int set_attention_status (struct hotplug_slot *slot, u8 value);
 static int enable_slot		(struct hotplug_slot *slot);
 static int enable_slot		(struct hotplug_slot *slot);
 static int disable_slot		(struct hotplug_slot *slot);
 static int disable_slot		(struct hotplug_slot *slot);
@@ -94,107 +94,120 @@ static void release_slot(struct hotplug_slot *hotplug_slot)
 	dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
 	dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
 
 
 	kfree(slot->hotplug_slot->info);
 	kfree(slot->hotplug_slot->info);
-	kfree(slot->hotplug_slot->name);
 	kfree(slot->hotplug_slot);
 	kfree(slot->hotplug_slot);
 	kfree(slot);
 	kfree(slot);
 }
 }
 
 
+static void make_slot_name(struct slot *slot)
+{
+	snprintf(slot->hotplug_slot->name, SLOT_NAME_SIZE, "%04d_%04d",
+		 slot->bus, slot->number);
+}
+
+
+
+
+static int
+shpchprm_get_physical_slot_number(struct controller *ctrl, u32 *sun,
+				u8 busnum, u8 devnum)
+{
+	int offset = devnum - ctrl->slot_device_offset;
+
+	dbg("%s: ctrl->slot_num_inc %d, offset %d\n", __FUNCTION__,
+			ctrl->slot_num_inc, offset);
+	*sun = (u8) (ctrl->first_slot + ctrl->slot_num_inc *offset);
+	return 0;
+}
+
+
+
 static int init_slots(struct controller *ctrl)
 static int init_slots(struct controller *ctrl)
 {
 {
-	struct slot *new_slot;
-	u8 number_of_slots;
-	u8 slot_device;
-	u32 slot_number, sun;
-	int result = -ENOMEM;
-
-	number_of_slots = ctrl->num_slots;
-	slot_device = ctrl->slot_device_offset;
-	slot_number = ctrl->first_slot;
-
-	while (number_of_slots) {
-		new_slot = (struct slot *) kmalloc(sizeof(struct slot), GFP_KERNEL);
-		if (!new_slot)
+	struct slot *slot;
+	struct hotplug_slot *hotplug_slot;
+	struct hotplug_slot_info *info;
+	int retval = -ENOMEM;
+	int i;
+	u32 sun;
+
+	for (i = 0; i < ctrl->num_slots; i++) {
+		slot = kzalloc(sizeof(*slot), GFP_KERNEL);
+		if (!slot)
 			goto error;
 			goto error;
 
 
-		memset(new_slot, 0, sizeof(struct slot));
-		new_slot->hotplug_slot = kmalloc (sizeof (struct hotplug_slot), GFP_KERNEL);
-		if (!new_slot->hotplug_slot)
+		hotplug_slot = kzalloc(sizeof(*hotplug_slot), GFP_KERNEL);
+		if (!hotplug_slot)
 			goto error_slot;
 			goto error_slot;
-		memset(new_slot->hotplug_slot, 0, sizeof (struct hotplug_slot));
+		slot->hotplug_slot = hotplug_slot;
 
 
-		new_slot->hotplug_slot->info = kmalloc (sizeof (struct hotplug_slot_info), GFP_KERNEL);
-		if (!new_slot->hotplug_slot->info)
+		info = kzalloc(sizeof(*info), GFP_KERNEL);
+		if (!info)
 			goto error_hpslot;
 			goto error_hpslot;
-		memset(new_slot->hotplug_slot->info, 0, sizeof (struct hotplug_slot_info));
-		new_slot->hotplug_slot->name = kmalloc (SLOT_NAME_SIZE, GFP_KERNEL);
-		if (!new_slot->hotplug_slot->name)
-			goto error_info;
+		hotplug_slot->info = info;
+
+		hotplug_slot->name = slot->name;
 
 
-		new_slot->magic = SLOT_MAGIC;
-		new_slot->ctrl = ctrl;
-		new_slot->bus = ctrl->slot_bus;
-		new_slot->device = slot_device;
-		new_slot->hpc_ops = ctrl->hpc_ops;
+		slot->hp_slot = i;
+		slot->ctrl = ctrl;
+		slot->bus = ctrl->slot_bus;
+		slot->device = ctrl->slot_device_offset + i;
+		slot->hpc_ops = ctrl->hpc_ops;
+		mutex_init(&slot->lock);
 
 
 		if (shpchprm_get_physical_slot_number(ctrl, &sun,
 		if (shpchprm_get_physical_slot_number(ctrl, &sun,
-					new_slot->bus, new_slot->device))
-			goto error_name;
+						      slot->bus, slot->device))
+			goto error_info;
 
 
-		new_slot->number = sun;
-		new_slot->hp_slot = slot_device - ctrl->slot_device_offset;
+		slot->number = sun;
+		INIT_WORK(&slot->work, queue_pushbutton_work, slot);
 
 
 		/* register this slot with the hotplug pci core */
 		/* register this slot with the hotplug pci core */
-		new_slot->hotplug_slot->private = new_slot;
-		new_slot->hotplug_slot->release = &release_slot;
-		make_slot_name(new_slot->hotplug_slot->name, SLOT_NAME_SIZE, new_slot);
-		new_slot->hotplug_slot->ops = &shpchp_hotplug_slot_ops;
-
-		new_slot->hpc_ops->get_power_status(new_slot, &(new_slot->hotplug_slot->info->power_status));
-		new_slot->hpc_ops->get_attention_status(new_slot, &(new_slot->hotplug_slot->info->attention_status));
-		new_slot->hpc_ops->get_latch_status(new_slot, &(new_slot->hotplug_slot->info->latch_status));
-		new_slot->hpc_ops->get_adapter_status(new_slot, &(new_slot->hotplug_slot->info->adapter_status));
-
-		dbg("Registering bus=%x dev=%x hp_slot=%x sun=%x slot_device_offset=%x\n", new_slot->bus, 
-			new_slot->device, new_slot->hp_slot, new_slot->number, ctrl->slot_device_offset);
-		result = pci_hp_register (new_slot->hotplug_slot);
-		if (result) {
-			err ("pci_hp_register failed with error %d\n", result);
-			goto error_name;
+		hotplug_slot->private = slot;
+		hotplug_slot->release = &release_slot;
+		make_slot_name(slot);
+		hotplug_slot->ops = &shpchp_hotplug_slot_ops;
+
+		get_power_status(hotplug_slot, &info->power_status);
+		get_attention_status(hotplug_slot, &info->attention_status);
+		get_latch_status(hotplug_slot, &info->latch_status);
+		get_adapter_status(hotplug_slot, &info->adapter_status);
+
+		dbg("Registering bus=%x dev=%x hp_slot=%x sun=%x "
+		    "slot_device_offset=%x\n", slot->bus, slot->device,
+		    slot->hp_slot, slot->number, ctrl->slot_device_offset);
+		retval = pci_hp_register(slot->hotplug_slot);
+		if (retval) {
+			err("pci_hp_register failed with error %d\n", retval);
+			goto error_info;
 		}
 		}
 
 
-		new_slot->next = ctrl->slot;
-		ctrl->slot = new_slot;
-
-		number_of_slots--;
-		slot_device++;
-		slot_number += ctrl->slot_num_inc;
+		list_add(&slot->slot_list, &ctrl->slot_list);
 	}
 	}
 
 
 	return 0;
 	return 0;
-
-error_name:
-	kfree(new_slot->hotplug_slot->name);
 error_info:
 error_info:
-	kfree(new_slot->hotplug_slot->info);
+	kfree(info);
 error_hpslot:
 error_hpslot:
-	kfree(new_slot->hotplug_slot);
+	kfree(hotplug_slot);
 error_slot:
 error_slot:
-	kfree(new_slot);
+	kfree(slot);
 error:
 error:
-	return result;
+	return retval;
 }
 }
 
 
-static void cleanup_slots(struct controller *ctrl)
+void cleanup_slots(struct controller *ctrl)
 {
 {
-	struct slot *old_slot, *next_slot;
-
-	old_slot = ctrl->slot;
-	ctrl->slot = NULL;
-
-	while (old_slot) {
-		next_slot = old_slot->next;
-		pci_hp_deregister(old_slot->hotplug_slot);
-		old_slot = next_slot;
+	struct list_head *tmp;
+	struct list_head *next;
+	struct slot *slot;
+
+	list_for_each_safe(tmp, next, &ctrl->slot_list) {
+		slot = list_entry(tmp, struct slot, slot_list);
+		list_del(&slot->slot_list);
+		cancel_delayed_work(&slot->work);
+		flush_scheduled_work();
+		flush_workqueue(shpchp_wq);
+		pci_hp_deregister(slot->hotplug_slot);
 	}
 	}
 }
 }
 
 
@@ -207,9 +220,12 @@ static int get_ctlr_slot_config(struct controller *ctrl)
 	int rc;
 	int rc;
 	int flags;
 	int flags;
 
 
-	rc = shpc_get_ctlr_slot_config(ctrl, &num_ctlr_slots, &first_device_num, &physical_slot_num, &updown, &flags);
+	rc = shpc_get_ctlr_slot_config(ctrl, &num_ctlr_slots,
+				       &first_device_num, &physical_slot_num,
+				       &updown, &flags);
 	if (rc) {
 	if (rc) {
-		err("%s: get_ctlr_slot_config fail for b:d (%x:%x)\n", __FUNCTION__, ctrl->bus, ctrl->device);
+		err("%s: get_ctlr_slot_config fail for b:d (%x:%x)\n",
+		    __FUNCTION__, ctrl->bus, ctrl->device);
 		return -1;
 		return -1;
 	}
 	}
 
 
@@ -218,19 +234,19 @@ static int get_ctlr_slot_config(struct controller *ctrl)
 	ctrl->first_slot = physical_slot_num;
 	ctrl->first_slot = physical_slot_num;
 	ctrl->slot_num_inc = updown;		/* either -1 or 1 */
 	ctrl->slot_num_inc = updown;		/* either -1 or 1 */
 
 
-	dbg("%s: num_slot(0x%x) 1st_dev(0x%x) psn(0x%x) updown(%d) for b:d (%x:%x)\n",
-		__FUNCTION__, num_ctlr_slots, first_device_num, physical_slot_num, updown, ctrl->bus, ctrl->device);
+	dbg("%s: num_slot(0x%x) 1st_dev(0x%x) psn(0x%x) updown(%d) for b:d "
+	    "(%x:%x)\n", __FUNCTION__, num_ctlr_slots, first_device_num,
+	    physical_slot_num, updown, ctrl->bus, ctrl->device);
 
 
 	return 0;
 	return 0;
 }
 }
 
 
-
 /*
 /*
  * set_attention_status - Turns the Amber LED for a slot on, off or blink
  * set_attention_status - Turns the Amber LED for a slot on, off or blink
  */
  */
 static int set_attention_status (struct hotplug_slot *hotplug_slot, u8 status)
 static int set_attention_status (struct hotplug_slot *hotplug_slot, u8 status)
 {
 {
-	struct slot *slot = get_slot (hotplug_slot, __FUNCTION__);
+	struct slot *slot = get_slot(hotplug_slot, __FUNCTION__);
 
 
 	dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
 	dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
 
 
@@ -240,29 +256,27 @@ static int set_attention_status (struct hotplug_slot *hotplug_slot, u8 status)
 	return 0;
 	return 0;
 }
 }
 
 
-
 static int enable_slot (struct hotplug_slot *hotplug_slot)
 static int enable_slot (struct hotplug_slot *hotplug_slot)
 {
 {
-	struct slot *slot = get_slot (hotplug_slot, __FUNCTION__);
+	struct slot *slot = get_slot(hotplug_slot, __FUNCTION__);
 
 
 	dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
 	dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
 
 
-	return shpchp_enable_slot(slot);
+	return shpchp_sysfs_enable_slot(slot);
 }
 }
 
 
-
 static int disable_slot (struct hotplug_slot *hotplug_slot)
 static int disable_slot (struct hotplug_slot *hotplug_slot)
 {
 {
-	struct slot *slot = get_slot (hotplug_slot, __FUNCTION__);
+	struct slot *slot = get_slot(hotplug_slot, __FUNCTION__);
 
 
 	dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
 	dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
 
 
-	return shpchp_disable_slot(slot);
+	return shpchp_sysfs_disable_slot(slot);
 }
 }
 
 
 static int get_power_status (struct hotplug_slot *hotplug_slot, u8 *value)
 static int get_power_status (struct hotplug_slot *hotplug_slot, u8 *value)
 {
 {
-	struct slot *slot = get_slot (hotplug_slot, __FUNCTION__);
+	struct slot *slot = get_slot(hotplug_slot, __FUNCTION__);
 	int retval;
 	int retval;
 
 
 	dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
 	dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
@@ -276,7 +290,7 @@ static int get_power_status (struct hotplug_slot *hotplug_slot, u8 *value)
 
 
 static int get_attention_status (struct hotplug_slot *hotplug_slot, u8 *value)
 static int get_attention_status (struct hotplug_slot *hotplug_slot, u8 *value)
 {
 {
-	struct slot *slot = get_slot (hotplug_slot, __FUNCTION__);
+	struct slot *slot = get_slot(hotplug_slot, __FUNCTION__);
 	int retval;
 	int retval;
 
 
 	dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
 	dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
@@ -290,7 +304,7 @@ static int get_attention_status (struct hotplug_slot *hotplug_slot, u8 *value)
 
 
 static int get_latch_status (struct hotplug_slot *hotplug_slot, u8 *value)
 static int get_latch_status (struct hotplug_slot *hotplug_slot, u8 *value)
 {
 {
-	struct slot *slot = get_slot (hotplug_slot, __FUNCTION__);
+	struct slot *slot = get_slot(hotplug_slot, __FUNCTION__);
 	int retval;
 	int retval;
 
 
 	dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
 	dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
@@ -304,7 +318,7 @@ static int get_latch_status (struct hotplug_slot *hotplug_slot, u8 *value)
 
 
 static int get_adapter_status (struct hotplug_slot *hotplug_slot, u8 *value)
 static int get_adapter_status (struct hotplug_slot *hotplug_slot, u8 *value)
 {
 {
-	struct slot *slot = get_slot (hotplug_slot, __FUNCTION__);
+	struct slot *slot = get_slot(hotplug_slot, __FUNCTION__);
 	int retval;
 	int retval;
 
 
 	dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
 	dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
@@ -318,7 +332,7 @@ static int get_adapter_status (struct hotplug_slot *hotplug_slot, u8 *value)
 
 
 static int get_address (struct hotplug_slot *hotplug_slot, u32 *value)
 static int get_address (struct hotplug_slot *hotplug_slot, u32 *value)
 {
 {
-	struct slot *slot = get_slot (hotplug_slot, __FUNCTION__);
+	struct slot *slot = get_slot(hotplug_slot, __FUNCTION__);
 	struct pci_bus *bus = slot->ctrl->pci_dev->subordinate;
 	struct pci_bus *bus = slot->ctrl->pci_dev->subordinate;
 
 
 	dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
 	dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
@@ -330,11 +344,11 @@ static int get_address (struct hotplug_slot *hotplug_slot, u32 *value)
 
 
 static int get_max_bus_speed (struct hotplug_slot *hotplug_slot, enum pci_bus_speed *value)
 static int get_max_bus_speed (struct hotplug_slot *hotplug_slot, enum pci_bus_speed *value)
 {
 {
-	struct slot *slot = get_slot (hotplug_slot, __FUNCTION__);
+	struct slot *slot = get_slot(hotplug_slot, __FUNCTION__);
 	int retval;
 	int retval;
 
 
 	dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
 	dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
-	
+
 	retval = slot->hpc_ops->get_max_bus_speed(slot, value);
 	retval = slot->hpc_ops->get_max_bus_speed(slot, value);
 	if (retval < 0)
 	if (retval < 0)
 		*value = PCI_SPEED_UNKNOWN;
 		*value = PCI_SPEED_UNKNOWN;
@@ -344,11 +358,11 @@ static int get_max_bus_speed (struct hotplug_slot *hotplug_slot, enum pci_bus_sp
 
 
 static int get_cur_bus_speed (struct hotplug_slot *hotplug_slot, enum pci_bus_speed *value)
 static int get_cur_bus_speed (struct hotplug_slot *hotplug_slot, enum pci_bus_speed *value)
 {
 {
-	struct slot *slot = get_slot (hotplug_slot, __FUNCTION__);
+	struct slot *slot = get_slot(hotplug_slot, __FUNCTION__);
 	int retval;
 	int retval;
 
 
 	dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
 	dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
-	
+
 	retval = slot->hpc_ops->get_cur_bus_speed(slot, value);
 	retval = slot->hpc_ops->get_cur_bus_speed(slot, value);
 	if (retval < 0)
 	if (retval < 0)
 		*value = PCI_SPEED_UNKNOWN;
 		*value = PCI_SPEED_UNKNOWN;
@@ -372,61 +386,54 @@ static int shpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 	int rc;
 	int rc;
 	struct controller *ctrl;
 	struct controller *ctrl;
 	struct slot *t_slot;
 	struct slot *t_slot;
-	int first_device_num;	/* first PCI device number supported by this SHPC */
-	int num_ctlr_slots;	/* number of slots supported by this SHPC */
+	int first_device_num;	/* first PCI device number */
+	int num_ctlr_slots;	/* number of slots implemented */
 
 
 	if (!is_shpc_capable(pdev))
 	if (!is_shpc_capable(pdev))
 		return -ENODEV;
 		return -ENODEV;
 
 
-	ctrl = (struct controller *) kmalloc(sizeof(struct controller), GFP_KERNEL);
+	ctrl = kzalloc(sizeof(*ctrl), GFP_KERNEL);
 	if (!ctrl) {
 	if (!ctrl) {
 		err("%s : out of memory\n", __FUNCTION__);
 		err("%s : out of memory\n", __FUNCTION__);
 		goto err_out_none;
 		goto err_out_none;
 	}
 	}
-	memset(ctrl, 0, sizeof(struct controller));
+	INIT_LIST_HEAD(&ctrl->slot_list);
 
 
 	rc = shpc_init(ctrl, pdev);
 	rc = shpc_init(ctrl, pdev);
 	if (rc) {
 	if (rc) {
-		dbg("%s: controller initialization failed\n", SHPC_MODULE_NAME);
+		dbg("%s: controller initialization failed\n",
+		    SHPC_MODULE_NAME);
 		goto err_out_free_ctrl;
 		goto err_out_free_ctrl;
 	}
 	}
 
 
 	pci_set_drvdata(pdev, ctrl);
 	pci_set_drvdata(pdev, ctrl);
 
 
-	ctrl->pci_bus = kmalloc (sizeof (*ctrl->pci_bus), GFP_KERNEL);
-	if (!ctrl->pci_bus) {
-		err("out of memory\n");
-		rc = -ENOMEM;
-		goto err_out_unmap_mmio_region;
-	}
-	
-	memcpy (ctrl->pci_bus, pdev->bus, sizeof (*ctrl->pci_bus));
 	ctrl->bus = pdev->bus->number;
 	ctrl->bus = pdev->bus->number;
 	ctrl->slot_bus = pdev->subordinate->number;
 	ctrl->slot_bus = pdev->subordinate->number;
-
 	ctrl->device = PCI_SLOT(pdev->devfn);
 	ctrl->device = PCI_SLOT(pdev->devfn);
 	ctrl->function = PCI_FUNC(pdev->devfn);
 	ctrl->function = PCI_FUNC(pdev->devfn);
-	dbg("ctrl bus=0x%x, device=%x, function=%x, irq=%x\n", ctrl->bus, ctrl->device, ctrl->function, pdev->irq);
+
+	dbg("ctrl bus=0x%x, device=%x, function=%x, irq=%x\n",
+	    ctrl->bus, ctrl->device, ctrl->function, pdev->irq);
 
 
 	/*
 	/*
-	 *	Save configuration headers for this and subordinate PCI buses
+	 * Save configuration headers for this and subordinate PCI buses
 	 */
 	 */
-
 	rc = get_ctlr_slot_config(ctrl);
 	rc = get_ctlr_slot_config(ctrl);
 	if (rc) {
 	if (rc) {
 		err(msg_initialization_err, rc);
 		err(msg_initialization_err, rc);
-		goto err_out_free_ctrl_bus;
+		goto err_out_release_ctlr;
 	}
 	}
 	first_device_num = ctrl->slot_device_offset;
 	first_device_num = ctrl->slot_device_offset;
 	num_ctlr_slots = ctrl->num_slots;
 	num_ctlr_slots = ctrl->num_slots;
 
 
 	ctrl->add_support = 1;
 	ctrl->add_support = 1;
-	
+
 	/* Setup the slot information structures */
 	/* Setup the slot information structures */
 	rc = init_slots(ctrl);
 	rc = init_slots(ctrl);
 	if (rc) {
 	if (rc) {
 		err(msg_initialization_err, 6);
 		err(msg_initialization_err, 6);
-		goto err_out_free_ctrl_slot;
+		goto err_out_release_ctlr;
 	}
 	}
 
 
 	/* Now hpc_functions (slot->hpc_ops->functions) are ready  */
 	/* Now hpc_functions (slot->hpc_ops->functions) are ready  */
@@ -437,30 +444,16 @@ static int shpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 	dbg("%s: t_slot->hp_slot %x\n", __FUNCTION__,t_slot->hp_slot);
 	dbg("%s: t_slot->hp_slot %x\n", __FUNCTION__,t_slot->hp_slot);
 
 
 	if (rc || ctrl->speed == PCI_SPEED_UNKNOWN) {
 	if (rc || ctrl->speed == PCI_SPEED_UNKNOWN) {
-		err(SHPC_MODULE_NAME ": Can't get current bus speed. Set to 33MHz PCI.\n");
+		err(SHPC_MODULE_NAME ": Can't get current bus speed. "
+		    "Set to 33MHz PCI.\n");
 		ctrl->speed = PCI_SPEED_33MHz;
 		ctrl->speed = PCI_SPEED_33MHz;
 	}
 	}
 
 
-	/* Finish setting up the hot plug ctrl device */
-	ctrl->next_event = 0;
-
-	if (!shpchp_ctrl_list) {
-		shpchp_ctrl_list = ctrl;
-		ctrl->next = NULL;
-	} else {
-		ctrl->next = shpchp_ctrl_list;
-		shpchp_ctrl_list = ctrl;
-	}
-
 	shpchp_create_ctrl_files(ctrl);
 	shpchp_create_ctrl_files(ctrl);
 
 
 	return 0;
 	return 0;
 
 
-err_out_free_ctrl_slot:
-	cleanup_slots(ctrl);
-err_out_free_ctrl_bus:
-	kfree(ctrl->pci_bus);
-err_out_unmap_mmio_region:
+err_out_release_ctlr:
 	ctrl->hpc_ops->release_ctlr(ctrl);
 	ctrl->hpc_ops->release_ctlr(ctrl);
 err_out_free_ctrl:
 err_out_free_ctrl:
 	kfree(ctrl);
 	kfree(ctrl);
@@ -468,74 +461,28 @@ err_out_none:
 	return -ENODEV;
 	return -ENODEV;
 }
 }
 
 
-
-static int shpc_start_thread(void)
-{
-	int retval = 0;
-	
-	dbg("Initialize + Start the notification/polling mechanism \n");
-
-	retval = shpchp_event_start_thread();
-	if (retval) {
-		dbg("shpchp_event_start_thread() failed\n");
-		return retval;
-	}
-
-	return retval;
-}
-
-static void __exit unload_shpchpd(void)
+static void shpc_remove(struct pci_dev *dev)
 {
 {
-	struct controller *ctrl;
-	struct controller *tctrl;
-
-	ctrl = shpchp_ctrl_list;
-
-	while (ctrl) {
-		shpchp_remove_ctrl_files(ctrl);
-		cleanup_slots(ctrl);
-
-		kfree (ctrl->pci_bus);
-		ctrl->hpc_ops->release_ctlr(ctrl);
-
-		tctrl = ctrl;
-		ctrl = ctrl->next;
-
-		kfree(tctrl);
-	}
-
-	/* Stop the notification mechanism */
-	shpchp_event_stop_thread();
+	struct controller *ctrl = pci_get_drvdata(dev);
 
 
+	shpchp_remove_ctrl_files(ctrl);
+	ctrl->hpc_ops->release_ctlr(ctrl);
+	kfree(ctrl);
 }
 }
 
 
-
 static struct pci_device_id shpcd_pci_tbl[] = {
 static struct pci_device_id shpcd_pci_tbl[] = {
-	{
-	.class =        ((PCI_CLASS_BRIDGE_PCI << 8) | 0x00),
-	.class_mask =	~0,
-	.vendor =       PCI_ANY_ID,
-	.device =       PCI_ANY_ID,
-	.subvendor =    PCI_ANY_ID,
-	.subdevice =    PCI_ANY_ID,
-	},
-	
+	{PCI_DEVICE_CLASS(((PCI_CLASS_BRIDGE_PCI << 8) | 0x00), ~0)},
 	{ /* end: all zeroes */ }
 	{ /* end: all zeroes */ }
 };
 };
-
 MODULE_DEVICE_TABLE(pci, shpcd_pci_tbl);
 MODULE_DEVICE_TABLE(pci, shpcd_pci_tbl);
 
 
-
-
 static struct pci_driver shpc_driver = {
 static struct pci_driver shpc_driver = {
 	.name =		SHPC_MODULE_NAME,
 	.name =		SHPC_MODULE_NAME,
 	.id_table =	shpcd_pci_tbl,
 	.id_table =	shpcd_pci_tbl,
 	.probe =	shpc_probe,
 	.probe =	shpc_probe,
-	/* remove:	shpc_remove_one, */
+	.remove =	shpc_remove,
 };
 };
 
 
-
-
 static int __init shpcd_init(void)
 static int __init shpcd_init(void)
 {
 {
 	int retval = 0;
 	int retval = 0;
@@ -544,17 +491,15 @@ static int __init shpcd_init(void)
 	shpchp_poll_mode = 1;
 	shpchp_poll_mode = 1;
 #endif
 #endif
 
 
-	retval = shpc_start_thread();
-	if (retval)
-		goto error_hpc_init;
+	shpchp_wq = create_singlethread_workqueue("shpchpd");
+	if (!shpchp_wq)
+		return -ENOMEM;
 
 
 	retval = pci_register_driver(&shpc_driver);
 	retval = pci_register_driver(&shpc_driver);
 	dbg("%s: pci_register_driver = %d\n", __FUNCTION__, retval);
 	dbg("%s: pci_register_driver = %d\n", __FUNCTION__, retval);
 	info(DRIVER_DESC " version: " DRIVER_VERSION "\n");
 	info(DRIVER_DESC " version: " DRIVER_VERSION "\n");
-
-error_hpc_init:
 	if (retval) {
 	if (retval) {
-		shpchp_event_stop_thread();
+		destroy_workqueue(shpchp_wq);
 	}
 	}
 	return retval;
 	return retval;
 }
 }
@@ -562,10 +507,8 @@ error_hpc_init:
 static void __exit shpcd_cleanup(void)
 static void __exit shpcd_cleanup(void)
 {
 {
 	dbg("unload_shpchpd()\n");
 	dbg("unload_shpchpd()\n");
-	unload_shpchpd();
-
 	pci_unregister_driver(&shpc_driver);
 	pci_unregister_driver(&shpc_driver);
-
+	destroy_workqueue(shpchp_wq);
 	info(DRIVER_DESC " version: " DRIVER_VERSION " unloaded\n");
 	info(DRIVER_DESC " version: " DRIVER_VERSION " unloaded\n");
 }
 }
 
 

+ 287 - 521
drivers/pci/hotplug/shpchp_ctrl.c

@@ -32,65 +32,50 @@
 #include <linux/types.h>
 #include <linux/types.h>
 #include <linux/smp_lock.h>
 #include <linux/smp_lock.h>
 #include <linux/pci.h>
 #include <linux/pci.h>
+#include <linux/workqueue.h>
 #include "../pci.h"
 #include "../pci.h"
 #include "shpchp.h"
 #include "shpchp.h"
 
 
-static void interrupt_event_handler(struct controller *ctrl);
+static void interrupt_event_handler(void *data);
+static int shpchp_enable_slot(struct slot *p_slot);
+static int shpchp_disable_slot(struct slot *p_slot);
 
 
-static struct semaphore event_semaphore;	/* mutex for process loop (up if something to process) */
-static struct semaphore event_exit;		/* guard ensure thread has exited before calling it quits */
-static int event_finished;
-static unsigned long pushbutton_pending;	/* = 0 */
+static int queue_interrupt_event(struct slot *p_slot, u32 event_type)
+{
+	struct event_info *info;
+
+	info = kmalloc(sizeof(*info), GFP_ATOMIC);
+	if (!info)
+		return -ENOMEM;
+
+	info->event_type = event_type;
+	info->p_slot = p_slot;
+	INIT_WORK(&info->work, interrupt_event_handler, info);
+
+	schedule_work(&info->work);
+
+	return 0;
+}
 
 
 u8 shpchp_handle_attention_button(u8 hp_slot, void *inst_id)
 u8 shpchp_handle_attention_button(u8 hp_slot, void *inst_id)
 {
 {
 	struct controller *ctrl = (struct controller *) inst_id;
 	struct controller *ctrl = (struct controller *) inst_id;
 	struct slot *p_slot;
 	struct slot *p_slot;
-	u8 rc = 0;
-	u8 getstatus;
-	struct event_info *taskInfo;
+	u32 event_type;
 
 
 	/* Attention Button Change */
 	/* Attention Button Change */
 	dbg("shpchp:  Attention button interrupt received.\n");
 	dbg("shpchp:  Attention button interrupt received.\n");
 	
 	
-	/* 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 = shpchp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset);
-
 	p_slot->hpc_ops->get_adapter_status(p_slot, &(p_slot->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;
-	taskInfo->hp_slot = hp_slot;
-
-	rc++;
 
 
 	/*
 	/*
 	 *  Button pressed - See if need to TAKE ACTION!!!
 	 *  Button pressed - See if need to TAKE ACTION!!!
 	 */
 	 */
 	info("Button pressed on Slot(%d)\n", ctrl->first_slot + hp_slot);
 	info("Button pressed on Slot(%d)\n", ctrl->first_slot + hp_slot);
-	taskInfo->event_type = INT_BUTTON_PRESS;
-
-	if ((p_slot->state == BLINKINGON_STATE)
-	    || (p_slot->state == BLINKINGOFF_STATE)) {
-		/* Cancel if we are still blinking; this means that we press the
-		 * attention again before the 5 sec. limit expires to cancel hot-add
-		 * or hot-remove
-		 */
-		taskInfo->event_type = INT_BUTTON_CANCEL;
-		info("Button cancel on Slot(%d)\n", ctrl->first_slot + hp_slot);
-	} else if ((p_slot->state == POWERON_STATE)
-		   || (p_slot->state == POWEROFF_STATE)) {
-		/* Ignore if the slot is on power-on or power-off state; this 
-		 * means that the previous attention button action to hot-add or
-		 * hot-remove is undergoing
-		 */
-		taskInfo->event_type = INT_BUTTON_IGNORE;
-		info("Button ignore on Slot(%d)\n", ctrl->first_slot + hp_slot);
-	}
+	event_type = INT_BUTTON_PRESS;
 
 
-	if (rc)
-		up(&event_semaphore);	/* signal event thread that new event is posted */
+	queue_interrupt_event(p_slot, event_type);
 
 
 	return 0;
 	return 0;
 
 
@@ -100,21 +85,12 @@ u8 shpchp_handle_switch_change(u8 hp_slot, void *inst_id)
 {
 {
 	struct controller *ctrl = (struct controller *) inst_id;
 	struct controller *ctrl = (struct controller *) inst_id;
 	struct slot *p_slot;
 	struct slot *p_slot;
-	u8 rc = 0;
 	u8 getstatus;
 	u8 getstatus;
-	struct event_info *taskInfo;
+	u32 event_type;
 
 
 	/* Switch Change */
 	/* Switch Change */
 	dbg("shpchp:  Switch interrupt received.\n");
 	dbg("shpchp:  Switch interrupt received.\n");
 
 
-	/* This is the structure that tells the worker thread
-	 * what to do
-	 */
-	taskInfo = &(ctrl->event_queue[ctrl->next_event]);
-	ctrl->next_event = (ctrl->next_event + 1) % 10;
-	taskInfo->hp_slot = hp_slot;
-
-	rc++;
 	p_slot = shpchp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset);
 	p_slot = shpchp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset);
 	p_slot->hpc_ops->get_adapter_status(p_slot, &(p_slot->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);
 	p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
@@ -126,9 +102,9 @@ u8 shpchp_handle_switch_change(u8 hp_slot, void *inst_id)
 		 * Switch opened
 		 * Switch opened
 		 */
 		 */
 		info("Latch open on Slot(%d)\n", ctrl->first_slot + hp_slot);
 		info("Latch open on Slot(%d)\n", ctrl->first_slot + hp_slot);
-		taskInfo->event_type = INT_SWITCH_OPEN;
+		event_type = INT_SWITCH_OPEN;
 		if (p_slot->pwr_save && p_slot->presence_save) {
 		if (p_slot->pwr_save && p_slot->presence_save) {
-			taskInfo->event_type = INT_POWER_FAULT;
+			event_type = INT_POWER_FAULT;
 			err("Surprise Removal of card\n");
 			err("Surprise Removal of card\n");
 		}
 		}
 	} else {
 	} else {
@@ -136,34 +112,23 @@ u8 shpchp_handle_switch_change(u8 hp_slot, void *inst_id)
 		 *  Switch closed
 		 *  Switch closed
 		 */
 		 */
 		info("Latch close on Slot(%d)\n", ctrl->first_slot + hp_slot);
 		info("Latch close on Slot(%d)\n", ctrl->first_slot + hp_slot);
-		taskInfo->event_type = INT_SWITCH_CLOSE;
+		event_type = INT_SWITCH_CLOSE;
 	}
 	}
 
 
-	if (rc)
-		up(&event_semaphore);	/* signal event thread that new event is posted */
+	queue_interrupt_event(p_slot, event_type);
 
 
-	return rc;
+	return 1;
 }
 }
 
 
 u8 shpchp_handle_presence_change(u8 hp_slot, void *inst_id)
 u8 shpchp_handle_presence_change(u8 hp_slot, void *inst_id)
 {
 {
 	struct controller *ctrl = (struct controller *) inst_id;
 	struct controller *ctrl = (struct controller *) inst_id;
 	struct slot *p_slot;
 	struct slot *p_slot;
-	u8 rc = 0;
-	/*u8 temp_byte;*/
-	struct event_info *taskInfo;
+	u32 event_type;
 
 
 	/* Presence Change */
 	/* Presence Change */
 	dbg("shpchp:  Presence/Notify input change.\n");
 	dbg("shpchp:  Presence/Notify input change.\n");
 
 
-	/* This is the structure that tells the worker thread
-	 * what to do
-	 */
-	taskInfo = &(ctrl->event_queue[ctrl->next_event]);
-	ctrl->next_event = (ctrl->next_event + 1) % 10;
-	taskInfo->hp_slot = hp_slot;
-
-	rc++;
 	p_slot = shpchp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset);
 	p_slot = shpchp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset);
 
 
 	/* 
 	/* 
@@ -175,39 +140,29 @@ u8 shpchp_handle_presence_change(u8 hp_slot, void *inst_id)
 		 * Card Present
 		 * Card Present
 		 */
 		 */
 		info("Card present on Slot(%d)\n", ctrl->first_slot + hp_slot);
 		info("Card present on Slot(%d)\n", ctrl->first_slot + hp_slot);
-		taskInfo->event_type = INT_PRESENCE_ON;
+		event_type = INT_PRESENCE_ON;
 	} else {
 	} else {
 		/*
 		/*
 		 * Not Present
 		 * Not Present
 		 */
 		 */
 		info("Card not present on Slot(%d)\n", ctrl->first_slot + hp_slot);
 		info("Card not present on Slot(%d)\n", ctrl->first_slot + hp_slot);
-		taskInfo->event_type = INT_PRESENCE_OFF;
+		event_type = INT_PRESENCE_OFF;
 	}
 	}
 
 
-	if (rc)
-		up(&event_semaphore);	/* signal event thread that new event is posted */
+	queue_interrupt_event(p_slot, event_type);
 
 
-	return rc;
+	return 1;
 }
 }
 
 
 u8 shpchp_handle_power_fault(u8 hp_slot, void *inst_id)
 u8 shpchp_handle_power_fault(u8 hp_slot, void *inst_id)
 {
 {
 	struct controller *ctrl = (struct controller *) inst_id;
 	struct controller *ctrl = (struct controller *) inst_id;
 	struct slot *p_slot;
 	struct slot *p_slot;
-	u8 rc = 0;
-	struct event_info *taskInfo;
+	u32 event_type;
 
 
 	/* Power fault */
 	/* Power fault */
 	dbg("shpchp:  Power fault interrupt received.\n");
 	dbg("shpchp:  Power fault interrupt received.\n");
 
 
-	/* This is the structure that tells the worker thread
-	 * what to do
-	 */
-	taskInfo = &(ctrl->event_queue[ctrl->next_event]);
-	ctrl->next_event = (ctrl->next_event + 1) % 10;
-	taskInfo->hp_slot = hp_slot;
-
-	rc++;
 	p_slot = shpchp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset);
 	p_slot = shpchp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset);
 
 
 	if ( !(p_slot->hpc_ops->query_power_fault(p_slot))) {
 	if ( !(p_slot->hpc_ops->query_power_fault(p_slot))) {
@@ -216,21 +171,21 @@ u8 shpchp_handle_power_fault(u8 hp_slot, void *inst_id)
 		 */
 		 */
 		info("Power fault cleared on Slot(%d)\n", ctrl->first_slot + hp_slot);
 		info("Power fault cleared on Slot(%d)\n", ctrl->first_slot + hp_slot);
 		p_slot->status = 0x00;
 		p_slot->status = 0x00;
-		taskInfo->event_type = INT_POWER_FAULT_CLEAR;
+		event_type = INT_POWER_FAULT_CLEAR;
 	} else {
 	} else {
 		/*
 		/*
 		 *   Power fault
 		 *   Power fault
 		 */
 		 */
 		info("Power fault on Slot(%d)\n", ctrl->first_slot + hp_slot);
 		info("Power fault on Slot(%d)\n", ctrl->first_slot + hp_slot);
-		taskInfo->event_type = INT_POWER_FAULT;
+		event_type = INT_POWER_FAULT;
 		/* set power fault status for this board */
 		/* set power fault status for this board */
 		p_slot->status = 0xFF;
 		p_slot->status = 0xFF;
 		info("power fault bit %x set\n", hp_slot);
 		info("power fault bit %x set\n", hp_slot);
 	}
 	}
-	if (rc)
-		up(&event_semaphore);	/* signal event thread that new event is posted */
 
 
-	return rc;
+	queue_interrupt_event(p_slot, event_type);
+
+	return 1;
 }
 }
 
 
 /* The following routines constitute the bulk of the 
 /* The following routines constitute the bulk of the 
@@ -242,21 +197,11 @@ static int change_bus_speed(struct controller *ctrl, struct slot *p_slot,
 	int rc = 0;
 	int rc = 0;
 
 
 	dbg("%s: change to speed %d\n", __FUNCTION__, speed);
 	dbg("%s: change to speed %d\n", __FUNCTION__, speed);
-	down(&ctrl->crit_sect);
 	if ((rc = p_slot->hpc_ops->set_bus_speed_mode(p_slot, speed))) {
 	if ((rc = p_slot->hpc_ops->set_bus_speed_mode(p_slot, speed))) {
-		err("%s: Issue of set bus speed mode command failed\n", __FUNCTION__);
-		up(&ctrl->crit_sect);
+		err("%s: Issue of set bus speed mode command failed\n",
+		    __FUNCTION__);
 		return WRONG_BUS_FREQUENCY;
 		return WRONG_BUS_FREQUENCY;
 	}
 	}
-		
-	if ((rc = p_slot->hpc_ops->check_cmd_status(ctrl))) {
-		err("%s: Can't set bus speed/mode in the case of adapter & bus mismatch\n",
-			  __FUNCTION__);
-		err("%s: Error code (%d)\n", __FUNCTION__, rc);
-		up(&ctrl->crit_sect);
-		return WRONG_BUS_FREQUENCY;
-	}
-	up(&ctrl->crit_sect);
 	return rc;
 	return rc;
 }
 }
 
 
@@ -265,33 +210,26 @@ static int fix_bus_speed(struct controller *ctrl, struct slot *pslot,
 		enum pci_bus_speed msp)
 		enum pci_bus_speed msp)
 { 
 { 
 	int rc = 0;
 	int rc = 0;
-	
-	if (flag != 0) { /* Other slots on the same bus are occupied */
-		if ( asp < bsp ) {
-			err("%s: speed of bus %x and adapter %x mismatch\n", __FUNCTION__, bsp, asp);
-			return WRONG_BUS_FREQUENCY;
+
+	/*
+	 * If other slots on the same bus are occupied, we cannot
+	 * change the bus speed.
+	 */
+	if (flag) {
+		if (asp < bsp) {
+			err("%s: speed of bus %x and adapter %x mismatch\n",
+			    __FUNCTION__, bsp, asp);
+			rc = WRONG_BUS_FREQUENCY;
 		}
 		}
+		return rc;
+	}
+
+	if (asp < msp) {
+		if (bsp != asp)
+			rc = change_bus_speed(ctrl, pslot, asp);
 	} else {
 	} else {
-		/* Other slots on the same bus are empty */
-		if (msp == bsp) {
-		/* if adapter_speed >= bus_speed, do nothing */
-			if (asp < bsp) {
-				/* 
-				* Try to lower bus speed to accommodate the adapter if other slots 
-				* on the same controller are empty
-				*/
-				if ((rc = change_bus_speed(ctrl, pslot, asp)))
-					return rc;
-			} 
-		} else {
-			if (asp < msp) {
-				if ((rc = change_bus_speed(ctrl, pslot, asp)))
-					return rc;
-			} else {
-				if ((rc = change_bus_speed(ctrl, pslot, msp)))
-					return rc;
-			}
-		}
+		if (bsp != msp)
+			rc = change_bus_speed(ctrl, pslot, msp);
 	}
 	}
 	return rc;
 	return rc;
 }
 }
@@ -308,8 +246,7 @@ static int board_added(struct slot *p_slot)
 	u8 hp_slot;
 	u8 hp_slot;
 	u8 slots_not_empty = 0;
 	u8 slots_not_empty = 0;
 	int rc = 0;
 	int rc = 0;
-	enum pci_bus_speed adapter_speed, bus_speed, max_bus_speed;
-	u8 pi, mode;
+	enum pci_bus_speed asp, bsp, msp;
 	struct controller *ctrl = p_slot->ctrl;
 	struct controller *ctrl = p_slot->ctrl;
 
 
 	hp_slot = p_slot->device - ctrl->slot_device_offset;
 	hp_slot = p_slot->device - ctrl->slot_device_offset;
@@ -318,187 +255,68 @@ static int board_added(struct slot *p_slot)
 			__FUNCTION__, p_slot->device,
 			__FUNCTION__, p_slot->device,
 			ctrl->slot_device_offset, hp_slot);
 			ctrl->slot_device_offset, hp_slot);
 
 
-	/* Wait for exclusive access to hardware */
-	down(&ctrl->crit_sect);
-
 	/* Power on slot without connecting to bus */
 	/* Power on slot without connecting to bus */
 	rc = p_slot->hpc_ops->power_on_slot(p_slot);
 	rc = p_slot->hpc_ops->power_on_slot(p_slot);
 	if (rc) {
 	if (rc) {
 		err("%s: Failed to power on slot\n", __FUNCTION__);
 		err("%s: Failed to power on slot\n", __FUNCTION__);
-		/* Done with exclusive hardware access */
-		up(&ctrl->crit_sect);
 		return -1;
 		return -1;
 	}
 	}
 	
 	
-	rc = p_slot->hpc_ops->check_cmd_status(ctrl);
-	if (rc) {
-		err("%s: Failed to power on slot, error code(%d)\n", __FUNCTION__, rc);
-		/* Done with exclusive hardware access */
-		up(&ctrl->crit_sect);
-		return -1;
-	}
-
-	
 	if ((ctrl->pci_dev->vendor == 0x8086) && (ctrl->pci_dev->device == 0x0332)) {
 	if ((ctrl->pci_dev->vendor == 0x8086) && (ctrl->pci_dev->device == 0x0332)) {
 		if (slots_not_empty)
 		if (slots_not_empty)
 			return WRONG_BUS_FREQUENCY;
 			return WRONG_BUS_FREQUENCY;
 		
 		
 		if ((rc = p_slot->hpc_ops->set_bus_speed_mode(p_slot, PCI_SPEED_33MHz))) {
 		if ((rc = p_slot->hpc_ops->set_bus_speed_mode(p_slot, PCI_SPEED_33MHz))) {
 			err("%s: Issue of set bus speed mode command failed\n", __FUNCTION__);
 			err("%s: Issue of set bus speed mode command failed\n", __FUNCTION__);
-			up(&ctrl->crit_sect);
 			return WRONG_BUS_FREQUENCY;
 			return WRONG_BUS_FREQUENCY;
 		}
 		}
 		
 		
-		if ((rc = p_slot->hpc_ops->check_cmd_status(ctrl))) {
-			err("%s: Can't set bus speed/mode in the case of adapter & bus mismatch\n",
-				  __FUNCTION__);
-			err("%s: Error code (%d)\n", __FUNCTION__, rc);
-			up(&ctrl->crit_sect);
-			return WRONG_BUS_FREQUENCY;
-		}
 		/* turn on board, blink green LED, turn off Amber LED */
 		/* turn on board, blink green LED, turn off Amber LED */
 		if ((rc = p_slot->hpc_ops->slot_enable(p_slot))) {
 		if ((rc = p_slot->hpc_ops->slot_enable(p_slot))) {
 			err("%s: Issue of Slot Enable command failed\n", __FUNCTION__);
 			err("%s: Issue of Slot Enable command failed\n", __FUNCTION__);
-			up(&ctrl->crit_sect);
 			return rc;
 			return rc;
 		}
 		}
-
-		if ((rc = p_slot->hpc_ops->check_cmd_status(ctrl))) {
-			err("%s: Failed to enable slot, error code(%d)\n", __FUNCTION__, rc);
-			up(&ctrl->crit_sect);
-			return rc;  
-		}
 	}
 	}
  
  
-	rc = p_slot->hpc_ops->get_adapter_speed(p_slot, &adapter_speed);
-	/* 0 = PCI 33Mhz, 1 = PCI 66 Mhz, 2 = PCI-X 66 PA, 4 = PCI-X 66 ECC, */
-	/* 5 = PCI-X 133 PA, 7 = PCI-X 133 ECC,  0xa = PCI-X 133 Mhz 266, */
-	/* 0xd = PCI-X 133 Mhz 533 */
-	/* This encoding is different from the one used in cur_bus_speed & */
-	/* max_bus_speed */
-
-	if (rc  || adapter_speed == PCI_SPEED_UNKNOWN) {
-		err("%s: Can't get adapter speed or bus mode mismatch\n", __FUNCTION__);
-		/* Done with exclusive hardware access */
-		up(&ctrl->crit_sect);
+	rc = p_slot->hpc_ops->get_adapter_speed(p_slot, &asp);
+	if (rc) {
+		err("%s: Can't get adapter speed or bus mode mismatch\n",
+		    __FUNCTION__);
 		return WRONG_BUS_FREQUENCY;
 		return WRONG_BUS_FREQUENCY;
 	}
 	}
 
 
-	rc = p_slot->hpc_ops->get_cur_bus_speed(p_slot, &bus_speed);
-	if (rc || bus_speed == PCI_SPEED_UNKNOWN) {
+	rc = p_slot->hpc_ops->get_cur_bus_speed(p_slot, &bsp);
+	if (rc) {
 		err("%s: Can't get bus operation speed\n", __FUNCTION__);
 		err("%s: Can't get bus operation speed\n", __FUNCTION__);
-		/* Done with exclusive hardware access */
-		up(&ctrl->crit_sect);
 		return WRONG_BUS_FREQUENCY;
 		return WRONG_BUS_FREQUENCY;
 	}
 	}
 
 
-	rc = p_slot->hpc_ops->get_max_bus_speed(p_slot, &max_bus_speed);
-	if (rc || max_bus_speed == PCI_SPEED_UNKNOWN) {
+	rc = p_slot->hpc_ops->get_max_bus_speed(p_slot, &msp);
+	if (rc) {
 		err("%s: Can't get max bus operation speed\n", __FUNCTION__);
 		err("%s: Can't get max bus operation speed\n", __FUNCTION__);
-		max_bus_speed = bus_speed;
-	}
-
-	/* Done with exclusive hardware access */
-	up(&ctrl->crit_sect);
-
-	if ((rc  = p_slot->hpc_ops->get_prog_int(p_slot, &pi))) {
-		err("%s: Can't get controller programming interface, set it to 1\n", __FUNCTION__);
-		pi = 1;
+		msp = bsp;
 	}
 	}
 
 
 	/* Check if there are other slots or devices on the same bus */
 	/* Check if there are other slots or devices on the same bus */
 	if (!list_empty(&ctrl->pci_dev->subordinate->devices))
 	if (!list_empty(&ctrl->pci_dev->subordinate->devices))
 		slots_not_empty = 1;
 		slots_not_empty = 1;
 
 
-	dbg("%s: slots_not_empty %d, pi %d\n", __FUNCTION__, 
-		slots_not_empty, pi);
-	dbg("adapter_speed %d, bus_speed %d, max_bus_speed %d\n", 
-		adapter_speed, bus_speed, max_bus_speed);
-
-	if (pi == 2) {
-		dbg("%s: In PI = %d\n", __FUNCTION__, pi);
-		if ((rc = p_slot->hpc_ops->get_mode1_ECC_cap(p_slot, &mode))) {
-			err("%s: Can't get Mode1_ECC, set mode to 0\n", __FUNCTION__);
-			mode = 0;
-		}
+	dbg("%s: slots_not_empty %d, adapter_speed %d, bus_speed %d, "
+	    "max_bus_speed %d\n", __FUNCTION__, slots_not_empty, asp,
+	    bsp, msp);
 
 
-		switch (adapter_speed) {
-		case PCI_SPEED_133MHz_PCIX_533:
-		case PCI_SPEED_133MHz_PCIX_266:
-			if ((bus_speed != adapter_speed) &&
-			   ((rc = fix_bus_speed(ctrl, p_slot, slots_not_empty, adapter_speed, bus_speed, max_bus_speed)))) 
-				return rc;
-			break;	
-		case PCI_SPEED_133MHz_PCIX_ECC:
-		case PCI_SPEED_133MHz_PCIX:
-			if (mode) { /* Bus - Mode 1 ECC */
-				if ((bus_speed != 0x7) &&
-				   ((rc = fix_bus_speed(ctrl, p_slot, slots_not_empty, adapter_speed, bus_speed, max_bus_speed)))) 
-					return rc;
-			} else {
-				if ((bus_speed != 0x4) &&
-				   ((rc = fix_bus_speed(ctrl, p_slot, slots_not_empty, adapter_speed, bus_speed, max_bus_speed)))) 
-					return rc;
-			}
-			break;
-		case PCI_SPEED_66MHz_PCIX_ECC:
-		case PCI_SPEED_66MHz_PCIX:
-			if (mode) { /* Bus - Mode 1 ECC */
-				if ((bus_speed != 0x5) &&
-				   ((rc = fix_bus_speed(ctrl, p_slot, slots_not_empty, adapter_speed, bus_speed, max_bus_speed)))) 
-					return rc;
-			} else {
-				if ((bus_speed != 0x2) &&
-				   ((rc = fix_bus_speed(ctrl, p_slot, slots_not_empty, adapter_speed, bus_speed, max_bus_speed)))) 
-					return rc;
-			}
-			break;
-		case PCI_SPEED_66MHz:
-			if ((bus_speed != 0x1) &&
-			   ((rc = fix_bus_speed(ctrl, p_slot, slots_not_empty, adapter_speed, bus_speed, max_bus_speed)))) 
-				return rc;
-			break;	
-		case PCI_SPEED_33MHz:
-			if (bus_speed > 0x0) {
-				if (slots_not_empty == 0) {
-					if ((rc = change_bus_speed(ctrl, p_slot, adapter_speed)))
-						return rc;
-				} else {
-					err("%s: speed of bus %x and adapter %x mismatch\n", __FUNCTION__, bus_speed, adapter_speed);
-					return WRONG_BUS_FREQUENCY;
-				}
-			}
-			break;
-		default:
-			err("%s: speed of bus %x and adapter %x mismatch\n", __FUNCTION__, bus_speed, adapter_speed);
-			return WRONG_BUS_FREQUENCY;
-		}
-	} else {
-		/* If adpater_speed == bus_speed, nothing to do here */
-		dbg("%s: In PI = %d\n", __FUNCTION__, pi);
-		if ((adapter_speed != bus_speed) &&
-		   ((rc = fix_bus_speed(ctrl, p_slot, slots_not_empty, adapter_speed, bus_speed, max_bus_speed))))
-				return rc;
-	}
+	rc = fix_bus_speed(ctrl, p_slot, slots_not_empty, asp, bsp, msp);
+	if (rc)
+		return rc;
 
 
-	down(&ctrl->crit_sect);
 	/* turn on board, blink green LED, turn off Amber LED */
 	/* turn on board, blink green LED, turn off Amber LED */
 	if ((rc = p_slot->hpc_ops->slot_enable(p_slot))) {
 	if ((rc = p_slot->hpc_ops->slot_enable(p_slot))) {
 		err("%s: Issue of Slot Enable command failed\n", __FUNCTION__);
 		err("%s: Issue of Slot Enable command failed\n", __FUNCTION__);
-		up(&ctrl->crit_sect);
 		return rc;
 		return rc;
 	}
 	}
 
 
-	if ((rc = p_slot->hpc_ops->check_cmd_status(ctrl))) {
-		err("%s: Failed to enable slot, error code(%d)\n", __FUNCTION__, rc);
-		up(&ctrl->crit_sect);
-		return rc;  
-	}
-
-	up(&ctrl->crit_sect);
-
 	/* Wait for ~1 second */
 	/* Wait for ~1 second */
-	wait_for_ctrl_irq (ctrl);
+	msleep(1000);
 
 
 	dbg("%s: slot status = %x\n", __FUNCTION__, p_slot->status);
 	dbg("%s: slot status = %x\n", __FUNCTION__, p_slot->status);
 	/* Check for a power fault */
 	/* Check for a power fault */
@@ -520,40 +338,18 @@ static int board_added(struct slot *p_slot)
 	p_slot->is_a_board = 0x01;
 	p_slot->is_a_board = 0x01;
 	p_slot->pwr_save = 1;
 	p_slot->pwr_save = 1;
 
 
-	/* Wait for exclusive access to hardware */
-	down(&ctrl->crit_sect);
-
 	p_slot->hpc_ops->green_led_on(p_slot);
 	p_slot->hpc_ops->green_led_on(p_slot);
 
 
-	/* Done with exclusive hardware access */
-	up(&ctrl->crit_sect);
-
 	return 0;
 	return 0;
 
 
 err_exit:
 err_exit:
-	/* Wait for exclusive access to hardware */
-	down(&ctrl->crit_sect);
-
 	/* turn off slot, turn on Amber LED, turn off Green LED */
 	/* turn off slot, turn on Amber LED, turn off Green LED */
 	rc = p_slot->hpc_ops->slot_disable(p_slot);
 	rc = p_slot->hpc_ops->slot_disable(p_slot);
 	if (rc) {
 	if (rc) {
 		err("%s: Issue of Slot Disable command failed\n", __FUNCTION__);
 		err("%s: Issue of Slot Disable command failed\n", __FUNCTION__);
-		/* 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;
 	}
 	}
 
 
-	/* Done with exclusive hardware access */
-	up(&ctrl->crit_sect);
-
 	return(rc);
 	return(rc);
 }
 }
 
 
@@ -580,37 +376,19 @@ static int remove_board(struct slot *p_slot)
 	if (p_slot->is_a_board)
 	if (p_slot->is_a_board)
 		p_slot->status = 0x01;
 		p_slot->status = 0x01;
 
 
-	/* Wait for exclusive access to hardware */
-	down(&ctrl->crit_sect);
-
 	/* turn off slot, turn on Amber LED, turn off Green LED */
 	/* turn off slot, turn on Amber LED, turn off Green LED */
 	rc = p_slot->hpc_ops->slot_disable(p_slot);
 	rc = p_slot->hpc_ops->slot_disable(p_slot);
 	if (rc) {
 	if (rc) {
 		err("%s: Issue of Slot Disable command failed\n", __FUNCTION__);
 		err("%s: Issue of Slot Disable command failed\n", __FUNCTION__);
-		/* Done with exclusive hardware access */
-		up(&ctrl->crit_sect);
 		return rc;
 		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;  
-	}
 	
 	
 	rc = p_slot->hpc_ops->set_attention_status(p_slot, 0);
 	rc = p_slot->hpc_ops->set_attention_status(p_slot, 0);
 	if (rc) {
 	if (rc) {
 		err("%s: Issue of Set Attention command failed\n", __FUNCTION__);
 		err("%s: Issue of Set Attention command failed\n", __FUNCTION__);
-		/* Done with exclusive hardware access */
-		up(&ctrl->crit_sect);
 		return rc;
 		return rc;
 	}
 	}
 
 
-	/* Done with exclusive hardware access */
-	up(&ctrl->crit_sect);
-
 	p_slot->pwr_save = 0;
 	p_slot->pwr_save = 0;
 	p_slot->is_a_board = 0;
 	p_slot->is_a_board = 0;
 
 
@@ -618,13 +396,10 @@ static int remove_board(struct slot *p_slot)
 }
 }
 
 
 
 
-static void pushbutton_helper_thread (unsigned long data)
-{
-	pushbutton_pending = data;
-
-	up(&event_semaphore);
-}
-
+struct pushbutton_work_info {
+	struct slot *p_slot;
+	struct work_struct work;
+};
 
 
 /**
 /**
  * shpchp_pushbutton_thread
  * shpchp_pushbutton_thread
@@ -633,96 +408,63 @@ static void pushbutton_helper_thread (unsigned long data)
  * Handles all pending events and exits.
  * Handles all pending events and exits.
  *
  *
  */
  */
-static void shpchp_pushbutton_thread (unsigned long slot)
+static void shpchp_pushbutton_thread(void *data)
 {
 {
-	struct slot *p_slot = (struct slot *) slot;
-	u8 getstatus;
-	
-	pushbutton_pending = 0;
-
-	if (!p_slot) {
-		dbg("%s: Error! slot NULL\n", __FUNCTION__);
-		return;
-	}
-
-	p_slot->hpc_ops->get_power_status(p_slot, &getstatus);
-	if (getstatus) {
-		p_slot->state = POWEROFF_STATE;
+	struct pushbutton_work_info *info = data;
+	struct slot *p_slot = info->p_slot;
 
 
+	mutex_lock(&p_slot->lock);
+	switch (p_slot->state) {
+	case POWEROFF_STATE:
+		mutex_unlock(&p_slot->lock);
 		shpchp_disable_slot(p_slot);
 		shpchp_disable_slot(p_slot);
+		mutex_lock(&p_slot->lock);
 		p_slot->state = STATIC_STATE;
 		p_slot->state = STATIC_STATE;
-	} else {
-		p_slot->state = POWERON_STATE;
-
-		if (shpchp_enable_slot(p_slot)) {
-			/* Wait for exclusive access to hardware */
-			down(&p_slot->ctrl->crit_sect);
-
+		break;
+	case POWERON_STATE:
+		mutex_unlock(&p_slot->lock);
+		if (shpchp_enable_slot(p_slot))
 			p_slot->hpc_ops->green_led_off(p_slot);
 			p_slot->hpc_ops->green_led_off(p_slot);
-
-			/* Done with exclusive hardware access */
-			up(&p_slot->ctrl->crit_sect);
-		}
+		mutex_lock(&p_slot->lock);
 		p_slot->state = STATIC_STATE;
 		p_slot->state = STATIC_STATE;
+		break;
+	default:
+		break;
 	}
 	}
+	mutex_unlock(&p_slot->lock);
 
 
-	return;
-}
-
-
-/* this is the main worker thread */
-static int event_thread(void* data)
-{
-	struct controller *ctrl;
-	lock_kernel();
-	daemonize("shpchpd_event");
-	unlock_kernel();
-
-	while (1) {
-		dbg("!!!!event_thread sleeping\n");
-		down_interruptible (&event_semaphore);
-		dbg("event_thread woken finished = %d\n", event_finished);
-		if (event_finished || signal_pending(current))
-			break;
-		/* Do stuff here */
-		if (pushbutton_pending)
-			shpchp_pushbutton_thread(pushbutton_pending);
-		else
-			for (ctrl = shpchp_ctrl_list; ctrl; ctrl=ctrl->next)
-				interrupt_event_handler(ctrl);
-	}
-	dbg("event_thread signals exit\n");
-	up(&event_exit);
-	return 0;
+	kfree(info);
 }
 }
 
 
-int shpchp_event_start_thread (void)
+void queue_pushbutton_work(void *data)
 {
 {
-	int pid;
+	struct slot *p_slot = data;
+	struct pushbutton_work_info *info;
 
 
-	/* initialize our semaphores */
-	init_MUTEX_LOCKED(&event_exit);
-	event_finished=0;
-
-	init_MUTEX_LOCKED(&event_semaphore);
-	pid = kernel_thread(event_thread, NULL, 0);
-
-	if (pid < 0) {
-		err ("Can't start up our event thread\n");
-		return -1;
+	info = kmalloc(sizeof(*info), GFP_KERNEL);
+	if (!info) {
+		err("%s: Cannot allocate memory\n", __FUNCTION__);
+		return;
 	}
 	}
-	return 0;
-}
-
+	info->p_slot = p_slot;
+	INIT_WORK(&info->work, shpchp_pushbutton_thread, info);
 
 
-void shpchp_event_stop_thread (void)
-{
-	event_finished = 1;
-	up(&event_semaphore);
-	down(&event_exit);
+	mutex_lock(&p_slot->lock);
+	switch (p_slot->state) {
+	case BLINKINGOFF_STATE:
+		p_slot->state = POWEROFF_STATE;
+		break;
+	case BLINKINGON_STATE:
+		p_slot->state = POWERON_STATE;
+		break;
+	default:
+		goto out;
+	}
+	queue_work(shpchp_wq, &info->work);
+ out:
+	mutex_unlock(&p_slot->lock);
 }
 }
 
 
-
 static int update_slot_info (struct slot *slot)
 static int update_slot_info (struct slot *slot)
 {
 {
 	struct hotplug_slot_info *info;
 	struct hotplug_slot_info *info;
@@ -742,149 +484,110 @@ static int update_slot_info (struct slot *slot)
 	return result;
 	return result;
 }
 }
 
 
-static void interrupt_event_handler(struct controller *ctrl)
+/*
+ * Note: This function must be called with slot->lock held
+ */
+static void handle_button_press_event(struct slot *p_slot)
 {
 {
-	int loop = 0;
-	int change = 1;
-	u8 hp_slot;
 	u8 getstatus;
 	u8 getstatus;
-	struct slot *p_slot;
 
 
-	while (change) {
-		change = 0;
-
-		for (loop = 0; loop < 10; loop++) {
-			if (ctrl->event_queue[loop].event_type != 0) {
-				dbg("%s:loop %x event_type %x\n", __FUNCTION__, loop, 
-					ctrl->event_queue[loop].event_type);
-				hp_slot = ctrl->event_queue[loop].hp_slot;
-
-				p_slot = shpchp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset);
-
-				if (ctrl->event_queue[loop].event_type == INT_BUTTON_CANCEL) {
-					dbg("%s: button cancel\n", __FUNCTION__);
-					del_timer(&p_slot->task_event);
-
-					switch (p_slot->state) {
-					case BLINKINGOFF_STATE:
-						/* Wait for exclusive access to hardware */
-						down(&ctrl->crit_sect);
-
-						p_slot->hpc_ops->green_led_on(p_slot);
-
-						p_slot->hpc_ops->set_attention_status(p_slot, 0);
-
-						/* Done with exclusive hardware access */
-						up(&ctrl->crit_sect);
-						break;
-					case BLINKINGON_STATE:
-						/* Wait for exclusive access to hardware */
-						down(&ctrl->crit_sect);
-
-						p_slot->hpc_ops->green_led_off(p_slot);
-
-						p_slot->hpc_ops->set_attention_status(p_slot, 0);
-
-						/* Done with exclusive hardware access */
-						up(&ctrl->crit_sect);
-
-						break;
-					default:
-						warn("Not a valid state\n");
-						return;
-					}
-					info(msg_button_cancel, p_slot->number);
-					p_slot->state = STATIC_STATE;
-				} else if (ctrl->event_queue[loop].event_type == INT_BUTTON_PRESS) {
-					/* Button Pressed (No action on 1st press...) */
-					dbg("%s: Button pressed\n", __FUNCTION__);
-
-					p_slot->hpc_ops->get_power_status(p_slot, &getstatus);
-					if (getstatus) {
-						/* slot is on */
-						dbg("%s: slot is on\n", __FUNCTION__);
-						p_slot->state = BLINKINGOFF_STATE;
-						info(msg_button_off, p_slot->number);
-					} else {
-						/* slot is off */
-						dbg("%s: slot is off\n", __FUNCTION__);
-						p_slot->state = BLINKINGON_STATE;
-						info(msg_button_on, p_slot->number);
-					}
-
-					/* Wait for exclusive access to hardware */
-					down(&ctrl->crit_sect);
-
-					/* blink green LED and turn off amber */
-					p_slot->hpc_ops->green_led_blink(p_slot);
-					
-					p_slot->hpc_ops->set_attention_status(p_slot, 0);
-
-					/* Done with exclusive hardware access */
-					up(&ctrl->crit_sect);
-
-					init_timer(&p_slot->task_event);
-					p_slot->task_event.expires = jiffies + 5 * HZ;   /* 5 second delay */
-					p_slot->task_event.function = (void (*)(unsigned long)) pushbutton_helper_thread;
-					p_slot->task_event.data = (unsigned long) p_slot;
-
-					dbg("%s: add_timer p_slot = %p\n", __FUNCTION__,(void *) p_slot);
-					add_timer(&p_slot->task_event);
-				} else if (ctrl->event_queue[loop].event_type == INT_POWER_FAULT) {
-					/***********POWER FAULT********************/
-					dbg("%s: power fault\n", __FUNCTION__);
-					/* Wait for exclusive access to hardware */
-					down(&ctrl->crit_sect);
-
-					p_slot->hpc_ops->set_attention_status(p_slot, 1);
-					
-					p_slot->hpc_ops->green_led_off(p_slot);
-
-					/* Done with exclusive hardware access */
-					up(&ctrl->crit_sect);
-				} else {
-					/* refresh notification */
-					if (p_slot)
-						update_slot_info(p_slot);
-				}
-
-				ctrl->event_queue[loop].event_type = 0;
-
-				change = 1;
-			}
-		}		/* End of FOR loop */
+	switch (p_slot->state) {
+	case STATIC_STATE:
+		p_slot->hpc_ops->get_power_status(p_slot, &getstatus);
+		if (getstatus) {
+			p_slot->state = BLINKINGOFF_STATE;
+			info(msg_button_off, p_slot->number);
+		} else {
+			p_slot->state = BLINKINGON_STATE;
+			info(msg_button_on, p_slot->number);
+		}
+		/* blink green LED and turn off amber */
+		p_slot->hpc_ops->green_led_blink(p_slot);
+		p_slot->hpc_ops->set_attention_status(p_slot, 0);
+
+		schedule_delayed_work(&p_slot->work, 5*HZ);
+		break;
+	case BLINKINGOFF_STATE:
+	case BLINKINGON_STATE:
+		/*
+		 * Cancel if we are still blinking; this means that we
+		 * press the attention again before the 5 sec. limit
+		 * expires to cancel hot-add or hot-remove
+		 */
+		info("Button cancel on Slot(%s)\n", p_slot->name);
+		dbg("%s: button cancel\n", __FUNCTION__);
+		cancel_delayed_work(&p_slot->work);
+		if (p_slot->state == BLINKINGOFF_STATE)
+			p_slot->hpc_ops->green_led_on(p_slot);
+		else
+			p_slot->hpc_ops->green_led_off(p_slot);
+		p_slot->hpc_ops->set_attention_status(p_slot, 0);
+		info(msg_button_cancel, p_slot->number);
+		p_slot->state = STATIC_STATE;
+		break;
+	case POWEROFF_STATE:
+	case POWERON_STATE:
+		/*
+		 * Ignore if the slot is on power-on or power-off state;
+		 * this means that the previous attention button action
+		 * to hot-add or hot-remove is undergoing
+		 */
+		info("Button ignore on Slot(%s)\n", p_slot->name);
+		update_slot_info(p_slot);
+		break;
+	default:
+		warn("Not a valid state\n");
+		break;
 	}
 	}
+}
+
+static void interrupt_event_handler(void *data)
+{
+	struct event_info *info = data;
+	struct slot *p_slot = info->p_slot;
+
+	mutex_lock(&p_slot->lock);
+	switch (info->event_type) {
+	case INT_BUTTON_PRESS:
+		handle_button_press_event(p_slot);
+		break;
+	case INT_POWER_FAULT:
+		dbg("%s: power fault\n", __FUNCTION__);
+		p_slot->hpc_ops->set_attention_status(p_slot, 1);
+		p_slot->hpc_ops->green_led_off(p_slot);
+		break;
+	default:
+		update_slot_info(p_slot);
+		break;
+	}
+	mutex_unlock(&p_slot->lock);
 
 
-	return;
+	kfree(info);
 }
 }
 
 
 
 
-int shpchp_enable_slot (struct slot *p_slot)
+static int shpchp_enable_slot (struct slot *p_slot)
 {
 {
 	u8 getstatus = 0;
 	u8 getstatus = 0;
-	int rc;
+	int rc, retval = -ENODEV;
 
 
 	/* Check to see if (latch closed, card present, power off) */
 	/* Check to see if (latch closed, card present, power off) */
-	down(&p_slot->ctrl->crit_sect);
+	mutex_lock(&p_slot->ctrl->crit_sect);
 	rc = p_slot->hpc_ops->get_adapter_status(p_slot, &getstatus);
 	rc = p_slot->hpc_ops->get_adapter_status(p_slot, &getstatus);
 	if (rc || !getstatus) {
 	if (rc || !getstatus) {
 		info("%s: no adapter on slot(%x)\n", __FUNCTION__, p_slot->number);
 		info("%s: no adapter on slot(%x)\n", __FUNCTION__, p_slot->number);
-		up(&p_slot->ctrl->crit_sect);
-		return -ENODEV;
+		goto out;
 	}
 	}
 	rc = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
 	rc = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
 	if (rc || getstatus) {
 	if (rc || getstatus) {
 		info("%s: latch open on slot(%x)\n", __FUNCTION__, p_slot->number);
 		info("%s: latch open on slot(%x)\n", __FUNCTION__, p_slot->number);
-		up(&p_slot->ctrl->crit_sect);
-		return -ENODEV;
+		goto out;
 	}
 	}
 	rc = p_slot->hpc_ops->get_power_status(p_slot, &getstatus);
 	rc = p_slot->hpc_ops->get_power_status(p_slot, &getstatus);
 	if (rc || getstatus) {
 	if (rc || getstatus) {
 		info("%s: already enabled on slot(%x)\n", __FUNCTION__, p_slot->number);
 		info("%s: already enabled on slot(%x)\n", __FUNCTION__, p_slot->number);
-		up(&p_slot->ctrl->crit_sect);
-		return -ENODEV;
+		goto out;
 	}
 	}
-	up(&p_slot->ctrl->crit_sect);
 
 
 	p_slot->is_a_board = 1;
 	p_slot->is_a_board = 1;
 
 
@@ -899,56 +602,119 @@ int shpchp_enable_slot (struct slot *p_slot)
 	     && p_slot->ctrl->num_slots == 1) {
 	     && p_slot->ctrl->num_slots == 1) {
 		/* handle amd pogo errata; this must be done before enable  */
 		/* handle amd pogo errata; this must be done before enable  */
 		amd_pogo_errata_save_misc_reg(p_slot);
 		amd_pogo_errata_save_misc_reg(p_slot);
-		rc = board_added(p_slot);
+		retval = board_added(p_slot);
 		/* handle amd pogo errata; this must be done after enable  */
 		/* handle amd pogo errata; this must be done after enable  */
 		amd_pogo_errata_restore_misc_reg(p_slot);
 		amd_pogo_errata_restore_misc_reg(p_slot);
 	} else
 	} else
-		rc = board_added(p_slot);
+		retval = board_added(p_slot);
 
 
-	if (rc) {
+	if (retval) {
 		p_slot->hpc_ops->get_adapter_status(p_slot,
 		p_slot->hpc_ops->get_adapter_status(p_slot,
 				&(p_slot->presence_save));
 				&(p_slot->presence_save));
 		p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
 		p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
 	}
 	}
 
 
 	update_slot_info(p_slot);
 	update_slot_info(p_slot);
-	return rc;
+ out:
+	mutex_unlock(&p_slot->ctrl->crit_sect);
+	return retval;
 }
 }
 
 
 
 
-int shpchp_disable_slot (struct slot *p_slot)
+static int shpchp_disable_slot (struct slot *p_slot)
 {
 {
 	u8 getstatus = 0;
 	u8 getstatus = 0;
-	int ret = 0;
+	int rc, retval = -ENODEV;
 
 
 	if (!p_slot->ctrl)
 	if (!p_slot->ctrl)
 		return -ENODEV;
 		return -ENODEV;
 
 
 	/* Check to see if (latch closed, card present, power on) */
 	/* Check to see if (latch closed, card present, power on) */
-	down(&p_slot->ctrl->crit_sect);
+	mutex_lock(&p_slot->ctrl->crit_sect);
 
 
-	ret = p_slot->hpc_ops->get_adapter_status(p_slot, &getstatus);
-	if (ret || !getstatus) {
+	rc = p_slot->hpc_ops->get_adapter_status(p_slot, &getstatus);
+	if (rc || !getstatus) {
 		info("%s: no adapter on slot(%x)\n", __FUNCTION__, p_slot->number);
 		info("%s: no adapter on slot(%x)\n", __FUNCTION__, p_slot->number);
-		up(&p_slot->ctrl->crit_sect);
-		return -ENODEV;
+		goto out;
 	}
 	}
-	ret = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
-	if (ret || getstatus) {
+	rc = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
+	if (rc || getstatus) {
 		info("%s: latch open on slot(%x)\n", __FUNCTION__, p_slot->number);
 		info("%s: latch open on slot(%x)\n", __FUNCTION__, p_slot->number);
-		up(&p_slot->ctrl->crit_sect);
-		return -ENODEV;
+		goto out;
 	}
 	}
-	ret = p_slot->hpc_ops->get_power_status(p_slot, &getstatus);
-	if (ret || !getstatus) {
+	rc = p_slot->hpc_ops->get_power_status(p_slot, &getstatus);
+	if (rc || !getstatus) {
 		info("%s: already disabled slot(%x)\n", __FUNCTION__, p_slot->number);
 		info("%s: already disabled slot(%x)\n", __FUNCTION__, p_slot->number);
-		up(&p_slot->ctrl->crit_sect);
-		return -ENODEV;
+		goto out;
 	}
 	}
-	up(&p_slot->ctrl->crit_sect);
 
 
-	ret = remove_board(p_slot);
+	retval = remove_board(p_slot);
 	update_slot_info(p_slot);
 	update_slot_info(p_slot);
-	return ret;
+ out:
+	mutex_unlock(&p_slot->ctrl->crit_sect);
+	return retval;
 }
 }
 
 
+int shpchp_sysfs_enable_slot(struct slot *p_slot)
+{
+	int retval = -ENODEV;
+
+	mutex_lock(&p_slot->lock);
+	switch (p_slot->state) {
+	case BLINKINGON_STATE:
+		cancel_delayed_work(&p_slot->work);
+	case STATIC_STATE:
+		p_slot->state = POWERON_STATE;
+		mutex_unlock(&p_slot->lock);
+		retval = shpchp_enable_slot(p_slot);
+		mutex_lock(&p_slot->lock);
+		p_slot->state = STATIC_STATE;
+		break;
+	case POWERON_STATE:
+		info("Slot %s is already in powering on state\n",
+		     p_slot->name);
+		break;
+	case BLINKINGOFF_STATE:
+	case POWEROFF_STATE:
+		info("Already enabled on slot %s\n", p_slot->name);
+		break;
+	default:
+		err("Not a valid state on slot %s\n", p_slot->name);
+		break;
+	}
+	mutex_unlock(&p_slot->lock);
+
+	return retval;
+}
+
+int shpchp_sysfs_disable_slot(struct slot *p_slot)
+{
+	int retval = -ENODEV;
+
+	mutex_lock(&p_slot->lock);
+	switch (p_slot->state) {
+	case BLINKINGOFF_STATE:
+		cancel_delayed_work(&p_slot->work);
+	case STATIC_STATE:
+		p_slot->state = POWEROFF_STATE;
+		mutex_unlock(&p_slot->lock);
+		retval = shpchp_disable_slot(p_slot);
+		mutex_lock(&p_slot->lock);
+		p_slot->state = STATIC_STATE;
+		break;
+	case POWEROFF_STATE:
+		info("Slot %s is already in powering off state\n",
+		     p_slot->name);
+		break;
+	case BLINKINGON_STATE:
+	case POWERON_STATE:
+		info("Already disabled on slot %s\n", p_slot->name);
+		break;
+	default:
+		err("Not a valid state on slot %s\n", p_slot->name);
+		break;
+	}
+	mutex_unlock(&p_slot->lock);
+
+	return retval;
+}

+ 189 - 329
drivers/pci/hotplug/shpchp_hpc.c

@@ -82,31 +82,6 @@
 #define SLOT_100MHZ_PCIX_533	0x0f000000
 #define SLOT_100MHZ_PCIX_533	0x0f000000
 #define SLOT_133MHZ_PCIX_533	0xf0000000
 #define SLOT_133MHZ_PCIX_533	0xf0000000
 
 
-
-/* Secondary Bus Configuration Register */
-/* For PI = 1, Bits 0 to 2 have been encoded as follows to show current bus speed/mode */
-#define PCI_33MHZ		0x0
-#define PCI_66MHZ		0x1
-#define PCIX_66MHZ		0x2
-#define PCIX_100MHZ		0x3
-#define PCIX_133MHZ		0x4
-
-/* For PI = 2, Bits 0 to 3 have been encoded as follows to show current bus speed/mode */
-#define PCI_33MHZ		0x0
-#define PCI_66MHZ		0x1
-#define PCIX_66MHZ		0x2
-#define PCIX_100MHZ		0x3
-#define PCIX_133MHZ		0x4
-#define PCIX_66MHZ_ECC		0x5
-#define PCIX_100MHZ_ECC		0x6
-#define PCIX_133MHZ_ECC		0x7
-#define PCIX_66MHZ_266		0x9
-#define PCIX_100MHZ_266		0xa
-#define PCIX_133MHZ_266		0xb
-#define PCIX_66MHZ_533		0x11
-#define PCIX_100MHZ_533		0x12
-#define PCIX_133MHZ_533		0x13
-
 /* Slot Configuration */
 /* Slot Configuration */
 #define SLOT_NUM		0x0000001F
 #define SLOT_NUM		0x0000001F
 #define	FIRST_DEV_NUM		0x00001F00
 #define	FIRST_DEV_NUM		0x00001F00
@@ -231,6 +206,7 @@ static spinlock_t list_lock;
 static irqreturn_t shpc_isr(int IRQ, void *dev_id, struct pt_regs *regs);
 static irqreturn_t shpc_isr(int IRQ, void *dev_id, struct pt_regs *regs);
 
 
 static void start_int_poll_timer(struct php_ctlr_state_s *php_ctlr, int seconds);
 static void start_int_poll_timer(struct php_ctlr_state_s *php_ctlr, int seconds);
+static int hpc_check_cmd_status(struct controller *ctrl);
 
 
 /* This is the interrupt polling timeout function. */
 /* This is the interrupt polling timeout function. */
 static void int_poll_timeout(unsigned long lphp_ctlr)
 static void int_poll_timeout(unsigned long lphp_ctlr)
@@ -303,10 +279,13 @@ static int shpc_write_cmd(struct slot *slot, u8 t_slot, u8 cmd)
 	int i;
 	int i;
 
 
 	DBG_ENTER_ROUTINE 
 	DBG_ENTER_ROUTINE 
-	
+
+	mutex_lock(&slot->ctrl->cmd_lock);
+
 	if (!php_ctlr) {
 	if (!php_ctlr) {
 		err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
 		err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
-		return -1;
+		retval = -EINVAL;
+		goto out;
 	}
 	}
 
 
 	for (i = 0; i < 10; i++) {
 	for (i = 0; i < 10; i++) {
@@ -323,7 +302,8 @@ static int shpc_write_cmd(struct slot *slot, u8 t_slot, u8 cmd)
 	if (cmd_status & 0x1) { 
 	if (cmd_status & 0x1) { 
 		/* After 1 sec and and the controller is still busy */
 		/* After 1 sec and and the controller is still busy */
 		err("%s : Controller is still busy after 1 sec.\n", __FUNCTION__);
 		err("%s : Controller is still busy after 1 sec.\n", __FUNCTION__);
-		return -1;
+		retval = -EBUSY;
+		goto out;
 	}
 	}
 
 
 	++t_slot;
 	++t_slot;
@@ -340,6 +320,17 @@ static int shpc_write_cmd(struct slot *slot, u8 t_slot, u8 cmd)
 	 * Wait for command completion.
 	 * Wait for command completion.
 	 */
 	 */
 	retval = shpc_wait_cmd(slot->ctrl);
 	retval = shpc_wait_cmd(slot->ctrl);
+	if (retval)
+		goto out;
+
+	cmd_status = hpc_check_cmd_status(slot->ctrl);
+	if (cmd_status) {
+		err("%s: Failed to issued command 0x%x (error code = %d)\n",
+		    __FUNCTION__, cmd, cmd_status);
+		retval = -EIO;
+	}
+ out:
+	mutex_unlock(&slot->ctrl->cmd_lock);
 
 
 	DBG_LEAVE_ROUTINE 
 	DBG_LEAVE_ROUTINE 
 	return retval;
 	return retval;
@@ -532,81 +523,41 @@ 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)
 static int hpc_get_adapter_speed(struct slot *slot, enum pci_bus_speed *value)
 {
 {
-	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;
 	int retval = 0;
 	int retval = 0;
+	struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle;
+	u32 slot_reg = readl(php_ctlr->creg + SLOT1 + 4 * slot->hp_slot);
+	u8 pcix_cap = (slot_reg >> 12) & 7;
+	u8 m66_cap  = (slot_reg >> 9) & 1;
 
 
 	DBG_ENTER_ROUTINE 
 	DBG_ENTER_ROUTINE 
 
 
-	if (!slot->ctrl->hpc_ctlr_handle) {
-		err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
-		return -1;
-	}
-
-	if (slot->hp_slot >= php_ctlr->num_slots) {
-		err("%s: Invalid HPC slot number!\n", __FUNCTION__);
-		return -1;
-	}
-	
-	pi = readb(php_ctlr->creg + PROG_INTERFACE);
-	slot_reg = readl(php_ctlr->creg + SLOT1 + 4*(slot->hp_slot));
-	dbg("%s: pi = %d, slot_reg = %x\n", __FUNCTION__, pi, slot_reg);
-	slot_status = (u16) slot_reg;
-	dbg("%s: slot_status = %x\n", __FUNCTION__, slot_status);
-	sec_bus_status = readw(php_ctlr->creg + SEC_BUS_CONFIG);
-
-	pcix_cap = (u8) ((slot_status & 0x3000) >> 12);
-	dbg("%s:  pcix_cap = %x\n", __FUNCTION__, pcix_cap);
-	m66_cap = (u8) ((slot_status & 0x0200) >> 9);
-	dbg("%s:  m66_cap = %x\n", __FUNCTION__, m66_cap);
-
+	dbg("%s: slot_reg = %x, pcix_cap = %x, m66_cap = %x\n",
+	    __FUNCTION__, slot_reg, pcix_cap, m66_cap);
 
 
-	if (pi == 2) {
-		switch (pcix_cap) {
-		case 0:
-			*value = m66_cap ? PCI_SPEED_66MHz : PCI_SPEED_33MHz;
-			break;
-		case 1:
-			*value = PCI_SPEED_66MHz_PCIX;
-			break;
-		case 3:
-			*value = PCI_SPEED_133MHz_PCIX;
-			break;
-		case 4:
-			*value = PCI_SPEED_133MHz_PCIX_266;	
-			break;
-		case 5:
-			*value = PCI_SPEED_133MHz_PCIX_533;	
-			break;
-		case 2:	/* Reserved */
-		default:
-			*value = PCI_SPEED_UNKNOWN;
-			retval = -ENODEV;
-			break;
-		}
-	} else {
-		switch (pcix_cap) {
-		case 0:
-			*value = m66_cap ? PCI_SPEED_66MHz : PCI_SPEED_33MHz;
-			break;
-		case 1:
-			*value = PCI_SPEED_66MHz_PCIX;
-			break;
-		case 3:
-			*value = PCI_SPEED_133MHz_PCIX;	
-			break;
-		case 2:	/* Reserved */
-		default:
-			*value = PCI_SPEED_UNKNOWN;
-			retval = -ENODEV;
-			break;
-		}
+	switch (pcix_cap) {
+	case 0x0:
+		*value = m66_cap ? PCI_SPEED_66MHz : PCI_SPEED_33MHz;
+		break;
+	case 0x1:
+		*value = PCI_SPEED_66MHz_PCIX;
+		break;
+	case 0x3:
+		*value = PCI_SPEED_133MHz_PCIX;
+		break;
+	case 0x4:
+		*value = PCI_SPEED_133MHz_PCIX_266;
+		break;
+	case 0x5:
+		*value = PCI_SPEED_133MHz_PCIX_533;
+		break;
+	case 0x2:
+	default:
+		*value = PCI_SPEED_UNKNOWN;
+		retval = -ENODEV;
+		break;
 	}
 	}
 
 
 	dbg("Adapter speed = %d\n", *value);
 	dbg("Adapter speed = %d\n", *value);
-	
 	DBG_LEAVE_ROUTINE 
 	DBG_LEAVE_ROUTINE 
 	return retval;
 	return retval;
 }
 }
@@ -797,6 +748,7 @@ static void hpc_release_ctlr(struct controller *ctrl)
 {
 {
 	struct php_ctlr_state_s *php_ctlr = ctrl->hpc_ctlr_handle;
 	struct php_ctlr_state_s *php_ctlr = ctrl->hpc_ctlr_handle;
 	struct php_ctlr_state_s *p, *p_prev;
 	struct php_ctlr_state_s *p, *p_prev;
+	int i;
 
 
 	DBG_ENTER_ROUTINE 
 	DBG_ENTER_ROUTINE 
 
 
@@ -805,6 +757,14 @@ static void hpc_release_ctlr(struct controller *ctrl)
 		return ;
 		return ;
 	}
 	}
 
 
+	/*
+	 * Mask all slot event interrupts
+	 */
+	for (i = 0; i < ctrl->num_slots; i++)
+		writel(0xffff3fff, php_ctlr->creg + SLOT1 + (4 * i));
+
+	cleanup_slots(ctrl);
+
 	if (shpchp_poll_mode) {
 	if (shpchp_poll_mode) {
 	    del_timer(&php_ctlr->int_poll_timer);
 	    del_timer(&php_ctlr->int_poll_timer);
 	} else {	
 	} else {	
@@ -814,6 +774,7 @@ static void hpc_release_ctlr(struct controller *ctrl)
 			pci_disable_msi(php_ctlr->pci_dev);
 			pci_disable_msi(php_ctlr->pci_dev);
 		}
 		}
 	}
 	}
+
 	if (php_ctlr->pci_dev) {
 	if (php_ctlr->pci_dev) {
 		iounmap(php_ctlr->creg);
 		iounmap(php_ctlr->creg);
 		release_mem_region(ctrl->mmio_base, ctrl->mmio_size);
 		release_mem_region(ctrl->mmio_base, ctrl->mmio_size);
@@ -939,98 +900,66 @@ static int hpc_slot_disable(struct slot * slot)
 
 
 static int hpc_set_bus_speed_mode(struct slot * slot, enum pci_bus_speed value)
 static int hpc_set_bus_speed_mode(struct slot * slot, enum pci_bus_speed value)
 {
 {
-	u8 slot_cmd;
-	u8 pi;
-	int retval = 0;
+	int retval;
 	struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle;
 	struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle;
+	u8 pi, cmd;
 
 
 	DBG_ENTER_ROUTINE 
 	DBG_ENTER_ROUTINE 
-	
-	if (!slot->ctrl->hpc_ctlr_handle) {
-		err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
-		return -1;
-	}
 
 
 	pi = readb(php_ctlr->creg + PROG_INTERFACE);
 	pi = readb(php_ctlr->creg + PROG_INTERFACE);
-	
-	if (pi == 1) {
-		switch (value) {
-		case 0:
-			slot_cmd = SETA_PCI_33MHZ;
-			break;
-		case 1:
-			slot_cmd = SETA_PCI_66MHZ;
-			break;
-		case 2:
-			slot_cmd = SETA_PCIX_66MHZ;
-			break;
-		case 3:
-			slot_cmd = SETA_PCIX_100MHZ;	
-			break;
-		case 4:
-			slot_cmd = SETA_PCIX_133MHZ;	
-			break;
-		default:
-			slot_cmd = PCI_SPEED_UNKNOWN;
-			retval = -ENODEV;
-			return retval;	
-		}
-	} else {
-		switch (value) {
-		case 0:
-			slot_cmd = SETB_PCI_33MHZ;
-			break;
-		case 1:
-			slot_cmd = SETB_PCI_66MHZ;
-			break;
-		case 2:
-			slot_cmd = SETB_PCIX_66MHZ_PM;
-			break;
-		case 3:
-			slot_cmd = SETB_PCIX_100MHZ_PM;	
-			break;
-		case 4:
-			slot_cmd = SETB_PCIX_133MHZ_PM;	
-			break;
-		case 5:
-			slot_cmd = SETB_PCIX_66MHZ_EM;	
-			break;
-		case 6:
-			slot_cmd = SETB_PCIX_100MHZ_EM;	
-			break;
-		case 7:
-			slot_cmd = SETB_PCIX_133MHZ_EM;	
-			break;
-		case 8:
-			slot_cmd = SETB_PCIX_66MHZ_266;	
-			break;
-		case 0x9:
-			slot_cmd = SETB_PCIX_100MHZ_266;	
-			break;
-		case 0xa:
-			slot_cmd = SETB_PCIX_133MHZ_266;	
-			break;
-		case 0xb:
-			slot_cmd = SETB_PCIX_66MHZ_533;	
-			break;
-		case 0xc:
-			slot_cmd = SETB_PCIX_100MHZ_533;	
-			break;
-		case 0xd:
-			slot_cmd = SETB_PCIX_133MHZ_533;	
-			break;
-		default:
-			slot_cmd = PCI_SPEED_UNKNOWN;
-			retval = -ENODEV;
-			return retval;	
-		}
+	if ((pi == 1) && (value > PCI_SPEED_133MHz_PCIX))
+		return -EINVAL;
 
 
+	switch (value) {
+	case PCI_SPEED_33MHz:
+		cmd = SETA_PCI_33MHZ;
+		break;
+	case PCI_SPEED_66MHz:
+		cmd = SETA_PCI_66MHZ;
+		break;
+	case PCI_SPEED_66MHz_PCIX:
+		cmd = SETA_PCIX_66MHZ;
+		break;
+	case PCI_SPEED_100MHz_PCIX:
+		cmd = SETA_PCIX_100MHZ;
+		break;
+	case PCI_SPEED_133MHz_PCIX:
+		cmd = SETA_PCIX_133MHZ;
+		break;
+	case PCI_SPEED_66MHz_PCIX_ECC:
+		cmd = SETB_PCIX_66MHZ_EM;
+		break;
+	case PCI_SPEED_100MHz_PCIX_ECC:
+		cmd = SETB_PCIX_100MHZ_EM;
+		break;
+	case PCI_SPEED_133MHz_PCIX_ECC:
+		cmd = SETB_PCIX_133MHZ_EM;
+		break;
+	case PCI_SPEED_66MHz_PCIX_266:
+		cmd = SETB_PCIX_66MHZ_266;
+		break;
+	case PCI_SPEED_100MHz_PCIX_266:
+		cmd = SETB_PCIX_100MHZ_266;
+		break;
+	case PCI_SPEED_133MHz_PCIX_266:
+		cmd = SETB_PCIX_133MHZ_266;
+		break;
+	case PCI_SPEED_66MHz_PCIX_533:
+		cmd = SETB_PCIX_66MHZ_533;
+		break;
+	case PCI_SPEED_100MHz_PCIX_533:
+		cmd = SETB_PCIX_100MHZ_533;
+		break;
+	case PCI_SPEED_133MHz_PCIX_533:
+		cmd = SETB_PCIX_133MHZ_533;
+		break;
+	default:
+		return -EINVAL;
 	}
 	}
-	retval = shpc_write_cmd(slot, 0, slot_cmd);
-	if (retval) {
+
+	retval = shpc_write_cmd(slot, 0, cmd);
+	if (retval)
 		err("%s: Write command failed!\n", __FUNCTION__);
 		err("%s: Write command failed!\n", __FUNCTION__);
-		return -1;
-	}
 
 
 	DBG_LEAVE_ROUTINE
 	DBG_LEAVE_ROUTINE
 	return retval;
 	return retval;
@@ -1093,14 +1022,8 @@ static irqreturn_t shpc_isr(int IRQ, void *dev_id, struct pt_regs *regs)
 		wake_up_interruptible(&ctrl->queue);
 		wake_up_interruptible(&ctrl->queue);
 	}
 	}
 
 
-	if ((intr_loc = (intr_loc >> 1)) == 0) {
-		/* Unmask Global Interrupt Mask */
-		temp_dword = readl(php_ctlr->creg + SERR_INTR_ENABLE);
-		temp_dword &= 0xfffffffe;
-		writel(temp_dword, php_ctlr->creg + SERR_INTR_ENABLE);
-
-		return IRQ_NONE;
-	}
+	if ((intr_loc = (intr_loc >> 1)) == 0)
+		goto out;
 
 
 	for (hp_slot = 0; hp_slot < ctrl->num_slots; hp_slot++) { 
 	for (hp_slot = 0; hp_slot < ctrl->num_slots; hp_slot++) { 
 	/* To find out which slot has interrupt pending */
 	/* To find out which slot has interrupt pending */
@@ -1130,6 +1053,7 @@ static irqreturn_t shpc_isr(int IRQ, void *dev_id, struct pt_regs *regs)
 			dbg("%s: intr_loc2 = %x\n",__FUNCTION__, intr_loc2); 
 			dbg("%s: intr_loc2 = %x\n",__FUNCTION__, intr_loc2); 
 		}
 		}
 	}
 	}
+ out:
 	if (!shpchp_poll_mode) {
 	if (!shpchp_poll_mode) {
 		/* Unmask Global Interrupt Mask */
 		/* Unmask Global Interrupt Mask */
 		temp_dword = readl(php_ctlr->creg + SERR_INTR_ENABLE);
 		temp_dword = readl(php_ctlr->creg + SERR_INTR_ENABLE);
@@ -1142,64 +1066,43 @@ 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)
 static int hpc_get_max_bus_speed (struct slot *slot, enum pci_bus_speed *value)
 {
 {
+	int retval = 0;
 	struct php_ctlr_state_s *php_ctlr = 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;
 	enum pci_bus_speed bus_speed = PCI_SPEED_UNKNOWN;
-	int retval = 0;
-	u8 pi;
-	u32 slot_avail1, slot_avail2;
+	u8 pi = readb(php_ctlr->creg + PROG_INTERFACE);
+	u32 slot_avail1 = readl(php_ctlr->creg + SLOT_AVAIL1);
+	u32 slot_avail2 = readl(php_ctlr->creg + SLOT_AVAIL2);
 
 
 	DBG_ENTER_ROUTINE 
 	DBG_ENTER_ROUTINE 
 
 
-	if (!slot->ctrl->hpc_ctlr_handle) {
-		err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
-		return -1;
-	}
-
-	if (slot->hp_slot >= php_ctlr->num_slots) {
-		err("%s: Invalid HPC slot number!\n", __FUNCTION__);
-		return -1;
-	}
-
-	pi = readb(php_ctlr->creg + PROG_INTERFACE);
-	slot_avail1 = readl(php_ctlr->creg + SLOT_AVAIL1);
-	slot_avail2 = readl(php_ctlr->creg + SLOT_AVAIL2);
-
 	if (pi == 2) {
 	if (pi == 2) {
 		if (slot_avail2 & SLOT_133MHZ_PCIX_533)
 		if (slot_avail2 & SLOT_133MHZ_PCIX_533)
-			bus_speed = PCIX_133MHZ_533;
+			bus_speed = PCI_SPEED_133MHz_PCIX_533;
 		else if (slot_avail2 & SLOT_100MHZ_PCIX_533)
 		else if (slot_avail2 & SLOT_100MHZ_PCIX_533)
-			bus_speed = PCIX_100MHZ_533;
+			bus_speed = PCI_SPEED_100MHz_PCIX_533;
 		else if (slot_avail2 & SLOT_66MHZ_PCIX_533)
 		else if (slot_avail2 & SLOT_66MHZ_PCIX_533)
-			bus_speed = PCIX_66MHZ_533;
+			bus_speed = PCI_SPEED_66MHz_PCIX_533;
 		else if (slot_avail2 & SLOT_133MHZ_PCIX_266)
 		else if (slot_avail2 & SLOT_133MHZ_PCIX_266)
-			bus_speed = PCIX_133MHZ_266;
+			bus_speed = PCI_SPEED_133MHz_PCIX_266;
 		else if (slot_avail2 & SLOT_100MHZ_PCIX_266)
 		else if (slot_avail2 & SLOT_100MHZ_PCIX_266)
-			bus_speed = PCIX_100MHZ_266;
+			bus_speed = PCI_SPEED_100MHz_PCIX_266;
 		else if (slot_avail2 & SLOT_66MHZ_PCIX_266)
 		else if (slot_avail2 & SLOT_66MHZ_PCIX_266)
-			bus_speed = PCIX_66MHZ_266;
-		else if (slot_avail1 & SLOT_133MHZ_PCIX)
-			bus_speed = PCIX_133MHZ;
-		else if (slot_avail1 & SLOT_100MHZ_PCIX)
-			bus_speed = PCIX_100MHZ;
-		else if (slot_avail1 & SLOT_66MHZ_PCIX)
-			bus_speed = PCIX_66MHZ;
-		else if (slot_avail2 & SLOT_66MHZ)
-			bus_speed = PCI_66MHZ;
-		else if (slot_avail1 & SLOT_33MHZ)
-			bus_speed = PCI_33MHZ;
-		else bus_speed = PCI_SPEED_UNKNOWN;
-	} else {
+			bus_speed = PCI_SPEED_66MHz_PCIX_266;
+	}
+
+	if (bus_speed == PCI_SPEED_UNKNOWN) {
 		if (slot_avail1 & SLOT_133MHZ_PCIX)
 		if (slot_avail1 & SLOT_133MHZ_PCIX)
-			bus_speed = PCIX_133MHZ;
+			bus_speed = PCI_SPEED_133MHz_PCIX;
 		else if (slot_avail1 & SLOT_100MHZ_PCIX)
 		else if (slot_avail1 & SLOT_100MHZ_PCIX)
-			bus_speed = PCIX_100MHZ;
+			bus_speed = PCI_SPEED_100MHz_PCIX;
 		else if (slot_avail1 & SLOT_66MHZ_PCIX)
 		else if (slot_avail1 & SLOT_66MHZ_PCIX)
-			bus_speed = PCIX_66MHZ;
+			bus_speed = PCI_SPEED_66MHz_PCIX;
 		else if (slot_avail2 & SLOT_66MHZ)
 		else if (slot_avail2 & SLOT_66MHZ)
-			bus_speed = PCI_66MHZ;
+			bus_speed = PCI_SPEED_66MHz;
 		else if (slot_avail1 & SLOT_33MHZ)
 		else if (slot_avail1 & SLOT_33MHZ)
-			bus_speed = PCI_33MHZ;
-		else bus_speed = PCI_SPEED_UNKNOWN;
+			bus_speed = PCI_SPEED_33MHz;
+		else
+			retval = -ENODEV;
 	}
 	}
 
 
 	*value = bus_speed;
 	*value = bus_speed;
@@ -1210,111 +1113,69 @@ 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)
 static int hpc_get_cur_bus_speed (struct slot *slot, enum pci_bus_speed *value)
 {
 {
+	int retval = 0;
 	struct php_ctlr_state_s *php_ctlr = 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;
 	enum pci_bus_speed bus_speed = PCI_SPEED_UNKNOWN;
-	u16 sec_bus_status;
-	int retval = 0;
-	u8 pi;
+	u16 sec_bus_reg = readw(php_ctlr->creg + SEC_BUS_CONFIG);
+	u8 pi = readb(php_ctlr->creg + PROG_INTERFACE);
+	u8 speed_mode = (pi == 2) ? (sec_bus_reg & 0xF) : (sec_bus_reg & 0x7);
 
 
 	DBG_ENTER_ROUTINE 
 	DBG_ENTER_ROUTINE 
 
 
-	if (!slot->ctrl->hpc_ctlr_handle) {
-		err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
-		return -1;
-	}
-
-	if (slot->hp_slot >= php_ctlr->num_slots) {
-		err("%s: Invalid HPC slot number!\n", __FUNCTION__);
-		return -1;
+	if ((pi == 1) && (speed_mode > 4)) {
+		*value = PCI_SPEED_UNKNOWN;
+		return -ENODEV;
 	}
 	}
 
 
-	pi = readb(php_ctlr->creg + PROG_INTERFACE);
-	sec_bus_status = readw(php_ctlr->creg + SEC_BUS_CONFIG);
-
-	if (pi == 2) {
-		switch (sec_bus_status & 0x000f) {
-		case 0:
-			bus_speed = PCI_SPEED_33MHz;
-			break;
-		case 1:
-			bus_speed = PCI_SPEED_66MHz;
-			break;
-		case 2:
-			bus_speed = PCI_SPEED_66MHz_PCIX;
-			break;
-		case 3:
-			bus_speed = PCI_SPEED_100MHz_PCIX;	
-			break;
-		case 4:
-			bus_speed = PCI_SPEED_133MHz_PCIX;	
-			break;
-		case 5:
-			bus_speed = PCI_SPEED_66MHz_PCIX_ECC;
-			break;
-		case 6:
-			bus_speed = PCI_SPEED_100MHz_PCIX_ECC;
-			break;
-		case 7:
-			bus_speed = PCI_SPEED_133MHz_PCIX_ECC;	
-			break;
-		case 8:
-			bus_speed = PCI_SPEED_66MHz_PCIX_266;	
-			break;
-		case 9:
-			bus_speed = PCI_SPEED_100MHz_PCIX_266;	
-			break;
-		case 0xa:
-			bus_speed = PCI_SPEED_133MHz_PCIX_266;	
-			break;
-		case 0xb:
-			bus_speed = PCI_SPEED_66MHz_PCIX_533;	
-			break;
-		case 0xc:
-			bus_speed = PCI_SPEED_100MHz_PCIX_533;	
-			break;
-		case 0xd:
-			bus_speed = PCI_SPEED_133MHz_PCIX_533;	
-			break;
-		case 0xe:
-		case 0xf:
-		default:
-			bus_speed = PCI_SPEED_UNKNOWN;
-			break;
-		}
-	} else {
-		/* In the case where pi is undefined, default it to 1 */ 
-		switch (sec_bus_status & 0x0007) {
-		case 0:
-			bus_speed = PCI_SPEED_33MHz;
-			break;
-		case 1:
-			bus_speed = PCI_SPEED_66MHz;
-			break;
-		case 2:
-			bus_speed = PCI_SPEED_66MHz_PCIX;
-			break;
-		case 3:
-			bus_speed = PCI_SPEED_100MHz_PCIX;	
-			break;
-		case 4:
-			bus_speed = PCI_SPEED_133MHz_PCIX;	
-			break;
-		case 5:
-			bus_speed = PCI_SPEED_UNKNOWN;		/*	Reserved */
-			break;
-		case 6:
-			bus_speed = PCI_SPEED_UNKNOWN;		/*	Reserved */
-			break;
-		case 7:
-			bus_speed = PCI_SPEED_UNKNOWN;		/*	Reserved */	
-			break;
-		default:
-			bus_speed = PCI_SPEED_UNKNOWN;
-			break;
-		}
+	switch (speed_mode) {
+	case 0x0:
+		*value = PCI_SPEED_33MHz;
+		break;
+	case 0x1:
+		*value = PCI_SPEED_66MHz;
+		break;
+	case 0x2:
+		*value = PCI_SPEED_66MHz_PCIX;
+		break;
+	case 0x3:
+		*value = PCI_SPEED_100MHz_PCIX;
+		break;
+	case 0x4:
+		*value = PCI_SPEED_133MHz_PCIX;
+		break;
+	case 0x5:
+		*value = PCI_SPEED_66MHz_PCIX_ECC;
+		break;
+	case 0x6:
+		*value = PCI_SPEED_100MHz_PCIX_ECC;
+		break;
+	case 0x7:
+		*value = PCI_SPEED_133MHz_PCIX_ECC;
+		break;
+	case 0x8:
+		*value = PCI_SPEED_66MHz_PCIX_266;
+		break;
+	case 0x9:
+		*value = PCI_SPEED_100MHz_PCIX_266;
+		break;
+	case 0xa:
+		*value = PCI_SPEED_133MHz_PCIX_266;
+		break;
+	case 0xb:
+		*value = PCI_SPEED_66MHz_PCIX_533;
+		break;
+	case 0xc:
+		*value = PCI_SPEED_100MHz_PCIX_533;
+		break;
+	case 0xd:
+		*value = PCI_SPEED_133MHz_PCIX_533;
+		break;
+	default:
+		*value = PCI_SPEED_UNKNOWN;
+		retval = -ENODEV;
+		break;
 	}
 	}
 
 
-	*value = bus_speed;
 	dbg("Current bus speed = %d\n", bus_speed);
 	dbg("Current bus speed = %d\n", bus_speed);
 	DBG_LEAVE_ROUTINE 
 	DBG_LEAVE_ROUTINE 
 	return retval;
 	return retval;
@@ -1343,7 +1204,6 @@ static struct hpc_ops shpchp_hpc_ops = {
 	.green_led_blink		= hpc_set_green_led_blink,
 	.green_led_blink		= hpc_set_green_led_blink,
 	
 	
 	.release_ctlr			= hpc_release_ctlr,
 	.release_ctlr			= hpc_release_ctlr,
-	.check_cmd_status		= hpc_check_cmd_status,
 };
 };
 
 
 inline static int shpc_indirect_creg_read(struct controller *ctrl, int index,
 inline static int shpc_indirect_creg_read(struct controller *ctrl, int index,
@@ -1375,15 +1235,13 @@ int shpc_init(struct controller * ctrl, struct pci_dev * pdev)
 	ctrl->pci_dev = pdev;  /* pci_dev of the P2P bridge */
 	ctrl->pci_dev = pdev;  /* pci_dev of the P2P bridge */
 
 
 	spin_lock_init(&list_lock);
 	spin_lock_init(&list_lock);
-	php_ctlr = (struct php_ctlr_state_s *) kmalloc(sizeof(struct php_ctlr_state_s), GFP_KERNEL);
+	php_ctlr = kzalloc(sizeof(*php_ctlr), GFP_KERNEL);
 
 
 	if (!php_ctlr) {	/* allocate controller state data */
 	if (!php_ctlr) {	/* allocate controller state data */
 		err("%s: HPC controller memory allocation error!\n", __FUNCTION__);
 		err("%s: HPC controller memory allocation error!\n", __FUNCTION__);
 		goto abort;
 		goto abort;
 	}
 	}
 
 
-	memset(php_ctlr, 0, sizeof(struct php_ctlr_state_s));
-
 	php_ctlr->pci_dev = pdev;	/* save pci_dev in context */
 	php_ctlr->pci_dev = pdev;	/* save pci_dev in context */
 
 
 	if ((pdev->vendor == PCI_VENDOR_ID_AMD) || (pdev->device ==
 	if ((pdev->vendor == PCI_VENDOR_ID_AMD) || (pdev->device ==
@@ -1454,7 +1312,9 @@ int shpc_init(struct controller * ctrl, struct pci_dev * pdev)
 	}
 	}
 	dbg("%s: php_ctlr->creg %p\n", __FUNCTION__, php_ctlr->creg);
 	dbg("%s: php_ctlr->creg %p\n", __FUNCTION__, php_ctlr->creg);
 
 
-	init_MUTEX(&ctrl->crit_sect);
+	mutex_init(&ctrl->crit_sect);
+	mutex_init(&ctrl->cmd_lock);
+
 	/* Setup wait queue */
 	/* Setup wait queue */
 	init_waitqueue_head(&ctrl->queue);
 	init_waitqueue_head(&ctrl->queue);
 
 

+ 8 - 2
drivers/pci/hotplug/shpchp_pci.c

@@ -38,7 +38,7 @@ static void program_fw_provided_values(struct pci_dev *dev)
 {
 {
 	u16 pci_cmd, pci_bctl;
 	u16 pci_cmd, pci_bctl;
 	struct pci_dev *cdev;
 	struct pci_dev *cdev;
-	struct hotplug_params hpp = {0x8, 0x40, 0, 0}; /* defaults */
+	struct hotplug_params hpp;
 
 
 	/* Program hpp values for this device */
 	/* Program hpp values for this device */
 	if (!(dev->hdr_type == PCI_HEADER_TYPE_NORMAL ||
 	if (!(dev->hdr_type == PCI_HEADER_TYPE_NORMAL ||
@@ -46,7 +46,13 @@ static void program_fw_provided_values(struct pci_dev *dev)
 			(dev->class >> 8) == PCI_CLASS_BRIDGE_PCI)))
 			(dev->class >> 8) == PCI_CLASS_BRIDGE_PCI)))
 		return;
 		return;
 
 
-	get_hp_params_from_firmware(dev, &hpp);
+	/* use default values if we can't get them from firmware */
+	if (get_hp_params_from_firmware(dev, &hpp)) {
+		hpp.cache_line_size = 8;
+		hpp.latency_timer = 0x40;
+		hpp.enable_serr = 0;
+		hpp.enable_perr = 0;
+	}
 
 
 	pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, hpp.cache_line_size);
 	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_write_config_byte(dev, PCI_LATENCY_TIMER, hpp.latency_timer);

+ 0 - 54
drivers/pci/hotplug/shpchprm_legacy.c

@@ -1,54 +0,0 @@
-/*
- * SHPCHPRM Legacy: 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>
- *
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/pci.h>
-#include "shpchp.h"
-
-int shpchprm_get_physical_slot_number(struct controller *ctrl, u32 *sun, u8 busnum, u8 devnum)
-{
-	int	offset = devnum - ctrl->slot_device_offset;
-
-	*sun = (u8) (ctrl->first_slot + ctrl->slot_num_inc * offset);
-	return 0;
-}
-
-void get_hp_params_from_firmware(struct pci_dev *dev,
-		struct hotplug_params *hpp)
-{
-	return;
-}
-
-void get_hp_hw_control_from_firmware(struct pci_dev *dev)
-{
-	return;
-}
-

+ 0 - 57
drivers/pci/hotplug/shpchprm_nonacpi.c

@@ -1,57 +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>
- *
- */
-
-#include <linux/config.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/pci.h>
-#include <linux/slab.h>
-
-#include "shpchp.h"
-
-int shpchprm_get_physical_slot_number(struct controller *ctrl, u32 *sun, u8 busnum, u8 devnum)
-{
-	int	offset = devnum - ctrl->slot_device_offset;
-
-	dbg("%s: ctrl->slot_num_inc %d, offset %d\n", __FUNCTION__, ctrl->slot_num_inc, offset);
-	*sun = (u8) (ctrl->first_slot + ctrl->slot_num_inc * offset);
-	return 0;
-}
-
-void get_hp_params_from_firmware(struct pci_dev *dev,
-		struct hotplug_params *hpp)
-{
-	return;
-}
-
-void get_hp_hw_control_from_firmware(struct pci_dev *dev)
-{
-	return;
-}

+ 72 - 33
drivers/pci/msi.c

@@ -103,9 +103,9 @@ static void set_msi_affinity(unsigned int vector, cpumask_t cpu_mask)
 	switch (entry->msi_attrib.type) {
 	switch (entry->msi_attrib.type) {
 	case PCI_CAP_ID_MSI:
 	case PCI_CAP_ID_MSI:
 	{
 	{
-		int pos;
+		int pos = pci_find_capability(entry->dev, PCI_CAP_ID_MSI);
 
 
-   		if (!(pos = pci_find_capability(entry->dev, PCI_CAP_ID_MSI)))
+		if (!pos)
 			return;
 			return;
 
 
 		pci_read_config_dword(entry->dev, msi_lower_address_reg(pos),
 		pci_read_config_dword(entry->dev, msi_lower_address_reg(pos),
@@ -347,9 +347,9 @@ static int assign_msi_vector(void)
 
 
 static int get_new_vector(void)
 static int get_new_vector(void)
 {
 {
-	int vector;
+	int vector = assign_msi_vector();
 
 
-	if ((vector = assign_msi_vector()) > 0)
+	if (vector > 0)
 		set_intr_gate(vector, interrupt[vector]);
 		set_intr_gate(vector, interrupt[vector]);
 
 
 	return vector;
 	return vector;
@@ -369,7 +369,8 @@ static int msi_init(void)
 		return status;
 		return status;
 	}
 	}
 
 
-	if ((status = msi_cache_init()) < 0) {
+	status = msi_cache_init();
+	if (status < 0) {
 		pci_msi_enable = 0;
 		pci_msi_enable = 0;
 		printk(KERN_WARNING "PCI: MSI cache init failed\n");
 		printk(KERN_WARNING "PCI: MSI cache init failed\n");
 		return status;
 		return status;
@@ -523,10 +524,12 @@ static int msi_capability_init(struct pci_dev *dev)
    	pos = pci_find_capability(dev, PCI_CAP_ID_MSI);
    	pos = pci_find_capability(dev, PCI_CAP_ID_MSI);
 	pci_read_config_word(dev, msi_control_reg(pos), &control);
 	pci_read_config_word(dev, msi_control_reg(pos), &control);
 	/* MSI Entry Initialization */
 	/* MSI Entry Initialization */
-	if (!(entry = alloc_msi_entry()))
+	entry = alloc_msi_entry();
+	if (!entry)
 		return -ENOMEM;
 		return -ENOMEM;
 
 
-	if ((vector = get_msi_vector(dev)) < 0) {
+	vector = get_msi_vector(dev);
+	if (vector < 0) {
 		kmem_cache_free(msi_cachep, entry);
 		kmem_cache_free(msi_cachep, entry);
 		return -EBUSY;
 		return -EBUSY;
 	}
 	}
@@ -597,7 +600,8 @@ static int msix_capability_init(struct pci_dev *dev,
 	struct msg_address address;
 	struct msg_address address;
 	struct msg_data data;
 	struct msg_data data;
 	int vector, pos, i, j, nr_entries, temp = 0;
 	int vector, pos, i, j, nr_entries, temp = 0;
-	u32 phys_addr, table_offset;
+	unsigned long phys_addr;
+	u32 table_offset;
  	u16 control;
  	u16 control;
 	u8 bir;
 	u8 bir;
 	void __iomem *base;
 	void __iomem *base;
@@ -606,11 +610,11 @@ static int msix_capability_init(struct pci_dev *dev,
 	/* Request & Map MSI-X table region */
 	/* Request & Map MSI-X table region */
  	pci_read_config_word(dev, msi_control_reg(pos), &control);
  	pci_read_config_word(dev, msi_control_reg(pos), &control);
 	nr_entries = multi_msix_capable(control);
 	nr_entries = multi_msix_capable(control);
- 	pci_read_config_dword(dev, msix_table_offset_reg(pos),
- 		&table_offset);
+
+ 	pci_read_config_dword(dev, msix_table_offset_reg(pos), &table_offset);
 	bir = (u8)(table_offset & PCI_MSIX_FLAGS_BIRMASK);
 	bir = (u8)(table_offset & PCI_MSIX_FLAGS_BIRMASK);
-	phys_addr = pci_resource_start (dev, bir);
-	phys_addr += (u32)(table_offset & ~PCI_MSIX_FLAGS_BIRMASK);
+	table_offset &= ~PCI_MSIX_FLAGS_BIRMASK;
+	phys_addr = pci_resource_start (dev, bir) + table_offset;
 	base = ioremap_nocache(phys_addr, nr_entries * PCI_MSIX_ENTRY_SIZE);
 	base = ioremap_nocache(phys_addr, nr_entries * PCI_MSIX_ENTRY_SIZE);
 	if (base == NULL)
 	if (base == NULL)
 		return -ENOMEM;
 		return -ENOMEM;
@@ -620,7 +624,8 @@ static int msix_capability_init(struct pci_dev *dev,
 		entry = alloc_msi_entry();
 		entry = alloc_msi_entry();
 		if (!entry)
 		if (!entry)
 			break;
 			break;
-		if ((vector = get_msi_vector(dev)) < 0)
+		vector = get_msi_vector(dev);
+		if (vector < 0)
 			break;
 			break;
 
 
  		j = entries[i].entry;
  		j = entries[i].entry;
@@ -699,12 +704,17 @@ int pci_enable_msi(struct pci_dev* dev)
 	if (dev->no_msi)
 	if (dev->no_msi)
 		return status;
 		return status;
 
 
+	if (dev->bus->bus_flags & PCI_BUS_FLAGS_NO_MSI)
+		return -EINVAL;
+
 	temp = dev->irq;
 	temp = dev->irq;
 
 
-	if ((status = msi_init()) < 0)
+	status = msi_init();
+	if (status < 0)
 		return status;
 		return status;
 
 
-   	if (!(pos = pci_find_capability(dev, PCI_CAP_ID_MSI)))
+	pos = pci_find_capability(dev, PCI_CAP_ID_MSI);
+	if (!pos)
 		return -EINVAL;
 		return -EINVAL;
 
 
 	pci_read_config_word(dev, msi_control_reg(pos), &control);
 	pci_read_config_word(dev, msi_control_reg(pos), &control);
@@ -728,8 +738,8 @@ int pci_enable_msi(struct pci_dev* dev)
 		dev->irq = temp;
 		dev->irq = temp;
 	}
 	}
 	/* Check whether driver already requested for MSI-X vectors */
 	/* Check whether driver already requested for MSI-X vectors */
-   	if ((pos = pci_find_capability(dev, PCI_CAP_ID_MSIX)) > 0 &&
-		!msi_lookup_vector(dev, PCI_CAP_ID_MSIX)) {
+	pos = pci_find_capability(dev, PCI_CAP_ID_MSIX);
+	if (pos > 0 && !msi_lookup_vector(dev, PCI_CAP_ID_MSIX)) {
 			printk(KERN_INFO "PCI: %s: Can't enable MSI.  "
 			printk(KERN_INFO "PCI: %s: Can't enable MSI.  "
 			       "Device already has MSI-X vectors assigned\n",
 			       "Device already has MSI-X vectors assigned\n",
 			       pci_name(dev));
 			       pci_name(dev));
@@ -755,7 +765,13 @@ void pci_disable_msi(struct pci_dev* dev)
 	u16 control;
 	u16 control;
 	unsigned long flags;
 	unsigned long flags;
 
 
-   	if (!dev || !(pos = pci_find_capability(dev, PCI_CAP_ID_MSI)))
+	if (!pci_msi_enable)
+		return;
+	if (!dev)
+		return;
+
+	pos = pci_find_capability(dev, PCI_CAP_ID_MSI);
+	if (!pos)
 		return;
 		return;
 
 
 	pci_read_config_word(dev, msi_control_reg(pos), &control);
 	pci_read_config_word(dev, msi_control_reg(pos), &control);
@@ -826,8 +842,10 @@ static int msi_free_vector(struct pci_dev* dev, int vector, int reassign)
 			 * Detect last MSI-X vector to be released.
 			 * Detect last MSI-X vector to be released.
 			 * Release the MSI-X memory-mapped table.
 			 * Release the MSI-X memory-mapped table.
 			 */
 			 */
+#if 0
 			int pos, nr_entries;
 			int pos, nr_entries;
-			u32 phys_addr, table_offset;
+			unsigned long phys_addr;
+			u32 table_offset;
 			u16 control;
 			u16 control;
 			u8 bir;
 			u8 bir;
 
 
@@ -838,9 +856,12 @@ static int msi_free_vector(struct pci_dev* dev, int vector, int reassign)
 			pci_read_config_dword(dev, msix_table_offset_reg(pos),
 			pci_read_config_dword(dev, msix_table_offset_reg(pos),
 				&table_offset);
 				&table_offset);
 			bir = (u8)(table_offset & PCI_MSIX_FLAGS_BIRMASK);
 			bir = (u8)(table_offset & PCI_MSIX_FLAGS_BIRMASK);
-			phys_addr = pci_resource_start (dev, bir);
-			phys_addr += (u32)(table_offset &
-				~PCI_MSIX_FLAGS_BIRMASK);
+			table_offset &= ~PCI_MSIX_FLAGS_BIRMASK;
+			phys_addr = pci_resource_start(dev, bir) + table_offset;
+/*
+ * FIXME!  and what did you want to do with phys_addr?
+ */
+#endif
 			iounmap(base);
 			iounmap(base);
 		}
 		}
 	}
 	}
@@ -924,10 +945,12 @@ int pci_enable_msix(struct pci_dev* dev, struct msix_entry *entries, int nvec)
 	if (!pci_msi_enable || !dev || !entries)
 	if (!pci_msi_enable || !dev || !entries)
  		return -EINVAL;
  		return -EINVAL;
 
 
-	if ((status = msi_init()) < 0)
+	status = msi_init();
+	if (status < 0)
 		return status;
 		return status;
 
 
-   	if (!(pos = pci_find_capability(dev, PCI_CAP_ID_MSIX)))
+	pos = pci_find_capability(dev, PCI_CAP_ID_MSIX);
+	if (!pos)
  		return -EINVAL;
  		return -EINVAL;
 
 
 	pci_read_config_word(dev, msi_control_reg(pos), &control);
 	pci_read_config_word(dev, msi_control_reg(pos), &control);
@@ -1006,7 +1029,13 @@ void pci_disable_msix(struct pci_dev* dev)
 	int pos, temp;
 	int pos, temp;
 	u16 control;
 	u16 control;
 
 
-   	if (!dev || !(pos = pci_find_capability(dev, PCI_CAP_ID_MSIX)))
+	if (!pci_msi_enable)
+		return;
+	if (!dev)
+		return;
+
+	pos = pci_find_capability(dev, PCI_CAP_ID_MSIX);
+	if (!pos)
 		return;
 		return;
 
 
 	pci_read_config_word(dev, msi_control_reg(pos), &control);
 	pci_read_config_word(dev, msi_control_reg(pos), &control);
@@ -1066,8 +1095,8 @@ void msi_remove_pci_irq_vectors(struct pci_dev* dev)
  		return;
  		return;
 
 
 	temp = dev->irq;		/* Save IOAPIC IRQ */
 	temp = dev->irq;		/* Save IOAPIC IRQ */
-   	if ((pos = pci_find_capability(dev, PCI_CAP_ID_MSI)) > 0 &&
-		!msi_lookup_vector(dev, PCI_CAP_ID_MSI)) {
+	pos = pci_find_capability(dev, PCI_CAP_ID_MSI);
+	if (pos > 0 && !msi_lookup_vector(dev, PCI_CAP_ID_MSI)) {
 		spin_lock_irqsave(&msi_lock, flags);
 		spin_lock_irqsave(&msi_lock, flags);
 		state = msi_desc[dev->irq]->msi_attrib.state;
 		state = msi_desc[dev->irq]->msi_attrib.state;
 		spin_unlock_irqrestore(&msi_lock, flags);
 		spin_unlock_irqrestore(&msi_lock, flags);
@@ -1080,8 +1109,8 @@ void msi_remove_pci_irq_vectors(struct pci_dev* dev)
 			msi_free_vector(dev, dev->irq, 0);
 			msi_free_vector(dev, dev->irq, 0);
 		dev->irq = temp;		/* Restore IOAPIC IRQ */
 		dev->irq = temp;		/* Restore IOAPIC IRQ */
 	}
 	}
-   	if ((pos = pci_find_capability(dev, PCI_CAP_ID_MSIX)) > 0 &&
-		!msi_lookup_vector(dev, PCI_CAP_ID_MSIX)) {
+	pos = pci_find_capability(dev, PCI_CAP_ID_MSIX);
+	if (pos > 0 && !msi_lookup_vector(dev, PCI_CAP_ID_MSIX)) {
 		int vector, head, tail = 0, warning = 0;
 		int vector, head, tail = 0, warning = 0;
 		void __iomem *base = NULL;
 		void __iomem *base = NULL;
 
 
@@ -1101,7 +1130,9 @@ void msi_remove_pci_irq_vectors(struct pci_dev* dev)
 		msi_free_vector(dev, vector, 0);
 		msi_free_vector(dev, vector, 0);
 		if (warning) {
 		if (warning) {
 			/* Force to release the MSI-X memory-mapped table */
 			/* Force to release the MSI-X memory-mapped table */
-			u32 phys_addr, table_offset;
+#if 0
+			unsigned long phys_addr;
+			u32 table_offset;
 			u16 control;
 			u16 control;
 			u8 bir;
 			u8 bir;
 
 
@@ -1110,9 +1141,12 @@ void msi_remove_pci_irq_vectors(struct pci_dev* dev)
 			pci_read_config_dword(dev, msix_table_offset_reg(pos),
 			pci_read_config_dword(dev, msix_table_offset_reg(pos),
 				&table_offset);
 				&table_offset);
 			bir = (u8)(table_offset & PCI_MSIX_FLAGS_BIRMASK);
 			bir = (u8)(table_offset & PCI_MSIX_FLAGS_BIRMASK);
-			phys_addr = pci_resource_start (dev, bir);
-			phys_addr += (u32)(table_offset &
-				~PCI_MSIX_FLAGS_BIRMASK);
+			table_offset &= ~PCI_MSIX_FLAGS_BIRMASK;
+			phys_addr = pci_resource_start(dev, bir) + table_offset;
+/*
+ * FIXME! and what did you want to do with phys_addr?
+ */
+#endif
 			iounmap(base);
 			iounmap(base);
 			printk(KERN_WARNING "PCI: %s: msi_remove_pci_irq_vectors() "
 			printk(KERN_WARNING "PCI: %s: msi_remove_pci_irq_vectors() "
 			       "called without free_irq() on all MSI-X vectors\n",
 			       "called without free_irq() on all MSI-X vectors\n",
@@ -1123,6 +1157,11 @@ void msi_remove_pci_irq_vectors(struct pci_dev* dev)
 	}
 	}
 }
 }
 
 
+void pci_no_msi(void)
+{
+	pci_msi_enable = 0;
+}
+
 EXPORT_SYMBOL(pci_enable_msi);
 EXPORT_SYMBOL(pci_enable_msi);
 EXPORT_SYMBOL(pci_disable_msi);
 EXPORT_SYMBOL(pci_disable_msi);
 EXPORT_SYMBOL(pci_enable_msix);
 EXPORT_SYMBOL(pci_enable_msix);

+ 2 - 10
drivers/pci/pci-driver.c

@@ -53,11 +53,10 @@ store_new_id(struct device_driver *driver, const char *buf, size_t count)
 	if (fields < 0)
 	if (fields < 0)
 		return -EINVAL;
 		return -EINVAL;
 
 
-	dynid = kmalloc(sizeof(*dynid), GFP_KERNEL);
+	dynid = kzalloc(sizeof(*dynid), GFP_KERNEL);
 	if (!dynid)
 	if (!dynid)
 		return -ENOMEM;
 		return -ENOMEM;
 
 
-	memset(dynid, 0, sizeof(*dynid));
 	INIT_LIST_HEAD(&dynid->node);
 	INIT_LIST_HEAD(&dynid->node);
 	dynid->id.vendor = vendor;
 	dynid->id.vendor = vendor;
 	dynid->id.device = device;
 	dynid->id.device = device;
@@ -380,14 +379,6 @@ int __pci_register_driver(struct pci_driver *drv, struct module *owner)
 	/* initialize common driver fields */
 	/* initialize common driver fields */
 	drv->driver.name = drv->name;
 	drv->driver.name = drv->name;
 	drv->driver.bus = &pci_bus_type;
 	drv->driver.bus = &pci_bus_type;
-	/* FIXME, once all of the existing PCI drivers have been fixed to set
-	 * 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 = owner;
 	drv->driver.owner = owner;
 	drv->driver.kobj.ktype = &pci_driver_kobj_type;
 	drv->driver.kobj.ktype = &pci_driver_kobj_type;
 
 
@@ -514,6 +505,7 @@ struct bus_type pci_bus_type = {
 	.probe		= pci_device_probe,
 	.probe		= pci_device_probe,
 	.remove		= pci_device_remove,
 	.remove		= pci_device_remove,
 	.suspend	= pci_device_suspend,
 	.suspend	= pci_device_suspend,
+	.shutdown	= pci_device_shutdown,
 	.resume		= pci_device_resume,
 	.resume		= pci_device_resume,
 	.dev_attrs	= pci_dev_attrs,
 	.dev_attrs	= pci_dev_attrs,
 };
 };

+ 1 - 2
drivers/pci/pci-sysfs.c

@@ -501,9 +501,8 @@ int pci_create_sysfs_dev_files (struct pci_dev *pdev)
 	if (pci_resource_len(pdev, PCI_ROM_RESOURCE)) {
 	if (pci_resource_len(pdev, PCI_ROM_RESOURCE)) {
 		struct bin_attribute *rom_attr;
 		struct bin_attribute *rom_attr;
 		
 		
-		rom_attr = kmalloc(sizeof(*rom_attr), GFP_ATOMIC);
+		rom_attr = kzalloc(sizeof(*rom_attr), GFP_ATOMIC);
 		if (rom_attr) {
 		if (rom_attr) {
-			memset(rom_attr, 0x00, sizeof(*rom_attr));
 			pdev->rom_attr = rom_attr;
 			pdev->rom_attr = rom_attr;
 			rom_attr->size = pci_resource_len(pdev, PCI_ROM_RESOURCE);
 			rom_attr->size = pci_resource_len(pdev, PCI_ROM_RESOURCE);
 			rom_attr->attr.name = "rom";
 			rom_attr->attr.name = "rom";

+ 13 - 9
drivers/pci/pci.c

@@ -19,7 +19,6 @@
 #include <asm/dma.h>	/* isa_dma_bridge_buggy */
 #include <asm/dma.h>	/* isa_dma_bridge_buggy */
 #include "pci.h"
 #include "pci.h"
 
 
-#if 0
 
 
 /**
 /**
  * pci_bus_max_busnr - returns maximum PCI bus number of given bus' children
  * pci_bus_max_busnr - returns maximum PCI bus number of given bus' children
@@ -34,7 +33,7 @@ pci_bus_max_busnr(struct pci_bus* bus)
 	struct list_head *tmp;
 	struct list_head *tmp;
 	unsigned char max, n;
 	unsigned char max, n;
 
 
-	max = bus->number;
+	max = bus->subordinate;
 	list_for_each(tmp, &bus->children) {
 	list_for_each(tmp, &bus->children) {
 		n = pci_bus_max_busnr(pci_bus_b(tmp));
 		n = pci_bus_max_busnr(pci_bus_b(tmp));
 		if(n > max)
 		if(n > max)
@@ -42,7 +41,9 @@ pci_bus_max_busnr(struct pci_bus* bus)
 	}
 	}
 	return max;
 	return max;
 }
 }
+EXPORT_SYMBOL_GPL(pci_bus_max_busnr);
 
 
+#if 0
 /**
 /**
  * pci_max_busnr - returns maximum PCI bus number
  * pci_max_busnr - returns maximum PCI bus number
  *
  *
@@ -495,9 +496,8 @@ pci_enable_device_bars(struct pci_dev *dev, int bars)
 int
 int
 pci_enable_device(struct pci_dev *dev)
 pci_enable_device(struct pci_dev *dev)
 {
 {
-	int err;
-
-	if ((err = pci_enable_device_bars(dev, (1 << PCI_NUM_RESOURCES) - 1)))
+	int err = pci_enable_device_bars(dev, (1 << PCI_NUM_RESOURCES) - 1);
+	if (err)
 		return err;
 		return err;
 	pci_fixup_device(pci_fixup_enable, dev);
 	pci_fixup_device(pci_fixup_enable, dev);
 	dev->is_enabled = 1;
 	dev->is_enabled = 1;
@@ -639,7 +639,7 @@ void pci_release_region(struct pci_dev *pdev, int bar)
  *	Returns 0 on success, or %EBUSY on error.  A warning
  *	Returns 0 on success, or %EBUSY on error.  A warning
  *	message is also printed on failure.
  *	message is also printed on failure.
  */
  */
-int pci_request_region(struct pci_dev *pdev, int bar, char *res_name)
+int pci_request_region(struct pci_dev *pdev, int bar, const char *res_name)
 {
 {
 	if (pci_resource_len(pdev, bar) == 0)
 	if (pci_resource_len(pdev, bar) == 0)
 		return 0;
 		return 0;
@@ -697,7 +697,7 @@ void pci_release_regions(struct pci_dev *pdev)
  *	Returns 0 on success, or %EBUSY on error.  A warning
  *	Returns 0 on success, or %EBUSY on error.  A warning
  *	message is also printed on failure.
  *	message is also printed on failure.
  */
  */
-int pci_request_regions(struct pci_dev *pdev, char *res_name)
+int pci_request_regions(struct pci_dev *pdev, const char *res_name)
 {
 {
 	int i;
 	int i;
 	
 	
@@ -900,8 +900,12 @@ static int __devinit pci_setup(char *str)
 		if (k)
 		if (k)
 			*k++ = 0;
 			*k++ = 0;
 		if (*str && (str = pcibios_setup(str)) && *str) {
 		if (*str && (str = pcibios_setup(str)) && *str) {
-			/* PCI layer options should be handled here */
-			printk(KERN_ERR "PCI: Unknown option `%s'\n", str);
+			if (!strcmp(str, "nomsi")) {
+				pci_no_msi();
+			} else {
+				printk(KERN_ERR "PCI: Unknown option `%s'\n",
+						str);
+			}
 		}
 		}
 		str = k;
 		str = k;
 	}
 	}

+ 2 - 0
drivers/pci/pci.h

@@ -50,8 +50,10 @@ extern int pci_msi_quirk;
 
 
 #ifdef CONFIG_PCI_MSI
 #ifdef CONFIG_PCI_MSI
 void disable_msi_mode(struct pci_dev *dev, int pos, int type);
 void disable_msi_mode(struct pci_dev *dev, int pos, int type);
+void pci_no_msi(void);
 #else
 #else
 static inline void disable_msi_mode(struct pci_dev *dev, int pos, int type) { }
 static inline void disable_msi_mode(struct pci_dev *dev, int pos, int type) { }
+static inline void pci_no_msi(void) { }
 #endif
 #endif
 
 
 extern int pcie_mch_quirk;
 extern int pcie_mch_quirk;

+ 0 - 1
drivers/pci/pcie/portdrv.h

@@ -29,7 +29,6 @@
 
 
 struct pcie_port_device_ext {
 struct pcie_port_device_ext {
 	int interrupt_mode;	/* [0:INTx | 1:MSI | 2:MSI-X] */
 	int interrupt_mode;	/* [0:INTx | 1:MSI | 2:MSI-X] */
-	unsigned int saved_msi_config_space[5];
 };
 };
 
 
 extern struct bus_type pcie_port_bus_type;
 extern struct bus_type pcie_port_bus_type;

+ 1 - 2
drivers/pci/pcie/portdrv_core.c

@@ -248,11 +248,10 @@ static struct pcie_device* alloc_pcie_device(struct pci_dev *parent,
 {
 {
 	struct pcie_device *device;
 	struct pcie_device *device;
 
 
-	device = kmalloc(sizeof(struct pcie_device), GFP_KERNEL);
+	device = kzalloc(sizeof(struct pcie_device), GFP_KERNEL);
 	if (!device)
 	if (!device)
 		return NULL;
 		return NULL;
 
 
-	memset(device, 0, sizeof(struct pcie_device));
 	pcie_device_init(parent, device, port_type, service_type, irq,irq_mode);
 	pcie_device_init(parent, device, port_type, service_type, irq,irq_mode);
 	printk(KERN_DEBUG "Allocate Port Service[%s]\n", device->device.bus_id);
 	printk(KERN_DEBUG "Allocate Port Service[%s]\n", device->device.bus_id);
 	return device;
 	return device;

+ 4 - 62
drivers/pci/pcie/portdrv_pci.c

@@ -30,75 +30,16 @@ MODULE_LICENSE("GPL");
 /* global data */
 /* global data */
 static const char device_name[] = "pcieport-driver";
 static const char device_name[] = "pcieport-driver";
 
 
-static void pci_save_msi_state(struct pci_dev *dev)
+static int pcie_portdrv_save_config(struct pci_dev *dev)
 {
 {
-	struct pcie_port_device_ext *p_ext = pci_get_drvdata(dev);
-	int i = 0, pos;
-	u16 control;
-
-   	if ((pos = pci_find_capability(dev, PCI_CAP_ID_MSI)) <= 0)
-		return;
-
-	pci_read_config_dword(dev, pos, &p_ext->saved_msi_config_space[i++]);
-	control = p_ext->saved_msi_config_space[0] >> 16;
-	pci_read_config_dword(dev, pos + PCI_MSI_ADDRESS_LO,
-		&p_ext->saved_msi_config_space[i++]);
-	if (control & PCI_MSI_FLAGS_64BIT) {
-		pci_read_config_dword(dev, pos + PCI_MSI_ADDRESS_HI,
-			&p_ext->saved_msi_config_space[i++]);
-		pci_read_config_dword(dev, pos + PCI_MSI_DATA_64,
-			&p_ext->saved_msi_config_space[i++]);
-	} else
-		pci_read_config_dword(dev, pos + PCI_MSI_DATA_32,
-			&p_ext->saved_msi_config_space[i++]);
-	if (control & PCI_MSI_FLAGS_MASKBIT)
-		pci_read_config_dword(dev, pos + PCI_MSI_MASK_BIT,
-			&p_ext->saved_msi_config_space[i++]);
-}
-
-static void pci_restore_msi_state(struct pci_dev *dev)
-{
-	struct pcie_port_device_ext *p_ext = pci_get_drvdata(dev);
-	int i = 0, pos;
-	u16 control;
-
-   	if ((pos = pci_find_capability(dev, PCI_CAP_ID_MSI)) <= 0)
-		return;
-
-	control = p_ext->saved_msi_config_space[i++] >> 16;
-	pci_write_config_word(dev, pos + PCI_MSI_FLAGS, control);
-	pci_write_config_dword(dev, pos + PCI_MSI_ADDRESS_LO,
-		p_ext->saved_msi_config_space[i++]);
-	if (control & PCI_MSI_FLAGS_64BIT) {
-		pci_write_config_dword(dev, pos + PCI_MSI_ADDRESS_HI,
-			p_ext->saved_msi_config_space[i++]);
-		pci_write_config_dword(dev, pos + PCI_MSI_DATA_64,
-			p_ext->saved_msi_config_space[i++]);
-	} else
-		pci_write_config_dword(dev, pos + PCI_MSI_DATA_32,
-			p_ext->saved_msi_config_space[i++]);
-	if (control & PCI_MSI_FLAGS_MASKBIT)
-		pci_write_config_dword(dev, pos + PCI_MSI_MASK_BIT,
-			p_ext->saved_msi_config_space[i++]);
-}
-
-static void pcie_portdrv_save_config(struct pci_dev *dev)
-{
-	struct pcie_port_device_ext *p_ext = pci_get_drvdata(dev);
-
-	pci_save_state(dev);
-	if (p_ext->interrupt_mode == PCIE_PORT_MSI_MODE)
-		pci_save_msi_state(dev);
+	return pci_save_state(dev);
 }
 }
 
 
 static int pcie_portdrv_restore_config(struct pci_dev *dev)
 static int pcie_portdrv_restore_config(struct pci_dev *dev)
 {
 {
-	struct pcie_port_device_ext *p_ext = pci_get_drvdata(dev);
 	int retval;
 	int retval;
 
 
 	pci_restore_state(dev);
 	pci_restore_state(dev);
-	if (p_ext->interrupt_mode == PCIE_PORT_MSI_MODE)
-		pci_restore_msi_state(dev);
 	retval = pci_enable_device(dev);
 	retval = pci_enable_device(dev);
 	if (retval)
 	if (retval)
 		return retval;
 		return retval;
@@ -149,7 +90,8 @@ static int pcie_portdrv_suspend (struct pci_dev *dev, pm_message_t state)
 {
 {
 	int ret = pcie_port_device_suspend(dev, state);
 	int ret = pcie_port_device_suspend(dev, state);
 
 
-	pcie_portdrv_save_config(dev);
+	if (!ret)
+		ret = pcie_portdrv_save_config(dev);
 	return ret;
 	return ret;
 }
 }
 
 

+ 20 - 14
drivers/pci/probe.c

@@ -33,10 +33,9 @@ LIST_HEAD(pci_devices);
  */
  */
 static void pci_create_legacy_files(struct pci_bus *b)
 static void pci_create_legacy_files(struct pci_bus *b)
 {
 {
-	b->legacy_io = kmalloc(sizeof(struct bin_attribute) * 2,
+	b->legacy_io = kzalloc(sizeof(struct bin_attribute) * 2,
 			       GFP_ATOMIC);
 			       GFP_ATOMIC);
 	if (b->legacy_io) {
 	if (b->legacy_io) {
-		memset(b->legacy_io, 0, sizeof(struct bin_attribute) * 2);
 		b->legacy_io->attr.name = "legacy_io";
 		b->legacy_io->attr.name = "legacy_io";
 		b->legacy_io->size = 0xffff;
 		b->legacy_io->size = 0xffff;
 		b->legacy_io->attr.mode = S_IRUSR | S_IWUSR;
 		b->legacy_io->attr.mode = S_IRUSR | S_IWUSR;
@@ -320,9 +319,8 @@ static struct pci_bus * __devinit pci_alloc_bus(void)
 {
 {
 	struct pci_bus *b;
 	struct pci_bus *b;
 
 
-	b = kmalloc(sizeof(*b), GFP_KERNEL);
+	b = kzalloc(sizeof(*b), GFP_KERNEL);
 	if (b) {
 	if (b) {
-		memset(b, 0, sizeof(*b));
 		INIT_LIST_HEAD(&b->node);
 		INIT_LIST_HEAD(&b->node);
 		INIT_LIST_HEAD(&b->children);
 		INIT_LIST_HEAD(&b->children);
 		INIT_LIST_HEAD(&b->devices);
 		INIT_LIST_HEAD(&b->devices);
@@ -347,6 +345,7 @@ pci_alloc_child_bus(struct pci_bus *parent, struct pci_dev *bridge, int busnr)
 	child->parent = parent;
 	child->parent = parent;
 	child->ops = parent->ops;
 	child->ops = parent->ops;
 	child->sysdata = parent->sysdata;
 	child->sysdata = parent->sysdata;
+	child->bus_flags = parent->bus_flags;
 	child->bridge = get_device(&bridge->dev);
 	child->bridge = get_device(&bridge->dev);
 
 
 	child->class_dev.class = &pcibus_class;
 	child->class_dev.class = &pcibus_class;
@@ -456,7 +455,7 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev * dev, int max
 		 * pass and just note the configuration.
 		 * pass and just note the configuration.
 		 */
 		 */
 		if (pass)
 		if (pass)
-			return max;
+			goto out;
 		busnr = (buses >> 8) & 0xFF;
 		busnr = (buses >> 8) & 0xFF;
 
 
 		/*
 		/*
@@ -466,12 +465,12 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev * dev, int max
 		if (pci_find_bus(pci_domain_nr(bus), busnr)) {
 		if (pci_find_bus(pci_domain_nr(bus), busnr)) {
 			printk(KERN_INFO "PCI: Bus %04x:%02x already known\n",
 			printk(KERN_INFO "PCI: Bus %04x:%02x already known\n",
 					pci_domain_nr(bus), busnr);
 					pci_domain_nr(bus), busnr);
-			return max;
+			goto out;
 		}
 		}
 
 
 		child = pci_add_new_bus(bus, dev, busnr);
 		child = pci_add_new_bus(bus, dev, busnr);
 		if (!child)
 		if (!child)
-			return max;
+			goto out;
 		child->primary = buses & 0xFF;
 		child->primary = buses & 0xFF;
 		child->subordinate = (buses >> 16) & 0xFF;
 		child->subordinate = (buses >> 16) & 0xFF;
 		child->bridge_ctl = bctl;
 		child->bridge_ctl = bctl;
@@ -496,7 +495,7 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev * dev, int max
 				   bus ranges. */
 				   bus ranges. */
 				pci_write_config_dword(dev, PCI_PRIMARY_BUS,
 				pci_write_config_dword(dev, PCI_PRIMARY_BUS,
 						       buses & ~0xffffff);
 						       buses & ~0xffffff);
-			return max;
+			goto out;
 		}
 		}
 
 
 		/* Clear errors */
 		/* Clear errors */
@@ -505,7 +504,7 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev * dev, int max
 		/* Prevent assigning a bus number that already exists.
 		/* Prevent assigning a bus number that already exists.
 		 * This can happen when a bridge is hot-plugged */
 		 * This can happen when a bridge is hot-plugged */
 		if (pci_find_bus(pci_domain_nr(bus), max+1))
 		if (pci_find_bus(pci_domain_nr(bus), max+1))
-			return max;
+			goto out;
 		child = pci_add_new_bus(bus, dev, ++max);
 		child = pci_add_new_bus(bus, dev, ++max);
 		buses = (buses & 0xff000000)
 		buses = (buses & 0xff000000)
 		      | ((unsigned int)(child->primary)     <<  0)
 		      | ((unsigned int)(child->primary)     <<  0)
@@ -537,6 +536,11 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev * dev, int max
 			pci_fixup_parent_subordinate_busnr(child, max);
 			pci_fixup_parent_subordinate_busnr(child, max);
 			/* Now we can scan all subordinate buses... */
 			/* Now we can scan all subordinate buses... */
 			max = pci_scan_child_bus(child);
 			max = pci_scan_child_bus(child);
+			/*
+			 * now fix it up again since we have found
+			 * the real value of max.
+			 */
+			pci_fixup_parent_subordinate_busnr(child, max);
 		} else {
 		} else {
 			/*
 			/*
 			 * For CardBus bridges, we leave 4 bus numbers
 			 * For CardBus bridges, we leave 4 bus numbers
@@ -576,8 +580,6 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev * dev, int max
 		pci_write_config_byte(dev, PCI_SUBORDINATE_BUS, max);
 		pci_write_config_byte(dev, PCI_SUBORDINATE_BUS, max);
 	}
 	}
 
 
-	pci_write_config_word(dev, PCI_BRIDGE_CONTROL, bctl);
-
 	sprintf(child->name, (is_cardbus ? "PCI CardBus #%02x" : "PCI Bus #%02x"), child->number);
 	sprintf(child->name, (is_cardbus ? "PCI CardBus #%02x" : "PCI Bus #%02x"), child->number);
 
 
 	while (bus->parent) {
 	while (bus->parent) {
@@ -585,17 +587,22 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev * dev, int max
 		    (child->number > bus->subordinate) ||
 		    (child->number > bus->subordinate) ||
 		    (child->number < bus->number) ||
 		    (child->number < bus->number) ||
 		    (child->subordinate < bus->number)) {
 		    (child->subordinate < bus->number)) {
-			printk(KERN_WARNING "PCI: Bus #%02x (-#%02x) may be "
+			printk(KERN_WARNING "PCI: Bus #%02x (-#%02x) is "
 			       "hidden behind%s bridge #%02x (-#%02x)%s\n",
 			       "hidden behind%s bridge #%02x (-#%02x)%s\n",
 			       child->number, child->subordinate,
 			       child->number, child->subordinate,
 			       bus->self->transparent ? " transparent" : " ",
 			       bus->self->transparent ? " transparent" : " ",
 			       bus->number, bus->subordinate,
 			       bus->number, bus->subordinate,
 			       pcibios_assign_all_busses() ? " " :
 			       pcibios_assign_all_busses() ? " " :
 			       " (try 'pci=assign-busses')");
 			       " (try 'pci=assign-busses')");
+			printk(KERN_WARNING "Please report the result to "
+			       "linux-kernel to fix this permanently\n");
 		}
 		}
 		bus = bus->parent;
 		bus = bus->parent;
 	}
 	}
 
 
+out:
+	pci_write_config_word(dev, PCI_BRIDGE_CONTROL, bctl);
+
 	return max;
 	return max;
 }
 }
 
 
@@ -788,11 +795,10 @@ pci_scan_device(struct pci_bus *bus, int devfn)
 	if (pci_bus_read_config_byte(bus, devfn, PCI_HEADER_TYPE, &hdr_type))
 	if (pci_bus_read_config_byte(bus, devfn, PCI_HEADER_TYPE, &hdr_type))
 		return NULL;
 		return NULL;
 
 
-	dev = kmalloc(sizeof(struct pci_dev), GFP_KERNEL);
+	dev = kzalloc(sizeof(struct pci_dev), GFP_KERNEL);
 	if (!dev)
 	if (!dev)
 		return NULL;
 		return NULL;
 
 
-	memset(dev, 0, sizeof(struct pci_dev));
 	dev->bus = bus;
 	dev->bus = bus;
 	dev->sysdata = bus->sysdata;
 	dev->sysdata = bus->sysdata;
 	dev->dev.parent = bus->bridge;
 	dev->dev.parent = bus->bridge;

+ 0 - 126
drivers/pci/proc.c

@@ -458,131 +458,6 @@ int pci_proc_detach_bus(struct pci_bus* bus)
 	return 0;
 	return 0;
 }
 }
 
 
-#ifdef CONFIG_PCI_LEGACY_PROC
-
-/*
- *  Backward compatible /proc/pci interface.
- */
-
-/*
- * Convert some of the configuration space registers of the device at
- * address (bus,devfn) into a string (possibly several lines each).
- * The configuration string is stored starting at buf[len].  If the
- * string would exceed the size of the buffer (SIZE), 0 is returned.
- */
-static int show_dev_config(struct seq_file *m, void *v)
-{
-	struct pci_dev *dev = v;
-	struct pci_dev *first_dev;
-	struct pci_driver *drv;
-	u32 class_rev;
-	unsigned char latency, min_gnt, max_lat;
-	int reg;
-
-	first_dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, NULL);
-	if (dev == first_dev)
-		seq_puts(m, "PCI devices found:\n");
-	pci_dev_put(first_dev);
-
-	drv = pci_dev_driver(dev);
-
-	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);
-	seq_printf(m, ": PCI device %04x:%04x", dev->vendor, dev->device);
-	seq_printf(m, " (rev %d).\n", class_rev & 0xff);
-
-	if (dev->irq)
-		seq_printf(m, "      IRQ %d.\n", dev->irq);
-
-	if (latency || min_gnt || max_lat) {
-		seq_printf(m, "      Master Capable.  ");
-		if (latency)
-			seq_printf(m, "Latency=%d.  ", latency);
-		else
-			seq_puts(m, "No bursts.  ");
-		if (min_gnt)
-			seq_printf(m, "Min Gnt=%d.", min_gnt);
-		if (max_lat)
-			seq_printf(m, "Max Lat=%d.", max_lat);
-		seq_putc(m, '\n');
-	}
-
-	for (reg = 0; reg < 6; reg++) {
-		struct resource *res = dev->resource + reg;
-		unsigned long base, end, flags;
-
-		base = res->start;
-		end = res->end;
-		flags = res->flags;
-		if (!end)
-			continue;
-
-		if (flags & PCI_BASE_ADDRESS_SPACE_IO) {
-			seq_printf(m, "      I/O at 0x%lx [0x%lx].\n",
-				base, end);
-		} else {
-			const char *pref, *type = "unknown";
-
-			if (flags & PCI_BASE_ADDRESS_MEM_PREFETCH)
-				pref = "P";
-			else
-				pref = "Non-p";
-			switch (flags & PCI_BASE_ADDRESS_MEM_TYPE_MASK) {
-			      case PCI_BASE_ADDRESS_MEM_TYPE_32:
-				type = "32 bit"; break;
-			      case PCI_BASE_ADDRESS_MEM_TYPE_1M:
-				type = "20 bit"; break;
-			      case PCI_BASE_ADDRESS_MEM_TYPE_64:
-				type = "64 bit"; break;
-			}
-			seq_printf(m, "      %srefetchable %s memory at "
-				       "0x%lx [0x%lx].\n", pref, type,
-				       base,
-				       end);
-		}
-	}
-	return 0;
-}
-
-static struct seq_operations proc_pci_op = {
-	.start	= pci_seq_start,
-	.next	= pci_seq_next,
-	.stop	= pci_seq_stop,
-	.show	= show_dev_config
-};
-
-static int proc_pci_open(struct inode *inode, struct file *file)
-{
-	return seq_open(file, &proc_pci_op);
-}
-static struct file_operations proc_pci_operations = {
-	.open		= proc_pci_open,
-	.read		= seq_read,
-	.llseek		= seq_lseek,
-	.release	= seq_release,
-};
-
-static void legacy_proc_init(void)
-{
-	struct proc_dir_entry * entry = create_proc_entry("pci", 0, NULL);
-	if (entry)
-		entry->proc_fops = &proc_pci_operations;
-}
-
-#else
-
-static void legacy_proc_init(void)
-{
-
-}
-
-#endif /* CONFIG_PCI_LEGACY_PROC */
-
 static int proc_bus_pci_dev_open(struct inode *inode, struct file *file)
 static int proc_bus_pci_dev_open(struct inode *inode, struct file *file)
 {
 {
 	return seq_open(file, &proc_bus_pci_devices_op);
 	return seq_open(file, &proc_bus_pci_devices_op);
@@ -606,7 +481,6 @@ static int __init pci_proc_init(void)
 	while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
 	while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
 		pci_proc_attach_device(dev);
 		pci_proc_attach_device(dev);
 	}
 	}
-	legacy_proc_init();
 	return 0;
 	return 0;
 }
 }
 
 

+ 69 - 2
drivers/pci/quirks.c

@@ -575,8 +575,11 @@ static void __init quirk_amd_8131_ioapic(struct pci_dev *dev)
 { 
 { 
         unsigned char revid, tmp;
         unsigned char revid, tmp;
         
         
-	pci_msi_quirk = 1;
-	printk(KERN_WARNING "PCI: MSI quirk detected. pci_msi_quirk set.\n");
+	if (dev->subordinate) {
+		printk(KERN_WARNING "PCI: MSI quirk detected. "
+		       "PCI_BUS_FLAGS_NO_MSI set for subordinate bus.\n");
+		dev->subordinate->bus_flags |= PCI_BUS_FLAGS_NO_MSI;
+	}
 
 
         if (nr_ioapics == 0) 
         if (nr_ioapics == 0) 
                 return;
                 return;
@@ -934,6 +937,12 @@ static void __init asus_hides_smbus_hostbridge(struct pci_dev *dev)
 			case 0x12bd: /* HP D530 */
 			case 0x12bd: /* HP D530 */
 				asus_hides_smbus = 1;
 				asus_hides_smbus = 1;
 			}
 			}
+		if (dev->device == PCI_DEVICE_ID_INTEL_82915GM_HB) {
+			switch (dev->subsystem_device) {
+			case 0x099c: /* HP Compaq nx6110 */
+				asus_hides_smbus = 1;
+			}
+		}
 	} else if (unlikely(dev->subsystem_vendor == PCI_VENDOR_ID_TOSHIBA)) {
 	} else if (unlikely(dev->subsystem_vendor == PCI_VENDOR_ID_TOSHIBA)) {
 		if (dev->device == PCI_DEVICE_ID_INTEL_82855GM_HB)
 		if (dev->device == PCI_DEVICE_ID_INTEL_82855GM_HB)
 			switch(dev->subsystem_device) {
 			switch(dev->subsystem_device) {
@@ -1068,6 +1077,37 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI,	PCI_DEVICE_ID_SI_651,		quirk_sis_96x_
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI,	PCI_DEVICE_ID_SI_735,		quirk_sis_96x_compatible );
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI,	PCI_DEVICE_ID_SI_735,		quirk_sis_96x_compatible );
 
 
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI,	PCI_DEVICE_ID_SI_503,		quirk_sis_503 );
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI,	PCI_DEVICE_ID_SI_503,		quirk_sis_503 );
+/*
+ * On ASUS A8V and A8V Deluxe boards, the onboard AC97 audio controller
+ * and MC97 modem controller are disabled when a second PCI soundcard is
+ * present. This patch, tweaking the VT8237 ISA bridge, enables them.
+ * -- bjd
+ */
+static void __init asus_hides_ac97_lpc(struct pci_dev *dev)
+{
+	u8 val;
+	int asus_hides_ac97 = 0;
+
+	if (likely(dev->subsystem_vendor == PCI_VENDOR_ID_ASUSTEK)) {
+		if (dev->device == PCI_DEVICE_ID_VIA_8237)
+			asus_hides_ac97 = 1;
+	}
+
+	if (!asus_hides_ac97)
+		return;
+
+	pci_read_config_byte(dev, 0x50, &val);
+	if (val & 0xc0) {
+		pci_write_config_byte(dev, 0x50, val & (~0xc0));
+		pci_read_config_byte(dev, 0x50, &val);
+		if (val & 0xc0)
+			printk(KERN_INFO "PCI: onboard AC97/MC97 devices continue to play 'hide and seek'! 0x%x\n", val);
+		else
+			printk(KERN_INFO "PCI: enabled onboard AC97/MC97 devices\n");
+	}
+}
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_8237, asus_hides_ac97_lpc );
+
 
 
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI,	PCI_DEVICE_ID_SI_961,		quirk_sis_96x_smbus );
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI,	PCI_DEVICE_ID_SI_961,		quirk_sis_96x_smbus );
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI,	PCI_DEVICE_ID_SI_962,		quirk_sis_96x_smbus );
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI,	PCI_DEVICE_ID_SI_962,		quirk_sis_96x_smbus );
@@ -1242,6 +1282,33 @@ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_PXH_1,	quirk_pc
 DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_PXHV,	quirk_pcie_pxh);
 DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_PXHV,	quirk_pcie_pxh);
 
 
 
 
+/*
+ * Fixup the cardbus bridges on the IBM Dock II docking station
+ */
+static void __devinit quirk_ibm_dock2_cardbus(struct pci_dev *dev)
+{
+	u32 val;
+
+	/*
+	 * tie the 2 interrupt pins to INTA, and configure the
+	 * multifunction routing register to handle this.
+	 */
+	if ((dev->subsystem_vendor == PCI_VENDOR_ID_IBM) &&
+		(dev->subsystem_device == 0x0148)) {
+		printk(KERN_INFO "PCI: Found IBM Dock II Cardbus Bridge "
+			"applying quirk\n");
+		pci_read_config_dword(dev, 0x8c, &val);
+		val = ((val & 0xffffff00) | 0x1002);
+		pci_write_config_dword(dev, 0x8c, val);
+		pci_read_config_dword(dev, 0x80, &val);
+		val = ((val & 0x00ffff00) | 0x2864c077);
+		pci_write_config_dword(dev, 0x80, val);
+	}
+}
+
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_1420,
+				quirk_ibm_dock2_cardbus);
+
 static void __devinit quirk_netmos(struct pci_dev *dev)
 static void __devinit quirk_netmos(struct pci_dev *dev)
 {
 {
 	unsigned int num_parallel = (dev->subsystem_device & 0xf0) >> 4;
 	unsigned int num_parallel = (dev->subsystem_device & 0xf0) >> 4;

+ 2 - 2
drivers/pci/search.c

@@ -246,9 +246,9 @@ pci_get_subsys(unsigned int vendor, unsigned int device,
 	}
 	}
 	dev = NULL;
 	dev = NULL;
 exit:
 exit:
-	pci_dev_put(from);
 	dev = pci_dev_get(dev);
 	dev = pci_dev_get(dev);
 	spin_unlock(&pci_bus_lock);
 	spin_unlock(&pci_bus_lock);
+	pci_dev_put(from);
 	return dev;
 	return dev;
 }
 }
 
 
@@ -339,9 +339,9 @@ struct pci_dev *pci_get_class(unsigned int class, struct pci_dev *from)
 	}
 	}
 	dev = NULL;
 	dev = NULL;
 exit:
 exit:
-	pci_dev_put(from);
 	dev = pci_dev_get(dev);
 	dev = pci_dev_get(dev);
 	spin_unlock(&pci_bus_lock);
 	spin_unlock(&pci_bus_lock);
+	pci_dev_put(from);
 	return dev;
 	return dev;
 }
 }
 
 

+ 1 - 0
include/acpi/acpi_bus.h

@@ -330,6 +330,7 @@ int acpi_bus_register_driver(struct acpi_driver *driver);
 int acpi_bus_unregister_driver(struct acpi_driver *driver);
 int acpi_bus_unregister_driver(struct acpi_driver *driver);
 int acpi_bus_add(struct acpi_device **child, struct acpi_device *parent,
 int acpi_bus_add(struct acpi_device **child, struct acpi_device *parent,
 		 acpi_handle handle, int type);
 		 acpi_handle handle, int type);
+int acpi_bus_trim(struct acpi_device *start, int rmdevice);
 int acpi_bus_start(struct acpi_device *device);
 int acpi_bus_start(struct acpi_device *device);
 
 
 int acpi_match_ids(struct acpi_device *device, char *ids);
 int acpi_match_ids(struct acpi_device *device, char *ids);

+ 9 - 3
include/linux/pci.h

@@ -95,6 +95,11 @@ enum pci_channel_state {
 	pci_channel_io_perm_failure = (__force pci_channel_state_t) 3,
 	pci_channel_io_perm_failure = (__force pci_channel_state_t) 3,
 };
 };
 
 
+typedef unsigned short __bitwise pci_bus_flags_t;
+enum pci_bus_flags {
+	PCI_BUS_FLAGS_NO_MSI = (pci_bus_flags_t) 1,
+};
+
 /*
 /*
  * The pci_dev structure is used to describe PCI devices.
  * The pci_dev structure is used to describe PCI devices.
  */
  */
@@ -203,7 +208,7 @@ struct pci_bus {
 	char		name[48];
 	char		name[48];
 
 
 	unsigned short  bridge_ctl;	/* manage NO_ISA/FBB/et al behaviors */
 	unsigned short  bridge_ctl;	/* manage NO_ISA/FBB/et al behaviors */
-	unsigned short  pad2;
+	pci_bus_flags_t bus_flags;	/* Inherited by child busses */
 	struct device		*bridge;
 	struct device		*bridge;
 	struct class_device	class_dev;
 	struct class_device	class_dev;
 	struct bin_attribute	*legacy_io; /* legacy I/O for this bus */
 	struct bin_attribute	*legacy_io; /* legacy I/O for this bus */
@@ -485,9 +490,9 @@ void pdev_sort_resources(struct pci_dev *, struct resource_list *);
 void pci_fixup_irqs(u8 (*)(struct pci_dev *, u8 *),
 void pci_fixup_irqs(u8 (*)(struct pci_dev *, u8 *),
 		    int (*)(struct pci_dev *, u8, u8));
 		    int (*)(struct pci_dev *, u8, u8));
 #define HAVE_PCI_REQ_REGIONS	2
 #define HAVE_PCI_REQ_REGIONS	2
-int pci_request_regions(struct pci_dev *, char *);
+int pci_request_regions(struct pci_dev *, const char *);
 void pci_release_regions(struct pci_dev *);
 void pci_release_regions(struct pci_dev *);
-int pci_request_region(struct pci_dev *, int, char *);
+int pci_request_region(struct pci_dev *, int, const char *);
 void pci_release_region(struct pci_dev *, int);
 void pci_release_region(struct pci_dev *, int);
 
 
 /* drivers/pci/bus.c */
 /* drivers/pci/bus.c */
@@ -516,6 +521,7 @@ int pci_scan_bridge(struct pci_bus *bus, struct pci_dev * dev, int max, int pass
 void pci_walk_bus(struct pci_bus *top, void (*cb)(struct pci_dev *, void *),
 void pci_walk_bus(struct pci_bus *top, void (*cb)(struct pci_dev *, void *),
 		  void *userdata);
 		  void *userdata);
 int pci_cfg_space_size(struct pci_dev *dev);
 int pci_cfg_space_size(struct pci_dev *dev);
+unsigned char pci_bus_max_busnr(struct pci_bus* bus);
 
 
 /* kmem_cache style wrapper around pci_alloc_consistent() */
 /* kmem_cache style wrapper around pci_alloc_consistent() */