diff mbox

PCI hotplug problems: how to debug?

Message ID 20091116195417.GH13239@ovro.caltech.edu (mailing list archive)
State Not Applicable, archived
Headers show

Commit Message

Ira Snyder Nov. 16, 2009, 7:54 p.m. UTC
None
diff mbox

Patch

diff --git a/arch/x86/pci/Makefile b/arch/x86/pci/Makefile
index d8a0a62..f762c05 100644
--- a/arch/x86/pci/Makefile
+++ b/arch/x86/pci/Makefile
@@ -15,6 +15,7 @@  obj-$(CONFIG_X86_NUMAQ)		+= numaq_32.o
 
 obj-y				+= common.o early.o
 obj-y				+= amd_bus.o
+obj-y				+= broadcom_bus.o
 obj-$(CONFIG_X86_64)		+= intel_bus.o
 
 ifeq ($(CONFIG_PCI_DEBUG),y)
diff --git a/arch/x86/pci/amd_bus.c b/arch/x86/pci/amd_bus.c
index 995f360..6bd3eb6 100644
--- a/arch/x86/pci/amd_bus.c
+++ b/arch/x86/pci/amd_bus.c
@@ -17,8 +17,6 @@ 
  * also get peer root bus resource for io,mmio
  */
 
-#ifdef CONFIG_X86_64
-
 int pci_root_num;
 struct pci_root_info pci_root_info[PCI_ROOT_NR];
 static int found_all_numa_early;
@@ -29,6 +27,8 @@  void x86_pci_root_bus_res_quirks(struct pci_bus *b)
 	int j;
 	struct pci_root_info *info;
 
+	printk(KERN_DEBUG "PCI: %s called\n", __func__);
+
 	/* don't go for it if _CRS is used already */
 	if (b->resource[0] != &ioport_resource ||
 	    b->resource[1] != &iomem_resource)
@@ -67,6 +67,8 @@  void x86_pci_root_bus_res_quirks(struct pci_bus *b)
 	}
 }
 
+#ifdef CONFIG_X86_64
+
 #define RANGE_NUM 16
 
 struct res_range {
@@ -119,6 +121,8 @@  static void __init update_range(struct res_range *range, size_t start,
 	}
 }
 
+#endif /* CONFIG_X86_64 */
+
 void __init update_res(struct pci_root_info *info, size_t start,
 			      size_t end, unsigned long flags, int merge)
 {
@@ -168,6 +172,8 @@  addit:
 	info->res_num++;
 }
 
