]> git.proxmox.com Git - mirror_ubuntu-zesty-kernel.git/blob - drivers/acpi/pci_mcfg.c
watchdog: wdat_wdt: Ping the watchdog on resume
[mirror_ubuntu-zesty-kernel.git] / drivers / acpi / pci_mcfg.c
1 /*
2 * Copyright (C) 2016 Broadcom
3 * Author: Jayachandran C <jchandra@broadcom.com>
4 * Copyright (C) 2016 Semihalf
5 * Author: Tomasz Nowicki <tn@semihalf.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License, version 2, as
9 * published by the Free Software Foundation (the "GPL").
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License version 2 (GPLv2) for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * version 2 (GPLv2) along with this source code.
18 */
19
20 #define pr_fmt(fmt) "ACPI: " fmt
21
22 #include <linux/kernel.h>
23 #include <linux/pci.h>
24 #include <linux/pci-acpi.h>
25
26 /* Structure to hold entries from the MCFG table */
27 struct mcfg_entry {
28 struct list_head list;
29 phys_addr_t addr;
30 u16 segment;
31 u8 bus_start;
32 u8 bus_end;
33 };
34
35 /* List to save MCFG entries */
36 static LIST_HEAD(pci_mcfg_list);
37
38 phys_addr_t pci_mcfg_lookup(u16 seg, struct resource *bus_res)
39 {
40 struct mcfg_entry *e;
41
42 /*
43 * We expect exact match, unless MCFG entry end bus covers more than
44 * specified by caller.
45 */
46 list_for_each_entry(e, &pci_mcfg_list, list) {
47 if (e->segment == seg && e->bus_start == bus_res->start &&
48 e->bus_end >= bus_res->end)
49 return e->addr;
50 }
51
52 return 0;
53 }
54
55 static __init int pci_mcfg_parse(struct acpi_table_header *header)
56 {
57 struct acpi_table_mcfg *mcfg;
58 struct acpi_mcfg_allocation *mptr;
59 struct mcfg_entry *e, *arr;
60 int i, n;
61
62 if (header->length < sizeof(struct acpi_table_mcfg))
63 return -EINVAL;
64
65 n = (header->length - sizeof(struct acpi_table_mcfg)) /
66 sizeof(struct acpi_mcfg_allocation);
67 mcfg = (struct acpi_table_mcfg *)header;
68 mptr = (struct acpi_mcfg_allocation *) &mcfg[1];
69
70 arr = kcalloc(n, sizeof(*arr), GFP_KERNEL);
71 if (!arr)
72 return -ENOMEM;
73
74 for (i = 0, e = arr; i < n; i++, mptr++, e++) {
75 e->segment = mptr->pci_segment;
76 e->addr = mptr->address;
77 e->bus_start = mptr->start_bus_number;
78 e->bus_end = mptr->end_bus_number;
79 list_add(&e->list, &pci_mcfg_list);
80 }
81
82 pr_info("MCFG table detected, %d entries\n", n);
83 return 0;
84 }
85
86 /* Interface called by ACPI - parse and save MCFG table */
87 void __init pci_mmcfg_late_init(void)
88 {
89 int err = acpi_table_parse(ACPI_SIG_MCFG, pci_mcfg_parse);
90 if (err)
91 pr_err("Failed to parse MCFG (%d)\n", err);
92 }