Lines Matching +full:motherboard +full:- +full:bus
1 // SPDX-License-Identifier: GPL-2.0
3 * Low-level direct PCI config space access via ECAM - common code between
4 * i386 and x86-64.
7 * - known chipset handling
8 * - ACPI decoding and validation
10 * Per-architecture code takes care of the mappings and accesses
39 if (cfg->res.parent) in pci_mmconfig_remove()
40 release_resource(&cfg->res); in pci_mmconfig_remove()
41 list_del(&cfg->list); in pci_mmconfig_remove()
58 /* keep list sorted by segment and starting bus number */ in list_add_sorted()
60 if (cfg->segment > new->segment || in list_add_sorted()
61 (cfg->segment == new->segment && in list_add_sorted()
62 cfg->start_bus >= new->start_bus)) { in list_add_sorted()
63 list_add_tail_rcu(&new->list, &cfg->list); in list_add_sorted()
67 list_add_tail_rcu(&new->list, &pci_mmcfg_list); in list_add_sorted()
83 new->address = addr; in pci_mmconfig_alloc()
84 new->segment = segment; in pci_mmconfig_alloc()
85 new->start_bus = start; in pci_mmconfig_alloc()
86 new->end_bus = end; in pci_mmconfig_alloc()
88 res = &new->res; in pci_mmconfig_alloc()
89 res->start = addr + PCI_MMCFG_BUS_OFFSET(start); in pci_mmconfig_alloc()
90 res->end = addr + PCI_MMCFG_BUS_OFFSET(end + 1) - 1; in pci_mmconfig_alloc()
91 res->flags = IORESOURCE_MEM | IORESOURCE_BUSY; in pci_mmconfig_alloc()
92 snprintf(new->name, PCI_MMCFG_RESOURCE_NAME_LEN, in pci_mmconfig_alloc()
93 "PCI ECAM %04x [bus %02x-%02x]", segment, start, end); in pci_mmconfig_alloc()
94 res->name = new->name; in pci_mmconfig_alloc()
112 pr_info("ECAM %pR (base %#lx) for domain %04x [bus %02x-%02x]\n", in pci_mmconfig_add()
113 &new->res, (unsigned long)addr, segment, start, end); in pci_mmconfig_add()
118 struct pci_mmcfg_region *pci_mmconfig_lookup(int segment, int bus) in pci_mmconfig_lookup() argument
123 if (cfg->segment == segment && in pci_mmconfig_lookup()
124 cfg->start_bus <= bus && bus <= cfg->end_bus) in pci_mmconfig_lookup()
133 raw_pci_ops->read(0, 0, PCI_DEVFN(0, 0), 0xce, 2, &win); in pci_mmcfg_e7520()
149 raw_pci_ops->read(0, 0, PCI_DEVFN(0, 0), 0x48, 4, &pciexbar); in pci_mmcfg_intel_945()
183 if (pci_mmconfig_add(0, 0, (len >> 20) - 1, pciexbar & mask) == NULL) in pci_mmcfg_intel_945()
217 * only handle bus 0 ? in pci_mmcfg_amd_fam10h()
224 segnbits = busnbits - 8; in pci_mmcfg_amd_fam10h()
228 end_bus = (1 << busnbits) - 1; in pci_mmcfg_amd_fam10h()
242 int bus; in pci_mmcfg_nvidia_mcp55() local
267 for (bus = 0; bus < 256; bus++) { in pci_mmcfg_nvidia_mcp55()
273 raw_pci_ops->read(0, bus, PCI_DEVFN(0, 0), 0, 4, &l); in pci_mmcfg_nvidia_mcp55()
280 raw_pci_ops->read(0, bus, PCI_DEVFN(0, 0), extcfg_regnum, in pci_mmcfg_nvidia_mcp55()
291 end = start + extcfg_sizebus[size_index] - 1; in pci_mmcfg_nvidia_mcp55()
304 u32 bus; member
330 if (cfg->end_bus < cfg->start_bus) in pci_mmcfg_check_end_bus_number()
331 cfg->end_bus = 255; in pci_mmcfg_check_end_bus_number()
334 if (cfg->list.next == &pci_mmcfg_list) in pci_mmcfg_check_end_bus_number()
337 cfgx = list_entry(cfg->list.next, typeof(*cfg), list); in pci_mmcfg_check_end_bus_number()
338 if (cfg->end_bus >= cfgx->start_bus) in pci_mmcfg_check_end_bus_number()
339 cfg->end_bus = cfgx->start_bus - 1; in pci_mmcfg_check_end_bus_number()
346 u32 bus, devfn; in pci_mmcfg_check_hostbridge() local
357 bus = pci_mmcfg_probes[i].bus; in pci_mmcfg_check_hostbridge()
359 raw_pci_ops->read(0, bus, devfn, 0, 4, &l); in pci_mmcfg_check_hostbridge()
384 if (res->type == ACPI_RESOURCE_TYPE_FIXED_MEMORY32) { in check_mcfg_resource()
386 &res->data.fixed_memory32; in check_mcfg_resource()
389 if ((mcfg_res->start >= fixmem32->address) && in check_mcfg_resource()
390 (mcfg_res->end < (fixmem32->address + in check_mcfg_resource()
391 fixmem32->address_length))) { in check_mcfg_resource()
392 mcfg_res->flags = 1; in check_mcfg_resource()
396 if ((res->type != ACPI_RESOURCE_TYPE_ADDRESS32) && in check_mcfg_resource()
397 (res->type != ACPI_RESOURCE_TYPE_ADDRESS64)) in check_mcfg_resource()
406 if ((mcfg_res->start >= address.address.minimum) && in check_mcfg_resource()
407 (mcfg_res->end < (address.address.minimum + address.address.address_length))) { in check_mcfg_resource()
408 mcfg_res->flags = 1; in check_mcfg_resource()
422 if (mcfg_res->flags) in find_mboard_resource()
433 mcfg_res.end = end - 1; in is_acpi_reserved()
448 u64 start = res->start; in is_efi_mmio()
449 u64 end = res->start + resource_size(res); in is_efi_mmio()
454 if (md->type == EFI_MEMORY_MAPPED_IO) { in is_efi_mmio()
455 size = md->num_pages << EFI_PAGE_SHIFT; in is_efi_mmio()
456 mmio_start = md->phys_addr; in is_efi_mmio()
474 u64 addr = cfg->res.start; in is_mmconf_reserved()
475 u64 size = resource_size(&cfg->res); in is_mmconf_reserved()
490 &cfg->res, method); in is_mmconf_reserved()
492 pr_info("ECAM %pR reserved as %s\n", &cfg->res, method); in is_mmconf_reserved()
496 cfg->end_bus = cfg->start_bus + ((size>>20) - 1); in is_mmconf_reserved()
497 num_buses = cfg->end_bus - cfg->start_bus + 1; in is_mmconf_reserved()
498 cfg->res.end = cfg->res.start + in is_mmconf_reserved()
499 PCI_MMCFG_BUS_OFFSET(num_buses) - 1; in is_mmconf_reserved()
500 snprintf(cfg->name, PCI_MMCFG_RESOURCE_NAME_LEN, in is_mmconf_reserved()
501 "PCI ECAM %04x [bus %02x-%02x]", in is_mmconf_reserved()
502 cfg->segment, cfg->start_bus, cfg->end_bus); in is_mmconf_reserved()
506 &cfg->res, (unsigned long) cfg->address); in is_mmconf_reserved()
508 pr_info("ECAM %pR (base %#lx) for %04x [bus%02x-%02x] (size reduced!)\n", in is_mmconf_reserved()
509 &cfg->res, (unsigned long) cfg->address, in is_mmconf_reserved()
510 cfg->segment, cfg->start_bus, cfg->end_bus); in is_mmconf_reserved()
550 "ACPI motherboard resource")) in pci_mmcfg_reserved()
554 dev_info(dev, FW_INFO "ECAM %pR not reserved in ACPI motherboard resources\n", in pci_mmcfg_reserved()
555 &cfg->res); in pci_mmcfg_reserved()
557 pr_info(FW_INFO "ECAM %pR not reserved in ACPI motherboard resources\n", in pci_mmcfg_reserved()
558 &cfg->res); in pci_mmcfg_reserved()
560 if (is_efi_mmio(&cfg->res)) { in pci_mmcfg_reserved()
562 &cfg->res); in pci_mmcfg_reserved()
564 &cfg->res); in pci_mmcfg_reserved()
567 &cfg->res, conflict->name, conflict); in pci_mmcfg_reserved()
569 pr_info("ECAM %pR reserved to work around lack of ACPI motherboard _CRS\n", in pci_mmcfg_reserved()
570 &cfg->res); in pci_mmcfg_reserved()
591 &cfg->res); in pci_mmcfg_reject_broken()
601 if (cfg->address < 0xFFFFFFFF) in acpi_mcfg_valid_entry()
604 if (!strncmp(mcfg->header.oem_id, "SGI", 3)) in acpi_mcfg_valid_entry()
607 if ((mcfg->header.revision >= 1) && (dmi_get_bios_year() >= 2010)) in acpi_mcfg_valid_entry()
610 pr_err("ECAM at %#llx for %04x [bus %02x-%02x] is above 4GB, ignored\n", in acpi_mcfg_valid_entry()
611 cfg->address, cfg->pci_segment, cfg->start_bus_number, in acpi_mcfg_valid_entry()
612 cfg->end_bus_number); in acpi_mcfg_valid_entry()
624 return -EINVAL; in pci_parse_mcfg()
631 i = header->length - sizeof(struct acpi_table_mcfg); in pci_parse_mcfg()
634 i -= sizeof(struct acpi_mcfg_allocation); in pci_parse_mcfg()
638 return -ENODEV; in pci_parse_mcfg()
646 return -ENODEV; in pci_parse_mcfg()
649 if (pci_mmconfig_add(cfg->pci_segment, cfg->start_bus_number, in pci_parse_mcfg()
650 cfg->end_bus_number, cfg->address) == NULL) { in pci_parse_mcfg()
653 return -ENOMEM; in pci_parse_mcfg()
674 rc = func(cfg->res.start, resource_size(&cfg->res), data); in pci_mmcfg_for_each_region()
698 if (cfg->segment) in __pci_mmcfg_init()
700 pcibios_last_bus = cfg->end_bus; in __pci_mmcfg_init()
765 if (!cfg->res.parent) { in pci_mmcfg_late_insert_resources()
766 pr_debug("%s() insert %pR\n", __func__, &cfg->res); in pci_mmcfg_late_insert_resources()
767 insert_resource(&iomem_resource, &cfg->res); in pci_mmcfg_late_insert_resources()
789 dev_dbg(dev, "%s(%04x [bus %02x-%02x])\n", __func__, seg, start, end); in pci_mmconfig_insert()
792 return -ENODEV; in pci_mmconfig_insert()
795 return -EINVAL; in pci_mmconfig_insert()
800 if (cfg->end_bus < end) in pci_mmconfig_insert()
801 …dev_info(dev, FW_INFO "ECAM %pR for domain %04x [bus %02x-%02x] only partially covers this bridge\… in pci_mmconfig_insert()
802 &cfg->res, cfg->segment, cfg->start_bus, in pci_mmconfig_insert()
803 cfg->end_bus); in pci_mmconfig_insert()
805 return -EEXIST; in pci_mmconfig_insert()
809 * Don't move earlier; we must return -EEXIST, not -EINVAL, if in pci_mmconfig_insert()
814 return -EINVAL; in pci_mmconfig_insert()
817 rc = -EBUSY; in pci_mmconfig_insert()
821 rc = -ENOMEM; in pci_mmconfig_insert()
824 &cfg->res); in pci_mmconfig_insert()
829 &cfg->res); in pci_mmconfig_insert()
833 &cfg->res, tmp->name, tmp); in pci_mmconfig_insert()
835 dev_warn(dev, "fail to map ECAM %pR\n", &cfg->res); in pci_mmconfig_insert()
839 &cfg->res, (unsigned long)addr); in pci_mmconfig_insert()
846 if (cfg->res.parent) in pci_mmconfig_insert()
847 release_resource(&cfg->res); in pci_mmconfig_insert()
863 if (cfg->segment == seg && cfg->start_bus == start && in pci_mmconfig_delete()
864 cfg->end_bus == end) { in pci_mmconfig_delete()
865 list_del_rcu(&cfg->list); in pci_mmconfig_delete()
868 if (cfg->res.parent) in pci_mmconfig_delete()
869 release_resource(&cfg->res); in pci_mmconfig_delete()
876 return -ENOENT; in pci_mmconfig_delete()