--- zzzz-none-000/linux-3.10.107/arch/mips/pci/pci.c 2017-06-27 09:49:32.000000000 +0000 +++ scorpion-7490-727/linux-3.10.107/arch/mips/pci/pci.c 2021-02-04 17:41:59.000000000 +0000 @@ -76,9 +76,10 @@ return start; } +static int next_busno; + static void pcibios_scanbus(struct pci_controller *hose) { - static int next_busno; static int need_domain_info; LIST_HEAD(resources); struct pci_bus *bus; @@ -91,81 +92,79 @@ pci_add_resource_offset(&resources, hose->mem_resource, hose->mem_offset); - pci_add_resource_offset(&resources, hose->io_resource, hose->io_offset); + pci_add_resource_offset(&resources, + hose->io_resource, hose->io_offset); + pci_add_resource_offset(&resources, + hose->busn_resource, hose->busn_offset); bus = pci_scan_root_bus(NULL, next_busno, hose->pci_ops, hose, &resources); - if (!bus) - pci_free_resource_list(&resources); - hose->bus = bus; need_domain_info = need_domain_info || hose->index; hose->need_domain_info = need_domain_info; - if (bus) { - next_busno = bus->busn_res.end + 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_has_flag(PCI_PROBE_ONLY)) { - pci_bus_size_bridges(bus); - pci_bus_assign_resources(bus); - pci_enable_bridges(bus); - } + if (!bus) { + pci_free_resource_list(&resources); + return; } + + next_busno = bus->busn_res.end + 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_has_flag(PCI_PROBE_ONLY)) { + pci_bus_size_bridges(bus); + pci_bus_assign_resources(bus); + } + + pci_fixup_irqs(pci_common_swizzle, pcibios_map_irq); + + pci_bus_add_devices(bus); +} + +void pcibios_reset_busno(void) +{ + next_busno = 0; } #ifdef CONFIG_OF void pci_load_of_ranges(struct pci_controller *hose, struct device_node *node) { - const __be32 *ranges; - int rlen; - int pna = of_n_addr_cells(node); - int np = pna + 5; + struct of_pci_range range; + struct of_pci_range_parser parser; pr_info("PCI host bridge %s ranges:\n", node->full_name); - ranges = of_get_property(node, "ranges", &rlen); - if (ranges == NULL) - return; hose->of_node = node; - while ((rlen -= np * 4) >= 0) { - u32 pci_space; + if (of_pci_range_parser_init(&parser, node)) + return; + + for_each_of_pci_range(&parser, &range) { struct resource *res = NULL; - u64 addr, size; - pci_space = be32_to_cpup(&ranges[0]); - addr = of_translate_address(node, ranges + 3); - size = of_read_number(ranges + pna + 3, 2); - ranges += np; - switch ((pci_space >> 24) & 0x3) { - case 1: /* PCI IO space */ + switch (range.flags & IORESOURCE_TYPE_BITS) { + case IORESOURCE_IO: pr_info(" IO 0x%016llx..0x%016llx\n", - addr, addr + size - 1); + range.cpu_addr, + range.cpu_addr + range.size - 1); hose->io_map_base = - (unsigned long)ioremap(addr, size); + (unsigned long)ioremap(range.cpu_addr, + range.size); res = hose->io_resource; - res->flags = IORESOURCE_IO; break; - case 2: /* PCI Memory space */ - case 3: /* PCI 64 bits Memory space */ + case IORESOURCE_MEM: pr_info(" MEM 0x%016llx..0x%016llx\n", - addr, addr + size - 1); + range.cpu_addr, + range.cpu_addr + range.size - 1); res = hose->mem_resource; - res->flags = IORESOURCE_MEM; break; } - if (res != NULL) { - res->start = addr; - res->name = node->full_name; - res->end = res->start + size - 1; - res->parent = NULL; - res->sibling = NULL; - res->child = NULL; - } + if (res != NULL) + of_pci_range_to_resource(&range, node, res); } } @@ -227,6 +226,70 @@ "Skipping PCI bus scan due to resource conflict\n"); } +void unregister_pci_controller(struct pci_controller *hose) +{ + struct pci_controller **head; + + if (hose->bus) { + struct pci_dev *d, *tmp; + + list_for_each_entry_safe(d, tmp, &hose->bus->devices, bus_list) { + pci_stop_and_remove_bus_device(d); + } + device_unregister(hose->bus->bridge); + /* pci_remove_bus() causes + * 1906-10:42:59 [ 34.420278] pci_bus 0000:00: busn_res: [bus 00] is released + * 1906-10:42:59 [ 34.420292] ------------[ cut here ]------------ + * 1906-10:42:59 [ 34.420329] WARNING: CPU: 0 PID: 293 at fs/sysfs/group.c:237 0x80198898 sysfs_remove_group+0x60/0xb0() + * 1906-10:42:59 [ 34.420342] sysfs group 80501f30 not found for kobject '0000:00' + * 1906-10:42:59 [ 34.420352] Modules linked in: qca_ol qca_da ath_dev(P) ath_rate_atheros(P) ath_hal(P) umac ath_spectral(P) ath_dfs(P) qdf asf(P) mem_manager(P) aae(P) + * 1906-10:42:59 [ 34.420407] CPU: 0 PID: 293 Comm: kworker/0:2 Tainted: P 4.4.60 #21 + * 1906-10:42:59 [ 34.420434] Workqueue: events uga_pci_reset_work_func + * 1906-10:42:59 [ 34.420444] Stack : 804f0000 800a065c 00000000 00000000 80596a3a 00000046 00000001 852abc34 + * 1906-10:42:59 85d63cc0 8009c7b0 8044ee00 852abc6c 00001c3f 00000000 804a7ca4 804a0000 + * 1906-10:42:59 802ca2ac 814f7600 87c0bd80 6576656e 74730000 00000000 00000000 00000000 + * 1906-10:42:59 00000000 00000000 00000000 00000000 00000000 00000000 00000000 462af4b2 + * 1906-10:42:59 87597144 804edd03 8044ee00 800b4b24 80596a3a 8044ee00 00000000 00000125 + * 1906-10:42:59 ... + * 1906-10:42:59 [ 34.421376] Call Trace: + * 1906-10:42:59 [ 34.421395] 3c08: [<80073834>] 0x80073834 show_stack+0x50/0x84 + * 1906-10:42:59 [ 34.421417] 3cd8: [<801d6498>] 0x801d6498 dump_stack+0x20/0x2c + * 1906-10:42:59 [ 34.421441] 3cf0: [<80086c14>] 0x80086c14 warn_slowpath_common+0xa0/0xd0 + * 1906-10:42:59 [ 34.421462] 3d20: [<80086c70>] 0x80086c70 warn_slowpath_fmt+0x2c/0x38 + * 1906-10:42:59 [ 34.421490] 3d48: [<80198898>] 0x80198898 sysfs_remove_group+0x60/0xb0 + * 1906-10:42:59 [ 34.421518] 3d70: [<802743b0>] 0x802743b0 dpm_sysfs_remove+0x58/0x6c + * 1906-10:42:59 [ 34.421539] 3d90: [<80269794>] 0x80269794 device_del+0x54/0x218 + * 1906-10:42:59 [ 34.421558] 3dd0: [<8026996c>] 0x8026996c device_unregister+0x14/0x28 + * 1906-10:42:59 [ 34.421588] 3de8: [<80219314>] 0x80219314 pci_remove_bus+0x64/0x78 + * 1906-10:42:59 [ 34.421611] 3e08: [<802ca170>] 0x802ca170 ath_pci_down+0x128/0x1f0 + * 1906-10:42:59 [ 34.421631] 3e40: [<802ca2a0>] 0x802ca2a0 ath_pci_reset+0x10/0x1c + * 1906-10:42:59 [ 34.421660] 3e58: [<8009a410>] 0x8009a410 process_one_work+0x220/0x370 + * 1906-10:42:59 [ 34.421682] 3e98: [<8009b464>] 0x8009b464 worker_thread+0x31c/0x498 + * 1906-10:42:59 [ 34.421706] 3ed8: [<800a0134>] 0x800a0134 kthread+0xdc/0xe8 + * 1906-10:42:59 [ 34.421726] 3f28: [<800604a8>] 0x800604a8 ret_from_kernel_thread+0x10/0x18 + * 1906-10:42:59 [ 34.421737] + * 1906-10:42:59 [ 34.421747] ---[ end trace e30a0567eb722c84 ]--- + */ + pci_remove_bus(hose->bus); + } + + + /* Remove the controller from the hose */ + for (head = &hose_head; *head != NULL; head = &(*head)->next) { + if (*head == hose) { + *head = hose->next; + + // New end of list found, reset head_tail + if (*head == NULL) + hose_tail = head; + break; + } + } + + release_resource(hose->mem_resource); + release_resource(hose->io_resource); +} + static void __init pcibios_set_cache_line_size(void) { struct cpuinfo_mips *c = ¤t_cpu_data;