summaryrefslogtreecommitdiff
path: root/target/linux/brcm47xx/patches-2.6.25/690-mips-allow-pciregister-after-boot.patch
blob: 8b0445f5ba2778678ae801e2c5ac89725c39e5a3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
Allow registering PCI devices after early boot.

This is an ugly hack and needs to be rewritten before going upstream.
--- a/arch/mips/pci/pci.c
+++ b/arch/mips/pci/pci.c
@@ -21,6 +21,17 @@
  */
 int pci_probe_only;
 
+/*
+ * Indicate whether PCI-bios init was already done.
+ */
+static int pcibios_init_done;
+
+/*
+ * The currently used busnumber.
+ */
+static int next_busno;
+static int need_domain_info;
+
 #define PCI_ASSIGN_ALL_BUSSES	1
 
 unsigned int pci_probe = PCI_ASSIGN_ALL_BUSSES;
@@ -75,8 +86,32 @@ pcibios_align_resource(void *data, struc
 	res->start = start;
 }
 
-void __devinit register_pci_controller(struct pci_controller *hose)
+/* Most MIPS systems have straight-forward swizzling needs.  */
+
+static inline u8 bridge_swizzle(u8 pin, u8 slot)
+{
+	return (((pin - 1) + slot) % 4) + 1;
+}
+
+static u8 common_swizzle(struct pci_dev *dev, u8 *pinp)
 {
+	u8 pin = *pinp;
+
+	while (dev->bus->parent) {
+		pin = bridge_swizzle(pin, PCI_SLOT(dev->devfn));
+		/* Move up the chain of bridges. */
+		dev = dev->bus->self;
+        }
+	*pinp = pin;
+
+	/* The slot is the slot of the last bridge. */
+	return PCI_SLOT(dev->devfn);
+}
+
+void register_pci_controller(struct pci_controller *hose)
+{
+	struct pci_bus *bus;
+
 	if (request_resource(&iomem_resource, hose->mem_resource) < 0)
 		goto out;
 	if (request_resource(&ioport_resource, hose->io_resource) < 0) {
@@ -84,9 +119,6 @@ void __devinit register_pci_controller(s
 		goto out;
 	}
 
-	*hose_tail = hose;
-	hose_tail = &hose->next;
-
 	/*
 	 * Do not panic here but later - this might hapen before console init.
 	 */
@@ -94,41 +126,47 @@ void __devinit register_pci_controller(s
 		printk(KERN_WARNING
 		       "registering PCI controller with io_map_base unset\n");
 	}
-	return;
 
-out:
-	printk(KERN_WARNING
-	       "Skipping PCI bus scan due to resource conflict\n");
-}
+	if (pcibios_init_done) {
+		//TODO
 
-/* Most MIPS systems have straight-forward swizzling needs.  */
+		printk(KERN_INFO "Registering a PCI bus after boot\n");
 
-static inline u8 bridge_swizzle(u8 pin, u8 slot)
-{
-	return (((pin - 1) + slot) % 4) + 1;
-}
+		if (!hose->iommu)
+			PCI_DMA_BUS_IS_PHYS = 1;
 
-static u8 __init common_swizzle(struct pci_dev *dev, u8 *pinp)
-{
-	u8 pin = *pinp;
+		bus = pci_scan_bus(next_busno, hose->pci_ops, hose);
+		hose->bus = bus;
+		need_domain_info = need_domain_info || hose->index;
+		hose->need_domain_info = need_domain_info;
+		if (bus) {
+			next_busno = bus->subordinate + 1;
+			/* Don't allow 8-bit bus number overflow inside the hose -
+			   reserve some space for bridges. */
+			if (next_busno > 224) {
+				next_busno = 0;
+				need_domain_info = 1;
+			}
+		}
+		if (!pci_probe_only)
+			pci_assign_unassigned_resources();
+		pci_fixup_irqs(common_swizzle, pcibios_map_irq);
+	} else {
+		*hose_tail = hose;
+		hose_tail = &hose->next;
+	}
 
-	while (dev->bus->parent) {
-		pin = bridge_swizzle(pin, PCI_SLOT(dev->devfn));
-		/* Move up the chain of bridges. */
-		dev = dev->bus->self;
-        }
-	*pinp = pin;
+	return;
 
-	/* The slot is the slot of the last bridge. */
-	return PCI_SLOT(dev->devfn);
+out:
+	printk(KERN_WARNING
+	       "Skipping PCI bus scan due to resource conflict\n");
 }
 
 static int __init pcibios_init(void)
 {
 	struct pci_controller *hose;
 	struct pci_bus *bus;
-	int next_busno;
-	int need_domain_info = 0;
 
 	/* Scan all of the recorded PCI controllers.  */
 	for (next_busno = 0, hose = hose_head; hose; hose = hose->next) {
@@ -157,6 +195,7 @@ static int __init pcibios_init(void)
 	if (!pci_probe_only)
 		pci_assign_unassigned_resources();
 	pci_fixup_irqs(common_swizzle, pcibios_map_irq);
+	pcibios_init_done = 1;
 
 	return 0;
 }
--- a/drivers/ssb/main.c
+++ b/drivers/ssb/main.c
@@ -1191,9 +1191,7 @@ static int __init ssb_modinit(void)
 /* ssb must be initialized after PCI but before the ssb drivers.
  * That means we must use some initcall between subsys_initcall
  * and device_initcall. */
-//FIXME on embedded we need to be early to make sure we can register
-//      a new PCI bus, if needed.
-subsys_initcall(ssb_modinit);
+fs_initcall(ssb_modinit);
 
 static void __exit ssb_modexit(void)
 {