+#ifdef CONFIG_X86_64
+
 struct pci_hostbridge_probe {
 	u32 bus;
 	u32 slot;
diff --git a/arch/x86/pci/broadcom_bus.c b/arch/x86/pci/broadcom_bus.c
new file mode 100644
index 0000000..f53563b
--- /dev/null
+++ b/arch/x86/pci/broadcom_bus.c
@@ -0,0 +1,108 @@ 
+/*
+ * Read address ranges from a Broadcom CNB20LE Host Bridge
+ *
+ * Copyright (c) 2009 Ira W. Snyder <iws@ovro.caltech.edu>
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2. This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+#define DEBUG 1
+
+#include <linux/delay.h>
+#include <linux/dmi.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <asm/pci_x86.h>
+
+#include "bus_numa.h"
+
+#if 0
+static int res_num = 0;
+#endif
+
+static void __devinit cnb20le_res(struct pci_dev *dev)
+{
+#if 0
+	struct pci_bus *bus = dev->bus;
+#endif
+	struct pci_root_info *info;
+	unsigned long flags;
+	u16 word1, word2;
+	u32 start, end;
+	u8 fbus, lbus;
+
+	info = &pci_root_info[pci_root_num];
+	pci_root_num++;
+
+	pci_read_config_byte(dev, 0x44, &fbus);
+	pci_read_config_byte(dev, 0x45, &lbus);
+	dev_dbg(&dev->dev, "CNB20LE: busses: %d to %d\n", fbus, lbus);
+
+	info->bus_min = fbus;
+	info->bus_max = lbus;
+
+	pci_read_config_word(dev, 0xc0, &word1);
+	pci_read_config_word(dev, 0xc2, &word2);
+	dev_dbg(&dev->dev, "CNB20LE: noPF 0x%.4x 0x%.4x\n", word1, word2);
+	if (word1 != word2) {
+		start = word1;
+		end   = word2;
+		flags = IORESOURCE_MEM;
+		update_res(info, start, end, flags, 0);
+#if 0
+		bus->resource[res_num]->start = (word1 << 16) | 0x0000;
+		bus->resource[res_num]->end = (word2 << 16) | 0xffff;
+		bus->resource[res_num]->flags = IORESOURCE_MEM;
+		dev_dbg(&dev->dev, "CNB20LE: noPF %pR\n", bus->resource[res_num]);
+		res_num++;
+#endif
+	}
+
+	pci_read_config_word(dev, 0xc4, &word1);
+	pci_read_config_word(dev, 0xc6, &word2);
+	dev_dbg(&dev->dev, "CNB20LE: PF 0x%.4x 0x%.4x\n", word1, word2);
+	if (word1 != word2) {
+		start = (word1 << 16) | 0x0000;
+		end   = (word2 << 16) | 0xffff;
+		flags = IORESOURCE_MEM | IORESOURCE_PREFETCH;
+		update_res(info, start, end, flags, 0);
+#if 0
+		bus->resource[res_num]->start = (word1 << 16) | 0x0000;
+		bus->resource[res_num]->end = (word2 << 16) | 0xffff;
+		bus->resource[res_num]->flags = IORESOURCE_MEM | IORESOURCE_PREFETCH;
+		dev_dbg(&dev->dev, "CNB20LE: PF %pR\n", bus->resource[res_num]);
+		res_num++;
+#endif
+	}
+
+	pci_read_config_word(dev, 0xd0, &word1);
+	pci_read_config_word(dev, 0xd2, &word2);
+	dev_dbg(&dev->dev, "CNB20LE: IO 0x%.4x 0x%.4x\n", word1, word2);
+	if (word1 != word2) {
+		start = (word1 << 16) | 0x0000;
+		end   = (word2 << 16) | 0xffff;
+		flags = IORESOURCE_IO;
+		update_res(info, start, end, flags, 0);
+#if 0
+		bus->resource[res_num]->start = word1;
+		bus->resource[res_num]->end = word2;
+		bus->resource[res_num]->flags = IORESOURCE_IO;
+		dev_dbg(&dev->dev, "CNB20LE: IO %pR\n", bus->resource[res_num]);
+		res_num++;
+#endif
+	}
+
+#if 0
+	dev_dbg(&dev->dev, "CNB20LE: parent bus: %p number %d pri %d sec %d\n", bus, bus->number, bus->primary, bus->secondary);
+	dev_dbg(&dev->dev, "CNB20LE: parent res0: %pR\n", dev->bus->resource[0]);
+	dev_dbg(&dev->dev, "CNB20LE: parent res1: %pR\n", dev->bus->resource[1]);
+	dev_dbg(&dev->dev, "CNB20LE: parent res2: %pR\n", dev->bus->resource[2]);
+	dev_dbg(&dev->dev, "CNB20LE: parent res3: %pR\n", dev->bus->resource[3]);
+	dev_dbg(&dev->dev, "CNB20LE: parent res4: %pR\n", dev->bus->resource[4]);
+	dev_dbg(&dev->dev, "CNB20LE: parent res5: %pR\n", dev->bus->resource[5]);
+#endif
+}
+
+DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_LE, cnb20le_res);
diff --git a/arch/x86/pci/bus_numa.h b/arch/x86/pci/bus_numa.h
index 4ff126a..03ee918 100644
--- a/arch/x86/pci/bus_numa.h
+++ b/arch/x86/pci/bus_numa.h
@@ -1,5 +1,3 @@ 
-#ifdef CONFIG_X86_64
-
 /*
  * sub bus (transparent) will use entres from 3 to store extra from
  * root, so need to make sure we have enought slot there, Should we
@@ -23,4 +21,4 @@  extern struct pci_root_info pci_root_info[PCI_ROOT_NR];
 
 extern void update_res(struct pci_root_info *info, size_t start,
 			      size_t end, unsigned long flags, int merge);
-#endif
+