1 | // SPDX-License-Identifier: GPL-2.0+ |
2 | /* |
3 | * IBM Hot Plug Controller Driver |
4 | * |
5 | * Written By: Irene Zubarev, IBM Corporation |
6 | * |
7 | * Copyright (C) 2001 Greg Kroah-Hartman (greg@kroah.com) |
8 | * Copyright (C) 2001,2002 IBM Corp. |
9 | * |
10 | * All rights reserved. |
11 | * |
12 | * Send feedback to <gregkh@us.ibm.com> |
13 | * |
14 | */ |
15 | |
16 | #include <linux/module.h> |
17 | #include <linux/slab.h> |
18 | #include <linux/pci.h> |
19 | #include <linux/list.h> |
20 | #include "ibmphp.h" |
21 | |
22 | |
23 | static int configure_device(struct pci_func *); |
24 | static int configure_bridge(struct pci_func **, u8); |
25 | static struct res_needed *scan_behind_bridge(struct pci_func *, u8); |
26 | static int add_new_bus(struct bus_node *, struct resource_node *, struct resource_node *, struct resource_node *, u8); |
27 | static u8 find_sec_number(u8 primary_busno, u8 slotno); |
28 | |
29 | /* |
30 | * NOTE..... If BIOS doesn't provide default routing, we assign: |
31 | * 9 for SCSI, 10 for LAN adapters, and 11 for everything else. |
32 | * If adapter is bridged, then we assign 11 to it and devices behind it. |
33 | * We also assign the same irq numbers for multi function devices. |
34 | * These are PIC mode, so shouldn't matter n.e.ways (hopefully) |
35 | */ |
36 | static void assign_alt_irq(struct pci_func *cur_func, u8 class_code) |
37 | { |
38 | int j; |
39 | for (j = 0; j < 4; j++) { |
40 | if (cur_func->irq[j] == 0xff) { |
41 | switch (class_code) { |
42 | case PCI_BASE_CLASS_STORAGE: |
43 | cur_func->irq[j] = SCSI_IRQ; |
44 | break; |
45 | case PCI_BASE_CLASS_NETWORK: |
46 | cur_func->irq[j] = LAN_IRQ; |
47 | break; |
48 | default: |
49 | cur_func->irq[j] = OTHER_IRQ; |
50 | break; |
51 | } |
52 | } |
53 | } |
54 | } |
55 | |
56 | /* |
57 | * Configures the device to be added (will allocate needed resources if it |
58 | * can), the device can be a bridge or a regular pci device, can also be |
59 | * multi-functional |
60 | * |
61 | * Input: function to be added |
62 | * |
63 | * TO DO: The error case with Multifunction device or multi function bridge, |
64 | * if there is an error, will need to go through all previous functions and |
65 | * unconfigure....or can add some code into unconfigure_card.... |
66 | */ |
67 | int ibmphp_configure_card(struct pci_func *func, u8 slotno) |
68 | { |
69 | u16 vendor_id; |
70 | u32 class; |
71 | u8 class_code; |
72 | u8 hdr_type, device, sec_number; |
73 | u8 function; |
74 | struct pci_func *newfunc; /* for multi devices */ |
75 | struct pci_func *cur_func, *prev_func; |
76 | int rc, i, j; |
77 | int cleanup_count; |
78 | u8 flag; |
79 | u8 valid_device = 0x00; /* to see if we are able to read from card any device info at all */ |
80 | |
81 | debug("inside configure_card, func->busno = %x\n" , func->busno); |
82 | |
83 | device = func->device; |
84 | cur_func = func; |
85 | |
86 | /* We only get bus and device from IRQ routing table. So at this point, |
87 | * func->busno is correct, and func->device contains only device (at the 5 |
88 | * highest bits) |
89 | */ |
90 | |
91 | /* For every function on the card */ |
92 | for (function = 0x00; function < 0x08; function++) { |
93 | unsigned int devfn = PCI_DEVFN(device, function); |
94 | ibmphp_pci_bus->number = cur_func->busno; |
95 | |
96 | cur_func->function = function; |
97 | |
98 | debug("inside the loop, cur_func->busno = %x, cur_func->device = %x, cur_func->function = %x\n" , |
99 | cur_func->busno, cur_func->device, cur_func->function); |
100 | |
101 | pci_bus_read_config_word(bus: ibmphp_pci_bus, devfn, PCI_VENDOR_ID, val: &vendor_id); |
102 | |
103 | debug("vendor_id is %x\n" , vendor_id); |
104 | if (vendor_id != PCI_VENDOR_ID_NOTVALID) { |
105 | /* found correct device!!! */ |
106 | debug("found valid device, vendor_id = %x\n" , vendor_id); |
107 | |
108 | ++valid_device; |
109 | |
110 | /* header: x x x x x x x x |
111 | * | |___________|=> 1=PPB bridge, 0=normal device, 2=CardBus Bridge |
112 | * |_=> 0 = single function device, 1 = multi-function device |
113 | */ |
114 | |
115 | pci_bus_read_config_byte(bus: ibmphp_pci_bus, devfn, PCI_HEADER_TYPE, val: &hdr_type); |
116 | pci_bus_read_config_dword(bus: ibmphp_pci_bus, devfn, PCI_CLASS_REVISION, val: &class); |
117 | |
118 | class_code = class >> 24; |
119 | debug("hrd_type = %x, class = %x, class_code %x\n" , hdr_type, class, class_code); |
120 | class >>= 8; /* to take revision out, class = class.subclass.prog i/f */ |
121 | if (class == PCI_CLASS_NOT_DEFINED_VGA) { |
122 | err("The device %x is VGA compatible and as is not supported for hot plugging. " |
123 | "Please choose another device.\n" , cur_func->device); |
124 | return -ENODEV; |
125 | } else if (class == PCI_CLASS_DISPLAY_VGA) { |
126 | err("The device %x is not supported for hot plugging. Please choose another device.\n" , |
127 | cur_func->device); |
128 | return -ENODEV; |
129 | } |
130 | switch (hdr_type) { |
131 | case PCI_HEADER_TYPE_NORMAL: |
132 | debug("single device case.... vendor id = %x, hdr_type = %x, class = %x\n" , vendor_id, hdr_type, class); |
133 | assign_alt_irq(cur_func, class_code); |
134 | rc = configure_device(cur_func); |
135 | if (rc < 0) { |
136 | /* We need to do this in case some other BARs were properly inserted */ |
137 | err("was not able to configure devfunc %x on bus %x.\n" , |
138 | cur_func->device, cur_func->busno); |
139 | cleanup_count = 6; |
140 | goto error; |
141 | } |
142 | cur_func->next = NULL; |
143 | function = 0x8; |
144 | break; |
145 | case PCI_HEADER_TYPE_MULTIDEVICE: |
146 | assign_alt_irq(cur_func, class_code); |
147 | rc = configure_device(cur_func); |
148 | if (rc < 0) { |
149 | /* We need to do this in case some other BARs were properly inserted */ |
150 | err("was not able to configure devfunc %x on bus %x...bailing out\n" , |
151 | cur_func->device, cur_func->busno); |
152 | cleanup_count = 6; |
153 | goto error; |
154 | } |
155 | newfunc = kzalloc(size: sizeof(*newfunc), GFP_KERNEL); |
156 | if (!newfunc) |
157 | return -ENOMEM; |
158 | |
159 | newfunc->busno = cur_func->busno; |
160 | newfunc->device = device; |
161 | cur_func->next = newfunc; |
162 | cur_func = newfunc; |
163 | for (j = 0; j < 4; j++) |
164 | newfunc->irq[j] = cur_func->irq[j]; |
165 | break; |
166 | case PCI_HEADER_TYPE_MULTIBRIDGE: |
167 | class >>= 8; |
168 | if (class != PCI_CLASS_BRIDGE_PCI) { |
169 | err("This %x is not PCI-to-PCI bridge, and as is not supported for hot-plugging. Please insert another card.\n" , |
170 | cur_func->device); |
171 | return -ENODEV; |
172 | } |
173 | assign_alt_irq(cur_func, class_code); |
174 | rc = configure_bridge(&cur_func, slotno); |
175 | if (rc == -ENODEV) { |
176 | err("You chose to insert Single Bridge, or nested bridges, this is not supported...\n" ); |
177 | err("Bus %x, devfunc %x\n" , cur_func->busno, cur_func->device); |
178 | return rc; |
179 | } |
180 | if (rc) { |
181 | /* We need to do this in case some other BARs were properly inserted */ |
182 | err("was not able to hot-add PPB properly.\n" ); |
183 | func->bus = 1; /* To indicate to the unconfigure function that this is a PPB */ |
184 | cleanup_count = 2; |
185 | goto error; |
186 | } |
187 | |
188 | pci_bus_read_config_byte(bus: ibmphp_pci_bus, devfn, PCI_SECONDARY_BUS, val: &sec_number); |
189 | flag = 0; |
190 | for (i = 0; i < 32; i++) { |
191 | if (func->devices[i]) { |
192 | newfunc = kzalloc(size: sizeof(*newfunc), GFP_KERNEL); |
193 | if (!newfunc) |
194 | return -ENOMEM; |
195 | |
196 | newfunc->busno = sec_number; |
197 | newfunc->device = (u8) i; |
198 | for (j = 0; j < 4; j++) |
199 | newfunc->irq[j] = cur_func->irq[j]; |
200 | |
201 | if (flag) { |
202 | for (prev_func = cur_func; prev_func->next; prev_func = prev_func->next) ; |
203 | prev_func->next = newfunc; |
204 | } else |
205 | cur_func->next = newfunc; |
206 | |
207 | rc = ibmphp_configure_card(func: newfunc, slotno); |
208 | /* This could only happen if kmalloc failed */ |
209 | if (rc) { |
210 | /* We need to do this in case bridge itself got configured properly, but devices behind it failed */ |
211 | func->bus = 1; /* To indicate to the unconfigure function that this is a PPB */ |
212 | cleanup_count = 2; |
213 | goto error; |
214 | } |
215 | flag = 1; |
216 | } |
217 | } |
218 | |
219 | newfunc = kzalloc(size: sizeof(*newfunc), GFP_KERNEL); |
220 | if (!newfunc) |
221 | return -ENOMEM; |
222 | |
223 | newfunc->busno = cur_func->busno; |
224 | newfunc->device = device; |
225 | for (j = 0; j < 4; j++) |
226 | newfunc->irq[j] = cur_func->irq[j]; |
227 | for (prev_func = cur_func; prev_func->next; prev_func = prev_func->next); |
228 | prev_func->next = newfunc; |
229 | cur_func = newfunc; |
230 | break; |
231 | case PCI_HEADER_TYPE_BRIDGE: |
232 | class >>= 8; |
233 | debug("class now is %x\n" , class); |
234 | if (class != PCI_CLASS_BRIDGE_PCI) { |
235 | err("This %x is not PCI-to-PCI bridge, and as is not supported for hot-plugging. Please insert another card.\n" , |
236 | cur_func->device); |
237 | return -ENODEV; |
238 | } |
239 | |
240 | assign_alt_irq(cur_func, class_code); |
241 | |
242 | debug("cur_func->busno b4 configure_bridge is %x\n" , cur_func->busno); |
243 | rc = configure_bridge(&cur_func, slotno); |
244 | if (rc == -ENODEV) { |
245 | err("You chose to insert Single Bridge, or nested bridges, this is not supported...\n" ); |
246 | err("Bus %x, devfunc %x\n" , cur_func->busno, cur_func->device); |
247 | return rc; |
248 | } |
249 | if (rc) { |
250 | /* We need to do this in case some other BARs were properly inserted */ |
251 | func->bus = 1; /* To indicate to the unconfigure function that this is a PPB */ |
252 | err("was not able to hot-add PPB properly.\n" ); |
253 | cleanup_count = 2; |
254 | goto error; |
255 | } |
256 | debug("cur_func->busno = %x, device = %x, function = %x\n" , |
257 | cur_func->busno, device, function); |
258 | pci_bus_read_config_byte(bus: ibmphp_pci_bus, devfn, PCI_SECONDARY_BUS, val: &sec_number); |
259 | debug("after configuring bridge..., sec_number = %x\n" , sec_number); |
260 | flag = 0; |
261 | for (i = 0; i < 32; i++) { |
262 | if (func->devices[i]) { |
263 | debug("inside for loop, device is %x\n" , i); |
264 | newfunc = kzalloc(size: sizeof(*newfunc), GFP_KERNEL); |
265 | if (!newfunc) |
266 | return -ENOMEM; |
267 | |
268 | newfunc->busno = sec_number; |
269 | newfunc->device = (u8) i; |
270 | for (j = 0; j < 4; j++) |
271 | newfunc->irq[j] = cur_func->irq[j]; |
272 | |
273 | if (flag) { |
274 | for (prev_func = cur_func; prev_func->next; prev_func = prev_func->next); |
275 | prev_func->next = newfunc; |
276 | } else |
277 | cur_func->next = newfunc; |
278 | |
279 | rc = ibmphp_configure_card(func: newfunc, slotno); |
280 | |
281 | /* Again, this case should not happen... For complete paranoia, will need to call remove_bus */ |
282 | if (rc) { |
283 | /* We need to do this in case some other BARs were properly inserted */ |
284 | func->bus = 1; /* To indicate to the unconfigure function that this is a PPB */ |
285 | cleanup_count = 2; |
286 | goto error; |
287 | } |
288 | flag = 1; |
289 | } |
290 | } |
291 | |
292 | function = 0x8; |
293 | break; |
294 | default: |
295 | err("MAJOR PROBLEM!!!!, header type not supported? %x\n" , hdr_type); |
296 | return -ENXIO; |
297 | } /* end of switch */ |
298 | } /* end of valid device */ |
299 | } /* end of for */ |
300 | |
301 | if (!valid_device) { |
302 | err("Cannot find any valid devices on the card. Or unable to read from card.\n" ); |
303 | return -ENODEV; |
304 | } |
305 | |
306 | return 0; |
307 | |
308 | error: |
309 | for (i = 0; i < cleanup_count; i++) { |
310 | if (cur_func->io[i]) { |
311 | ibmphp_remove_resource(cur_func->io[i]); |
312 | cur_func->io[i] = NULL; |
313 | } else if (cur_func->pfmem[i]) { |
314 | ibmphp_remove_resource(cur_func->pfmem[i]); |
315 | cur_func->pfmem[i] = NULL; |
316 | } else if (cur_func->mem[i]) { |
317 | ibmphp_remove_resource(cur_func->mem[i]); |
318 | cur_func->mem[i] = NULL; |
319 | } |
320 | } |
321 | return rc; |
322 | } |
323 | |
324 | /* |
325 | * This function configures the pci BARs of a single device. |
326 | * Input: pointer to the pci_func |
327 | * Output: configured PCI, 0, or error |
328 | */ |
329 | static int configure_device(struct pci_func *func) |
330 | { |
331 | u32 bar[6]; |
332 | static const u32 address[] = { |
333 | PCI_BASE_ADDRESS_0, |
334 | PCI_BASE_ADDRESS_1, |
335 | PCI_BASE_ADDRESS_2, |
336 | PCI_BASE_ADDRESS_3, |
337 | PCI_BASE_ADDRESS_4, |
338 | PCI_BASE_ADDRESS_5, |
339 | 0 |
340 | }; |
341 | u8 irq; |
342 | int count; |
343 | int len[6]; |
344 | struct resource_node *io[6]; |
345 | struct resource_node *mem[6]; |
346 | struct resource_node *mem_tmp; |
347 | struct resource_node *pfmem[6]; |
348 | unsigned int devfn; |
349 | |
350 | debug("%s - inside\n" , __func__); |
351 | |
352 | devfn = PCI_DEVFN(func->device, func->function); |
353 | ibmphp_pci_bus->number = func->busno; |
354 | |
355 | for (count = 0; address[count]; count++) { /* for 6 BARs */ |
356 | |
357 | /* not sure if i need this. per scott, said maybe need * something like this |
358 | if devices don't adhere 100% to the spec, so don't want to write |
359 | to the reserved bits |
360 | |
361 | pcibios_read_config_byte(cur_func->busno, cur_func->device, |
362 | PCI_BASE_ADDRESS_0 + 4 * count, &tmp); |
363 | if (tmp & 0x01) // IO |
364 | pcibios_write_config_dword(cur_func->busno, cur_func->device, |
365 | PCI_BASE_ADDRESS_0 + 4 * count, 0xFFFFFFFD); |
366 | else // Memory |
367 | pcibios_write_config_dword(cur_func->busno, cur_func->device, |
368 | PCI_BASE_ADDRESS_0 + 4 * count, 0xFFFFFFFF); |
369 | */ |
370 | pci_bus_write_config_dword(bus: ibmphp_pci_bus, devfn, where: address[count], val: 0xFFFFFFFF); |
371 | pci_bus_read_config_dword(bus: ibmphp_pci_bus, devfn, where: address[count], val: &bar[count]); |
372 | |
373 | if (!bar[count]) /* This BAR is not implemented */ |
374 | continue; |
375 | |
376 | debug("Device %x BAR %d wants %x\n" , func->device, count, bar[count]); |
377 | |
378 | if (bar[count] & PCI_BASE_ADDRESS_SPACE_IO) { |
379 | /* This is IO */ |
380 | debug("inside IO SPACE\n" ); |
381 | |
382 | len[count] = bar[count] & 0xFFFFFFFC; |
383 | len[count] = ~len[count] + 1; |
384 | |
385 | debug("len[count] in IO %x, count %d\n" , len[count], count); |
386 | |
387 | io[count] = kzalloc(size: sizeof(struct resource_node), GFP_KERNEL); |
388 | |
389 | if (!io[count]) |
390 | return -ENOMEM; |
391 | |
392 | io[count]->type = IO; |
393 | io[count]->busno = func->busno; |
394 | io[count]->devfunc = PCI_DEVFN(func->device, func->function); |
395 | io[count]->len = len[count]; |
396 | if (ibmphp_check_resource(io[count], 0) == 0) { |
397 | ibmphp_add_resource(io[count]); |
398 | func->io[count] = io[count]; |
399 | } else { |
400 | err("cannot allocate requested io for bus %x device %x function %x len %x\n" , |
401 | func->busno, func->device, func->function, len[count]); |
402 | kfree(objp: io[count]); |
403 | return -EIO; |
404 | } |
405 | pci_bus_write_config_dword(bus: ibmphp_pci_bus, devfn, where: address[count], val: func->io[count]->start); |
406 | |
407 | /* _______________This is for debugging purposes only_____________________ */ |
408 | debug("b4 writing, the IO address is %x\n" , func->io[count]->start); |
409 | pci_bus_read_config_dword(bus: ibmphp_pci_bus, devfn, where: address[count], val: &bar[count]); |
410 | debug("after writing.... the start address is %x\n" , bar[count]); |
411 | /* _________________________________________________________________________*/ |
412 | |
413 | } else { |
414 | /* This is Memory */ |
415 | if (bar[count] & PCI_BASE_ADDRESS_MEM_PREFETCH) { |
416 | /* pfmem */ |
417 | debug("PFMEM SPACE\n" ); |
418 | |
419 | len[count] = bar[count] & 0xFFFFFFF0; |
420 | len[count] = ~len[count] + 1; |
421 | |
422 | debug("len[count] in PFMEM %x, count %d\n" , len[count], count); |
423 | |
424 | pfmem[count] = kzalloc(size: sizeof(struct resource_node), GFP_KERNEL); |
425 | if (!pfmem[count]) |
426 | return -ENOMEM; |
427 | |
428 | pfmem[count]->type = PFMEM; |
429 | pfmem[count]->busno = func->busno; |
430 | pfmem[count]->devfunc = PCI_DEVFN(func->device, |
431 | func->function); |
432 | pfmem[count]->len = len[count]; |
433 | pfmem[count]->fromMem = 0; |
434 | if (ibmphp_check_resource(pfmem[count], 0) == 0) { |
435 | ibmphp_add_resource(pfmem[count]); |
436 | func->pfmem[count] = pfmem[count]; |
437 | } else { |
438 | mem_tmp = kzalloc(size: sizeof(*mem_tmp), GFP_KERNEL); |
439 | if (!mem_tmp) { |
440 | kfree(objp: pfmem[count]); |
441 | return -ENOMEM; |
442 | } |
443 | mem_tmp->type = MEM; |
444 | mem_tmp->busno = pfmem[count]->busno; |
445 | mem_tmp->devfunc = pfmem[count]->devfunc; |
446 | mem_tmp->len = pfmem[count]->len; |
447 | debug("there's no pfmem... going into mem.\n" ); |
448 | if (ibmphp_check_resource(mem_tmp, 0) == 0) { |
449 | ibmphp_add_resource(mem_tmp); |
450 | pfmem[count]->fromMem = 1; |
451 | pfmem[count]->rangeno = mem_tmp->rangeno; |
452 | pfmem[count]->start = mem_tmp->start; |
453 | pfmem[count]->end = mem_tmp->end; |
454 | ibmphp_add_pfmem_from_mem(pfmem[count]); |
455 | func->pfmem[count] = pfmem[count]; |
456 | } else { |
457 | err("cannot allocate requested pfmem for bus %x, device %x, len %x\n" , |
458 | func->busno, func->device, len[count]); |
459 | kfree(objp: mem_tmp); |
460 | kfree(objp: pfmem[count]); |
461 | return -EIO; |
462 | } |
463 | } |
464 | |
465 | pci_bus_write_config_dword(bus: ibmphp_pci_bus, devfn, where: address[count], val: func->pfmem[count]->start); |
466 | |
467 | /*_______________This is for debugging purposes only______________________________*/ |
468 | debug("b4 writing, start address is %x\n" , func->pfmem[count]->start); |
469 | pci_bus_read_config_dword(bus: ibmphp_pci_bus, devfn, where: address[count], val: &bar[count]); |
470 | debug("after writing, start address is %x\n" , bar[count]); |
471 | /*_________________________________________________________________________________*/ |
472 | |
473 | if (bar[count] & PCI_BASE_ADDRESS_MEM_TYPE_64) { /* takes up another dword */ |
474 | debug("inside the mem 64 case, count %d\n" , count); |
475 | count += 1; |
476 | /* on the 2nd dword, write all 0s, since we can't handle them n.e.ways */ |
477 | pci_bus_write_config_dword(bus: ibmphp_pci_bus, devfn, where: address[count], val: 0x00000000); |
478 | } |
479 | } else { |
480 | /* regular memory */ |
481 | debug("REGULAR MEM SPACE\n" ); |
482 | |
483 | len[count] = bar[count] & 0xFFFFFFF0; |
484 | len[count] = ~len[count] + 1; |
485 | |
486 | debug("len[count] in Mem %x, count %d\n" , len[count], count); |
487 | |
488 | mem[count] = kzalloc(size: sizeof(struct resource_node), GFP_KERNEL); |
489 | if (!mem[count]) |
490 | return -ENOMEM; |
491 | |
492 | mem[count]->type = MEM; |
493 | mem[count]->busno = func->busno; |
494 | mem[count]->devfunc = PCI_DEVFN(func->device, |
495 | func->function); |
496 | mem[count]->len = len[count]; |
497 | if (ibmphp_check_resource(mem[count], 0) == 0) { |
498 | ibmphp_add_resource(mem[count]); |
499 | func->mem[count] = mem[count]; |
500 | } else { |
501 | err("cannot allocate requested mem for bus %x, device %x, len %x\n" , |
502 | func->busno, func->device, len[count]); |
503 | kfree(objp: mem[count]); |
504 | return -EIO; |
505 | } |
506 | pci_bus_write_config_dword(bus: ibmphp_pci_bus, devfn, where: address[count], val: func->mem[count]->start); |
507 | /* _______________________This is for debugging purposes only _______________________*/ |
508 | debug("b4 writing, start address is %x\n" , func->mem[count]->start); |
509 | pci_bus_read_config_dword(bus: ibmphp_pci_bus, devfn, where: address[count], val: &bar[count]); |
510 | debug("after writing, the address is %x\n" , bar[count]); |
511 | /* __________________________________________________________________________________*/ |
512 | |
513 | if (bar[count] & PCI_BASE_ADDRESS_MEM_TYPE_64) { |
514 | /* takes up another dword */ |
515 | debug("inside mem 64 case, reg. mem, count %d\n" , count); |
516 | count += 1; |
517 | /* on the 2nd dword, write all 0s, since we can't handle them n.e.ways */ |
518 | pci_bus_write_config_dword(bus: ibmphp_pci_bus, devfn, where: address[count], val: 0x00000000); |
519 | } |
520 | } |
521 | } /* end of mem */ |
522 | } /* end of for */ |
523 | |
524 | func->bus = 0; /* To indicate that this is not a PPB */ |
525 | pci_bus_read_config_byte(bus: ibmphp_pci_bus, devfn, PCI_INTERRUPT_PIN, val: &irq); |
526 | if ((irq > 0x00) && (irq < 0x05)) |
527 | pci_bus_write_config_byte(bus: ibmphp_pci_bus, devfn, PCI_INTERRUPT_LINE, val: func->irq[irq - 1]); |
528 | |
529 | pci_bus_write_config_byte(bus: ibmphp_pci_bus, devfn, PCI_CACHE_LINE_SIZE, CACHE); |
530 | pci_bus_write_config_byte(bus: ibmphp_pci_bus, devfn, PCI_LATENCY_TIMER, LATENCY); |
531 | |
532 | pci_bus_write_config_dword(bus: ibmphp_pci_bus, devfn, PCI_ROM_ADDRESS, val: 0x00L); |
533 | pci_bus_write_config_word(bus: ibmphp_pci_bus, devfn, PCI_COMMAND, DEVICEENABLE); |
534 | |
535 | return 0; |
536 | } |
537 | |
538 | /****************************************************************************** |
539 | * This routine configures a PCI-2-PCI bridge and the functions behind it |
540 | * Parameters: pci_func |
541 | * Returns: |
542 | ******************************************************************************/ |
543 | static int configure_bridge(struct pci_func **func_passed, u8 slotno) |
544 | { |
545 | int count; |
546 | int i; |
547 | int rc; |
548 | u8 sec_number; |
549 | u8 io_base; |
550 | u16 pfmem_base; |
551 | u32 bar[2]; |
552 | u32 len[2]; |
553 | u8 flag_io = 0; |
554 | u8 flag_mem = 0; |
555 | u8 flag_pfmem = 0; |
556 | u8 need_io_upper = 0; |
557 | u8 need_pfmem_upper = 0; |
558 | struct res_needed *amount_needed = NULL; |
559 | struct resource_node *io = NULL; |
560 | struct resource_node *bus_io[2] = {NULL, NULL}; |
561 | struct resource_node *mem = NULL; |
562 | struct resource_node *bus_mem[2] = {NULL, NULL}; |
563 | struct resource_node *mem_tmp = NULL; |
564 | struct resource_node *pfmem = NULL; |
565 | struct resource_node *bus_pfmem[2] = {NULL, NULL}; |
566 | struct bus_node *bus; |
567 | static const u32 address[] = { |
568 | PCI_BASE_ADDRESS_0, |
569 | PCI_BASE_ADDRESS_1, |
570 | 0 |
571 | }; |
572 | struct pci_func *func = *func_passed; |
573 | unsigned int devfn; |
574 | u8 irq; |
575 | int retval; |
576 | |
577 | debug("%s - enter\n" , __func__); |
578 | |
579 | devfn = PCI_DEVFN(func->function, func->device); |
580 | ibmphp_pci_bus->number = func->busno; |
581 | |
582 | /* Configuring necessary info for the bridge so that we could see the devices |
583 | * behind it |
584 | */ |
585 | |
586 | pci_bus_write_config_byte(bus: ibmphp_pci_bus, devfn, PCI_PRIMARY_BUS, val: func->busno); |
587 | |
588 | /* _____________________For debugging purposes only __________________________ |
589 | pci_bus_config_byte(ibmphp_pci_bus, devfn, PCI_PRIMARY_BUS, &pri_number); |
590 | debug("primary # written into the bridge is %x\n", pri_number); |
591 | ___________________________________________________________________________*/ |
592 | |
593 | /* in EBDA, only get allocated 1 additional bus # per slot */ |
594 | sec_number = find_sec_number(primary_busno: func->busno, slotno); |
595 | if (sec_number == 0xff) { |
596 | err("cannot allocate secondary bus number for the bridged device\n" ); |
597 | return -EINVAL; |
598 | } |
599 | |
600 | debug("after find_sec_number, the number we got is %x\n" , sec_number); |
601 | debug("AFTER FIND_SEC_NUMBER, func->busno IS %x\n" , func->busno); |
602 | |
603 | pci_bus_write_config_byte(bus: ibmphp_pci_bus, devfn, PCI_SECONDARY_BUS, val: sec_number); |
604 | |
605 | /* __________________For debugging purposes only __________________________________ |
606 | pci_bus_read_config_byte(ibmphp_pci_bus, devfn, PCI_SECONDARY_BUS, &sec_number); |
607 | debug("sec_number after write/read is %x\n", sec_number); |
608 | ________________________________________________________________________________*/ |
609 | |
610 | pci_bus_write_config_byte(bus: ibmphp_pci_bus, devfn, PCI_SUBORDINATE_BUS, val: sec_number); |
611 | |
612 | /* __________________For debugging purposes only ____________________________________ |
613 | pci_bus_read_config_byte(ibmphp_pci_bus, devfn, PCI_SUBORDINATE_BUS, &sec_number); |
614 | debug("subordinate number after write/read is %x\n", sec_number); |
615 | __________________________________________________________________________________*/ |
616 | |
617 | pci_bus_write_config_byte(bus: ibmphp_pci_bus, devfn, PCI_CACHE_LINE_SIZE, CACHE); |
618 | pci_bus_write_config_byte(bus: ibmphp_pci_bus, devfn, PCI_LATENCY_TIMER, LATENCY); |
619 | pci_bus_write_config_byte(bus: ibmphp_pci_bus, devfn, PCI_SEC_LATENCY_TIMER, LATENCY); |
620 | |
621 | debug("func->busno is %x\n" , func->busno); |
622 | debug("sec_number after writing is %x\n" , sec_number); |
623 | |
624 | |
625 | /* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! |
626 | !!!!!!!!!!!!!!!NEED TO ADD!!! FAST BACK-TO-BACK ENABLE!!!!!!!!!!!!!!!!!!!! |
627 | !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/ |
628 | |
629 | |
630 | /* First we need to allocate mem/io for the bridge itself in case it needs it */ |
631 | for (count = 0; address[count]; count++) { /* for 2 BARs */ |
632 | pci_bus_write_config_dword(bus: ibmphp_pci_bus, devfn, where: address[count], val: 0xFFFFFFFF); |
633 | pci_bus_read_config_dword(bus: ibmphp_pci_bus, devfn, where: address[count], val: &bar[count]); |
634 | |
635 | if (!bar[count]) { |
636 | /* This BAR is not implemented */ |
637 | debug("so we come here then, eh?, count = %d\n" , count); |
638 | continue; |
639 | } |
640 | // tmp_bar = bar[count]; |
641 | |
642 | debug("Bar %d wants %x\n" , count, bar[count]); |
643 | |
644 | if (bar[count] & PCI_BASE_ADDRESS_SPACE_IO) { |
645 | /* This is IO */ |
646 | len[count] = bar[count] & 0xFFFFFFFC; |
647 | len[count] = ~len[count] + 1; |
648 | |
649 | debug("len[count] in IO = %x\n" , len[count]); |
650 | |
651 | bus_io[count] = kzalloc(size: sizeof(struct resource_node), GFP_KERNEL); |
652 | |
653 | if (!bus_io[count]) { |
654 | retval = -ENOMEM; |
655 | goto error; |
656 | } |
657 | bus_io[count]->type = IO; |
658 | bus_io[count]->busno = func->busno; |
659 | bus_io[count]->devfunc = PCI_DEVFN(func->device, |
660 | func->function); |
661 | bus_io[count]->len = len[count]; |
662 | if (ibmphp_check_resource(bus_io[count], 0) == 0) { |
663 | ibmphp_add_resource(bus_io[count]); |
664 | func->io[count] = bus_io[count]; |
665 | } else { |
666 | err("cannot allocate requested io for bus %x, device %x, len %x\n" , |
667 | func->busno, func->device, len[count]); |
668 | kfree(objp: bus_io[count]); |
669 | return -EIO; |
670 | } |
671 | |
672 | pci_bus_write_config_dword(bus: ibmphp_pci_bus, devfn, where: address[count], val: func->io[count]->start); |
673 | |
674 | } else { |
675 | /* This is Memory */ |
676 | if (bar[count] & PCI_BASE_ADDRESS_MEM_PREFETCH) { |
677 | /* pfmem */ |
678 | len[count] = bar[count] & 0xFFFFFFF0; |
679 | len[count] = ~len[count] + 1; |
680 | |
681 | debug("len[count] in PFMEM = %x\n" , len[count]); |
682 | |
683 | bus_pfmem[count] = kzalloc(size: sizeof(struct resource_node), GFP_KERNEL); |
684 | if (!bus_pfmem[count]) { |
685 | retval = -ENOMEM; |
686 | goto error; |
687 | } |
688 | bus_pfmem[count]->type = PFMEM; |
689 | bus_pfmem[count]->busno = func->busno; |
690 | bus_pfmem[count]->devfunc = PCI_DEVFN(func->device, |
691 | func->function); |
692 | bus_pfmem[count]->len = len[count]; |
693 | bus_pfmem[count]->fromMem = 0; |
694 | if (ibmphp_check_resource(bus_pfmem[count], 0) == 0) { |
695 | ibmphp_add_resource(bus_pfmem[count]); |
696 | func->pfmem[count] = bus_pfmem[count]; |
697 | } else { |
698 | mem_tmp = kzalloc(size: sizeof(*mem_tmp), GFP_KERNEL); |
699 | if (!mem_tmp) { |
700 | retval = -ENOMEM; |
701 | goto error; |
702 | } |
703 | mem_tmp->type = MEM; |
704 | mem_tmp->busno = bus_pfmem[count]->busno; |
705 | mem_tmp->devfunc = bus_pfmem[count]->devfunc; |
706 | mem_tmp->len = bus_pfmem[count]->len; |
707 | if (ibmphp_check_resource(mem_tmp, 0) == 0) { |
708 | ibmphp_add_resource(mem_tmp); |
709 | bus_pfmem[count]->fromMem = 1; |
710 | bus_pfmem[count]->rangeno = mem_tmp->rangeno; |
711 | ibmphp_add_pfmem_from_mem(bus_pfmem[count]); |
712 | func->pfmem[count] = bus_pfmem[count]; |
713 | } else { |
714 | err("cannot allocate requested pfmem for bus %x, device %x, len %x\n" , |
715 | func->busno, func->device, len[count]); |
716 | kfree(objp: mem_tmp); |
717 | kfree(objp: bus_pfmem[count]); |
718 | return -EIO; |
719 | } |
720 | } |
721 | |
722 | pci_bus_write_config_dword(bus: ibmphp_pci_bus, devfn, where: address[count], val: func->pfmem[count]->start); |
723 | |
724 | if (bar[count] & PCI_BASE_ADDRESS_MEM_TYPE_64) { |
725 | /* takes up another dword */ |
726 | count += 1; |
727 | /* on the 2nd dword, write all 0s, since we can't handle them n.e.ways */ |
728 | pci_bus_write_config_dword(bus: ibmphp_pci_bus, devfn, where: address[count], val: 0x00000000); |
729 | |
730 | } |
731 | } else { |
732 | /* regular memory */ |
733 | len[count] = bar[count] & 0xFFFFFFF0; |
734 | len[count] = ~len[count] + 1; |
735 | |
736 | debug("len[count] in Memory is %x\n" , len[count]); |
737 | |
738 | bus_mem[count] = kzalloc(size: sizeof(struct resource_node), GFP_KERNEL); |
739 | if (!bus_mem[count]) { |
740 | retval = -ENOMEM; |
741 | goto error; |
742 | } |
743 | bus_mem[count]->type = MEM; |
744 | bus_mem[count]->busno = func->busno; |
745 | bus_mem[count]->devfunc = PCI_DEVFN(func->device, |
746 | func->function); |
747 | bus_mem[count]->len = len[count]; |
748 | if (ibmphp_check_resource(bus_mem[count], 0) == 0) { |
749 | ibmphp_add_resource(bus_mem[count]); |
750 | func->mem[count] = bus_mem[count]; |
751 | } else { |
752 | err("cannot allocate requested mem for bus %x, device %x, len %x\n" , |
753 | func->busno, func->device, len[count]); |
754 | kfree(objp: bus_mem[count]); |
755 | return -EIO; |
756 | } |
757 | |
758 | pci_bus_write_config_dword(bus: ibmphp_pci_bus, devfn, where: address[count], val: func->mem[count]->start); |
759 | |
760 | if (bar[count] & PCI_BASE_ADDRESS_MEM_TYPE_64) { |
761 | /* takes up another dword */ |
762 | count += 1; |
763 | /* on the 2nd dword, write all 0s, since we can't handle them n.e.ways */ |
764 | pci_bus_write_config_dword(bus: ibmphp_pci_bus, devfn, where: address[count], val: 0x00000000); |
765 | |
766 | } |
767 | } |
768 | } /* end of mem */ |
769 | } /* end of for */ |
770 | |
771 | /* Now need to see how much space the devices behind the bridge needed */ |
772 | amount_needed = scan_behind_bridge(func, sec_number); |
773 | if (amount_needed == NULL) |
774 | return -ENOMEM; |
775 | |
776 | ibmphp_pci_bus->number = func->busno; |
777 | debug("after coming back from scan_behind_bridge\n" ); |
778 | debug("amount_needed->not_correct = %x\n" , amount_needed->not_correct); |
779 | debug("amount_needed->io = %x\n" , amount_needed->io); |
780 | debug("amount_needed->mem = %x\n" , amount_needed->mem); |
781 | debug("amount_needed->pfmem = %x\n" , amount_needed->pfmem); |
782 | |
783 | if (amount_needed->not_correct) { |
784 | debug("amount_needed is not correct\n" ); |
785 | for (count = 0; address[count]; count++) { |
786 | /* for 2 BARs */ |
787 | if (bus_io[count]) { |
788 | ibmphp_remove_resource(bus_io[count]); |
789 | func->io[count] = NULL; |
790 | } else if (bus_pfmem[count]) { |
791 | ibmphp_remove_resource(bus_pfmem[count]); |
792 | func->pfmem[count] = NULL; |
793 | } else if (bus_mem[count]) { |
794 | ibmphp_remove_resource(bus_mem[count]); |
795 | func->mem[count] = NULL; |
796 | } |
797 | } |
798 | kfree(objp: amount_needed); |
799 | return -ENODEV; |
800 | } |
801 | |
802 | if (!amount_needed->io) { |
803 | debug("it doesn't want IO?\n" ); |
804 | flag_io = 1; |
805 | } else { |
806 | debug("it wants %x IO behind the bridge\n" , amount_needed->io); |
807 | io = kzalloc(size: sizeof(*io), GFP_KERNEL); |
808 | |
809 | if (!io) { |
810 | retval = -ENOMEM; |
811 | goto error; |
812 | } |
813 | io->type = IO; |
814 | io->busno = func->busno; |
815 | io->devfunc = PCI_DEVFN(func->device, func->function); |
816 | io->len = amount_needed->io; |
817 | if (ibmphp_check_resource(io, 1) == 0) { |
818 | debug("were we able to add io\n" ); |
819 | ibmphp_add_resource(io); |
820 | flag_io = 1; |
821 | } |
822 | } |
823 | |
824 | if (!amount_needed->mem) { |
825 | debug("it doesn't want n.e.memory?\n" ); |
826 | flag_mem = 1; |
827 | } else { |
828 | debug("it wants %x memory behind the bridge\n" , amount_needed->mem); |
829 | mem = kzalloc(size: sizeof(*mem), GFP_KERNEL); |
830 | if (!mem) { |
831 | retval = -ENOMEM; |
832 | goto error; |
833 | } |
834 | mem->type = MEM; |
835 | mem->busno = func->busno; |
836 | mem->devfunc = PCI_DEVFN(func->device, func->function); |
837 | mem->len = amount_needed->mem; |
838 | if (ibmphp_check_resource(mem, 1) == 0) { |
839 | ibmphp_add_resource(mem); |
840 | flag_mem = 1; |
841 | debug("were we able to add mem\n" ); |
842 | } |
843 | } |
844 | |
845 | if (!amount_needed->pfmem) { |
846 | debug("it doesn't want n.e.pfmem mem?\n" ); |
847 | flag_pfmem = 1; |
848 | } else { |
849 | debug("it wants %x pfmemory behind the bridge\n" , amount_needed->pfmem); |
850 | pfmem = kzalloc(size: sizeof(*pfmem), GFP_KERNEL); |
851 | if (!pfmem) { |
852 | retval = -ENOMEM; |
853 | goto error; |
854 | } |
855 | pfmem->type = PFMEM; |
856 | pfmem->busno = func->busno; |
857 | pfmem->devfunc = PCI_DEVFN(func->device, func->function); |
858 | pfmem->len = amount_needed->pfmem; |
859 | pfmem->fromMem = 0; |
860 | if (ibmphp_check_resource(pfmem, 1) == 0) { |
861 | ibmphp_add_resource(pfmem); |
862 | flag_pfmem = 1; |
863 | } else { |
864 | mem_tmp = kzalloc(size: sizeof(*mem_tmp), GFP_KERNEL); |
865 | if (!mem_tmp) { |
866 | retval = -ENOMEM; |
867 | goto error; |
868 | } |
869 | mem_tmp->type = MEM; |
870 | mem_tmp->busno = pfmem->busno; |
871 | mem_tmp->devfunc = pfmem->devfunc; |
872 | mem_tmp->len = pfmem->len; |
873 | if (ibmphp_check_resource(mem_tmp, 1) == 0) { |
874 | ibmphp_add_resource(mem_tmp); |
875 | pfmem->fromMem = 1; |
876 | pfmem->rangeno = mem_tmp->rangeno; |
877 | ibmphp_add_pfmem_from_mem(pfmem); |
878 | flag_pfmem = 1; |
879 | } |
880 | } |
881 | } |
882 | |
883 | debug("b4 if (flag_io && flag_mem && flag_pfmem)\n" ); |
884 | debug("flag_io = %x, flag_mem = %x, flag_pfmem = %x\n" , flag_io, flag_mem, flag_pfmem); |
885 | |
886 | if (flag_io && flag_mem && flag_pfmem) { |
887 | /* If on bootup, there was a bridged card in this slot, |
888 | * then card was removed and ibmphp got unloaded and loaded |
889 | * back again, there's no way for us to remove the bus |
890 | * struct, so no need to kmalloc, can use existing node |
891 | */ |
892 | bus = ibmphp_find_res_bus(sec_number); |
893 | if (!bus) { |
894 | bus = kzalloc(size: sizeof(*bus), GFP_KERNEL); |
895 | if (!bus) { |
896 | retval = -ENOMEM; |
897 | goto error; |
898 | } |
899 | bus->busno = sec_number; |
900 | debug("b4 adding new bus\n" ); |
901 | rc = add_new_bus(bus, io, mem, pfmem, func->busno); |
902 | } else if (!(bus->rangeIO) && !(bus->rangeMem) && !(bus->rangePFMem)) |
903 | rc = add_new_bus(bus, io, mem, pfmem, 0xFF); |
904 | else { |
905 | err("expected bus structure not empty?\n" ); |
906 | retval = -EIO; |
907 | goto error; |
908 | } |
909 | if (rc) { |
910 | if (rc == -ENOMEM) { |
911 | ibmphp_remove_bus(bus, func->busno); |
912 | kfree(objp: amount_needed); |
913 | return rc; |
914 | } |
915 | retval = rc; |
916 | goto error; |
917 | } |
918 | pci_bus_read_config_byte(bus: ibmphp_pci_bus, devfn, PCI_IO_BASE, val: &io_base); |
919 | pci_bus_read_config_word(bus: ibmphp_pci_bus, devfn, PCI_PREF_MEMORY_BASE, val: &pfmem_base); |
920 | |
921 | if ((io_base & PCI_IO_RANGE_TYPE_MASK) == PCI_IO_RANGE_TYPE_32) { |
922 | debug("io 32\n" ); |
923 | need_io_upper = 1; |
924 | } |
925 | if ((pfmem_base & PCI_PREF_RANGE_TYPE_MASK) == PCI_PREF_RANGE_TYPE_64) { |
926 | debug("pfmem 64\n" ); |
927 | need_pfmem_upper = 1; |
928 | } |
929 | |
930 | if (bus->noIORanges) { |
931 | pci_bus_write_config_byte(bus: ibmphp_pci_bus, devfn, PCI_IO_BASE, val: 0x00 | bus->rangeIO->start >> 8); |
932 | pci_bus_write_config_byte(bus: ibmphp_pci_bus, devfn, PCI_IO_LIMIT, val: 0x00 | bus->rangeIO->end >> 8); |
933 | |
934 | /* _______________This is for debugging purposes only ____________________ |
935 | pci_bus_read_config_byte(ibmphp_pci_bus, devfn, PCI_IO_BASE, &temp); |
936 | debug("io_base = %x\n", (temp & PCI_IO_RANGE_TYPE_MASK) << 8); |
937 | pci_bus_read_config_byte(ibmphp_pci_bus, devfn, PCI_IO_LIMIT, &temp); |
938 | debug("io_limit = %x\n", (temp & PCI_IO_RANGE_TYPE_MASK) << 8); |
939 | ________________________________________________________________________*/ |
940 | |
941 | if (need_io_upper) { /* since can't support n.e.ways */ |
942 | pci_bus_write_config_word(bus: ibmphp_pci_bus, devfn, PCI_IO_BASE_UPPER16, val: 0x0000); |
943 | pci_bus_write_config_word(bus: ibmphp_pci_bus, devfn, PCI_IO_LIMIT_UPPER16, val: 0x0000); |
944 | } |
945 | } else { |
946 | pci_bus_write_config_byte(bus: ibmphp_pci_bus, devfn, PCI_IO_BASE, val: 0x00); |
947 | pci_bus_write_config_byte(bus: ibmphp_pci_bus, devfn, PCI_IO_LIMIT, val: 0x00); |
948 | } |
949 | |
950 | if (bus->noMemRanges) { |
951 | pci_bus_write_config_word(bus: ibmphp_pci_bus, devfn, PCI_MEMORY_BASE, val: 0x0000 | bus->rangeMem->start >> 16); |
952 | pci_bus_write_config_word(bus: ibmphp_pci_bus, devfn, PCI_MEMORY_LIMIT, val: 0x0000 | bus->rangeMem->end >> 16); |
953 | |
954 | /* ____________________This is for debugging purposes only ________________________ |
955 | pci_bus_read_config_word(ibmphp_pci_bus, devfn, PCI_MEMORY_BASE, &temp); |
956 | debug("mem_base = %x\n", (temp & PCI_MEMORY_RANGE_TYPE_MASK) << 16); |
957 | pci_bus_read_config_word(ibmphp_pci_bus, devfn, PCI_MEMORY_LIMIT, &temp); |
958 | debug("mem_limit = %x\n", (temp & PCI_MEMORY_RANGE_TYPE_MASK) << 16); |
959 | __________________________________________________________________________________*/ |
960 | |
961 | } else { |
962 | pci_bus_write_config_word(bus: ibmphp_pci_bus, devfn, PCI_MEMORY_BASE, val: 0xffff); |
963 | pci_bus_write_config_word(bus: ibmphp_pci_bus, devfn, PCI_MEMORY_LIMIT, val: 0x0000); |
964 | } |
965 | if (bus->noPFMemRanges) { |
966 | pci_bus_write_config_word(bus: ibmphp_pci_bus, devfn, PCI_PREF_MEMORY_BASE, val: 0x0000 | bus->rangePFMem->start >> 16); |
967 | pci_bus_write_config_word(bus: ibmphp_pci_bus, devfn, PCI_PREF_MEMORY_LIMIT, val: 0x0000 | bus->rangePFMem->end >> 16); |
968 | |
969 | /* __________________________This is for debugging purposes only _______________________ |
970 | pci_bus_read_config_word(ibmphp_pci_bus, devfn, PCI_PREF_MEMORY_BASE, &temp); |
971 | debug("pfmem_base = %x", (temp & PCI_MEMORY_RANGE_TYPE_MASK) << 16); |
972 | pci_bus_read_config_word(ibmphp_pci_bus, devfn, PCI_PREF_MEMORY_LIMIT, &temp); |
973 | debug("pfmem_limit = %x\n", (temp & PCI_MEMORY_RANGE_TYPE_MASK) << 16); |
974 | ______________________________________________________________________________________*/ |
975 | |
976 | if (need_pfmem_upper) { /* since can't support n.e.ways */ |
977 | pci_bus_write_config_dword(bus: ibmphp_pci_bus, devfn, PCI_PREF_BASE_UPPER32, val: 0x00000000); |
978 | pci_bus_write_config_dword(bus: ibmphp_pci_bus, devfn, PCI_PREF_LIMIT_UPPER32, val: 0x00000000); |
979 | } |
980 | } else { |
981 | pci_bus_write_config_word(bus: ibmphp_pci_bus, devfn, PCI_PREF_MEMORY_BASE, val: 0xffff); |
982 | pci_bus_write_config_word(bus: ibmphp_pci_bus, devfn, PCI_PREF_MEMORY_LIMIT, val: 0x0000); |
983 | } |
984 | |
985 | debug("b4 writing control information\n" ); |
986 | |
987 | pci_bus_read_config_byte(bus: ibmphp_pci_bus, devfn, PCI_INTERRUPT_PIN, val: &irq); |
988 | if ((irq > 0x00) && (irq < 0x05)) |
989 | pci_bus_write_config_byte(bus: ibmphp_pci_bus, devfn, PCI_INTERRUPT_LINE, val: func->irq[irq - 1]); |
990 | /* |
991 | pci_bus_write_config_byte(ibmphp_pci_bus, devfn, PCI_BRIDGE_CONTROL, ctrl); |
992 | pci_bus_write_config_byte(ibmphp_pci_bus, devfn, PCI_BRIDGE_CONTROL, PCI_BRIDGE_CTL_PARITY); |
993 | pci_bus_write_config_byte(ibmphp_pci_bus, devfn, PCI_BRIDGE_CONTROL, PCI_BRIDGE_CTL_SERR); |
994 | */ |
995 | |
996 | pci_bus_write_config_word(bus: ibmphp_pci_bus, devfn, PCI_COMMAND, DEVICEENABLE); |
997 | pci_bus_write_config_word(bus: ibmphp_pci_bus, devfn, PCI_BRIDGE_CONTROL, val: 0x07); |
998 | for (i = 0; i < 32; i++) { |
999 | if (amount_needed->devices[i]) { |
1000 | debug("device where devices[i] is 1 = %x\n" , i); |
1001 | func->devices[i] = 1; |
1002 | } |
1003 | } |
1004 | func->bus = 1; /* For unconfiguring, to indicate it's PPB */ |
1005 | func_passed = &func; |
1006 | debug("func->busno b4 returning is %x\n" , func->busno); |
1007 | debug("func->busno b4 returning in the other structure is %x\n" , (*func_passed)->busno); |
1008 | kfree(objp: amount_needed); |
1009 | return 0; |
1010 | } else { |
1011 | err("Configuring bridge was unsuccessful...\n" ); |
1012 | mem_tmp = NULL; |
1013 | retval = -EIO; |
1014 | goto error; |
1015 | } |
1016 | |
1017 | error: |
1018 | kfree(objp: amount_needed); |
1019 | if (pfmem) |
1020 | ibmphp_remove_resource(pfmem); |
1021 | if (io) |
1022 | ibmphp_remove_resource(io); |
1023 | if (mem) |
1024 | ibmphp_remove_resource(mem); |
1025 | for (i = 0; i < 2; i++) { /* for 2 BARs */ |
1026 | if (bus_io[i]) { |
1027 | ibmphp_remove_resource(bus_io[i]); |
1028 | func->io[i] = NULL; |
1029 | } else if (bus_pfmem[i]) { |
1030 | ibmphp_remove_resource(bus_pfmem[i]); |
1031 | func->pfmem[i] = NULL; |
1032 | } else if (bus_mem[i]) { |
1033 | ibmphp_remove_resource(bus_mem[i]); |
1034 | func->mem[i] = NULL; |
1035 | } |
1036 | } |
1037 | return retval; |
1038 | } |
1039 | |
1040 | /***************************************************************************** |
1041 | * This function adds up the amount of resources needed behind the PPB bridge |
1042 | * and passes it to the configure_bridge function |
1043 | * Input: bridge function |
1044 | * Output: amount of resources needed |
1045 | *****************************************************************************/ |
1046 | static struct res_needed *scan_behind_bridge(struct pci_func *func, u8 busno) |
1047 | { |
1048 | int count, len[6]; |
1049 | u16 vendor_id; |
1050 | u8 hdr_type; |
1051 | u8 device, function; |
1052 | unsigned int devfn; |
1053 | int howmany = 0; /*this is to see if there are any devices behind the bridge */ |
1054 | |
1055 | u32 bar[6], class; |
1056 | static const u32 address[] = { |
1057 | PCI_BASE_ADDRESS_0, |
1058 | PCI_BASE_ADDRESS_1, |
1059 | PCI_BASE_ADDRESS_2, |
1060 | PCI_BASE_ADDRESS_3, |
1061 | PCI_BASE_ADDRESS_4, |
1062 | PCI_BASE_ADDRESS_5, |
1063 | 0 |
1064 | }; |
1065 | struct res_needed *amount; |
1066 | |
1067 | amount = kzalloc(size: sizeof(*amount), GFP_KERNEL); |
1068 | if (amount == NULL) |
1069 | return NULL; |
1070 | |
1071 | ibmphp_pci_bus->number = busno; |
1072 | |
1073 | debug("the bus_no behind the bridge is %x\n" , busno); |
1074 | debug("scanning devices behind the bridge...\n" ); |
1075 | for (device = 0; device < 32; device++) { |
1076 | amount->devices[device] = 0; |
1077 | for (function = 0; function < 8; function++) { |
1078 | devfn = PCI_DEVFN(device, function); |
1079 | |
1080 | pci_bus_read_config_word(bus: ibmphp_pci_bus, devfn, PCI_VENDOR_ID, val: &vendor_id); |
1081 | |
1082 | if (vendor_id != PCI_VENDOR_ID_NOTVALID) { |
1083 | /* found correct device!!! */ |
1084 | howmany++; |
1085 | |
1086 | pci_bus_read_config_byte(bus: ibmphp_pci_bus, devfn, PCI_HEADER_TYPE, val: &hdr_type); |
1087 | pci_bus_read_config_dword(bus: ibmphp_pci_bus, devfn, PCI_CLASS_REVISION, val: &class); |
1088 | |
1089 | debug("hdr_type behind the bridge is %x\n" , hdr_type); |
1090 | if ((hdr_type & PCI_HEADER_TYPE_MASK) == PCI_HEADER_TYPE_BRIDGE) { |
1091 | err("embedded bridges not supported for hot-plugging.\n" ); |
1092 | amount->not_correct = 1; |
1093 | return amount; |
1094 | } |
1095 | |
1096 | class >>= 8; /* to take revision out, class = class.subclass.prog i/f */ |
1097 | if (class == PCI_CLASS_NOT_DEFINED_VGA) { |
1098 | err("The device %x is VGA compatible and as is not supported for hot plugging. Please choose another device.\n" , device); |
1099 | amount->not_correct = 1; |
1100 | return amount; |
1101 | } else if (class == PCI_CLASS_DISPLAY_VGA) { |
1102 | err("The device %x is not supported for hot plugging. Please choose another device.\n" , device); |
1103 | amount->not_correct = 1; |
1104 | return amount; |
1105 | } |
1106 | |
1107 | amount->devices[device] = 1; |
1108 | |
1109 | for (count = 0; address[count]; count++) { |
1110 | /* for 6 BARs */ |
1111 | /* |
1112 | pci_bus_read_config_byte(ibmphp_pci_bus, devfn, address[count], &tmp); |
1113 | if (tmp & 0x01) // IO |
1114 | pci_bus_write_config_dword(ibmphp_pci_bus, devfn, address[count], 0xFFFFFFFD); |
1115 | else // MEMORY |
1116 | pci_bus_write_config_dword(ibmphp_pci_bus, devfn, address[count], 0xFFFFFFFF); |
1117 | */ |
1118 | pci_bus_write_config_dword(bus: ibmphp_pci_bus, devfn, where: address[count], val: 0xFFFFFFFF); |
1119 | pci_bus_read_config_dword(bus: ibmphp_pci_bus, devfn, where: address[count], val: &bar[count]); |
1120 | |
1121 | debug("what is bar[count]? %x, count = %d\n" , bar[count], count); |
1122 | |
1123 | if (!bar[count]) /* This BAR is not implemented */ |
1124 | continue; |
1125 | |
1126 | //tmp_bar = bar[count]; |
1127 | |
1128 | debug("count %d device %x function %x wants %x resources\n" , count, device, function, bar[count]); |
1129 | |
1130 | if (bar[count] & PCI_BASE_ADDRESS_SPACE_IO) { |
1131 | /* This is IO */ |
1132 | len[count] = bar[count] & 0xFFFFFFFC; |
1133 | len[count] = ~len[count] + 1; |
1134 | amount->io += len[count]; |
1135 | } else { |
1136 | /* This is Memory */ |
1137 | if (bar[count] & PCI_BASE_ADDRESS_MEM_PREFETCH) { |
1138 | /* pfmem */ |
1139 | len[count] = bar[count] & 0xFFFFFFF0; |
1140 | len[count] = ~len[count] + 1; |
1141 | amount->pfmem += len[count]; |
1142 | if (bar[count] & PCI_BASE_ADDRESS_MEM_TYPE_64) |
1143 | /* takes up another dword */ |
1144 | count += 1; |
1145 | |
1146 | } else { |
1147 | /* regular memory */ |
1148 | len[count] = bar[count] & 0xFFFFFFF0; |
1149 | len[count] = ~len[count] + 1; |
1150 | amount->mem += len[count]; |
1151 | if (bar[count] & PCI_BASE_ADDRESS_MEM_TYPE_64) { |
1152 | /* takes up another dword */ |
1153 | count += 1; |
1154 | } |
1155 | } |
1156 | } |
1157 | } /* end for */ |
1158 | } /* end if (valid) */ |
1159 | } /* end for */ |
1160 | } /* end for */ |
1161 | |
1162 | if (!howmany) |
1163 | amount->not_correct = 1; |
1164 | else |
1165 | amount->not_correct = 0; |
1166 | if ((amount->io) && (amount->io < IOBRIDGE)) |
1167 | amount->io = IOBRIDGE; |
1168 | if ((amount->mem) && (amount->mem < MEMBRIDGE)) |
1169 | amount->mem = MEMBRIDGE; |
1170 | if ((amount->pfmem) && (amount->pfmem < MEMBRIDGE)) |
1171 | amount->pfmem = MEMBRIDGE; |
1172 | return amount; |
1173 | } |
1174 | |
1175 | /* The following 3 unconfigure_boot_ routines deal with the case when we had the card |
1176 | * upon bootup in the system, since we don't allocate func to such case, we need to read |
1177 | * the start addresses from pci config space and then find the corresponding entries in |
1178 | * our resource lists. The functions return either 0, -ENODEV, or -1 (general failure) |
1179 | * Change: we also call these functions even if we configured the card ourselves (i.e., not |
1180 | * the bootup case), since it should work same way |
1181 | */ |
1182 | static int unconfigure_boot_device(u8 busno, u8 device, u8 function) |
1183 | { |
1184 | u32 start_address; |
1185 | static const u32 address[] = { |
1186 | PCI_BASE_ADDRESS_0, |
1187 | PCI_BASE_ADDRESS_1, |
1188 | PCI_BASE_ADDRESS_2, |
1189 | PCI_BASE_ADDRESS_3, |
1190 | PCI_BASE_ADDRESS_4, |
1191 | PCI_BASE_ADDRESS_5, |
1192 | 0 |
1193 | }; |
1194 | int count; |
1195 | struct resource_node *io; |
1196 | struct resource_node *mem; |
1197 | struct resource_node *pfmem; |
1198 | struct bus_node *bus; |
1199 | u32 end_address; |
1200 | u32 temp_end; |
1201 | u32 size; |
1202 | u32 tmp_address; |
1203 | unsigned int devfn; |
1204 | |
1205 | debug("%s - enter\n" , __func__); |
1206 | |
1207 | bus = ibmphp_find_res_bus(busno); |
1208 | if (!bus) { |
1209 | debug("cannot find corresponding bus.\n" ); |
1210 | return -EINVAL; |
1211 | } |
1212 | |
1213 | devfn = PCI_DEVFN(device, function); |
1214 | ibmphp_pci_bus->number = busno; |
1215 | for (count = 0; address[count]; count++) { /* for 6 BARs */ |
1216 | pci_bus_read_config_dword(bus: ibmphp_pci_bus, devfn, where: address[count], val: &start_address); |
1217 | |
1218 | /* We can do this here, b/c by that time the device driver of the card has been stopped */ |
1219 | |
1220 | pci_bus_write_config_dword(bus: ibmphp_pci_bus, devfn, where: address[count], val: 0xFFFFFFFF); |
1221 | pci_bus_read_config_dword(bus: ibmphp_pci_bus, devfn, where: address[count], val: &size); |
1222 | pci_bus_write_config_dword(bus: ibmphp_pci_bus, devfn, where: address[count], val: start_address); |
1223 | |
1224 | debug("start_address is %x\n" , start_address); |
1225 | debug("busno, device, function %x %x %x\n" , busno, device, function); |
1226 | if (!size) { |
1227 | /* This BAR is not implemented */ |
1228 | debug("is this bar no implemented?, count = %d\n" , count); |
1229 | continue; |
1230 | } |
1231 | tmp_address = start_address; |
1232 | if (start_address & PCI_BASE_ADDRESS_SPACE_IO) { |
1233 | /* This is IO */ |
1234 | start_address &= PCI_BASE_ADDRESS_IO_MASK; |
1235 | size = size & 0xFFFFFFFC; |
1236 | size = ~size + 1; |
1237 | end_address = start_address + size - 1; |
1238 | if (ibmphp_find_resource(bus, start_address, &io, IO)) |
1239 | goto report_search_failure; |
1240 | |
1241 | debug("io->start = %x\n" , io->start); |
1242 | temp_end = io->end; |
1243 | start_address = io->end + 1; |
1244 | ibmphp_remove_resource(io); |
1245 | /* This is needed b/c of the old I/O restrictions in the BIOS */ |
1246 | while (temp_end < end_address) { |
1247 | if (ibmphp_find_resource(bus, start_address, |
1248 | &io, IO)) |
1249 | goto report_search_failure; |
1250 | |
1251 | debug("io->start = %x\n" , io->start); |
1252 | temp_end = io->end; |
1253 | start_address = io->end + 1; |
1254 | ibmphp_remove_resource(io); |
1255 | } |
1256 | |
1257 | /* ????????? DO WE NEED TO WRITE ANYTHING INTO THE PCI CONFIG SPACE BACK ?????????? */ |
1258 | } else { |
1259 | /* This is Memory */ |
1260 | if (start_address & PCI_BASE_ADDRESS_MEM_PREFETCH) { |
1261 | /* pfmem */ |
1262 | debug("start address of pfmem is %x\n" , start_address); |
1263 | start_address &= PCI_BASE_ADDRESS_MEM_MASK; |
1264 | |
1265 | if (ibmphp_find_resource(bus, start_address, &pfmem, PFMEM) < 0) { |
1266 | err("cannot find corresponding PFMEM resource to remove\n" ); |
1267 | return -EIO; |
1268 | } |
1269 | if (pfmem) { |
1270 | debug("pfmem->start = %x\n" , pfmem->start); |
1271 | |
1272 | ibmphp_remove_resource(pfmem); |
1273 | } |
1274 | } else { |
1275 | /* regular memory */ |
1276 | debug("start address of mem is %x\n" , start_address); |
1277 | start_address &= PCI_BASE_ADDRESS_MEM_MASK; |
1278 | |
1279 | if (ibmphp_find_resource(bus, start_address, &mem, MEM) < 0) { |
1280 | err("cannot find corresponding MEM resource to remove\n" ); |
1281 | return -EIO; |
1282 | } |
1283 | if (mem) { |
1284 | debug("mem->start = %x\n" , mem->start); |
1285 | |
1286 | ibmphp_remove_resource(mem); |
1287 | } |
1288 | } |
1289 | if (tmp_address & PCI_BASE_ADDRESS_MEM_TYPE_64) { |
1290 | /* takes up another dword */ |
1291 | count += 1; |
1292 | } |
1293 | } /* end of mem */ |
1294 | } /* end of for */ |
1295 | |
1296 | return 0; |
1297 | |
1298 | report_search_failure: |
1299 | err("cannot find corresponding IO resource to remove\n" ); |
1300 | return -EIO; |
1301 | } |
1302 | |
1303 | static int unconfigure_boot_bridge(u8 busno, u8 device, u8 function) |
1304 | { |
1305 | int count; |
1306 | int bus_no, pri_no, sub_no, sec_no = 0; |
1307 | u32 start_address, tmp_address; |
1308 | u8 sec_number, sub_number, pri_number; |
1309 | struct resource_node *io = NULL; |
1310 | struct resource_node *mem = NULL; |
1311 | struct resource_node *pfmem = NULL; |
1312 | struct bus_node *bus; |
1313 | static const u32 address[] = { |
1314 | PCI_BASE_ADDRESS_0, |
1315 | PCI_BASE_ADDRESS_1, |
1316 | 0 |
1317 | }; |
1318 | unsigned int devfn; |
1319 | |
1320 | devfn = PCI_DEVFN(device, function); |
1321 | ibmphp_pci_bus->number = busno; |
1322 | bus_no = (int) busno; |
1323 | debug("busno is %x\n" , busno); |
1324 | pci_bus_read_config_byte(bus: ibmphp_pci_bus, devfn, PCI_PRIMARY_BUS, val: &pri_number); |
1325 | debug("%s - busno = %x, primary_number = %x\n" , __func__, busno, pri_number); |
1326 | |
1327 | pci_bus_read_config_byte(bus: ibmphp_pci_bus, devfn, PCI_SECONDARY_BUS, val: &sec_number); |
1328 | debug("sec_number is %x\n" , sec_number); |
1329 | sec_no = (int) sec_number; |
1330 | pri_no = (int) pri_number; |
1331 | if (pri_no != bus_no) { |
1332 | err("primary numbers in our structures and pci config space don't match.\n" ); |
1333 | return -EINVAL; |
1334 | } |
1335 | |
1336 | pci_bus_read_config_byte(bus: ibmphp_pci_bus, devfn, PCI_SUBORDINATE_BUS, val: &sub_number); |
1337 | sub_no = (int) sub_number; |
1338 | debug("sub_no is %d, sec_no is %d\n" , sub_no, sec_no); |
1339 | if (sec_no != sub_number) { |
1340 | err("there're more buses behind this bridge. Hot removal is not supported. Please choose another card\n" ); |
1341 | return -ENODEV; |
1342 | } |
1343 | |
1344 | bus = ibmphp_find_res_bus(sec_number); |
1345 | if (!bus) { |
1346 | err("cannot find Bus structure for the bridged device\n" ); |
1347 | return -EINVAL; |
1348 | } |
1349 | debug("bus->busno is %x\n" , bus->busno); |
1350 | debug("sec_number is %x\n" , sec_number); |
1351 | |
1352 | ibmphp_remove_bus(bus, busno); |
1353 | |
1354 | for (count = 0; address[count]; count++) { |
1355 | /* for 2 BARs */ |
1356 | pci_bus_read_config_dword(bus: ibmphp_pci_bus, devfn, where: address[count], val: &start_address); |
1357 | |
1358 | if (!start_address) { |
1359 | /* This BAR is not implemented */ |
1360 | continue; |
1361 | } |
1362 | |
1363 | tmp_address = start_address; |
1364 | |
1365 | if (start_address & PCI_BASE_ADDRESS_SPACE_IO) { |
1366 | /* This is IO */ |
1367 | start_address &= PCI_BASE_ADDRESS_IO_MASK; |
1368 | if (ibmphp_find_resource(bus, start_address, &io, IO) < 0) { |
1369 | err("cannot find corresponding IO resource to remove\n" ); |
1370 | return -EIO; |
1371 | } |
1372 | if (io) |
1373 | debug("io->start = %x\n" , io->start); |
1374 | |
1375 | ibmphp_remove_resource(io); |
1376 | |
1377 | /* ????????? DO WE NEED TO WRITE ANYTHING INTO THE PCI CONFIG SPACE BACK ?????????? */ |
1378 | } else { |
1379 | /* This is Memory */ |
1380 | if (start_address & PCI_BASE_ADDRESS_MEM_PREFETCH) { |
1381 | /* pfmem */ |
1382 | start_address &= PCI_BASE_ADDRESS_MEM_MASK; |
1383 | if (ibmphp_find_resource(bus, start_address, &pfmem, PFMEM) < 0) { |
1384 | err("cannot find corresponding PFMEM resource to remove\n" ); |
1385 | return -EINVAL; |
1386 | } |
1387 | if (pfmem) { |
1388 | debug("pfmem->start = %x\n" , pfmem->start); |
1389 | |
1390 | ibmphp_remove_resource(pfmem); |
1391 | } |
1392 | } else { |
1393 | /* regular memory */ |
1394 | start_address &= PCI_BASE_ADDRESS_MEM_MASK; |
1395 | if (ibmphp_find_resource(bus, start_address, &mem, MEM) < 0) { |
1396 | err("cannot find corresponding MEM resource to remove\n" ); |
1397 | return -EINVAL; |
1398 | } |
1399 | if (mem) { |
1400 | debug("mem->start = %x\n" , mem->start); |
1401 | |
1402 | ibmphp_remove_resource(mem); |
1403 | } |
1404 | } |
1405 | if (tmp_address & PCI_BASE_ADDRESS_MEM_TYPE_64) { |
1406 | /* takes up another dword */ |
1407 | count += 1; |
1408 | } |
1409 | } /* end of mem */ |
1410 | } /* end of for */ |
1411 | debug("%s - exiting, returning success\n" , __func__); |
1412 | return 0; |
1413 | } |
1414 | |
1415 | static int unconfigure_boot_card(struct slot *slot_cur) |
1416 | { |
1417 | u16 vendor_id; |
1418 | u32 class; |
1419 | u8 hdr_type; |
1420 | u8 device; |
1421 | u8 busno; |
1422 | u8 function; |
1423 | int rc; |
1424 | unsigned int devfn; |
1425 | u8 valid_device = 0x00; /* To see if we are ever able to find valid device and read it */ |
1426 | |
1427 | debug("%s - enter\n" , __func__); |
1428 | |
1429 | device = slot_cur->device; |
1430 | busno = slot_cur->bus; |
1431 | |
1432 | debug("b4 for loop, device is %x\n" , device); |
1433 | /* For every function on the card */ |
1434 | for (function = 0x0; function < 0x08; function++) { |
1435 | devfn = PCI_DEVFN(device, function); |
1436 | ibmphp_pci_bus->number = busno; |
1437 | |
1438 | pci_bus_read_config_word(bus: ibmphp_pci_bus, devfn, PCI_VENDOR_ID, val: &vendor_id); |
1439 | |
1440 | if (vendor_id != PCI_VENDOR_ID_NOTVALID) { |
1441 | /* found correct device!!! */ |
1442 | ++valid_device; |
1443 | |
1444 | debug("%s - found correct device\n" , __func__); |
1445 | |
1446 | /* header: x x x x x x x x |
1447 | * | |___________|=> 1=PPB bridge, 0=normal device, 2=CardBus Bridge |
1448 | * |_=> 0 = single function device, 1 = multi-function device |
1449 | */ |
1450 | |
1451 | pci_bus_read_config_byte(bus: ibmphp_pci_bus, devfn, PCI_HEADER_TYPE, val: &hdr_type); |
1452 | pci_bus_read_config_dword(bus: ibmphp_pci_bus, devfn, PCI_CLASS_REVISION, val: &class); |
1453 | |
1454 | debug("hdr_type %x, class %x\n" , hdr_type, class); |
1455 | class >>= 8; /* to take revision out, class = class.subclass.prog i/f */ |
1456 | if (class == PCI_CLASS_NOT_DEFINED_VGA) { |
1457 | err("The device %x function %x is VGA compatible and is not supported for hot removing. Please choose another device.\n" , device, function); |
1458 | return -ENODEV; |
1459 | } else if (class == PCI_CLASS_DISPLAY_VGA) { |
1460 | err("The device %x function %x is not supported for hot removing. Please choose another device.\n" , device, function); |
1461 | return -ENODEV; |
1462 | } |
1463 | |
1464 | switch (hdr_type) { |
1465 | case PCI_HEADER_TYPE_NORMAL: |
1466 | rc = unconfigure_boot_device(busno, device, function); |
1467 | if (rc) { |
1468 | err("was not able to unconfigure device %x func %x on bus %x. bailing out...\n" , |
1469 | device, function, busno); |
1470 | return rc; |
1471 | } |
1472 | function = 0x8; |
1473 | break; |
1474 | case PCI_HEADER_TYPE_MULTIDEVICE: |
1475 | rc = unconfigure_boot_device(busno, device, function); |
1476 | if (rc) { |
1477 | err("was not able to unconfigure device %x func %x on bus %x. bailing out...\n" , |
1478 | device, function, busno); |
1479 | return rc; |
1480 | } |
1481 | break; |
1482 | case PCI_HEADER_TYPE_BRIDGE: |
1483 | class >>= 8; |
1484 | if (class != PCI_CLASS_BRIDGE_PCI) { |
1485 | err("This device %x function %x is not PCI-to-PCI bridge, and is not supported for hot-removing. Please try another card.\n" , device, function); |
1486 | return -ENODEV; |
1487 | } |
1488 | rc = unconfigure_boot_bridge(busno, device, function); |
1489 | if (rc != 0) { |
1490 | err("was not able to hot-remove PPB properly.\n" ); |
1491 | return rc; |
1492 | } |
1493 | |
1494 | function = 0x8; |
1495 | break; |
1496 | case PCI_HEADER_TYPE_MULTIBRIDGE: |
1497 | class >>= 8; |
1498 | if (class != PCI_CLASS_BRIDGE_PCI) { |
1499 | err("This device %x function %x is not PCI-to-PCI bridge, and is not supported for hot-removing. Please try another card.\n" , device, function); |
1500 | return -ENODEV; |
1501 | } |
1502 | rc = unconfigure_boot_bridge(busno, device, function); |
1503 | if (rc != 0) { |
1504 | err("was not able to hot-remove PPB properly.\n" ); |
1505 | return rc; |
1506 | } |
1507 | break; |
1508 | default: |
1509 | err("MAJOR PROBLEM!!!! Cannot read device's header\n" ); |
1510 | return -1; |
1511 | } /* end of switch */ |
1512 | } /* end of valid device */ |
1513 | } /* end of for */ |
1514 | |
1515 | if (!valid_device) { |
1516 | err("Could not find device to unconfigure. Or could not read the card.\n" ); |
1517 | return -1; |
1518 | } |
1519 | return 0; |
1520 | } |
1521 | |
1522 | /* |
1523 | * free the resources of the card (multi, single, or bridged) |
1524 | * Parameters: slot, flag to say if this is for removing entire module or just |
1525 | * unconfiguring the device |
1526 | * TO DO: will probably need to add some code in case there was some resource, |
1527 | * to remove it... this is from when we have errors in the configure_card... |
1528 | * !!!!!!!!!!!!!!!!!!!!!!!!!FOR BUSES!!!!!!!!!!!! |
1529 | * Returns: 0, -1, -ENODEV |
1530 | */ |
1531 | int ibmphp_unconfigure_card(struct slot **slot_cur, int the_end) |
1532 | { |
1533 | int i; |
1534 | int count; |
1535 | int rc; |
1536 | struct slot *sl = *slot_cur; |
1537 | struct pci_func *cur_func = NULL; |
1538 | struct pci_func *temp_func; |
1539 | |
1540 | debug("%s - enter\n" , __func__); |
1541 | |
1542 | if (!the_end) { |
1543 | /* Need to unconfigure the card */ |
1544 | rc = unconfigure_boot_card(slot_cur: sl); |
1545 | if ((rc == -ENODEV) || (rc == -EIO) || (rc == -EINVAL)) { |
1546 | /* In all other cases, will still need to get rid of func structure if it exists */ |
1547 | return rc; |
1548 | } |
1549 | } |
1550 | |
1551 | if (sl->func) { |
1552 | cur_func = sl->func; |
1553 | while (cur_func) { |
1554 | /* TO DO: WILL MOST LIKELY NEED TO GET RID OF THE BUS STRUCTURE FROM RESOURCES AS WELL */ |
1555 | if (cur_func->bus) { |
1556 | /* in other words, it's a PPB */ |
1557 | count = 2; |
1558 | } else { |
1559 | count = 6; |
1560 | } |
1561 | |
1562 | for (i = 0; i < count; i++) { |
1563 | if (cur_func->io[i]) { |
1564 | debug("io[%d] exists\n" , i); |
1565 | if (the_end > 0) |
1566 | ibmphp_remove_resource(cur_func->io[i]); |
1567 | cur_func->io[i] = NULL; |
1568 | } |
1569 | if (cur_func->mem[i]) { |
1570 | debug("mem[%d] exists\n" , i); |
1571 | if (the_end > 0) |
1572 | ibmphp_remove_resource(cur_func->mem[i]); |
1573 | cur_func->mem[i] = NULL; |
1574 | } |
1575 | if (cur_func->pfmem[i]) { |
1576 | debug("pfmem[%d] exists\n" , i); |
1577 | if (the_end > 0) |
1578 | ibmphp_remove_resource(cur_func->pfmem[i]); |
1579 | cur_func->pfmem[i] = NULL; |
1580 | } |
1581 | } |
1582 | |
1583 | temp_func = cur_func->next; |
1584 | kfree(objp: cur_func); |
1585 | cur_func = temp_func; |
1586 | } |
1587 | } |
1588 | |
1589 | sl->func = NULL; |
1590 | *slot_cur = sl; |
1591 | debug("%s - exit\n" , __func__); |
1592 | return 0; |
1593 | } |
1594 | |
1595 | /* |
1596 | * add a new bus resulting from hot-plugging a PPB bridge with devices |
1597 | * |
1598 | * Input: bus and the amount of resources needed (we know we can assign those, |
1599 | * since they've been checked already |
1600 | * Output: bus added to the correct spot |
1601 | * 0, -1, error |
1602 | */ |
1603 | static int add_new_bus(struct bus_node *bus, struct resource_node *io, struct resource_node *mem, struct resource_node *pfmem, u8 parent_busno) |
1604 | { |
1605 | struct range_node *io_range = NULL; |
1606 | struct range_node *mem_range = NULL; |
1607 | struct range_node *pfmem_range = NULL; |
1608 | struct bus_node *cur_bus = NULL; |
1609 | |
1610 | /* Trying to find the parent bus number */ |
1611 | if (parent_busno != 0xFF) { |
1612 | cur_bus = ibmphp_find_res_bus(parent_busno); |
1613 | if (!cur_bus) { |
1614 | err("strange, cannot find bus which is supposed to be at the system... something is terribly wrong...\n" ); |
1615 | return -ENODEV; |
1616 | } |
1617 | |
1618 | list_add(new: &bus->bus_list, head: &cur_bus->bus_list); |
1619 | } |
1620 | if (io) { |
1621 | io_range = kzalloc(size: sizeof(*io_range), GFP_KERNEL); |
1622 | if (!io_range) |
1623 | return -ENOMEM; |
1624 | |
1625 | io_range->start = io->start; |
1626 | io_range->end = io->end; |
1627 | io_range->rangeno = 1; |
1628 | bus->noIORanges = 1; |
1629 | bus->rangeIO = io_range; |
1630 | } |
1631 | if (mem) { |
1632 | mem_range = kzalloc(size: sizeof(*mem_range), GFP_KERNEL); |
1633 | if (!mem_range) |
1634 | return -ENOMEM; |
1635 | |
1636 | mem_range->start = mem->start; |
1637 | mem_range->end = mem->end; |
1638 | mem_range->rangeno = 1; |
1639 | bus->noMemRanges = 1; |
1640 | bus->rangeMem = mem_range; |
1641 | } |
1642 | if (pfmem) { |
1643 | pfmem_range = kzalloc(size: sizeof(*pfmem_range), GFP_KERNEL); |
1644 | if (!pfmem_range) |
1645 | return -ENOMEM; |
1646 | |
1647 | pfmem_range->start = pfmem->start; |
1648 | pfmem_range->end = pfmem->end; |
1649 | pfmem_range->rangeno = 1; |
1650 | bus->noPFMemRanges = 1; |
1651 | bus->rangePFMem = pfmem_range; |
1652 | } |
1653 | return 0; |
1654 | } |
1655 | |
1656 | /* |
1657 | * find the 1st available bus number for PPB to set as its secondary bus |
1658 | * Parameters: bus_number of the primary bus |
1659 | * Returns: bus_number of the secondary bus or 0xff in case of failure |
1660 | */ |
1661 | static u8 find_sec_number(u8 primary_busno, u8 slotno) |
1662 | { |
1663 | int min, max; |
1664 | u8 busno; |
1665 | struct bus_info *bus; |
1666 | struct bus_node *bus_cur; |
1667 | |
1668 | bus = ibmphp_find_same_bus_num(primary_busno); |
1669 | if (!bus) { |
1670 | err("cannot get slot range of the bus from the BIOS\n" ); |
1671 | return 0xff; |
1672 | } |
1673 | max = bus->slot_max; |
1674 | min = bus->slot_min; |
1675 | if ((slotno > max) || (slotno < min)) { |
1676 | err("got the wrong range\n" ); |
1677 | return 0xff; |
1678 | } |
1679 | busno = (u8) (slotno - (u8) min); |
1680 | busno += primary_busno + 0x01; |
1681 | bus_cur = ibmphp_find_res_bus(busno); |
1682 | /* either there is no such bus number, or there are no ranges, which |
1683 | * can only happen if we removed the bridged device in previous load |
1684 | * of the driver, and now only have the skeleton bus struct |
1685 | */ |
1686 | if ((!bus_cur) || (!(bus_cur->rangeIO) && !(bus_cur->rangeMem) && !(bus_cur->rangePFMem))) |
1687 | return busno; |
1688 | return 0xff; |
1689 | } |
1690 | |