Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 #include <linux/init.h>
0003 #include <linux/pci.h>
0004 #include <linux/range.h>
0005 
0006 #include "bus_numa.h"
0007 
0008 LIST_HEAD(pci_root_infos);
0009 
0010 static struct pci_root_info *x86_find_pci_root_info(int bus)
0011 {
0012     struct pci_root_info *info;
0013 
0014     list_for_each_entry(info, &pci_root_infos, list)
0015         if (info->busn.start == bus)
0016             return info;
0017 
0018     return NULL;
0019 }
0020 
0021 int x86_pci_root_bus_node(int bus)
0022 {
0023     struct pci_root_info *info = x86_find_pci_root_info(bus);
0024 
0025     if (!info)
0026         return NUMA_NO_NODE;
0027 
0028     return info->node;
0029 }
0030 
0031 void x86_pci_root_bus_resources(int bus, struct list_head *resources)
0032 {
0033     struct pci_root_info *info = x86_find_pci_root_info(bus);
0034     struct pci_root_res *root_res;
0035     struct resource_entry *window;
0036     bool found = false;
0037 
0038     if (!info)
0039         goto default_resources;
0040 
0041     printk(KERN_DEBUG "PCI: root bus %02x: hardware-probed resources\n",
0042            bus);
0043 
0044     /* already added by acpi ? */
0045     resource_list_for_each_entry(window, resources)
0046         if (window->res->flags & IORESOURCE_BUS) {
0047             found = true;
0048             break;
0049         }
0050 
0051     if (!found)
0052         pci_add_resource(resources, &info->busn);
0053 
0054     list_for_each_entry(root_res, &info->resources, list)
0055         pci_add_resource(resources, &root_res->res);
0056 
0057     return;
0058 
0059 default_resources:
0060     /*
0061      * We don't have any host bridge aperture information from the
0062      * "native host bridge drivers," e.g., amd_bus or broadcom_bus,
0063      * so fall back to the defaults historically used by pci_create_bus().
0064      */
0065     printk(KERN_DEBUG "PCI: root bus %02x: using default resources\n", bus);
0066     pci_add_resource(resources, &ioport_resource);
0067     pci_add_resource(resources, &iomem_resource);
0068 }
0069 
0070 struct pci_root_info __init *alloc_pci_root_info(int bus_min, int bus_max,
0071                          int node, int link)
0072 {
0073     struct pci_root_info *info;
0074 
0075     info = kzalloc(sizeof(*info), GFP_KERNEL);
0076 
0077     if (!info)
0078         return info;
0079 
0080     sprintf(info->name, "PCI Bus #%02x", bus_min);
0081 
0082     INIT_LIST_HEAD(&info->resources);
0083     info->busn.name  = info->name;
0084     info->busn.start = bus_min;
0085     info->busn.end   = bus_max;
0086     info->busn.flags = IORESOURCE_BUS;
0087     info->node = node;
0088     info->link = link;
0089 
0090     list_add_tail(&info->list, &pci_root_infos);
0091 
0092     return info;
0093 }
0094 
0095 void update_res(struct pci_root_info *info, resource_size_t start,
0096         resource_size_t end, unsigned long flags, int merge)
0097 {
0098     struct resource *res;
0099     struct pci_root_res *root_res;
0100 
0101     if (start > end)
0102         return;
0103 
0104     if (start == MAX_RESOURCE)
0105         return;
0106 
0107     if (!merge)
0108         goto addit;
0109 
0110     /* try to merge it with old one */
0111     list_for_each_entry(root_res, &info->resources, list) {
0112         resource_size_t final_start, final_end;
0113         resource_size_t common_start, common_end;
0114 
0115         res = &root_res->res;
0116         if (res->flags != flags)
0117             continue;
0118 
0119         common_start = max(res->start, start);
0120         common_end = min(res->end, end);
0121         if (common_start > common_end + 1)
0122             continue;
0123 
0124         final_start = min(res->start, start);
0125         final_end = max(res->end, end);
0126 
0127         res->start = final_start;
0128         res->end = final_end;
0129         return;
0130     }
0131 
0132 addit:
0133 
0134     /* need to add that */
0135     root_res = kzalloc(sizeof(*root_res), GFP_KERNEL);
0136     if (!root_res)
0137         return;
0138 
0139     res = &root_res->res;
0140     res->name = info->name;
0141     res->flags = flags;
0142     res->start = start;
0143     res->end = end;
0144 
0145     list_add_tail(&root_res->list, &info->resources);
0146 }