diff options
author | rajesh.shah@intel.com <rajesh.shah@intel.com> | 2005-10-13 15:05:36 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2005-10-28 18:36:59 -0400 |
commit | dbd7a78818d125a0ebd5507d4edb4dd5900006ab (patch) | |
tree | 682a1681aad47f70bfb760fca077f54589be92c6 /drivers/pci/hotplug/shpchprm_legacy.c | |
parent | e3b1bd572f1cdb247bb4266a593b6894dc578d6a (diff) |
[PATCH] shpchp: use the PCI core for hotplug resource management
This patch converts the standard hotplug controller driver to use
the PCI core for resource management. This eliminates a whole lot
of duplicated code, and integrates shpchp in the system's normal
PCI handling code.
Signed-off-by: Rajesh Shah <rajesh.shah@intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/pci/hotplug/shpchprm_legacy.c')
-rw-r--r-- | drivers/pci/hotplug/shpchprm_legacy.c | 294 |
1 files changed, 0 insertions, 294 deletions
diff --git a/drivers/pci/hotplug/shpchprm_legacy.c b/drivers/pci/hotplug/shpchprm_legacy.c index ba6c549c9b9d..6c27debe9522 100644 --- a/drivers/pci/hotplug/shpchprm_legacy.c +++ b/drivers/pci/hotplug/shpchprm_legacy.c | |||
@@ -34,25 +34,11 @@ | |||
34 | #include <linux/pci.h> | 34 | #include <linux/pci.h> |
35 | #include <linux/init.h> | 35 | #include <linux/init.h> |
36 | #include <asm/uaccess.h> | 36 | #include <asm/uaccess.h> |
37 | #ifdef CONFIG_IA64 | ||
38 | #include <asm/iosapic.h> | ||
39 | #endif | ||
40 | #include "shpchp.h" | 37 | #include "shpchp.h" |
41 | #include "shpchprm.h" | 38 | #include "shpchprm.h" |
42 | #include "shpchprm_legacy.h" | ||
43 | |||
44 | static void __iomem *shpchp_rom_start; | ||
45 | static u16 unused_IRQ; | ||
46 | 39 | ||
47 | void shpchprm_cleanup(void) | 40 | void shpchprm_cleanup(void) |
48 | { | 41 | { |
49 | if (shpchp_rom_start) | ||
50 | iounmap(shpchp_rom_start); | ||
51 | } | ||
52 | |||
53 | int shpchprm_print_pirt(void) | ||
54 | { | ||
55 | return 0; | ||
56 | } | 42 | } |
57 | 43 | ||
58 | int shpchprm_get_physical_slot_number(struct controller *ctrl, u32 *sun, u8 busnum, u8 devnum) | 44 | int shpchprm_get_physical_slot_number(struct controller *ctrl, u32 *sun, u8 busnum, u8 devnum) |
@@ -63,280 +49,6 @@ int shpchprm_get_physical_slot_number(struct controller *ctrl, u32 *sun, u8 busn | |||
63 | return 0; | 49 | return 0; |
64 | } | 50 | } |
65 | 51 | ||
66 | /* Find the Hot Plug Resource Table in the specified region of memory */ | ||
67 | static void __iomem *detect_HRT_floating_pointer(void __iomem *begin, void __iomem *end) | ||
68 | { | ||
69 | void __iomem *fp; | ||
70 | void __iomem *endp; | ||
71 | u8 temp1, temp2, temp3, temp4; | ||
72 | int status = 0; | ||
73 | |||
74 | endp = (end - sizeof(struct hrt) + 1); | ||
75 | |||
76 | for (fp = begin; fp <= endp; fp += 16) { | ||
77 | temp1 = readb(fp + SIG0); | ||
78 | temp2 = readb(fp + SIG1); | ||
79 | temp3 = readb(fp + SIG2); | ||
80 | temp4 = readb(fp + SIG3); | ||
81 | if (temp1 == '$' && temp2 == 'H' && temp3 == 'R' && temp4 == 'T') { | ||
82 | status = 1; | ||
83 | break; | ||
84 | } | ||
85 | } | ||
86 | |||
87 | if (!status) | ||
88 | fp = NULL; | ||
89 | |||
90 | dbg("Discovered Hotplug Resource Table at %p\n", fp); | ||
91 | return fp; | ||
92 | } | ||
93 | |||
94 | /* | ||
95 | * shpchprm_find_available_resources | ||
96 | * | ||
97 | * Finds available memory, IO, and IRQ resources for programming | ||
98 | * devices which may be added to the system | ||
99 | * this function is for hot plug ADD! | ||
100 | * | ||
101 | * returns 0 if success | ||
102 | */ | ||
103 | int shpchprm_find_available_resources(struct controller *ctrl) | ||
104 | { | ||
105 | u8 populated_slot; | ||
106 | u8 bridged_slot; | ||
107 | void __iomem *one_slot; | ||
108 | struct pci_func *func = NULL; | ||
109 | int i = 10, index = 0; | ||
110 | u32 temp_dword, rc; | ||
111 | ulong temp_ulong; | ||
112 | struct pci_resource *mem_node; | ||
113 | struct pci_resource *p_mem_node; | ||
114 | struct pci_resource *io_node; | ||
115 | struct pci_resource *bus_node; | ||
116 | void __iomem *rom_resource_table; | ||
117 | struct pci_bus lpci_bus, *pci_bus; | ||
118 | u8 cfgspc_irq, temp; | ||
119 | |||
120 | memcpy(&lpci_bus, ctrl->pci_bus, sizeof(lpci_bus)); | ||
121 | pci_bus = &lpci_bus; | ||
122 | rom_resource_table = detect_HRT_floating_pointer(shpchp_rom_start, shpchp_rom_start + 0xffff); | ||
123 | dbg("rom_resource_table = %p\n", rom_resource_table); | ||
124 | if (rom_resource_table == NULL) | ||
125 | return -ENODEV; | ||
126 | |||
127 | /* Sum all resources and setup resource maps */ | ||
128 | unused_IRQ = readl(rom_resource_table + UNUSED_IRQ); | ||
129 | dbg("unused_IRQ = %x\n", unused_IRQ); | ||
130 | |||
131 | temp = 0; | ||
132 | while (unused_IRQ) { | ||
133 | if (unused_IRQ & 1) { | ||
134 | shpchp_disk_irq = temp; | ||
135 | break; | ||
136 | } | ||
137 | unused_IRQ = unused_IRQ >> 1; | ||
138 | temp++; | ||
139 | } | ||
140 | |||
141 | dbg("shpchp_disk_irq= %d\n", shpchp_disk_irq); | ||
142 | unused_IRQ = unused_IRQ >> 1; | ||
143 | temp++; | ||
144 | |||
145 | while (unused_IRQ) { | ||
146 | if (unused_IRQ & 1) { | ||
147 | shpchp_nic_irq = temp; | ||
148 | break; | ||
149 | } | ||
150 | unused_IRQ = unused_IRQ >> 1; | ||
151 | temp++; | ||
152 | } | ||
153 | |||
154 | dbg("shpchp_nic_irq= %d\n", shpchp_nic_irq); | ||
155 | unused_IRQ = readl(rom_resource_table + PCIIRQ); | ||
156 | |||
157 | temp = 0; | ||
158 | |||
159 | pci_read_config_byte(ctrl->pci_dev, PCI_INTERRUPT_LINE, &cfgspc_irq); | ||
160 | |||
161 | if (!shpchp_nic_irq) { | ||
162 | shpchp_nic_irq = cfgspc_irq; | ||
163 | } | ||
164 | |||
165 | if (!shpchp_disk_irq) { | ||
166 | shpchp_disk_irq = cfgspc_irq; | ||
167 | } | ||
168 | |||
169 | dbg("shpchp_disk_irq, shpchp_nic_irq= %d, %d\n", shpchp_disk_irq, shpchp_nic_irq); | ||
170 | |||
171 | one_slot = rom_resource_table + sizeof(struct hrt); | ||
172 | |||
173 | i = readb(rom_resource_table + NUMBER_OF_ENTRIES); | ||
174 | dbg("number_of_entries = %d\n", i); | ||
175 | |||
176 | if (!readb(one_slot + SECONDARY_BUS)) | ||
177 | return (1); | ||
178 | |||
179 | dbg("dev|IO base|length|MEMbase|length|PM base|length|PB SB MB\n"); | ||
180 | |||
181 | while (i && readb(one_slot + SECONDARY_BUS)) { | ||
182 | u8 dev_func = readb(one_slot + DEV_FUNC); | ||
183 | u8 primary_bus = readb(one_slot + PRIMARY_BUS); | ||
184 | u8 secondary_bus = readb(one_slot + SECONDARY_BUS); | ||
185 | u8 max_bus = readb(one_slot + MAX_BUS); | ||
186 | u16 io_base = readw(one_slot + IO_BASE); | ||
187 | u16 io_length = readw(one_slot + IO_LENGTH); | ||
188 | u16 mem_base = readw(one_slot + MEM_BASE); | ||
189 | u16 mem_length = readw(one_slot + MEM_LENGTH); | ||
190 | u16 pre_mem_base = readw(one_slot + PRE_MEM_BASE); | ||
191 | u16 pre_mem_length = readw(one_slot + PRE_MEM_LENGTH); | ||
192 | |||
193 | dbg("%2.2x | %4.4x | %4.4x | %4.4x | %4.4x | %4.4x | %4.4x |%2.2x %2.2x %2.2x\n", | ||
194 | dev_func, io_base, io_length, mem_base, mem_length, pre_mem_base, pre_mem_length, | ||
195 | primary_bus, secondary_bus, max_bus); | ||
196 | |||
197 | /* If this entry isn't for our controller's bus, ignore it */ | ||
198 | if (primary_bus != ctrl->slot_bus) { | ||
199 | i--; | ||
200 | one_slot += sizeof(struct slot_rt); | ||
201 | continue; | ||
202 | } | ||
203 | /* find out if this entry is for an occupied slot */ | ||
204 | temp_dword = 0xFFFFFFFF; | ||
205 | pci_bus->number = primary_bus; | ||
206 | pci_bus_read_config_dword(pci_bus, dev_func, PCI_VENDOR_ID, &temp_dword); | ||
207 | |||
208 | dbg("temp_D_word = %x\n", temp_dword); | ||
209 | |||
210 | if (temp_dword != 0xFFFFFFFF) { | ||
211 | index = 0; | ||
212 | func = shpchp_slot_find(primary_bus, dev_func >> 3, 0); | ||
213 | |||
214 | while (func && (func->function != (dev_func & 0x07))) { | ||
215 | dbg("func = %p b:d:f(%x:%x:%x)\n", func, primary_bus, dev_func >> 3, index); | ||
216 | func = shpchp_slot_find(primary_bus, dev_func >> 3, index++); | ||
217 | } | ||
218 | |||
219 | /* If we can't find a match, skip this table entry */ | ||
220 | if (!func) { | ||
221 | i--; | ||
222 | one_slot += sizeof(struct slot_rt); | ||
223 | continue; | ||
224 | } | ||
225 | /* this may not work and shouldn't be used */ | ||
226 | if (secondary_bus != primary_bus) | ||
227 | bridged_slot = 1; | ||
228 | else | ||
229 | bridged_slot = 0; | ||
230 | |||
231 | populated_slot = 1; | ||
232 | } else { | ||
233 | populated_slot = 0; | ||
234 | bridged_slot = 0; | ||
235 | } | ||
236 | dbg("slot populated =%s \n", populated_slot?"yes":"no"); | ||
237 | |||
238 | /* If we've got a valid IO base, use it */ | ||
239 | |||
240 | temp_ulong = io_base + io_length; | ||
241 | |||
242 | if ((io_base) && (temp_ulong <= 0x10000)) { | ||
243 | io_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); | ||
244 | if (!io_node) | ||
245 | return -ENOMEM; | ||
246 | |||
247 | io_node->base = (ulong)io_base; | ||
248 | io_node->length = (ulong)io_length; | ||
249 | dbg("found io_node(base, length) = %x, %x\n", io_node->base, io_node->length); | ||
250 | |||
251 | if (!populated_slot) { | ||
252 | io_node->next = ctrl->io_head; | ||
253 | ctrl->io_head = io_node; | ||
254 | } else { | ||
255 | io_node->next = func->io_head; | ||
256 | func->io_head = io_node; | ||
257 | } | ||
258 | } | ||
259 | |||
260 | /* If we've got a valid memory base, use it */ | ||
261 | temp_ulong = mem_base + mem_length; | ||
262 | if ((mem_base) && (temp_ulong <= 0x10000)) { | ||
263 | mem_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); | ||
264 | if (!mem_node) | ||
265 | return -ENOMEM; | ||
266 | |||
267 | mem_node->base = (ulong)mem_base << 16; | ||
268 | mem_node->length = (ulong)(mem_length << 16); | ||
269 | dbg("found mem_node(base, length) = %x, %x\n", mem_node->base, mem_node->length); | ||
270 | |||
271 | if (!populated_slot) { | ||
272 | mem_node->next = ctrl->mem_head; | ||
273 | ctrl->mem_head = mem_node; | ||
274 | } else { | ||
275 | mem_node->next = func->mem_head; | ||
276 | func->mem_head = mem_node; | ||
277 | } | ||
278 | } | ||
279 | |||
280 | /* | ||
281 | * If we've got a valid prefetchable memory base, and | ||
282 | * the base + length isn't greater than 0xFFFF | ||
283 | */ | ||
284 | temp_ulong = pre_mem_base + pre_mem_length; | ||
285 | if ((pre_mem_base) && (temp_ulong <= 0x10000)) { | ||
286 | p_mem_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); | ||
287 | if (!p_mem_node) | ||
288 | return -ENOMEM; | ||
289 | |||
290 | p_mem_node->base = (ulong)pre_mem_base << 16; | ||
291 | p_mem_node->length = (ulong)pre_mem_length << 16; | ||
292 | dbg("found p_mem_node(base, length) = %x, %x\n", p_mem_node->base, p_mem_node->length); | ||
293 | |||
294 | if (!populated_slot) { | ||
295 | p_mem_node->next = ctrl->p_mem_head; | ||
296 | ctrl->p_mem_head = p_mem_node; | ||
297 | } else { | ||
298 | p_mem_node->next = func->p_mem_head; | ||
299 | func->p_mem_head = p_mem_node; | ||
300 | } | ||
301 | } | ||
302 | |||
303 | /* | ||
304 | * If we've got a valid bus number, use it | ||
305 | * The second condition is to ignore bus numbers on | ||
306 | * populated slots that don't have PCI-PCI bridges | ||
307 | */ | ||
308 | if (secondary_bus && (secondary_bus != primary_bus)) { | ||
309 | bus_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); | ||
310 | if (!bus_node) | ||
311 | return -ENOMEM; | ||
312 | |||
313 | bus_node->base = (ulong)secondary_bus; | ||
314 | bus_node->length = (ulong)(max_bus - secondary_bus + 1); | ||
315 | dbg("found bus_node(base, length) = %x, %x\n", bus_node->base, bus_node->length); | ||
316 | |||
317 | if (!populated_slot) { | ||
318 | bus_node->next = ctrl->bus_head; | ||
319 | ctrl->bus_head = bus_node; | ||
320 | } else { | ||
321 | bus_node->next = func->bus_head; | ||
322 | func->bus_head = bus_node; | ||
323 | } | ||
324 | } | ||
325 | |||
326 | i--; | ||
327 | one_slot += sizeof(struct slot_rt); | ||
328 | } | ||
329 | |||
330 | /* If all of the following fail, we don't have any resources for hot plug add */ | ||
331 | rc = 1; | ||
332 | rc &= shpchp_resource_sort_and_combine(&(ctrl->mem_head)); | ||
333 | rc &= shpchp_resource_sort_and_combine(&(ctrl->p_mem_head)); | ||
334 | rc &= shpchp_resource_sort_and_combine(&(ctrl->io_head)); | ||
335 | rc &= shpchp_resource_sort_and_combine(&(ctrl->bus_head)); | ||
336 | |||
337 | return (rc); | ||
338 | } | ||
339 | |||
340 | int shpchprm_set_hpp( | 52 | int shpchprm_set_hpp( |
341 | struct controller *ctrl, | 53 | struct controller *ctrl, |
342 | struct pci_func *func, | 54 | struct pci_func *func, |
@@ -413,12 +125,6 @@ void shpchprm_enable_card( | |||
413 | 125 | ||
414 | static int legacy_shpchprm_init_pci(void) | 126 | static int legacy_shpchprm_init_pci(void) |
415 | { | 127 | { |
416 | shpchp_rom_start = ioremap(ROM_PHY_ADDR, ROM_PHY_LEN); | ||
417 | if (!shpchp_rom_start) { | ||
418 | err("Could not ioremap memory region for ROM\n"); | ||
419 | return -EIO; | ||
420 | } | ||
421 | |||
422 | return 0; | 128 | return 0; |
423 | } | 129 | } |
424 | 130 | ||