--- zzzz-none-000/linux-3.10.107/arch/ia64/pci/pci.c 2017-06-27 09:49:32.000000000 +0000 +++ scorpion-7490-727/linux-3.10.107/arch/ia64/pci/pci.c 2021-02-04 17:41:59.000000000 +0000 @@ -115,30 +115,13 @@ .write = pci_write, }; -/* Called by ACPI when it finds a new root bus. */ - -static struct pci_controller *alloc_pci_controller(int seg) -{ - struct pci_controller *controller; - - controller = kzalloc(sizeof(*controller), GFP_KERNEL); - if (!controller) - return NULL; - - controller->segment = seg; - controller->node = -1; - return controller; -} - struct pci_root_info { - struct acpi_device *bridge; - struct pci_controller *controller; - struct list_head resources; - char *name; + struct acpi_pci_root_info common; + struct pci_controller controller; + struct list_head io_resources; }; -static unsigned int -new_space (u64 phys_base, int sparse) +static unsigned int new_space(u64 phys_base, int sparse) { u64 mmio_base; int i; @@ -153,7 +136,7 @@ return i; if (num_io_spaces == MAX_IO_SPACES) { - printk(KERN_ERR "PCI: Too many IO port spaces " + pr_err("PCI: Too many IO port spaces " "(MAX_IO_SPACES=%lu)\n", MAX_IO_SPACES); return ~0; } @@ -165,42 +148,36 @@ return i; } -static u64 add_io_space(struct pci_root_info *info, - struct acpi_resource_address64 *addr) +static int add_io_space(struct device *dev, struct pci_root_info *info, + struct resource_entry *entry) { - struct resource *resource; + struct resource_entry *iospace; + struct resource *resource, *res = entry->res; char *name; unsigned long base, min, max, base_port; unsigned int sparse = 0, space_nr, len; - resource = kzalloc(sizeof(*resource), GFP_KERNEL); - if (!resource) { - printk(KERN_ERR "PCI: No memory for %s I/O port space\n", - info->name); - goto out; + len = strlen(info->common.name) + 32; + iospace = resource_list_create_entry(NULL, len); + if (!iospace) { + dev_err(dev, "PCI: No memory for %s I/O port space\n", + info->common.name); + return -ENOMEM; } - len = strlen(info->name) + 32; - name = kzalloc(len, GFP_KERNEL); - if (!name) { - printk(KERN_ERR "PCI: No memory for %s I/O port space name\n", - info->name); - goto free_resource; - } - - min = addr->minimum; - max = min + addr->address_length - 1; - if (addr->info.io.translation_type == ACPI_SPARSE_TRANSLATION) + if (res->flags & IORESOURCE_IO_SPARSE) sparse = 1; - - space_nr = new_space(addr->translation_offset, sparse); + space_nr = new_space(entry->offset, sparse); if (space_nr == ~0) - goto free_name; + goto free_resource; + name = (char *)(iospace + 1); + min = res->start - entry->offset; + max = res->end - entry->offset; base = __pa(io_space[space_nr].mmio_base); base_port = IO_SPACE_BASE(space_nr); - snprintf(name, len, "%s I/O Ports %08lx-%08lx", info->name, - base_port + min, base_port + max); + snprintf(name, len, "%s I/O Ports %08lx-%08lx", info->common.name, + base_port + min, base_port + max); /* * The SDM guarantees the legacy 0-64K space is sparse, but if the @@ -210,237 +187,175 @@ if (space_nr == 0) sparse = 1; + resource = iospace->res; resource->name = name; resource->flags = IORESOURCE_MEM; resource->start = base + (sparse ? IO_SPACE_SPARSE_ENCODING(min) : min); resource->end = base + (sparse ? IO_SPACE_SPARSE_ENCODING(max) : max); - insert_resource(&iomem_resource, resource); + if (insert_resource(&iomem_resource, resource)) { + dev_err(dev, + "can't allocate host bridge io space resource %pR\n", + resource); + goto free_resource; + } - return base_port; + entry->offset = base_port; + res->start = min + base_port; + res->end = max + base_port; + resource_list_add_tail(iospace, &info->io_resources); + + return 0; -free_name: - kfree(name); free_resource: - kfree(resource); -out: - return ~0; + resource_list_free_entry(iospace); + return -ENOSPC; } -static acpi_status resource_to_window(struct acpi_resource *resource, - struct acpi_resource_address64 *addr) +/* + * An IO port or MMIO resource assigned to a PCI host bridge may be + * consumed by the host bridge itself or available to its child + * bus/devices. The ACPI specification defines a bit (Producer/Consumer) + * to tell whether the resource is consumed by the host bridge itself, + * but firmware hasn't used that bit consistently, so we can't rely on it. + * + * On x86 and IA64 platforms, all IO port and MMIO resources are assumed + * to be available to child bus/devices except one special case: + * IO port [0xCF8-0xCFF] is consumed by the host bridge itself + * to access PCI configuration space. + * + * So explicitly filter out PCI CFG IO ports[0xCF8-0xCFF]. + */ +static bool resource_is_pcicfg_ioport(struct resource *res) { - acpi_status status; - - /* - * We're only interested in _CRS descriptors that are - * - address space descriptors for memory or I/O space - * - non-zero size - * - producers, i.e., the address space is routed downstream, - * not consumed by the bridge itself - */ - status = acpi_resource_to_address64(resource, addr); - if (ACPI_SUCCESS(status) && - (addr->resource_type == ACPI_MEMORY_RANGE || - addr->resource_type == ACPI_IO_RANGE) && - addr->address_length && - addr->producer_consumer == ACPI_PRODUCER) - return AE_OK; - - return AE_ERROR; -} - -static acpi_status count_window(struct acpi_resource *resource, void *data) -{ - unsigned int *windows = (unsigned int *) data; - struct acpi_resource_address64 addr; - acpi_status status; - - status = resource_to_window(resource, &addr); - if (ACPI_SUCCESS(status)) - (*windows)++; - - return AE_OK; -} - -static acpi_status add_window(struct acpi_resource *res, void *data) -{ - struct pci_root_info *info = data; - struct pci_window *window; - struct acpi_resource_address64 addr; - acpi_status status; - unsigned long flags, offset = 0; - struct resource *root; - - /* Return AE_OK for non-window resources to keep scanning for more */ - status = resource_to_window(res, &addr); - if (!ACPI_SUCCESS(status)) - return AE_OK; - - if (addr.resource_type == ACPI_MEMORY_RANGE) { - flags = IORESOURCE_MEM; - root = &iomem_resource; - offset = addr.translation_offset; - } else if (addr.resource_type == ACPI_IO_RANGE) { - flags = IORESOURCE_IO; - root = &ioport_resource; - offset = add_io_space(info, &addr); - if (offset == ~0) - return AE_OK; - } else - return AE_OK; - - window = &info->controller->window[info->controller->windows++]; - window->resource.name = info->name; - window->resource.flags = flags; - window->resource.start = addr.minimum + offset; - window->resource.end = window->resource.start + addr.address_length - 1; - window->offset = offset; - - if (insert_resource(root, &window->resource)) { - dev_err(&info->bridge->dev, - "can't allocate host bridge window %pR\n", - &window->resource); - } else { - if (offset) - dev_info(&info->bridge->dev, "host bridge window %pR " - "(PCI address [%#llx-%#llx])\n", - &window->resource, - window->resource.start - offset, - window->resource.end - offset); - else - dev_info(&info->bridge->dev, - "host bridge window %pR\n", - &window->resource); - } - - /* HP's firmware has a hack to work around a Windows bug. - * Ignore these tiny memory ranges */ - if (!((window->resource.flags & IORESOURCE_MEM) && - (window->resource.end - window->resource.start < 16))) - pci_add_resource_offset(&info->resources, &window->resource, - window->offset); - - return AE_OK; + return (res->flags & IORESOURCE_IO) && + res->start == 0xCF8 && res->end == 0xCFF; } +static int pci_acpi_root_prepare_resources(struct acpi_pci_root_info *ci) +{ + struct device *dev = &ci->bridge->dev; + struct pci_root_info *info; + struct resource *res; + struct resource_entry *entry, *tmp; + int status; + + status = acpi_pci_probe_root_resources(ci); + if (status > 0) { + info = container_of(ci, struct pci_root_info, common); + resource_list_for_each_entry_safe(entry, tmp, &ci->resources) { + res = entry->res; + if (res->flags & IORESOURCE_MEM) { + /* + * HP's firmware has a hack to work around a + * Windows bug. Ignore these tiny memory ranges. + */ + if (resource_size(res) <= 16) { + resource_list_del(entry); + insert_resource(&iomem_resource, + entry->res); + resource_list_add_tail(entry, + &info->io_resources); + } + } else if (res->flags & IORESOURCE_IO) { + if (resource_is_pcicfg_ioport(entry->res)) + resource_list_destroy_entry(entry); + else if (add_io_space(dev, info, entry)) + resource_list_destroy_entry(entry); + } + } + } + + return status; +} + +static void pci_acpi_root_release_info(struct acpi_pci_root_info *ci) +{ + struct pci_root_info *info; + struct resource_entry *entry, *tmp; + + info = container_of(ci, struct pci_root_info, common); + resource_list_for_each_entry_safe(entry, tmp, &info->io_resources) { + release_resource(entry->res); + resource_list_destroy_entry(entry); + } + kfree(info); +} + +static struct acpi_pci_root_ops pci_acpi_root_ops = { + .pci_ops = &pci_root_ops, + .release_info = pci_acpi_root_release_info, + .prepare_resources = pci_acpi_root_prepare_resources, +}; + struct pci_bus *pci_acpi_scan_root(struct acpi_pci_root *root) { struct acpi_device *device = root->device; - int domain = root->segment; - int bus = root->secondary.start; - struct pci_controller *controller; - unsigned int windows = 0; - struct pci_root_info info; - struct pci_bus *pbus; - char *name; - int pxm; + struct pci_root_info *info; - controller = alloc_pci_controller(domain); - if (!controller) - goto out1; - - controller->acpi_handle = device->handle; - - pxm = acpi_get_pxm(controller->acpi_handle); -#ifdef CONFIG_NUMA - if (pxm >= 0) - controller->node = pxm_to_node(pxm); -#endif - - INIT_LIST_HEAD(&info.resources); - /* insert busn resource at first */ - pci_add_resource(&info.resources, &root->secondary); - acpi_walk_resources(device->handle, METHOD_NAME__CRS, count_window, - &windows); - if (windows) { - controller->window = - kzalloc_node(sizeof(*controller->window) * windows, - GFP_KERNEL, controller->node); - if (!controller->window) - goto out2; - - name = kmalloc(16, GFP_KERNEL); - if (!name) - goto out3; - - sprintf(name, "PCI Bus %04x:%02x", domain, bus); - info.bridge = device; - info.controller = controller; - info.name = name; - acpi_walk_resources(device->handle, METHOD_NAME__CRS, - add_window, &info); - } - /* - * See arch/x86/pci/acpi.c. - * The desired pci bus might already be scanned in a quirk. We - * should handle the case here, but it appears that IA64 hasn't - * such quirk. So we just ignore the case now. - */ - pbus = pci_create_root_bus(NULL, bus, &pci_root_ops, controller, - &info.resources); - if (!pbus) { - pci_free_resource_list(&info.resources); + info = kzalloc(sizeof(*info), GFP_KERNEL); + if (!info) { + dev_err(&device->dev, + "pci_bus %04x:%02x: ignored (out of memory)\n", + root->segment, (int)root->secondary.start); return NULL; } - pci_scan_child_bus(pbus); - return pbus; - -out3: - kfree(controller->window); -out2: - kfree(controller); -out1: - return NULL; + info->controller.segment = root->segment; + info->controller.companion = device; + info->controller.node = acpi_get_node(device->handle); + INIT_LIST_HEAD(&info->io_resources); + return acpi_pci_root_create(root, &pci_acpi_root_ops, + &info->common, &info->controller); } int pcibios_root_bridge_prepare(struct pci_host_bridge *bridge) { - struct pci_controller *controller = bridge->bus->sysdata; - - ACPI_HANDLE_SET(&bridge->dev, controller->acpi_handle); + /* + * We pass NULL as parent to pci_create_root_bus(), so if it is not NULL + * here, pci_create_root_bus() has been called by someone else and + * sysdata is likely to be different from what we expect. Let it go in + * that case. + */ + if (!bridge->dev.parent) { + struct pci_controller *controller = bridge->bus->sysdata; + ACPI_COMPANION_SET(&bridge->dev, controller->companion); + } return 0; } -static int is_valid_resource(struct pci_dev *dev, int idx) +void pcibios_fixup_device_resources(struct pci_dev *dev) { - unsigned int i, type_mask = IORESOURCE_IO | IORESOURCE_MEM; - struct resource *devr = &dev->resource[idx], *busr; + int idx; if (!dev->bus) - return 0; + return; - pci_bus_for_each_resource(dev->bus, busr, i) { - if (!busr || ((busr->flags ^ devr->flags) & type_mask)) - continue; - if ((devr->start) && (devr->start >= busr->start) && - (devr->end <= busr->end)) - return 1; - } - return 0; -} + for (idx = 0; idx < PCI_BRIDGE_RESOURCES; idx++) { + struct resource *r = &dev->resource[idx]; -static void pcibios_fixup_resources(struct pci_dev *dev, int start, int limit) -{ - int i; - - for (i = start; i < limit; i++) { - if (!dev->resource[i].flags) + if (!r->flags || r->parent || !r->start) continue; - if ((is_valid_resource(dev, i))) - pci_claim_resource(dev, i); - } -} -void pcibios_fixup_device_resources(struct pci_dev *dev) -{ - pcibios_fixup_resources(dev, 0, PCI_BRIDGE_RESOURCES); + pci_claim_resource(dev, idx); + } } EXPORT_SYMBOL_GPL(pcibios_fixup_device_resources); static void pcibios_fixup_bridge_resources(struct pci_dev *dev) { - pcibios_fixup_resources(dev, PCI_BRIDGE_RESOURCES, PCI_NUM_RESOURCES); + int idx; + + if (!dev->bus) + return; + + for (idx = PCI_BRIDGE_RESOURCES; idx < PCI_NUM_RESOURCES; idx++) { + struct resource *r = &dev->resource[idx]; + + if (!r->flags || r->parent || !r->start) + continue; + + pci_claim_bridge_resource(dev, idx); + } } /* @@ -691,7 +606,7 @@ status = ia64_pal_cache_summary(&levels, &unique_caches); if (status != 0) { - printk(KERN_ERR "%s: ia64_pal_cache_summary() failed " + pr_err("%s: ia64_pal_cache_summary() failed " "(status=%ld)\n", __func__, status); return; } @@ -699,7 +614,7 @@ status = ia64_pal_cache_config_info(levels - 1, /* cache_type (data_or_unified)= */ 2, &cci); if (status != 0) { - printk(KERN_ERR "%s: ia64_pal_cache_config_info() failed " + pr_err("%s: ia64_pal_cache_config_info() failed " "(status=%ld)\n", __func__, status); return; }