aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTomasz Nowicki <tn@semihalf.com>2015-11-09 17:26:49 +0100
committerTomasz Nowicki <tn@semihalf.com>2016-01-22 12:18:44 +0100
commit83502f5839e4b38680295aa28645edba46f4cb0d (patch)
tree66915eaff9b932c4c32d4dd6412f6427ee178197
parent8e5cdd51d145b4bcfb4e4d410cfa990bc9007f9d (diff)
downloadleg-kernel-83502f5839e4b38680295aa28645edba46f4cb0d.tar.gz
acpi, mcfg: Add default PCI config accessors implementation and initial support for related quirks.
We use generic accessors from access.c by default. However, we already know platforms that need special handling while accessing to PCI config space. These platforms will need different accessors set matched against platform ID, domain, bus touple. Therefore we are going to add (in future) DECLARE_ACPI_MCFG_FIXUP which will register platform specific custom accessors. For now we let pci_mcfg_get_ops takes domain and bus arguments and left some space for matching algorithm. Signed-off-by: Tomasz Nowicki <tn@semihalf.com>
-rw-r--r--drivers/acpi/mcfg.c30
-rw-r--r--include/linux/pci-acpi.h8
2 files changed, 38 insertions, 0 deletions
diff --git a/drivers/acpi/mcfg.c b/drivers/acpi/mcfg.c
index dca4c4e0fcd3..dfc2d145e303 100644
--- a/drivers/acpi/mcfg.c
+++ b/drivers/acpi/mcfg.c
@@ -34,6 +34,36 @@ int __weak raw_pci_write(unsigned int domain, unsigned int bus,
return PCIBIOS_DEVICE_NOT_FOUND;
}
+void __iomem *
+pci_mcfg_dev_base(struct pci_bus *bus, unsigned int devfn, int offset)
+{
+ struct pci_mmcfg_region *cfg;
+
+ cfg = pci_mmconfig_lookup(pci_domain_nr(bus), bus->number);
+ if (cfg && cfg->virt)
+ return cfg->virt +
+ (PCI_MMCFG_BUS_OFFSET(bus->number) | (devfn << 12)) +
+ offset;
+ return NULL;
+}
+
+/* Default generic PCI config accessors */
+static struct pci_ops default_pci_mcfg_ops = {
+ .map_bus = pci_mcfg_dev_base,
+ .read = pci_generic_config_read,
+ .write = pci_generic_config_write,
+};
+
+struct pci_ops *pci_mcfg_get_ops(struct acpi_pci_root *root)
+{
+ /*
+ * TODO: Match against platform specific quirks and return
+ * corresponding PCI config space accessor set.
+ */
+
+ return &default_pci_mcfg_ops;
+}
+
int __init acpi_parse_mcfg(struct acpi_table_header *header)
{
struct acpi_table_mcfg *mcfg;
diff --git a/include/linux/pci-acpi.h b/include/linux/pci-acpi.h
index c2774158d0e9..45807a690942 100644
--- a/include/linux/pci-acpi.h
+++ b/include/linux/pci-acpi.h
@@ -82,10 +82,18 @@ void acpi_pci_remove_bus(struct pci_bus *bus);
#ifdef CONFIG_PCI_MMCONFIG
int pci_mmcfg_setup_map(struct acpi_pci_root_info *ci);
void pci_mmcfg_teardown_map(struct acpi_pci_root_info *ci);
+struct pci_ops *pci_mcfg_get_ops(struct acpi_pci_root *root);
+void __iomem *
+pci_mcfg_dev_base(struct pci_bus *bus, unsigned int devfn, int offset);
#else
static inline int pci_mmcfg_setup_map(struct acpi_pci_root_info *ci)
{ return 0; }
static inline void pci_mmcfg_teardown_map(struct acpi_pci_root_info *ci) { }
+static inline struct pci_ops *pci_mcfg_get_ops(struct acpi_pci_root *root)
+{ return NULL; }
+static inline void __iomem *
+pci_mcfg_dev_base(struct pci_bus *bus, unsigned int devfn, int offset)
+{ return NULL; }
#endif
#ifdef CONFIG_ACPI_PCI_SLOT