summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThorsten Leemhuis <fedora@leemhuis.info>2016-07-26 10:40:00 +0200
committerThorsten Leemhuis <fedora@leemhuis.info>2016-07-26 10:40:00 +0200
commit68203a666a4e9a3565c2cfb04a83b92cdfff1d4d (patch)
tree8d5ec2c6b0e29c6e98adf8358d31b02367130084
parent6a5a3287e055bd6870da642d35a7fe31a03eeb13 (diff)
parent9ffde4b8e9a353ed0d3d3c846d298e272a5484f9 (diff)
downloadkernel-68203a666a4e9a3565c2cfb04a83b92cdfff1d4d.tar.gz
kernel-68203a666a4e9a3565c2cfb04a83b92cdfff1d4d.tar.xz
kernel-68203a666a4e9a3565c2cfb04a83b92cdfff1d4d.zip
Conflicts: kernel.spec
-rw-r--r--Makefile3
-rw-r--r--arm64-pcie-acpi.patch1247
-rw-r--r--arm64-pcie-quirks-xgene.patch508
-rw-r--r--audit-fix-a-double-fetch-in-audit_log_single_execve_arg.patch413
-rw-r--r--bcm283x-upstream-fixes.patch194
-rw-r--r--config-arm-generic1
-rw-r--r--config-arm641
-rw-r--r--config-armv7-generic2
-rw-r--r--config-generic6
-rw-r--r--config-nodebug114
-rw-r--r--config-x86-generic2
-rw-r--r--gitrev2
-rw-r--r--kernel.spec36
-rwxr-xr-xscripts/generate-perf-man.sh54
-rw-r--r--sources6
-rw-r--r--tcp-make-challenge-acks-less-predictable.patch81
16 files changed, 2511 insertions, 159 deletions
diff --git a/Makefile b/Makefile
index 535403510..f20475f10 100644
--- a/Makefile
+++ b/Makefile
@@ -111,9 +111,6 @@ release: config-release
include Makefile.release
-unused-kernel-patches:
- @for f in *.patch; do if [ -e $$f ]; then (egrep -q "^Patch[[:digit:]]+:[[:space:]]+$$f" $(SPECFILE) || echo "Unused: $$f") && egrep -q "^ApplyPatch[[:space:]]+$$f|^ApplyOptionalPatch[[:space:]]+$$f" $(SPECFILE) || echo "Unapplied: $$f"; fi; done
-
ifeq ($(MAKECMDGOALS),me a sandwich)
.PHONY: me a sandwich
me a:
diff --git a/arm64-pcie-acpi.patch b/arm64-pcie-acpi.patch
new file mode 100644
index 000000000..e9a359db6
--- /dev/null
+++ b/arm64-pcie-acpi.patch
@@ -0,0 +1,1247 @@
+From 1fc02559de87cd88339a83ad05baa9c2b5bd1ac0 Mon Sep 17 00:00:00 2001
+From: Jayachandran C <jchandra@broadcom.com>
+Date: Fri, 10 Jun 2016 21:55:09 +0200
+Subject: [PATCH 01/11] PCI/ECAM: Move ecam.h to linux/include/pci-ecam.h
+
+This header will be used from arch/arm64 for ACPI PCI implementation
+so it needs to be moved out of drivers/pci.
+
+Update users of the header file to use the new name. No functional
+changes.
+
+Signed-off-by: Jayachandran C <jchandra@broadcom.com>
+Acked-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
+---
+ drivers/pci/ecam.c | 3 +-
+ drivers/pci/ecam.h | 67 -------------------------------------
+ drivers/pci/host/pci-host-common.c | 3 +-
+ drivers/pci/host/pci-host-generic.c | 3 +-
+ drivers/pci/host/pci-thunder-ecam.c | 3 +-
+ drivers/pci/host/pci-thunder-pem.c | 3 +-
+ include/linux/pci-ecam.h | 67 +++++++++++++++++++++++++++++++++++++
+ 7 files changed, 72 insertions(+), 77 deletions(-)
+ delete mode 100644 drivers/pci/ecam.h
+ create mode 100644 include/linux/pci-ecam.h
+
+diff --git a/drivers/pci/ecam.c b/drivers/pci/ecam.c
+index f9832ad..820e26b 100644
+--- a/drivers/pci/ecam.c
++++ b/drivers/pci/ecam.c
+@@ -19,10 +19,9 @@
+ #include <linux/kernel.h>
+ #include <linux/module.h>
+ #include <linux/pci.h>
++#include <linux/pci-ecam.h>
+ #include <linux/slab.h>
+
+-#include "ecam.h"
+-
+ /*
+ * On 64-bit systems, we do a single ioremap for the whole config space
+ * since we have enough virtual address range available. On 32-bit, we
+diff --git a/drivers/pci/ecam.h b/drivers/pci/ecam.h
+deleted file mode 100644
+index 9878beb..0000000
+--- a/drivers/pci/ecam.h
++++ /dev/null
+@@ -1,67 +0,0 @@
+-/*
+- * Copyright 2016 Broadcom
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License, version 2, as
+- * published by the Free Software Foundation (the "GPL").
+- *
+- * This program is distributed in the hope that it will be useful, but
+- * WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+- * General Public License version 2 (GPLv2) for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * version 2 (GPLv2) along with this source code.
+- */
+-#ifndef DRIVERS_PCI_ECAM_H
+-#define DRIVERS_PCI_ECAM_H
+-
+-#include <linux/kernel.h>
+-#include <linux/platform_device.h>
+-
+-/*
+- * struct to hold pci ops and bus shift of the config window
+- * for a PCI controller.
+- */
+-struct pci_config_window;
+-struct pci_ecam_ops {
+- unsigned int bus_shift;
+- struct pci_ops pci_ops;
+- int (*init)(struct device *,
+- struct pci_config_window *);
+-};
+-
+-/*
+- * struct to hold the mappings of a config space window. This
+- * is expected to be used as sysdata for PCI controllers that
+- * use ECAM.
+- */
+-struct pci_config_window {
+- struct resource res;
+- struct resource busr;
+- void *priv;
+- struct pci_ecam_ops *ops;
+- union {
+- void __iomem *win; /* 64-bit single mapping */
+- void __iomem **winp; /* 32-bit per-bus mapping */
+- };
+-};
+-
+-/* create and free pci_config_window */
+-struct pci_config_window *pci_ecam_create(struct device *dev,
+- struct resource *cfgres, struct resource *busr,
+- struct pci_ecam_ops *ops);
+-void pci_ecam_free(struct pci_config_window *cfg);
+-
+-/* map_bus when ->sysdata is an instance of pci_config_window */
+-void __iomem *pci_ecam_map_bus(struct pci_bus *bus, unsigned int devfn,
+- int where);
+-/* default ECAM ops */
+-extern struct pci_ecam_ops pci_generic_ecam_ops;
+-
+-#ifdef CONFIG_PCI_HOST_GENERIC
+-/* for DT-based PCI controllers that support ECAM */
+-int pci_host_common_probe(struct platform_device *pdev,
+- struct pci_ecam_ops *ops);
+-#endif
+-#endif
+diff --git a/drivers/pci/host/pci-host-common.c b/drivers/pci/host/pci-host-common.c
+index 8cba7ab..c18b9e3 100644
+--- a/drivers/pci/host/pci-host-common.c
++++ b/drivers/pci/host/pci-host-common.c
+@@ -20,10 +20,9 @@
+ #include <linux/module.h>
+ #include <linux/of_address.h>
+ #include <linux/of_pci.h>
++#include <linux/pci-ecam.h>
+ #include <linux/platform_device.h>
+
+-#include "../ecam.h"
+-
+ static int gen_pci_parse_request_of_pci_ranges(struct device *dev,
+ struct list_head *resources, struct resource **bus_range)
+ {
+diff --git a/drivers/pci/host/pci-host-generic.c b/drivers/pci/host/pci-host-generic.c
+index 6eaceab..f0ca6de 100644
+--- a/drivers/pci/host/pci-host-generic.c
++++ b/drivers/pci/host/pci-host-generic.c
+@@ -23,10 +23,9 @@
+ #include <linux/module.h>
+ #include <linux/of_address.h>
+ #include <linux/of_pci.h>
++#include <linux/pci-ecam.h>
+ #include <linux/platform_device.h>
+
+-#include "../ecam.h"
+-
+ static struct pci_ecam_ops gen_pci_cfg_cam_bus_ops = {
+ .bus_shift = 16,
+ .pci_ops = {
+diff --git a/drivers/pci/host/pci-thunder-ecam.c b/drivers/pci/host/pci-thunder-ecam.c
+index 540d030..a9fc1c9 100644
+--- a/drivers/pci/host/pci-thunder-ecam.c
++++ b/drivers/pci/host/pci-thunder-ecam.c
+@@ -11,10 +11,9 @@
+ #include <linux/ioport.h>
+ #include <linux/of_pci.h>
+ #include <linux/of.h>
++#include <linux/pci-ecam.h>
+ #include <linux/platform_device.h>
+
+-#include "../ecam.h"
+-
+ static void set_val(u32 v, int where, int size, u32 *val)
+ {
+ int shift = (where & 3) * 8;
+diff --git a/drivers/pci/host/pci-thunder-pem.c b/drivers/pci/host/pci-thunder-pem.c
+index 9b8ab94..5020d3d 100644
+--- a/drivers/pci/host/pci-thunder-pem.c
++++ b/drivers/pci/host/pci-thunder-pem.c
+@@ -18,10 +18,9 @@
+ #include <linux/module.h>
+ #include <linux/of_address.h>
+ #include <linux/of_pci.h>
++#include <linux/pci-ecam.h>
+ #include <linux/platform_device.h>
+
+-#include "../ecam.h"
+-
+ #define PEM_CFG_WR 0x28
+ #define PEM_CFG_RD 0x30
+
+diff --git a/include/linux/pci-ecam.h b/include/linux/pci-ecam.h
+new file mode 100644
+index 0000000..9878beb
+--- /dev/null
++++ b/include/linux/pci-ecam.h
+@@ -0,0 +1,67 @@
++/*
++ * Copyright 2016 Broadcom
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License, version 2, as
++ * published by the Free Software Foundation (the "GPL").
++ *
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * General Public License version 2 (GPLv2) for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * version 2 (GPLv2) along with this source code.
++ */
++#ifndef DRIVERS_PCI_ECAM_H
++#define DRIVERS_PCI_ECAM_H
++
++#include <linux/kernel.h>
++#include <linux/platform_device.h>
++
++/*
++ * struct to hold pci ops and bus shift of the config window
++ * for a PCI controller.
++ */
++struct pci_config_window;
++struct pci_ecam_ops {
++ unsigned int bus_shift;
++ struct pci_ops pci_ops;
++ int (*init)(struct device *,
++ struct pci_config_window *);
++};
++
++/*
++ * struct to hold the mappings of a config space window. This
++ * is expected to be used as sysdata for PCI controllers that
++ * use ECAM.
++ */
++struct pci_config_window {
++ struct resource res;
++ struct resource busr;
++ void *priv;
++ struct pci_ecam_ops *ops;
++ union {
++ void __iomem *win; /* 64-bit single mapping */
++ void __iomem **winp; /* 32-bit per-bus mapping */
++ };
++};
++
++/* create and free pci_config_window */
++struct pci_config_window *pci_ecam_create(struct device *dev,
++ struct resource *cfgres, struct resource *busr,
++ struct pci_ecam_ops *ops);
++void pci_ecam_free(struct pci_config_window *cfg);
++
++/* map_bus when ->sysdata is an instance of pci_config_window */
++void __iomem *pci_ecam_map_bus(struct pci_bus *bus, unsigned int devfn,
++ int where);
++/* default ECAM ops */
++extern struct pci_ecam_ops pci_generic_ecam_ops;
++
++#ifdef CONFIG_PCI_HOST_GENERIC
++/* for DT-based PCI controllers that support ECAM */
++int pci_host_common_probe(struct platform_device *pdev,
++ struct pci_ecam_ops *ops);
++#endif
++#endif
+--
+2.7.4
+
+From 5eb9996fc097629854f359f9ad3d959fdacb7f8f Mon Sep 17 00:00:00 2001
+From: Jayachandran C <jchandra@broadcom.com>
+Date: Fri, 10 Jun 2016 21:55:10 +0200
+Subject: [PATCH 02/11] PCI/ECAM: Add parent device field to pci_config_window
+
+Add a parent device field to struct pci_config_window. The parent
+is not saved now, but will be useful to save it in some cases.
+Specifically in case of ACPI for ARM64, it can be used to setup
+ACPI companion and domain.
+
+Since the parent dev is in struct pci_config_window now, we need
+not pass it to the init function as a separate argument.
+
+Signed-off-by: Jayachandran C <jchandra@broadcom.com>
+Acked-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
+---
+ drivers/pci/ecam.c | 3 ++-
+ drivers/pci/host/pci-thunder-pem.c | 3 ++-
+ include/linux/pci-ecam.h | 4 ++--
+ 3 files changed, 6 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/pci/ecam.c b/drivers/pci/ecam.c
+index 820e26b..66e0d71 100644
+--- a/drivers/pci/ecam.c
++++ b/drivers/pci/ecam.c
+@@ -51,6 +51,7 @@ struct pci_config_window *pci_ecam_create(struct device *dev,
+ if (!cfg)
+ return ERR_PTR(-ENOMEM);
+
++ cfg->parent = dev;
+ cfg->ops = ops;
+ cfg->busr.start = busr->start;
+ cfg->busr.end = busr->end;
+@@ -94,7 +95,7 @@ struct pci_config_window *pci_ecam_create(struct device *dev,
+ }
+
+ if (ops->init) {
+- err = ops->init(dev, cfg);
++ err = ops->init(cfg);
+ if (err)
+ goto err_exit;
+ }
+diff --git a/drivers/pci/host/pci-thunder-pem.c b/drivers/pci/host/pci-thunder-pem.c
+index 5020d3d..91f6fc6 100644
+--- a/drivers/pci/host/pci-thunder-pem.c
++++ b/drivers/pci/host/pci-thunder-pem.c
+@@ -284,8 +284,9 @@ static int thunder_pem_config_write(struct pci_bus *bus, unsigned int devfn,
+ return pci_generic_config_write(bus, devfn, where, size, val);
+ }
+
+-static int thunder_pem_init(struct device *dev, struct pci_config_window *cfg)
++static int thunder_pem_init(struct pci_config_window *cfg)
+ {
++ struct device *dev = cfg->parent;
+ resource_size_t bar4_start;
+ struct resource *res_pem;
+ struct thunder_pem_pci *pem_pci;
+diff --git a/include/linux/pci-ecam.h b/include/linux/pci-ecam.h
+index 9878beb..7adad20 100644
+--- a/include/linux/pci-ecam.h
++++ b/include/linux/pci-ecam.h
+@@ -27,8 +27,7 @@ struct pci_config_window;
+ struct pci_ecam_ops {
+ unsigned int bus_shift;
+ struct pci_ops pci_ops;
+- int (*init)(struct device *,
+- struct pci_config_window *);
++ int (*init)(struct pci_config_window *);
+ };
+
+ /*
+@@ -45,6 +44,7 @@ struct pci_config_window {
+ void __iomem *win; /* 64-bit single mapping */
+ void __iomem **winp; /* 32-bit per-bus mapping */
+ };
++ struct device *parent;/* ECAM res was from this dev */
+ };
+
+ /* create and free pci_config_window */
+--
+2.7.4
+
+From 6ed6c1365df5c9201e9b275e8ed4eaa64ef2ec0d Mon Sep 17 00:00:00 2001
+From: Sinan Kaya <okaya@codeaurora.org>
+Date: Fri, 10 Jun 2016 21:55:11 +0200
+Subject: [PATCH 03/11] PCI: Add new function to unmap IO resources
+
+We need to release I/O resources so that the same I/O resources
+can be allocated again in pci_remap_iospace(), like in PCI hotplug removal
+scenario. Therefore implement new pci_unmap_iospace() call which
+unmaps I/O space as the symmetry to pci_remap_iospace().
+
+Signed-off-by: Sinan Kaya <okaya@codeaurora.org>
+Signed-off-by: Tomasz Nowicki <tn@semihalf.com>
+Acked-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
+---
+ drivers/pci/pci.c | 18 ++++++++++++++++++
+ include/linux/pci.h | 1 +
+ 2 files changed, 19 insertions(+)
+
+diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
+index c8b4dbd..eb431b5 100644
+--- a/drivers/pci/pci.c
++++ b/drivers/pci/pci.c
+@@ -25,6 +25,7 @@
+ #include <linux/device.h>
+ #include <linux/pm_runtime.h>
+ #include <linux/pci_hotplug.h>
++#include <linux/vmalloc.h>
+ #include <asm/setup.h>
+ #include <linux/aer.h>
+ #include "pci.h"
+@@ -3165,6 +3166,23 @@ int __weak pci_remap_iospace(const struct resource *res, phys_addr_t phys_addr)
+ #endif
+ }
+
++/**
++ * pci_unmap_iospace - Unmap the memory mapped I/O space
++ * @res: resource to be unmapped
++ *
++ * Unmap the CPU virtual address @res from virtual address space.
++ * Only architectures that have memory mapped IO functions defined
++ * (and the PCI_IOBASE value defined) should call this function.
++ */
++void pci_unmap_iospace(struct resource *res)
++{
++#if defined(PCI_IOBASE) && defined(CONFIG_MMU)
++ unsigned long vaddr = (unsigned long)PCI_IOBASE + res->start;
++
++ unmap_kernel_range(vaddr, resource_size(res));
++#endif
++}
++
+ static void __pci_set_master(struct pci_dev *dev, bool enable)
+ {
+ u16 old_cmd, cmd;
+diff --git a/include/linux/pci.h b/include/linux/pci.h
+index b67e4df..12349de 100644
+--- a/include/linux/pci.h
++++ b/include/linux/pci.h
+@@ -1167,6 +1167,7 @@ int pci_register_io_range(phys_addr_t addr, resource_size_t size);
+ unsigned long pci_address_to_pio(phys_addr_t addr);
+ phys_addr_t pci_pio_to_address(unsigned long pio);
+ int pci_remap_iospace(const struct resource *res, phys_addr_t phys_addr);
++void pci_unmap_iospace(struct resource *res);
+
+ static inline pci_bus_addr_t pci_bus_address(struct pci_dev *pdev, int bar)
+ {
+--
+2.7.4
+
+From 62f4d54fc2d2882b9ebaa920189574f422e12207 Mon Sep 17 00:00:00 2001
+From: Jayachandran C <jchandra@broadcom.com>
+Date: Fri, 10 Jun 2016 21:55:12 +0200
+Subject: [PATCH 04/11] ACPI/PCI: Support IO resources when parsing PCI host
+ bridge resources
+
+Platforms that have memory mapped IO port (such as ARM64) need special
+handling for PCI I/O resources. For host bridge's resource probing case
+these resources need to be fixed up with
+pci_register_io_range()/pci_remap_iospace() etc.
+
+The same I/O resources need to be released after hotplug
+removal so that it can be re-added back by the pci_remap_iospace()
+function during insertion. As a consequence unmap I/O resources
+with pci_unmap_iospace() when we release host bridge resources.
+
+Signed-off-by: Jayachandran C <jchandra@broadcom.com>
+Signed-off-by: Sinan Kaya <okaya@codeaurora.org>
+[ Tomasz: merged in Sinan's patch to unmap IO resources properly, updated changelog]
+Signed-off-by: Tomasz Nowicki <tn@semihalf.com>
+Reviewed-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
+---
+ drivers/acpi/pci_root.c | 39 +++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 39 insertions(+)
+
+diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c
+index ae3fe4e..9a26dd1 100644
+--- a/drivers/acpi/pci_root.c
++++ b/drivers/acpi/pci_root.c
+@@ -720,6 +720,40 @@ next:
+ }
+ }
+
++#ifdef PCI_IOBASE
++static void acpi_pci_root_remap_iospace(struct resource_entry *entry)
++{
++ struct resource *res = entry->res;
++ resource_size_t cpu_addr = res->start;
++ resource_size_t pci_addr = cpu_addr - entry->offset;
++ resource_size_t length = resource_size(res);
++ unsigned long port;
++
++ if (pci_register_io_range(cpu_addr, length))
++ goto err;
++
++ port = pci_address_to_pio(cpu_addr);
++ if (port == (unsigned long)-1)
++ goto err;
++
++ res->start = port;
++ res->end = port + length - 1;
++ entry->offset = port - pci_addr;
++
++ if (pci_remap_iospace(res, cpu_addr) < 0)
++ goto err;
++
++ pr_info("Remapped I/O %pa to %pR\n", &cpu_addr, res);
++ return;
++err:
++ res->flags |= IORESOURCE_DISABLED;
++}
++#else
++static inline void acpi_pci_root_remap_iospace(struct resource_entry *entry)
++{
++}
++#endif
++
+ int acpi_pci_probe_root_resources(struct acpi_pci_root_info *info)
+ {
+ int ret;
+@@ -740,6 +774,9 @@ int acpi_pci_probe_root_resources(struct acpi_pci_root_info *info)
+ "no IO and memory resources present in _CRS\n");
+ else {
+ resource_list_for_each_entry_safe(entry, tmp, list) {
++ if (entry->res->flags & IORESOURCE_IO)
++ acpi_pci_root_remap_iospace(entry);
++
+ if (entry->res->flags & IORESOURCE_DISABLED)
+ resource_list_destroy_entry(entry);
+ else
+@@ -811,6 +848,8 @@ static void acpi_pci_root_release_info(struct pci_host_bridge *bridge)
+
+ resource_list_for_each_entry(entry, &bridge->windows) {
+ res = entry->res;
++ if (res->flags & IORESOURCE_IO)
++ pci_unmap_iospace(res);
+ if (res->parent &&
+ (res->flags & (IORESOURCE_MEM | IORESOURCE_IO)))
+ release_resource(res);
+--
+2.7.4
+
+From dd4f7822d702cca83baa1de7a5f69344ffb82af9 Mon Sep 17 00:00:00 2001
+From: Tomasz Nowicki <tn@semihalf.com>
+Date: Fri, 10 Jun 2016 21:55:13 +0200
+Subject: [PATCH 05/11] ACPI/PCI: Add generic MCFG table handling
+
+According to PCI firmware specifications, on systems booting with ACPI,
+PCI configuration for a host bridge must be set-up through the MCFG table
+regions for non-hotpluggable bridges and _CBA method for hotpluggable ones.
+
+Current MCFG table handling code, as implemented for x86, cannot be
+easily generalized owing to x86 specific quirks handling and related
+code, which makes it hard to reuse on other architectures.
+
+In order to implement MCFG PCI configuration handling for new platforms
+booting with ACPI (eg ARM64) this patch re-implements MCFG handling from
+scratch in a streamlined fashion and provides (through a generic
+interface available to all arches):
+
+- Simplified MCFG table parsing (executed through the pci_mmcfg_late_init()
+ hook as in current x86)
+- MCFG regions look-up interface through domain:bus_start:bus_end tuple
+
+The new MCFG regions handling interface is added to generic ACPI code
+so that existing architectures (eg x86) can be moved over to it and
+architectures relying on MCFG for ACPI PCI config space can rely on it
+without having to resort to arch specific implementations.
+
+Signed-off-by: Tomasz Nowicki <tn@semihalf.com>
+Signed-off-by: Jayachandran C <jchandra@broadcom.com>
+Reviewed-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
+---
+ drivers/acpi/Kconfig | 3 ++
+ drivers/acpi/Makefile | 1 +
+ drivers/acpi/pci_mcfg.c | 92 ++++++++++++++++++++++++++++++++++++++++++++++++
+ include/linux/pci-acpi.h | 2 ++
+ include/linux/pci.h | 2 +-
+ 5 files changed, 99 insertions(+), 1 deletion(-)
+ create mode 100644 drivers/acpi/pci_mcfg.c
+
+diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
+index b7e2e77..f98c328 100644
+--- a/drivers/acpi/Kconfig
++++ b/drivers/acpi/Kconfig
+@@ -217,6 +217,9 @@ config ACPI_PROCESSOR_IDLE
+ bool
+ select CPU_IDLE
+
++config ACPI_MCFG
++ bool
++
+ config ACPI_CPPC_LIB
+ bool
+ depends on ACPI_PROCESSOR
+diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile
+index 251ce85..632e81f 100644
+--- a/drivers/acpi/Makefile
++++ b/drivers/acpi/Makefile
+@@ -40,6 +40,7 @@ acpi-$(CONFIG_ARCH_MIGHT_HAVE_ACPI_PDC) += processor_pdc.o
+ acpi-y += ec.o
+ acpi-$(CONFIG_ACPI_DOCK) += dock.o
+ acpi-y += pci_root.o pci_link.o pci_irq.o
++obj-$(CONFIG_ACPI_MCFG) += pci_mcfg.o
+ acpi-y += acpi_lpss.o acpi_apd.o
+ acpi-y += acpi_platform.o
+ acpi-y += acpi_pnp.o
+diff --git a/drivers/acpi/pci_mcfg.c b/drivers/acpi/pci_mcfg.c
+new file mode 100644
+index 0000000..d3c3e85
+--- /dev/null
++++ b/drivers/acpi/pci_mcfg.c
+@@ -0,0 +1,92 @@
++/*
++ * Copyright (C) 2016 Broadcom
++ * Author: Jayachandran C <jchandra@broadcom.com>
++ * Copyright (C) 2016 Semihalf
++ * Author: Tomasz Nowicki <tn@semihalf.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License, version 2, as
++ * published by the Free Software Foundation (the "GPL").
++ *
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * General Public License version 2 (GPLv2) for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * version 2 (GPLv2) along with this source code.
++ */
++
++#define pr_fmt(fmt) "ACPI: " fmt
++
++#include <linux/kernel.h>
++#include <linux/pci.h>
++#include <linux/pci-acpi.h>
++
++/* Structure to hold entries from the MCFG table */
++struct mcfg_entry {
++ struct list_head list;
++ phys_addr_t addr;
++ u16 segment;
++ u8 bus_start;
++ u8 bus_end;
++};
++
++/* List to save mcfg entries */
++static LIST_HEAD(pci_mcfg_list);
++
++phys_addr_t pci_mcfg_lookup(u16 seg, struct resource *bus_res)
++{
++ struct mcfg_entry *e;
++
++ /*
++ * We expect exact match, unless MCFG entry end bus covers more than
++ * specified by caller.
++ */
++ list_for_each_entry(e, &pci_mcfg_list, list) {
++ if (e->segment == seg && e->bus_start == bus_res->start &&
++ e->bus_end >= bus_res->end)
++ return e->addr;
++ }
++
++ return 0;
++}
++
++static __init int pci_mcfg_parse(struct acpi_table_header *header)
++{
++ struct acpi_table_mcfg *mcfg;
++ struct acpi_mcfg_allocation *mptr;
++ struct mcfg_entry *e, *arr;
++ int i, n;
++
++ if (header->length < sizeof(struct acpi_table_mcfg))
++ return -EINVAL;
++
++ n = (header->length - sizeof(struct acpi_table_mcfg)) /
++ sizeof(struct acpi_mcfg_allocation);
++ mcfg = (struct acpi_table_mcfg *)header;
++ mptr = (struct acpi_mcfg_allocation *) &mcfg[1];
++
++ arr = kcalloc(n, sizeof(*arr), GFP_KERNEL);
++ if (!arr)
++ return -ENOMEM;
++
++ for (i = 0, e = arr; i < n; i++, mptr++, e++) {
++ e->segment = mptr->pci_segment;
++ e->addr = mptr->address;
++ e->bus_start = mptr->start_bus_number;
++ e->bus_end = mptr->end_bus_number;
++ list_add(&e->list, &pci_mcfg_list);
++ }
++
++ pr_info("MCFG table detected, %d entries\n", n);
++ return 0;
++}
++
++/* Interface called by ACPI - parse and save MCFG table */
++void __init pci_mmcfg_late_init(void)
++{
++ int err = acpi_table_parse(ACPI_SIG_MCFG, pci_mcfg_parse);
++ if (err)
++ pr_err("Failed to parse MCFG (%d)\n", err);
++}
+diff --git a/include/linux/pci-acpi.h b/include/linux/pci-acpi.h
+index 89ab057..7d63a66 100644
+--- a/include/linux/pci-acpi.h
++++ b/include/linux/pci-acpi.h
+@@ -24,6 +24,8 @@ static inline acpi_status pci_acpi_remove_pm_notifier(struct acpi_device *dev)
+ }
+ extern phys_addr_t acpi_pci_root_get_mcfg_addr(acpi_handle handle);
+
++extern phys_addr_t pci_mcfg_lookup(u16 domain, struct resource *bus_res);
++
+ static inline acpi_handle acpi_find_root_bridge_handle(struct pci_dev *pdev)
+ {
+ struct pci_bus *pbus = pdev->bus;
+diff --git a/include/linux/pci.h b/include/linux/pci.h
+index 12349de..ce03d65 100644
+--- a/include/linux/pci.h
++++ b/include/linux/pci.h
+@@ -1723,7 +1723,7 @@ void pcibios_free_irq(struct pci_dev *dev);
+ extern struct dev_pm_ops pcibios_pm_ops;
+ #endif
+
+-#ifdef CONFIG_PCI_MMCONFIG
++#if defined(CONFIG_PCI_MMCONFIG) || defined(CONFIG_ACPI_MCFG)
+ void __init pci_mmcfg_early_init(void);
+ void __init pci_mmcfg_late_init(void);
+ #else
+--
+2.7.4
+
+From fc1907f9c79f9a0a0c2f4d579896e678915fec48 Mon Sep 17 00:00:00 2001
+From: Tomasz Nowicki <tn@semihalf.com>
+Date: Fri, 10 Jun 2016 21:55:14 +0200
+Subject: [PATCH 06/11] PCI: Refactor generic bus domain assignment
+
+Change the way PCI bus domain number is assigned and improve function
+name to reflect what function does. No functional changes.
+
+Instead of assigning bus domain number inside of pci_bus_assign_domain_nr()
+simply return domain number and let pci_create_root_bus() do assignment.
+This way pci_create_root_bus() setups bus structure data in the consistent
+way. Since pci_bus_assign_domain_nr() now does not assign but retrieves
+domain number instead, rename it to pci_bus_find_domain_nr().
+
+Signed-off-by: Tomasz Nowicki <tn@semihalf.com>
+Reviewed-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
+---
+ drivers/pci/pci.c | 4 ++--
+ drivers/pci/probe.c | 4 +++-
+ include/linux/pci.h | 7 +------
+ 3 files changed, 6 insertions(+), 9 deletions(-)
+
+diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
+index eb431b5..b9a7833 100644
+--- a/drivers/pci/pci.c
++++ b/drivers/pci/pci.c
+@@ -4941,7 +4941,7 @@ int pci_get_new_domain_nr(void)
+ }
+
+ #ifdef CONFIG_PCI_DOMAINS_GENERIC
+-void pci_bus_assign_domain_nr(struct pci_bus *bus, struct device *parent)
++int pci_bus_find_domain_nr(struct pci_bus *bus, struct device *parent)
+ {
+ static int use_dt_domains = -1;
+ int domain = -1;
+@@ -4985,7 +4985,7 @@ void pci_bus_assign_domain_nr(struct pci_bus *bus, struct device *parent)
+ domain = -1;
+ }
+
+- bus->domain_nr = domain;
++ return domain;
+ }
+ #endif
+ #endif
+diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
+index 8e3ef72..380d46d 100644
+--- a/drivers/pci/probe.c
++++ b/drivers/pci/probe.c
+@@ -2127,7 +2127,9 @@ struct pci_bus *pci_create_root_bus(struct device *parent, int bus,
+ b->sysdata = sysdata;
+ b->ops = ops;
+ b->number = b->busn_res.start = bus;
+- pci_bus_assign_domain_nr(b, parent);
++#ifdef CONFIG_PCI_DOMAINS_GENERIC
++ b->domain_nr = pci_bus_find_domain_nr(b, parent);
++#endif
+ b2 = pci_find_bus(pci_domain_nr(b), bus);
+ if (b2) {
+ /* If we already got to this bus through a different bridge, ignore it */
+diff --git a/include/linux/pci.h b/include/linux/pci.h
+index ce03d65..48839e8 100644
+--- a/include/linux/pci.h
++++ b/include/linux/pci.h
+@@ -1390,12 +1390,7 @@ static inline int pci_domain_nr(struct pci_bus *bus)
+ {
+ return bus->domain_nr;
+ }
+-void pci_bus_assign_domain_nr(struct pci_bus *bus, struct device *parent);
+-#else
+-static inline void pci_bus_assign_domain_nr(struct pci_bus *bus,
+- struct device *parent)
+-{
+-}
++int pci_bus_find_domain_nr(struct pci_bus *bus, struct device *parent);
+ #endif
+
+ /* some architectures require additional setup to direct VGA traffic */
+--
+2.7.4
+
+From d6d45ae1d58658111d5e838c41b9ed4729bbb81e Mon Sep 17 00:00:00 2001
+From: Tomasz Nowicki <tn@semihalf.com>
+Date: Fri, 10 Jun 2016 21:55:15 +0200
+Subject: [PATCH 07/11] PCI: Factor DT specific pci_bus_find_domain_nr() code
+ out
+
+pci_bus_find_domain_nr() retrieves the host bridge domain number in a DT
+specific way. Factor our pci_bus_find_domain_nr() in a separate DT
+function (ie of_pci_bus_find_domain_nr()) so that DT code is self
+contained, paving the way for retrieving domain number in
+pci_bus_find_domain_nr() with additional firmware methods (ie ACPI).
+
+Signed-off-by: Tomasz Nowicki <tn@semihalf.com>
+Reviewed-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
+---
+ drivers/pci/pci.c | 7 ++++++-
+ 1 file changed, 6 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
+index b9a7833..97f7cd4 100644
+--- a/drivers/pci/pci.c
++++ b/drivers/pci/pci.c
+@@ -4941,7 +4941,7 @@ int pci_get_new_domain_nr(void)
+ }
+
+ #ifdef CONFIG_PCI_DOMAINS_GENERIC
+-int pci_bus_find_domain_nr(struct pci_bus *bus, struct device *parent)
++static int of_pci_bus_find_domain_nr(struct device *parent)
+ {
+ static int use_dt_domains = -1;
+ int domain = -1;
+@@ -4987,6 +4987,11 @@ int pci_bus_find_domain_nr(struct pci_bus *bus, struct device *parent)
+
+ return domain;
+ }
++
++int pci_bus_find_domain_nr(struct pci_bus *bus, struct device *parent)
++{
++ return of_pci_bus_find_domain_nr(parent);
++}
+ #endif
+ #endif
+
+--
+2.7.4
+
+From 92d59511fd365d3c0c31d074b5e96cf48c58f68b Mon Sep 17 00:00:00 2001
+From: Peter Robinson <pbrobinson@gmail.com>
+Date: Thu, 30 Jun 2016 16:56:24 +0100
+Subject: [PATCH 08/11] ARM64/PCI: Add ACPI hook to assign domain number
+
+PCI core code provides a config option (CONFIG_PCI_DOMAINS_GENERIC)
+that allows assigning the PCI bus domain number generically by
+relying on device tree bindings, and falling back to a simple counter
+when the respective DT properties (ie "linux,pci-domain") are not
+specified in the host bridge device tree node.
+
+In a similar way, when a system is booted through ACPI, architectures
+that are selecting CONFIG_PCI_DOMAINS_GENERIC (ie ARM64) require kernel
+hooks to retrieve the domain number so that the PCI bus domain number
+set-up can be handled seamlessly with DT and ACPI in generic core code
+when CONFIG_PCI_DOMAINS_GENERIC is selected.
+
+Since currently it is not possible to retrieve a pointer to the PCI
+host bridge ACPI device backing the host bridge from core PCI code
+(which would allow retrieving the domain number in an arch agnostic
+way through the ACPI _SEG method), an arch specific ACPI hook has to
+be declared and implemented by all arches that rely on
+CONFIG_PCI_DOMAINS_GENERIC to retrieve the domain number and set it
+up in core PCI code.
+
+For the aforementioned reasons, introduce acpi_pci_bus_find_domain_nr()
+hook to retrieve the domain number on a per-arch basis when the system
+boots through ACPI. ARM64 dummy implementation of the same is provided
+in first place in preparation for ARM64 ACPI based PCI host controller
+driver.
+
+acpi_pci_bus_find_domain_nr() is called from generic
+pci_bus_find_domain_nr() as an ACPI option to DT domain assignment.
+
+Signed-off-by: Tomasz Nowicki <tn@semihalf.com>
+Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
+---
+ arch/arm64/kernel/pci.c | 7 +++++++
+ drivers/pci/pci.c | 4 +++-
+ include/linux/pci.h | 7 +++++++
+ 3 files changed, 17 insertions(+), 1 deletion(-)
+
+diff --git a/arch/arm64/kernel/pci.c b/arch/arm64/kernel/pci.c
+index 3c4e308..d5d3d26 100644
+--- a/arch/arm64/kernel/pci.c
++++ b/arch/arm64/kernel/pci.c
+@@ -17,6 +17,7 @@
+ #include <linux/mm.h>
+ #include <linux/of_pci.h>
+ #include <linux/of_platform.h>
++#include <linux/pci.h>
+ #include <linux/slab.h>
+
+ /*
+@@ -85,6 +86,12 @@ EXPORT_SYMBOL(pcibus_to_node);
+ #endif
+
+ #ifdef CONFIG_ACPI
++
++int acpi_pci_bus_find_domain_nr(struct pci_bus *bus)
++{
++ return 0;
++}
++
+ /* Root bridge scanning */
+ struct pci_bus *pci_acpi_scan_root(struct acpi_pci_root *root)
+ {
+diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
+index 97f7cd4..4834cee 100644
+--- a/drivers/pci/pci.c
++++ b/drivers/pci/pci.c
+@@ -7,6 +7,7 @@
+ * Copyright 1997 -- 2000 Martin Mares <mj@ucw.cz>
+ */
+
++#include <linux/acpi.h>
+ #include <linux/kernel.h>
+ #include <linux/delay.h>
+ #include <linux/init.h>
+@@ -4990,7 +4991,8 @@ static int of_pci_bus_find_domain_nr(struct device *parent)
+
+ int pci_bus_find_domain_nr(struct pci_bus *bus, struct device *parent)
+ {
+- return of_pci_bus_find_domain_nr(parent);
++ return acpi_disabled ? of_pci_bus_find_domain_nr(parent) :
++ acpi_pci_bus_find_domain_nr(bus);
+ }
+ #endif
+ #endif
+diff --git a/include/linux/pci.h b/include/linux/pci.h
+index 48839e8..49ba8af 100644
+--- a/include/linux/pci.h
++++ b/include/linux/pci.h
+@@ -1390,6 +1390,13 @@ static inline int pci_domain_nr(struct pci_bus *bus)
+ {
+ return bus->domain_nr;
+ }
++/* Arch specific ACPI hook to set-up domain number */
++#ifdef CONFIG_ACPI
++int acpi_pci_bus_find_domain_nr(struct pci_bus *bus);
++#else
++static inline int acpi_pci_bus_find_domain_nr(struct pci_bus *bus)
++{ return 0; }
++#endif
+ int pci_bus_find_domain_nr(struct pci_bus *bus, struct device *parent);
+ #endif
+
+--
+2.7.4
+
+From bb06753d2e163d8100a017f06a6d9dd195d68a76 Mon Sep 17 00:00:00 2001
+From: Tomasz Nowicki <tn@semihalf.com>
+Date: Fri, 10 Jun 2016 21:55:17 +0200
+Subject: [PATCH 09/11] ARM64/PCI: ACPI support for legacy IRQs parsing and
+ consolidation with DT code
+
+To enable PCI legacy IRQs on platforms booting with ACPI, arch code
+should include ACPI specific callbacks that parse and set-up the
+device IRQ number, equivalent to the DT boot path. Owing to the current
+ACPI core scan handlers implementation, ACPI PCI legacy IRQs bindings
+cannot be parsed at device add time, since that would trigger ACPI scan
+handlers ordering issues depending on how the ACPI tables are defined.
+
+To solve this problem and consolidate FW PCI legacy IRQs parsing in
+one single pcibios callback (pending final removal), this patch moves
+DT PCI IRQ parsing to the pcibios_alloc_irq() callback (called by
+PCI core code at device probe time) and adds ACPI PCI legacy IRQs
+parsing to the same callback too, so that FW PCI legacy IRQs parsing
+is confined in one single arch callback that can be easily removed
+when code parsing PCI legacy IRQs is consolidated and moved to core
+PCI code.
+
+Signed-off-by: Tomasz Nowicki <tn@semihalf.com>
+Suggested-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
+---
+ arch/arm64/kernel/pci.c | 11 ++++++++---
+ 1 file changed, 8 insertions(+), 3 deletions(-)
+
+diff --git a/arch/arm64/kernel/pci.c b/arch/arm64/kernel/pci.c
+index d5d3d26..b3b8a2c 100644
+--- a/arch/arm64/kernel/pci.c
++++ b/arch/arm64/kernel/pci.c
+@@ -51,11 +51,16 @@ int pcibios_enable_device(struct pci_dev *dev, int mask)
+ }
+
+ /*
+- * Try to assign the IRQ number from DT when adding a new device
++ * Try to assign the IRQ number when probing a new device
+ */
+-int pcibios_add_device(struct pci_dev *dev)
++int pcibios_alloc_irq(struct pci_dev *dev)
+ {
+- dev->irq = of_irq_parse_and_map_pci(dev, 0, 0);
++ if (acpi_disabled)
++ dev->irq = of_irq_parse_and_map_pci(dev, 0, 0);
++#ifdef CONFIG_ACPI
++ else
++ return acpi_pci_irq_enable(dev);
++#endif
+
+ return 0;
+ }
+--
+2.7.4
+
+From b6e298840f532192a589f8ade128dec3fef3a4c6 Mon Sep 17 00:00:00 2001
+From: Tomasz Nowicki <tn@semihalf.com>
+Date: Fri, 10 Jun 2016 21:55:18 +0200
+Subject: [PATCH 10/11] ARM64/PCI: Implement ACPI low-level calls to access
+ PCI_Config region from AML
+
+ACPI spec6.1 - chapter: 5.5.2.4 defines OperationRegion (Declare Operation
+Region). Following the spec: " [...] An Operation Region is a specific
+region of operation within an address space that is declared as a subset
+of the entire address space using a starting address (offset) and a length.
+Control methods must have exclusive access to any address accessed via
+fields declared in Operation Regions. [...]".
+
+OperationRegion allows to declare various of operation region address space
+identifiers including PCI_Config. PCI_Config is meant to access PCI
+configuration space from the ASL. So every time ASL opcode operates
+on PCI_Config space region, ASL interpreter dispatches accesses to OS
+low-level calls - raw_pci_write() and raw_pci_read() for Linux - so-called
+ACPI RAW accessors.
+
+In order to support PCI_Config operation region, implement mentioned
+raw_pci_write() and raw_pci_read() calls so they find associated bus
+and call read/write ops.
+
+Waiting for clarification in the ACPI specifications in relation
+to PCI_Config space handling before PCI bus enumeration is completed,
+current code does not support PCI_Config region accesses before PCI bus
+enumeration whilst providing full AML PCI_Config access availability
+when the PCI bus enumeration is completed by the kernel so that
+RAW accessors can look-up PCI operations through the struct pci_bus
+associated with a PCI bus.
+
+Signed-off-by: Tomasz Nowicki <tn@semihalf.com>
+Signed-off-by: Jayachandran C <jchandra@broadcom.com>
+Reviewed-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
+---
+ arch/arm64/kernel/pci.c | 12 ++++++++++--
+ 1 file changed, 10 insertions(+), 2 deletions(-)
+
+diff --git a/arch/arm64/kernel/pci.c b/arch/arm64/kernel/pci.c
+index b3b8a2c..328f857 100644
+--- a/arch/arm64/kernel/pci.c
++++ b/arch/arm64/kernel/pci.c
+@@ -71,13 +71,21 @@ int pcibios_alloc_irq(struct pci_dev *dev)
+ int raw_pci_read(unsigned int domain, unsigned int bus,
+ unsigned int devfn, int reg, int len, u32 *val)
+ {
+- return -ENXIO;
++ struct pci_bus *b = pci_find_bus(domain, bus);
++
++ if (!b)
++ return PCIBIOS_DEVICE_NOT_FOUND;
++ return b->ops->read(b, devfn, reg, len, val);
+ }
+
+ int raw_pci_write(unsigned int domain, unsigned int bus,
+ unsigned int devfn, int reg, int len, u32 val)
+ {
+- return -ENXIO;
++ struct pci_bus *b = pci_find_bus(domain, bus);
++
++ if (!b)
++ return PCIBIOS_DEVICE_NOT_FOUND;
++ return b->ops->write(b, devfn, reg, len, val);
+ }
+
+ #ifdef CONFIG_NUMA
+--
+2.7.4
+
+From 3b8cff3fa89ba3ef6f1cf09a0667aa470b7fad0b Mon Sep 17 00:00:00 2001
+From: Tomasz Nowicki <tn@semihalf.com>
+Date: Fri, 10 Jun 2016 21:55:19 +0200
+Subject: [PATCH 11/11] ARM64/PCI: Support for ACPI based PCI host controller
+
+Implement pci_acpi_scan_root and other arch-specific call so that ARM64
+can start using ACPI to setup and enumerate PCI buses.
+
+Prior to buses enumeration the pci_acpi_scan_root() implementation looks
+for configuration space start address (obtained through ACPI _CBA method or
+MCFG interface). If succeed, it uses ECAM library to create new mapping.
+Then it attaches generic ECAM ops (pci_generic_ecam_ops) which are used
+for accessing configuration space later on.
+
+On ARM64, we need to use generic domains (CONFIG_PCI_DOMAINS_GENERIC).
+In order to achieve that for ACPI case implement
+acpi_pci_bus_find_domain_nr() body so that it retrieves pci_config_window
+structure from bus sysdata and eventually gets domain number from
+acpi_pci_root structure.
+
+ACPI requires to run acpi_pci_{add|remove}_bus while new PCI bus is created.
+This allows to do some ACPI-specific additional configuration, like
+PCI hotplug slot enumeration. In order to fulfill these requirements,
+we implement arch-specific pcibios_{add|remove}_bus calls
+and call acpi_pci_{add|remove}_bus from there.
+
+Signed-off-by: Tomasz Nowicki <tn@semihalf.com>
+Signed-off-by: Jayachandran C <jchandra@broadcom.com>
+Reviewed-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
+---
+ arch/arm64/Kconfig | 2 +
+ arch/arm64/kernel/pci.c | 116 ++++++++++++++++++++++++++++++++++++++++++++++--
+ 2 files changed, 115 insertions(+), 3 deletions(-)
+
+diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
+index 5a0a691..4806cde 100644
+--- a/arch/arm64/Kconfig
++++ b/arch/arm64/Kconfig
+@@ -3,6 +3,7 @@ config ARM64
+ select ACPI_CCA_REQUIRED if ACPI
+ select ACPI_GENERIC_GSI if ACPI
+ select ACPI_REDUCED_HARDWARE_ONLY if ACPI
++ select ACPI_MCFG if ACPI
+ select ARCH_HAS_DEVMEM_IS_ALLOWED
+ select ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE
+ select ARCH_HAS_ELF_RANDOMIZE
+@@ -96,6 +97,7 @@ config ARM64
+ select OF_EARLY_FLATTREE
+ select OF_NUMA if NUMA && OF
+ select OF_RESERVED_MEM
++ select PCI_ECAM if ACPI
+ select PERF_USE_VMALLOC
+ select POWER_RESET
+ select POWER_SUPPLY
+diff --git a/arch/arm64/kernel/pci.c b/arch/arm64/kernel/pci.c
+index 328f857..94cd43c 100644
+--- a/arch/arm64/kernel/pci.c
++++ b/arch/arm64/kernel/pci.c
+@@ -18,6 +18,8 @@
+ #include <linux/of_pci.h>
+ #include <linux/of_platform.h>
+ #include <linux/pci.h>
++#include <linux/pci-acpi.h>
++#include <linux/pci-ecam.h>
+ #include <linux/slab.h>
+
+ /*
+@@ -100,15 +102,123 @@ EXPORT_SYMBOL(pcibus_to_node);
+
+ #ifdef CONFIG_ACPI
+
++struct acpi_pci_generic_root_info {
++ struct acpi_pci_root_info common;
++ struct pci_config_window *cfg; /* config space mapping */
++};
++
+ int acpi_pci_bus_find_domain_nr(struct pci_bus *bus)
+ {
++ struct pci_config_window *cfg = bus->sysdata;
++ struct acpi_device *adev = to_acpi_device(cfg->parent);
++ struct acpi_pci_root *root = acpi_driver_data(adev);
++
++ return root->segment;
++}
++
++int pcibios_root_bridge_prepare(struct pci_host_bridge *bridge)
++{
++ if (!acpi_disabled) {
++ struct pci_config_window *cfg = bridge->bus->sysdata;
++ struct acpi_device *adev = to_acpi_device(cfg->parent);
++ ACPI_COMPANION_SET(&bridge->dev, adev);
++ }
++
+ return 0;
+ }
+
+-/* Root bridge scanning */
++/*
++ * Lookup the bus range for the domain in MCFG, and set up config space
++ * mapping.
++ */
++static struct pci_config_window *
++pci_acpi_setup_ecam_mapping(struct acpi_pci_root *root)
++{
++ struct resource *bus_res = &root->secondary;
++ u16 seg = root->segment;
++ struct pci_config_window *cfg;
++ struct resource cfgres;
++ unsigned int bsz;
++
++ /* Use address from _CBA if present, otherwise lookup MCFG */
++ if (!root->mcfg_addr)
++ root->mcfg_addr = pci_mcfg_lookup(seg, bus_res);
++
++ if (!root->mcfg_addr) {
++ dev_err(&root->device->dev, "%04x:%pR ECAM region not found\n",
++ seg, bus_res);
++ return NULL;
++ }
++
++ bsz = 1 << pci_generic_ecam_ops.bus_shift;
++ cfgres.start = root->mcfg_addr + bus_res->start * bsz;
++ cfgres.end = cfgres.start + resource_size(bus_res) * bsz - 1;
++ cfgres.flags = IORESOURCE_MEM;
++ cfg = pci_ecam_create(&root->device->dev, &cfgres, bus_res,
++ &pci_generic_ecam_ops);
++ if (IS_ERR(cfg)) {
++ dev_err(&root->device->dev, "%04x:%pR error %ld mapping ECAM\n",
++ seg, bus_res, PTR_ERR(cfg));
++ return NULL;
++ }
++
++ return cfg;
++}
++
++/* release_info: free resources allocated by init_info */
++static void pci_acpi_generic_release_info(struct acpi_pci_root_info *ci)
++{
++ struct acpi_pci_generic_root_info *ri;
++
++ ri = container_of(ci, struct acpi_pci_generic_root_info, common);
++ pci_ecam_free(ri->cfg);
++ kfree(ri);
++}
++
++static struct acpi_pci_root_ops acpi_pci_root_ops = {
++ .release_info = pci_acpi_generic_release_info,
++};
++
++/* Interface called from ACPI code to setup PCI host controller */
+ struct pci_bus *pci_acpi_scan_root(struct acpi_pci_root *root)
+ {
+- /* TODO: Should be revisited when implementing PCI on ACPI */
+- return NULL;
++ int node = acpi_get_node(root->device->handle);
++ struct acpi_pci_generic_root_info *ri;
++ struct pci_bus *bus, *child;
++
++ ri = kzalloc_node(sizeof(*ri), GFP_KERNEL, node);
++ if (!ri)
++ return NULL;
++
++ ri->cfg = pci_acpi_setup_ecam_mapping(root);
++ if (!ri->cfg) {
++ kfree(ri);
++ return NULL;
++ }
++
++ acpi_pci_root_ops.pci_ops = &ri->cfg->ops->pci_ops;
++ bus = acpi_pci_root_create(root, &acpi_pci_root_ops, &ri->common,
++ ri->cfg);
++ if (!bus)
++ return NULL;
++
++ pci_bus_size_bridges(bus);
++ pci_bus_assign_resources(bus);
++
++ list_for_each_entry(child, &bus->children, node)
++ pcie_bus_configure_settings(child);
++
++ return bus;
++}
++
++void pcibios_add_bus(struct pci_bus *bus)
++{
++ acpi_pci_add_bus(bus);
+ }
++
++void pcibios_remove_bus(struct pci_bus *bus)
++{
++ acpi_pci_remove_bus(bus);
++}
++
+ #endif
+--
+2.7.4
+
diff --git a/arm64-pcie-quirks-xgene.patch b/arm64-pcie-quirks-xgene.patch
new file mode 100644
index 000000000..8e6805df6
--- /dev/null
+++ b/arm64-pcie-quirks-xgene.patch
@@ -0,0 +1,508 @@
+From 767b70aa55d013f0c7589955f410d488fed5776a Mon Sep 17 00:00:00 2001
+From: Peter Robinson <pbrobinson@gmail.com>
+Date: Tue, 5 Jul 2016 23:49:39 +0100
+Subject: [PATCH 1/4] Some platforms may not be fully compliant with generic
+ set of PCI config accessors. For these cases we implement the way to
+ overwrite accessors set. Algorithm traverses available quirk list, matches
+ against <oem_id, oem_table_id, domain, bus number> tuple and returns
+ corresponding PCI config ops. oem_id and oem_table_id come from MCFG table
+ standard header. All quirks can be defined using DECLARE_ACPI_MCFG_FIXUP()
+ macro and kept self contained. Example:
+
+/* Custom PCI config ops */
+static struct pci_generic_ecam_ops foo_pci_ops = {
+ .bus_shift = 24,
+ .pci_ops = {
+ .map_bus = pci_ecam_map_bus,
+ .read = foo_ecam_config_read,
+ .write = foo_ecam_config_write,
+ }
+};
+
+DECLARE_ACPI_MCFG_FIXUP(&foo_pci_ops, <oem_id_str>, <oem_table_id>, <domain_nr>, <bus_nr>);
+
+Signed-off-by: Tomasz Nowicki <tn@semihalf.com>
+Signed-off-by: Dongdong Liu <liudongdong3@huawei.com>
+---
+ drivers/acpi/pci_mcfg.c | 41 ++++++++++++++++++++++++++++++++++++---
+ include/asm-generic/vmlinux.lds.h | 7 +++++++
+ include/linux/pci-acpi.h | 20 +++++++++++++++++++
+ 3 files changed, 65 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/acpi/pci_mcfg.c b/drivers/acpi/pci_mcfg.c
+index d3c3e85..deb0077 100644
+--- a/drivers/acpi/pci_mcfg.c
++++ b/drivers/acpi/pci_mcfg.c
+@@ -22,6 +22,10 @@
+ #include <linux/kernel.h>
+ #include <linux/pci.h>
+ #include <linux/pci-acpi.h>
++#include <linux/pci-ecam.h>
++
++/* Root pointer to the mapped MCFG table */
++static struct acpi_table_mcfg *mcfg_table;
+
+ /* Structure to hold entries from the MCFG table */
+ struct mcfg_entry {
+@@ -35,6 +39,38 @@ struct mcfg_entry {
+ /* List to save mcfg entries */
+ static LIST_HEAD(pci_mcfg_list);
+
++extern struct pci_cfg_fixup __start_acpi_mcfg_fixups[];
++extern struct pci_cfg_fixup __end_acpi_mcfg_fixups[];
++
++struct pci_ecam_ops *pci_mcfg_get_ops(struct acpi_pci_root *root)
++{
++ int bus_num = root->secondary.start;
++ int domain = root->segment;
++ struct pci_cfg_fixup *f;
++
++ if (!mcfg_table)
++ return &pci_generic_ecam_ops;
++
++ /*
++ * Match against platform specific quirks and return corresponding
++ * CAM ops.
++ *
++ * First match against PCI topology <domain:bus> then use OEM ID and
++ * OEM revision from MCFG table standard header.
++ */
++ for (f = __start_acpi_mcfg_fixups; f < __end_acpi_mcfg_fixups; f++) {
++ if ((f->domain == domain || f->domain == PCI_MCFG_DOMAIN_ANY) &&
++ (f->bus_num == bus_num || f->bus_num == PCI_MCFG_BUS_ANY) &&
++ (!strncmp(f->oem_id, mcfg_table->header.oem_id,
++ ACPI_OEM_ID_SIZE)) &&
++ (!strncmp(f->oem_table_id, mcfg_table->header.oem_table_id,
++ ACPI_OEM_TABLE_ID_SIZE)))
++ return f->ops;
++ }
++ /* No quirks, use ECAM */
++ return &pci_generic_ecam_ops;
++}
++
+ phys_addr_t pci_mcfg_lookup(u16 seg, struct resource *bus_res)
+ {
+ struct mcfg_entry *e;
+@@ -54,7 +90,6 @@ phys_addr_t pci_mcfg_lookup(u16 seg, struct resource *bus_res)
+
+ static __init int pci_mcfg_parse(struct acpi_table_header *header)
+ {
+- struct acpi_table_mcfg *mcfg;
+ struct acpi_mcfg_allocation *mptr;
+ struct mcfg_entry *e, *arr;
+ int i, n;
+@@ -64,8 +99,8 @@ static __init int pci_mcfg_parse(struct acpi_table_header *header)
+
+ n = (header->length - sizeof(struct acpi_table_mcfg)) /
+ sizeof(struct acpi_mcfg_allocation);
+- mcfg = (struct acpi_table_mcfg *)header;
+- mptr = (struct acpi_mcfg_allocation *) &mcfg[1];
++ mcfg_table = (struct acpi_table_mcfg *)header;
++ mptr = (struct acpi_mcfg_allocation *) &mcfg_table[1];
+
+ arr = kcalloc(n, sizeof(*arr), GFP_KERNEL);
+ if (!arr)
+diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
+index 6a67ab9..43604fc 100644
+--- a/include/asm-generic/vmlinux.lds.h
++++ b/include/asm-generic/vmlinux.lds.h
+@@ -300,6 +300,13 @@
+ VMLINUX_SYMBOL(__end_pci_fixups_suspend_late) = .; \
+ } \
+ \
++ /* ACPI MCFG quirks */ \
++ .acpi_fixup : AT(ADDR(.acpi_fixup) - LOAD_OFFSET) { \
++ VMLINUX_SYMBOL(__start_acpi_mcfg_fixups) = .; \
++ *(.acpi_fixup_mcfg) \
++ VMLINUX_SYMBOL(__end_acpi_mcfg_fixups) = .; \
++ } \
++ \
+ /* Built-in firmware blobs */ \
+ .builtin_fw : AT(ADDR(.builtin_fw) - LOAD_OFFSET) { \
+ VMLINUX_SYMBOL(__start_builtin_fw) = .; \
+diff --git a/include/linux/pci-acpi.h b/include/linux/pci-acpi.h
+index 7d63a66..c8a6559 100644
+--- a/include/linux/pci-acpi.h
++++ b/include/linux/pci-acpi.h
+@@ -25,6 +25,7 @@ static inline acpi_status pci_acpi_remove_pm_notifier(struct acpi_device *dev)
+ extern phys_addr_t acpi_pci_root_get_mcfg_addr(acpi_handle handle);
+
+ extern phys_addr_t pci_mcfg_lookup(u16 domain, struct resource *bus_res);
++extern struct pci_ecam_ops *pci_mcfg_get_ops(struct acpi_pci_root *root);
+
+ static inline acpi_handle acpi_find_root_bridge_handle(struct pci_dev *pdev)
+ {
+@@ -72,6 +73,25 @@ struct acpi_pci_root_ops {
+ int (*prepare_resources)(struct acpi_pci_root_info *info);
+ };
+
++struct pci_cfg_fixup {
++ struct pci_ecam_ops *ops;
++ char *oem_id;
++ char *oem_table_id;
++ int domain;
++ int bus_num;
++};
++
++#define PCI_MCFG_DOMAIN_ANY -1
++#define PCI_MCFG_BUS_ANY -1
++
++/* Designate a routine to fix up buggy MCFG */
++#define DECLARE_ACPI_MCFG_FIXUP(ops, oem_id, oem_table_id, dom, bus) \
++ static const struct pci_cfg_fixup \
++ __mcfg_fixup_##oem_id##oem_table_id##dom##bus \
++ __used __attribute__((__section__(".acpi_fixup_mcfg"), \
++ aligned((sizeof(void *))))) = \
++ { ops, oem_id, oem_table_id, dom, bus };
++
+ extern int acpi_pci_probe_root_resources(struct acpi_pci_root_info *info);
+ extern struct pci_bus *acpi_pci_root_create(struct acpi_pci_root *root,
+ struct acpi_pci_root_ops *ops,
+--
+2.7.4
+
+From 4f86a9b006b25dd7336043dab26058ed6fb2802d Mon Sep 17 00:00:00 2001
+From: Peter Robinson <pbrobinson@gmail.com>
+Date: Tue, 5 Jul 2016 23:52:46 +0100
+Subject: [PATCH 2/4] pci_generic_ecam_ops is used by default. Since there are
+ platforms which have non-compliant ECAM space we need to overwrite these
+ accessors prior to PCI buses enumeration. In order to do that we call
+ pci_mcfg_get_ops to retrieve pci_ecam_ops structure so that we can use proper
+ PCI config space accessors and bus_shift.
+
+pci_generic_ecam_ops is still used for platforms free from quirks.
+
+Signed-off-by: Tomasz Nowicki <tn@semihalf.com>
+---
+ arch/arm64/kernel/pci.c | 7 ++++---
+ 1 file changed, 4 insertions(+), 3 deletions(-)
+
+diff --git a/arch/arm64/kernel/pci.c b/arch/arm64/kernel/pci.c
+index 94cd43c..a891bda 100644
+--- a/arch/arm64/kernel/pci.c
++++ b/arch/arm64/kernel/pci.c
+@@ -139,6 +139,7 @@ pci_acpi_setup_ecam_mapping(struct acpi_pci_root *root)
+ struct pci_config_window *cfg;
+ struct resource cfgres;
+ unsigned int bsz;
++ struct pci_ecam_ops *ops;
+
+ /* Use address from _CBA if present, otherwise lookup MCFG */
+ if (!root->mcfg_addr)
+@@ -150,12 +151,12 @@ pci_acpi_setup_ecam_mapping(struct acpi_pci_root *root)
+ return NULL;
+ }
+
+- bsz = 1 << pci_generic_ecam_ops.bus_shift;
++ ops = pci_mcfg_get_ops(root);
++ bsz = 1 << ops->bus_shift;
+ cfgres.start = root->mcfg_addr + bus_res->start * bsz;
+ cfgres.end = cfgres.start + resource_size(bus_res) * bsz - 1;
+ cfgres.flags = IORESOURCE_MEM;
+- cfg = pci_ecam_create(&root->device->dev, &cfgres, bus_res,
+- &pci_generic_ecam_ops);
++ cfg = pci_ecam_create(&root->device->dev, &cfgres, bus_res, ops);
+ if (IS_ERR(cfg)) {
+ dev_err(&root->device->dev, "%04x:%pR error %ld mapping ECAM\n",
+ seg, bus_res, PTR_ERR(cfg));
+--
+2.7.4
+
+From cbdbd697bd6d716eb9d1705ee55445432e73eabb Mon Sep 17 00:00:00 2001
+From: Peter Robinson <pbrobinson@gmail.com>
+Date: Tue, 5 Jul 2016 23:53:59 +0100
+Subject: [PATCH 3/4] The ECAM quirk matching criteria per the discussion on
+ https://lkml.org/lkml/2016/6/13/944 includes: OEM ID, OEM Table ID and OEM
+ Revision. So this patch adds OEM Table ID into the check to match platform
+ specific ECAM quirks as well.
+
+This patch also improve strncmp check using strlen and
+min_t to ignore the padding spaces in OEM ID and OEM
+Table ID.
+
+Signed-off-by: Duc Dang <dhdang@apm.com>
+---
+ drivers/acpi/pci_mcfg.c | 7 +++++--
+ include/linux/pci-acpi.h | 7 ++++---
+ 2 files changed, 9 insertions(+), 5 deletions(-)
+
+diff --git a/drivers/acpi/pci_mcfg.c b/drivers/acpi/pci_mcfg.c
+index deb0077..307ca9a 100644
+--- a/drivers/acpi/pci_mcfg.c
++++ b/drivers/acpi/pci_mcfg.c
+@@ -62,9 +62,12 @@ struct pci_ecam_ops *pci_mcfg_get_ops(struct acpi_pci_root *root)
+ if ((f->domain == domain || f->domain == PCI_MCFG_DOMAIN_ANY) &&
+ (f->bus_num == bus_num || f->bus_num == PCI_MCFG_BUS_ANY) &&
+ (!strncmp(f->oem_id, mcfg_table->header.oem_id,
+- ACPI_OEM_ID_SIZE)) &&
++ min_t(size_t, strlen(f->oem_id),
++ ACPI_OEM_ID_SIZE))) &&
+ (!strncmp(f->oem_table_id, mcfg_table->header.oem_table_id,
+- ACPI_OEM_TABLE_ID_SIZE)))
++ min_t(size_t, strlen(f->oem_table_id),
++ ACPI_OEM_TABLE_ID_SIZE))) &&
++ (f->oem_revision == mcfg_table->header.oem_revision))
+ return f->ops;
+ }
+ /* No quirks, use ECAM */
+diff --git a/include/linux/pci-acpi.h b/include/linux/pci-acpi.h
+index c8a6559..5148c8d 100644
+--- a/include/linux/pci-acpi.h
++++ b/include/linux/pci-acpi.h
+@@ -77,6 +77,7 @@ struct pci_cfg_fixup {
+ struct pci_ecam_ops *ops;
+ char *oem_id;
+ char *oem_table_id;
++ u32 oem_revision;
+ int domain;
+ int bus_num;
+ };
+@@ -85,12 +86,12 @@ struct pci_cfg_fixup {
+ #define PCI_MCFG_BUS_ANY -1
+
+ /* Designate a routine to fix up buggy MCFG */
+-#define DECLARE_ACPI_MCFG_FIXUP(ops, oem_id, oem_table_id, dom, bus) \
++#define DECLARE_ACPI_MCFG_FIXUP(ops, oem_id, oem_table_id, rev, dom, bus) \
+ static const struct pci_cfg_fixup \
+- __mcfg_fixup_##oem_id##oem_table_id##dom##bus \
++ __mcfg_fixup_##oem_id##oem_table_id##rev##dom##bus \
+ __used __attribute__((__section__(".acpi_fixup_mcfg"), \
+ aligned((sizeof(void *))))) = \
+- { ops, oem_id, oem_table_id, dom, bus };
++ { ops, oem_id, oem_table_id, rev, dom, bus };
+
+ extern int acpi_pci_probe_root_resources(struct acpi_pci_root_info *info);
+ extern struct pci_bus *acpi_pci_root_create(struct acpi_pci_root *root,
+--
+2.7.4
+
+From 78766cf255bc6aafac2f57372a0446f78322da19 Mon Sep 17 00:00:00 2001
+From: Peter Robinson <pbrobinson@gmail.com>
+Date: Tue, 5 Jul 2016 23:55:11 +0100
+Subject: [PATCH 4/4] X-Gene PCIe controller does not fully support ECAM. This
+ patch adds required ECAM fixup to allow X-Gene PCIe controller to be
+ functional in ACPI boot mode.
+
+Signed-off-by: Duc Dang <dhdang@apm.com>
+---
+ drivers/pci/host/Makefile | 2 +-
+ drivers/pci/host/pci-xgene-ecam.c | 194 ++++++++++++++++++++++++++++++++++++++
+ 2 files changed, 195 insertions(+), 1 deletion(-)
+ create mode 100644 drivers/pci/host/pci-xgene-ecam.c
+
+diff --git a/drivers/pci/host/Makefile b/drivers/pci/host/Makefile
+index 9c8698e..3480696 100644
+--- a/drivers/pci/host/Makefile
++++ b/drivers/pci/host/Makefile
+@@ -14,7 +14,7 @@ obj-$(CONFIG_PCIE_SPEAR13XX) += pcie-spear13xx.o
+ obj-$(CONFIG_PCI_KEYSTONE) += pci-keystone-dw.o pci-keystone.o
+ obj-$(CONFIG_PCIE_XILINX) += pcie-xilinx.o
+ obj-$(CONFIG_PCIE_XILINX_NWL) += pcie-xilinx-nwl.o
+-obj-$(CONFIG_PCI_XGENE) += pci-xgene.o
++obj-$(CONFIG_PCI_XGENE) += pci-xgene.o pci-xgene-ecam.o
+ obj-$(CONFIG_PCI_XGENE_MSI) += pci-xgene-msi.o
+ obj-$(CONFIG_PCI_LAYERSCAPE) += pci-layerscape.o
+ obj-$(CONFIG_PCI_VERSATILE) += pci-versatile.o
+diff --git a/drivers/pci/host/pci-xgene-ecam.c b/drivers/pci/host/pci-xgene-ecam.c
+new file mode 100644
+index 0000000..1bea63f
+--- /dev/null
++++ b/drivers/pci/host/pci-xgene-ecam.c
+@@ -0,0 +1,194 @@
++/*
++ * APM X-Gene PCIe ECAM fixup driver
++ *
++ * Copyright (c) 2016, Applied Micro Circuits Corporation
++ * Author:
++ * Duc Dang <dhdang@apm.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program. If not, see <http://www.gnu.org/licenses/>.
++ */
++
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/of_address.h>
++#include <linux/of_pci.h>
++#include <linux/pci-acpi.h>
++#include <linux/platform_device.h>
++#include <linux/pci-ecam.h>
++
++#ifdef CONFIG_ACPI
++#define RTDID 0x160
++#define ROOT_CAP_AND_CTRL 0x5C
++
++/* PCIe IP version */
++#define XGENE_PCIE_IP_VER_UNKN 0
++#define XGENE_PCIE_IP_VER_1 1
++
++#define APM_OEM_ID "APM"
++#define APM_XGENE_OEM_TABLE_ID "XGENE"
++#define APM_XGENE_OEM_REV 0x00000002
++
++struct xgene_pcie_acpi_root {
++ void __iomem *csr_base;
++ u32 version;
++};
++
++static acpi_status xgene_pcie_find_csr_base(struct acpi_resource *acpi_res,
++ void *data)
++{
++ struct xgene_pcie_acpi_root *root = data;
++ struct acpi_resource_fixed_memory32 *fixed32;
++
++ if (acpi_res->type == ACPI_RESOURCE_TYPE_FIXED_MEMORY32) {
++ fixed32 = &acpi_res->data.fixed_memory32;
++ root->csr_base = ioremap(fixed32->address,
++ fixed32->address_length);
++ return AE_CTRL_TERMINATE;
++ }
++
++ return AE_OK;
++}
++
++static int xgene_pcie_ecam_init(struct pci_config_window *cfg)
++{
++ struct xgene_pcie_acpi_root *xgene_root;
++ struct device *dev = cfg->parent;
++ struct acpi_device *adev = to_acpi_device(dev);
++ acpi_handle handle = acpi_device_handle(adev);
++
++ xgene_root = devm_kzalloc(dev, sizeof(*xgene_root), GFP_KERNEL);
++ if (!xgene_root)
++ return -ENOMEM;
++
++ acpi_walk_resources(handle, METHOD_NAME__CRS,
++ xgene_pcie_find_csr_base, xgene_root);
++
++ if (!xgene_root->csr_base) {
++ kfree(xgene_root);
++ return -ENODEV;
++ }
++
++ xgene_root->version = XGENE_PCIE_IP_VER_1;
++
++ cfg->priv = xgene_root;
++
++ return 0;
++}
++
++/*
++ * For Configuration request, RTDID register is used as Bus Number,
++ * Device Number and Function number of the header fields.
++ */
++static void xgene_pcie_set_rtdid_reg(struct pci_bus *bus, uint devfn)
++{
++ struct pci_config_window *cfg = bus->sysdata;
++ struct xgene_pcie_acpi_root *port = cfg->priv;
++ unsigned int b, d, f;
++ u32 rtdid_val = 0;
++
++ b = bus->number;
++ d = PCI_SLOT(devfn);
++ f = PCI_FUNC(devfn);
++
++ if (!pci_is_root_bus(bus))
++ rtdid_val = (b << 8) | (d << 3) | f;
++
++ writel(rtdid_val, port->csr_base + RTDID);
++ /* read the register back to ensure flush */
++ readl(port->csr_base + RTDID);
++}
++
++/*
++ * X-Gene PCIe port uses BAR0-BAR1 of RC's configuration space as
++ * the translation from PCI bus to native BUS. Entire DDR region
++ * is mapped into PCIe space using these registers, so it can be
++ * reached by DMA from EP devices. The BAR0/1 of bridge should be
++ * hidden during enumeration to avoid the sizing and resource allocation
++ * by PCIe core.
++ */
++static bool xgene_pcie_hide_rc_bars(struct pci_bus *bus, int offset)
++{
++ if (pci_is_root_bus(bus) && ((offset == PCI_BASE_ADDRESS_0) ||
++ (offset == PCI_BASE_ADDRESS_1)))
++ return true;
++
++ return false;
++}
++
++void __iomem *xgene_pcie_ecam_map_bus(struct pci_bus *bus,
++ unsigned int devfn, int where)
++{
++ struct pci_config_window *cfg = bus->sysdata;
++ unsigned int busn = bus->number;
++ void __iomem *base;
++
++ if (busn < cfg->busr.start || busn > cfg->busr.end)
++ return NULL;
++
++ if ((pci_is_root_bus(bus) && devfn != 0) ||
++ xgene_pcie_hide_rc_bars(bus, where))
++ return NULL;
++
++ xgene_pcie_set_rtdid_reg(bus, devfn);
++
++ if (busn > cfg->busr.start)
++ base = cfg->win + (1 << cfg->ops->bus_shift);
++ else
++ base = cfg->win;
++
++ return base + where;
++}
++
++static int xgene_pcie_config_read32(struct pci_bus *bus, unsigned int devfn,
++ int where, int size, u32 *val)
++{
++ struct pci_config_window *cfg = bus->sysdata;
++ struct xgene_pcie_acpi_root *port = cfg->priv;
++
++ if (pci_generic_config_read32(bus, devfn, where & ~0x3, 4, val) !=
++ PCIBIOS_SUCCESSFUL)
++ return PCIBIOS_DEVICE_NOT_FOUND;
++
++ /*
++ * The v1 controller has a bug in its Configuration Request
++ * Retry Status (CRS) logic: when CRS is enabled and we read the
++ * Vendor and Device ID of a non-existent device, the controller
++ * fabricates return data of 0xFFFF0001 ("device exists but is not
++ * ready") instead of 0xFFFFFFFF ("device does not exist"). This
++ * causes the PCI core to retry the read until it times out.
++ * Avoid this by not claiming to support CRS.
++ */
++ if (pci_is_root_bus(bus) && (port->version == XGENE_PCIE_IP_VER_1) &&
++ ((where & ~0x3) == ROOT_CAP_AND_CTRL))
++ *val &= ~(PCI_EXP_RTCAP_CRSVIS << 16);
++
++ if (size <= 2)
++ *val = (*val >> (8 * (where & 3))) & ((1 << (size * 8)) - 1);
++
++ return PCIBIOS_SUCCESSFUL;
++}
++
++static struct pci_ecam_ops xgene_pcie_ecam_ops = {
++ .bus_shift = 16,
++ .init = xgene_pcie_ecam_init,
++ .pci_ops = {
++ .map_bus = xgene_pcie_ecam_map_bus,
++ .read = xgene_pcie_config_read32,
++ .write = pci_generic_config_write,
++ }
++};
++
++DECLARE_ACPI_MCFG_FIXUP(&xgene_pcie_ecam_ops, APM_OEM_ID,
++ APM_XGENE_OEM_TABLE_ID, APM_XGENE_OEM_REV,
++ PCI_MCFG_DOMAIN_ANY, PCI_MCFG_BUS_ANY);
++#endif
+--
+2.7.4
+
diff --git a/audit-fix-a-double-fetch-in-audit_log_single_execve_arg.patch b/audit-fix-a-double-fetch-in-audit_log_single_execve_arg.patch
new file mode 100644
index 000000000..6ee750466
--- /dev/null
+++ b/audit-fix-a-double-fetch-in-audit_log_single_execve_arg.patch
@@ -0,0 +1,413 @@
+From 43761473c254b45883a64441dd0bc85a42f3645c Mon Sep 17 00:00:00 2001
+From: Paul Moore <paul@paul-moore.com>
+Date: Tue, 19 Jul 2016 17:42:57 -0400
+Subject: [PATCH] audit: fix a double fetch in audit_log_single_execve_arg()
+
+There is a double fetch problem in audit_log_single_execve_arg()
+where we first check the execve(2) argumnets for any "bad" characters
+which would require hex encoding and then re-fetch the arguments for
+logging in the audit record[1]. Of course this leaves a window of
+opportunity for an unsavory application to munge with the data.
+
+This patch reworks things by only fetching the argument data once[2]
+into a buffer where it is scanned and logged into the audit
+records(s). In addition to fixing the double fetch, this patch
+improves on the original code in a few other ways: better handling
+of large arguments which require encoding, stricter record length
+checking, and some performance improvements (completely unverified,
+but we got rid of some strlen() calls, that's got to be a good
+thing).
+
+As part of the development of this patch, I've also created a basic
+regression test for the audit-testsuite, the test can be tracked on
+GitHub at the following link:
+
+ * https://github.com/linux-audit/audit-testsuite/issues/25
+
+[1] If you pay careful attention, there is actually a triple fetch
+problem due to a strnlen_user() call at the top of the function.
+
+[2] This is a tiny white lie, we do make a call to strnlen_user()
+prior to fetching the argument data. I don't like it, but due to the
+way the audit record is structured we really have no choice unless we
+copy the entire argument at once (which would require a rather
+wasteful allocation). The good news is that with this patch the
+kernel no longer relies on this strnlen_user() value for anything
+beyond recording it in the log, we also update it with a trustworthy
+value whenever possible.
+
+Reported-by: Pengfei Wang <wpengfeinudt@gmail.com>
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Paul Moore <paul@paul-moore.com>
+---
+ kernel/auditsc.c | 332 +++++++++++++++++++++++++++----------------------------
+ 1 file changed, 164 insertions(+), 168 deletions(-)
+
+diff --git a/kernel/auditsc.c b/kernel/auditsc.c
+index aa3feec..c65af21 100644
+--- a/kernel/auditsc.c
++++ b/kernel/auditsc.c
+@@ -73,6 +73,7 @@
+ #include <linux/compat.h>
+ #include <linux/ctype.h>
+ #include <linux/string.h>
++#include <linux/uaccess.h>
+ #include <uapi/linux/limits.h>
+
+ #include "audit.h"
+@@ -82,7 +83,8 @@
+ #define AUDITSC_SUCCESS 1
+ #define AUDITSC_FAILURE 2
+
+-/* no execve audit message should be longer than this (userspace limits) */
++/* no execve audit message should be longer than this (userspace limits),
++ * see the note near the top of audit_log_execve_info() about this value */
+ #define MAX_EXECVE_AUDIT_LEN 7500
+
+ /* max length to print of cmdline/proctitle value during audit */
+@@ -992,184 +994,178 @@ static int audit_log_pid_context(struct audit_context *context, pid_t pid,
+ return rc;
+ }
+
+-/*
+- * to_send and len_sent accounting are very loose estimates. We aren't
+- * really worried about a hard cap to MAX_EXECVE_AUDIT_LEN so much as being
+- * within about 500 bytes (next page boundary)
+- *
+- * why snprintf? an int is up to 12 digits long. if we just assumed when
+- * logging that a[%d]= was going to be 16 characters long we would be wasting
+- * space in every audit message. In one 7500 byte message we can log up to
+- * about 1000 min size arguments. That comes down to about 50% waste of space
+- * if we didn't do the snprintf to find out how long arg_num_len was.
+- */
+-static int audit_log_single_execve_arg(struct audit_context *context,
+- struct audit_buffer **ab,
+- int arg_num,
+- size_t *len_sent,
+- const char __user *p,
+- char *buf)
++static void audit_log_execve_info(struct audit_context *context,
++ struct audit_buffer **ab)
+ {
+- char arg_num_len_buf[12];
+- const char __user *tmp_p = p;
+- /* how many digits are in arg_num? 5 is the length of ' a=""' */
+- size_t arg_num_len = snprintf(arg_num_len_buf, 12, "%d", arg_num) + 5;
+- size_t len, len_left, to_send;
+- size_t max_execve_audit_len = MAX_EXECVE_AUDIT_LEN;
+- unsigned int i, has_cntl = 0, too_long = 0;
+- int ret;
+-
+- /* strnlen_user includes the null we don't want to send */
+- len_left = len = strnlen_user(p, MAX_ARG_STRLEN) - 1;
+-
+- /*
+- * We just created this mm, if we can't find the strings
+- * we just copied into it something is _very_ wrong. Similar
+- * for strings that are too long, we should not have created
+- * any.
+- */
+- if (WARN_ON_ONCE(len < 0 || len > MAX_ARG_STRLEN - 1)) {
+- send_sig(SIGKILL, current, 0);
+- return -1;
++ long len_max;
++ long len_rem;
++ long len_full;
++ long len_buf;
++ long len_abuf;
++ long len_tmp;
++ bool require_data;
++ bool encode;
++ unsigned int iter;
++ unsigned int arg;
++ char *buf_head;
++ char *buf;
++ const char __user *p = (const char __user *)current->mm->arg_start;
++
++ /* NOTE: this buffer needs to be large enough to hold all the non-arg
++ * data we put in the audit record for this argument (see the
++ * code below) ... at this point in time 96 is plenty */
++ char abuf[96];
++
++ /* NOTE: we set MAX_EXECVE_AUDIT_LEN to a rather arbitrary limit, the
++ * current value of 7500 is not as important as the fact that it
++ * is less than 8k, a setting of 7500 gives us plenty of wiggle
++ * room if we go over a little bit in the logging below */
++ WARN_ON_ONCE(MAX_EXECVE_AUDIT_LEN > 7500);
++ len_max = MAX_EXECVE_AUDIT_LEN;
++
++ /* scratch buffer to hold the userspace args */
++ buf_head = kmalloc(MAX_EXECVE_AUDIT_LEN + 1, GFP_KERNEL);
++ if (!buf_head) {
++ audit_panic("out of memory for argv string");
++ return;
+ }
++ buf = buf_head;
+
+- /* walk the whole argument looking for non-ascii chars */
++ audit_log_format(*ab, "argc=%d", context->execve.argc);
++
++ len_rem = len_max;
++ len_buf = 0;
++ len_full = 0;
++ require_data = true;
++ encode = false;
++ iter = 0;
++ arg = 0;
+ do {
+- if (len_left > MAX_EXECVE_AUDIT_LEN)
+- to_send = MAX_EXECVE_AUDIT_LEN;
+- else
+- to_send = len_left;
+- ret = copy_from_user(buf, tmp_p, to_send);
+- /*
+- * There is no reason for this copy to be short. We just
+- * copied them here, and the mm hasn't been exposed to user-
+- * space yet.
+- */
+- if (ret) {
+- WARN_ON(1);
+- send_sig(SIGKILL, current, 0);
+- return -1;
+- }
+- buf[to_send] = '\0';
+- has_cntl = audit_string_contains_control(buf, to_send);
+- if (has_cntl) {
+- /*
+- * hex messages get logged as 2 bytes, so we can only
+- * send half as much in each message
+- */
+- max_execve_audit_len = MAX_EXECVE_AUDIT_LEN / 2;
+- break;
+- }
+- len_left -= to_send;
+- tmp_p += to_send;
+- } while (len_left > 0);
+-
+- len_left = len;
+-
+- if (len > max_execve_audit_len)
+- too_long = 1;
+-
+- /* rewalk the argument actually logging the message */
+- for (i = 0; len_left > 0; i++) {
+- int room_left;
+-
+- if (len_left > max_execve_audit_len)
+- to_send = max_execve_audit_len;
+- else
+- to_send = len_left;
+-
+- /* do we have space left to send this argument in this ab? */
+- room_left = MAX_EXECVE_AUDIT_LEN - arg_num_len - *len_sent;
+- if (has_cntl)
+- room_left -= (to_send * 2);
+- else
+- room_left -= to_send;
+- if (room_left < 0) {
+- *len_sent = 0;
+- audit_log_end(*ab);
+- *ab = audit_log_start(context, GFP_KERNEL, AUDIT_EXECVE);
+- if (!*ab)
+- return 0;
+- }
++ /* NOTE: we don't ever want to trust this value for anything
++ * serious, but the audit record format insists we
++ * provide an argument length for really long arguments,
++ * e.g. > MAX_EXECVE_AUDIT_LEN, so we have no choice but
++ * to use strncpy_from_user() to obtain this value for
++ * recording in the log, although we don't use it
++ * anywhere here to avoid a double-fetch problem */
++ if (len_full == 0)
++ len_full = strnlen_user(p, MAX_ARG_STRLEN) - 1;
++
++ /* read more data from userspace */
++ if (require_data) {
++ /* can we make more room in the buffer? */
++ if (buf != buf_head) {
++ memmove(buf_head, buf, len_buf);
++ buf = buf_head;
++ }
++
++ /* fetch as much as we can of the argument */
++ len_tmp = strncpy_from_user(&buf_head[len_buf], p,
++ len_max - len_buf);
++ if (len_tmp == -EFAULT) {
++ /* unable to copy from userspace */
++ send_sig(SIGKILL, current, 0);
++ goto out;
++ } else if (len_tmp == (len_max - len_buf)) {
++ /* buffer is not large enough */
++ require_data = true;
++ /* NOTE: if we are going to span multiple
++ * buffers force the encoding so we stand
++ * a chance at a sane len_full value and
++ * consistent record encoding */
++ encode = true;
++ len_full = len_full * 2;
++ p += len_tmp;
++ } else {
++ require_data = false;
++ if (!encode)
++ encode = audit_string_contains_control(
++ buf, len_tmp);
++ /* try to use a trusted value for len_full */
++ if (len_full < len_max)
++ len_full = (encode ?
++ len_tmp * 2 : len_tmp);
++ p += len_tmp + 1;
++ }
++ len_buf += len_tmp;
++ buf_head[len_buf] = '\0';
+
+- /*
+- * first record needs to say how long the original string was
+- * so we can be sure nothing was lost.
+- */
+- if ((i == 0) && (too_long))
+- audit_log_format(*ab, " a%d_len=%zu", arg_num,
+- has_cntl ? 2*len : len);
+-
+- /*
+- * normally arguments are small enough to fit and we already
+- * filled buf above when we checked for control characters
+- * so don't bother with another copy_from_user
+- */
+- if (len >= max_execve_audit_len)
+- ret = copy_from_user(buf, p, to_send);
+- else
+- ret = 0;
+- if (ret) {
+- WARN_ON(1);
+- send_sig(SIGKILL, current, 0);
+- return -1;
++ /* length of the buffer in the audit record? */
++ len_abuf = (encode ? len_buf * 2 : len_buf + 2);
+ }
+- buf[to_send] = '\0';
+-
+- /* actually log it */
+- audit_log_format(*ab, " a%d", arg_num);
+- if (too_long)
+- audit_log_format(*ab, "[%d]", i);
+- audit_log_format(*ab, "=");
+- if (has_cntl)
+- audit_log_n_hex(*ab, buf, to_send);
+- else
+- audit_log_string(*ab, buf);
+-
+- p += to_send;
+- len_left -= to_send;
+- *len_sent += arg_num_len;
+- if (has_cntl)
+- *len_sent += to_send * 2;
+- else
+- *len_sent += to_send;
+- }
+- /* include the null we didn't log */
+- return len + 1;
+-}
+
+-static void audit_log_execve_info(struct audit_context *context,
+- struct audit_buffer **ab)
+-{
+- int i, len;
+- size_t len_sent = 0;
+- const char __user *p;
+- char *buf;
++ /* write as much as we can to the audit log */
++ if (len_buf > 0) {
++ /* NOTE: some magic numbers here - basically if we
++ * can't fit a reasonable amount of data into the
++ * existing audit buffer, flush it and start with
++ * a new buffer */
++ if ((sizeof(abuf) + 8) > len_rem) {
++ len_rem = len_max;
++ audit_log_end(*ab);
++ *ab = audit_log_start(context,
++ GFP_KERNEL, AUDIT_EXECVE);
++ if (!*ab)
++ goto out;
++ }
+
+- p = (const char __user *)current->mm->arg_start;
++ /* create the non-arg portion of the arg record */
++ len_tmp = 0;
++ if (require_data || (iter > 0) ||
++ ((len_abuf + sizeof(abuf)) > len_rem)) {
++ if (iter == 0) {
++ len_tmp += snprintf(&abuf[len_tmp],
++ sizeof(abuf) - len_tmp,
++ " a%d_len=%lu",
++ arg, len_full);
++ }
++ len_tmp += snprintf(&abuf[len_tmp],
++ sizeof(abuf) - len_tmp,
++ " a%d[%d]=", arg, iter++);
++ } else
++ len_tmp += snprintf(&abuf[len_tmp],
++ sizeof(abuf) - len_tmp,
++ " a%d=", arg);
++ WARN_ON(len_tmp >= sizeof(abuf));
++ abuf[sizeof(abuf) - 1] = '\0';
++
++ /* log the arg in the audit record */
++ audit_log_format(*ab, "%s", abuf);
++ len_rem -= len_tmp;
++ len_tmp = len_buf;
++ if (encode) {
++ if (len_abuf > len_rem)
++ len_tmp = len_rem / 2; /* encoding */
++ audit_log_n_hex(*ab, buf, len_tmp);
++ len_rem -= len_tmp * 2;
++ len_abuf -= len_tmp * 2;
++ } else {
++ if (len_abuf > len_rem)
++ len_tmp = len_rem - 2; /* quotes */
++ audit_log_n_string(*ab, buf, len_tmp);
++ len_rem -= len_tmp + 2;
++ /* don't subtract the "2" because we still need
++ * to add quotes to the remaining string */
++ len_abuf -= len_tmp;
++ }
++ len_buf -= len_tmp;
++ buf += len_tmp;
++ }
+
+- audit_log_format(*ab, "argc=%d", context->execve.argc);
++ /* ready to move to the next argument? */
++ if ((len_buf == 0) && !require_data) {
++ arg++;
++ iter = 0;
++ len_full = 0;
++ require_data = true;
++ encode = false;
++ }
++ } while (arg < context->execve.argc);
+
+- /*
+- * we need some kernel buffer to hold the userspace args. Just
+- * allocate one big one rather than allocating one of the right size
+- * for every single argument inside audit_log_single_execve_arg()
+- * should be <8k allocation so should be pretty safe.
+- */
+- buf = kmalloc(MAX_EXECVE_AUDIT_LEN + 1, GFP_KERNEL);
+- if (!buf) {
+- audit_panic("out of memory for argv string");
+- return;
+- }
++ /* NOTE: the caller handles the final audit_log_end() call */
+
+- for (i = 0; i < context->execve.argc; i++) {
+- len = audit_log_single_execve_arg(context, ab, i,
+- &len_sent, p, buf);
+- if (len <= 0)
+- break;
+- p += len;
+- }
+- kfree(buf);
++out:
++ kfree(buf_head);
+ }
+
+ static void show_special(struct audit_context *context, int *call_panic)
diff --git a/bcm283x-upstream-fixes.patch b/bcm283x-upstream-fixes.patch
new file mode 100644
index 000000000..c5ee31784
--- /dev/null
+++ b/bcm283x-upstream-fixes.patch
@@ -0,0 +1,194 @@
+From da77f737f9f5a487f3a1f80f8546585ee18cd7b9 Mon Sep 17 00:00:00 2001
+From: Eric Anholt <eric@anholt.net>
+Date: Fri, 4 Mar 2016 10:39:28 -0800
+Subject: [PATCH 27/36] dt-bindings: Add root properties for Raspberry Pi 3
+
+Signed-off-by: Eric Anholt <eric@anholt.net>
+Acked-by: Rob Herring <robh@kernel.org>
+---
+ Documentation/devicetree/bindings/arm/bcm/brcm,bcm2835.txt | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/Documentation/devicetree/bindings/arm/bcm/brcm,bcm2835.txt b/Documentation/devicetree/bindings/arm/bcm/brcm,bcm2835.txt
+index 11d3056..6ffe087 100644
+--- a/Documentation/devicetree/bindings/arm/bcm/brcm,bcm2835.txt
++++ b/Documentation/devicetree/bindings/arm/bcm/brcm,bcm2835.txt
+@@ -30,6 +30,10 @@ Raspberry Pi 2 Model B
+ Required root node properties:
+ compatible = "raspberrypi,2-model-b", "brcm,bcm2836";
+
++Raspberry Pi 3 Model B
++Required root node properties:
++compatible = "raspberrypi,3-model-b", "brcm,bcm2837";
++
+ Raspberry Pi Compute Module
+ Required root node properties:
+ compatible = "raspberrypi,compute-module", "brcm,bcm2835";
+--
+2.7.3
+
+From b76b1cdf2e569cceab41dcf3b3f6a90965d0a02c Mon Sep 17 00:00:00 2001
+From: Eric Anholt <eric@anholt.net>
+Date: Fri, 4 Mar 2016 10:39:29 -0800
+Subject: [PATCH 28/36] ARM: bcm2835: Add devicetree for the Raspberry Pi 3.
+
+For now this doesn't support the new hardware present on the Pi 3 (BT,
+wifi, GPIO expander). Since the GPIO expander isn't supported, we
+also don't have the LEDs like the other board files do.
+
+Signed-off-by: Eric Anholt <eric@anholt.net>
+Acked-by: Stephen Warren <swarren@wwwdotorg.org>
+---
+ arch/arm/boot/dts/Makefile | 3 +-
+ arch/arm/boot/dts/bcm2837-rpi-3-b.dts | 22 ++++++++++++
+ arch/arm/boot/dts/bcm2837.dtsi | 68 +++++++++++++++++++++++++++++++++++
+ 3 files changed, 92 insertions(+), 1 deletion(-)
+ create mode 100644 arch/arm/boot/dts/bcm2837-rpi-3-b.dts
+ create mode 100644 arch/arm/boot/dts/bcm2837.dtsi
+
+diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
+index d000814..a8a0767 100644
+--- a/arch/arm/boot/dts/Makefile
++++ b/arch/arm/boot/dts/Makefile
+@@ -64,7 +64,8 @@ dtb-$(CONFIG_ARCH_BCM2835) += \
+ bcm2835-rpi-b-rev2.dtb \
+ bcm2835-rpi-b-plus.dtb \
+ bcm2835-rpi-a-plus.dtb \
+- bcm2836-rpi-2-b.dtb
++ bcm2836-rpi-2-b.dtb \
++ bcm2837-rpi-3-b.dtb
+ dtb-$(CONFIG_ARCH_BCM_5301X) += \
+ bcm4708-asus-rt-ac56u.dtb \
+ bcm4708-asus-rt-ac68u.dtb \
+diff --git a/arch/arm/boot/dts/bcm2837-rpi-3-b.dts b/arch/arm/boot/dts/bcm2837-rpi-3-b.dts
+new file mode 100644
+index 0000000..5e8eafd
+--- /dev/null
++++ b/arch/arm/boot/dts/bcm2837-rpi-3-b.dts
+@@ -0,0 +1,22 @@
++/dts-v1/;
++#include "bcm2837.dtsi"
++#include "bcm2835-rpi.dtsi"
++
++/ {
++ compatible = "raspberrypi,3-model-b", "brcm,bcm2837";
++ model = "Raspberry Pi 3 Model B";
++
++ memory {
++ reg = <0 0x40000000>;
++ };
++};
++
++&gpio {
++ pinctrl-0 = <&gpioout &alt0 &i2s_alt0 &alt3>;
++
++ /* I2S interface */
++ i2s_alt0: i2s_alt0 {
++ brcm,pins = <28 29 30 31>;
++ brcm,function = <BCM2835_FSEL_ALT2>;
++ };
++};
+diff --git a/arch/arm/boot/dts/bcm2837.dtsi b/arch/arm/boot/dts/bcm2837.dtsi
+new file mode 100644
+index 0000000..2f36722
+--- /dev/null
++++ b/arch/arm/boot/dts/bcm2837.dtsi
+@@ -0,0 +1,68 @@
++#include "bcm283x.dtsi"
++
++/ {
++ compatible = "brcm,bcm2836";
++
++ soc {
++ ranges = <0x7e000000 0x3f000000 0x1000000>,
++ <0x40000000 0x40000000 0x00001000>;
++ dma-ranges = <0xc0000000 0x00000000 0x3f000000>;
++
++ local_intc: local_intc {
++ compatible = "brcm,bcm2836-l1-intc";
++ reg = <0x40000000 0x100>;
++ interrupt-controller;
++ #interrupt-cells = <1>;
++ interrupt-parent = <&local_intc>;
++ };
++ };
++
++ timer {
++ compatible = "arm,armv7-timer";
++ interrupt-parent = <&local_intc>;
++ interrupts = <0>, // PHYS_SECURE_PPI
++ <1>, // PHYS_NONSECURE_PPI
++ <3>, // VIRT_PPI
++ <2>; // HYP_PPI
++ always-on;
++ };
++
++ cpus: cpus {
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ cpu0: cpu@0 {
++ device_type = "cpu";
++ compatible = "arm,cortex-a53";
++ reg = <0>;
++ };
++
++ cpu1: cpu@1 {
++ device_type = "cpu";
++ compatible = "arm,cortex-a53";
++ reg = <1>;
++ };
++
++ cpu2: cpu@2 {
++ device_type = "cpu";
++ compatible = "arm,cortex-a53";
++ reg = <2>;
++ };
++
++ cpu3: cpu@3 {
++ device_type = "cpu";
++ compatible = "arm,cortex-a53";
++ reg = <3>;
++ };
++ };
++};
++
++/* Make the BCM2835-style global interrupt controller be a child of the
++ * CPU-local interrupt controller.
++ */
++&intc {
++ compatible = "brcm,bcm2836-armctrl-ic";
++ reg = <0x7e00b200 0x200>;
++ interrupt-parent = <&local_intc>;
++ interrupts = <8>;
++};
+--
+2.7.3
+
+From 528285e99c25249456023d28f521689bf9e9eb8b Mon Sep 17 00:00:00 2001
+From: Peter Robinson <pbrobinson@gmail.com>
+Date: Wed, 30 Mar 2016 09:35:13 +0100
+Subject: [PATCH 32/36] drop usb power domain support for the moment, kills usb
+
+---
+ arch/arm/boot/dts/bcm2835-rpi.dtsi | 4 ----
+ 1 file changed, 4 deletions(-)
+
+diff --git a/arch/arm/boot/dts/bcm2835-rpi.dtsi b/arch/arm/boot/dts/bcm2835-rpi.dtsi
+index caf2707..b1e8145 100644
+--- a/arch/arm/boot/dts/bcm2835-rpi.dtsi
++++ b/arch/arm/boot/dts/bcm2835-rpi.dtsi
+@@ -71,10 +71,6 @@
+ status = "okay";
+ };
+
+-&usb {
+- power-domains = <&power RPI_POWER_DOMAIN_USB>;
+-};
+-
+ &v3d {
+ power-domains = <&power RPI_POWER_DOMAIN_V3D>;
+ };
+--
+2.7.3
+
diff --git a/config-arm-generic b/config-arm-generic
index 4153f33c0..f81cdb1f8 100644
--- a/config-arm-generic
+++ b/config-arm-generic
@@ -215,6 +215,7 @@ CONFIG_DRM_TEGRA=m
CONFIG_DRM_TEGRA_STAGING=y
CONFIG_NOUVEAU_PLATFORM_DRIVER=y
CONFIG_SND_HDA_TEGRA=m
+CONFIG_RTC_DRV_MAX77686=m
# CONFIG_ARM_TEGRA20_CPUFREQ is not set
# CONFIG_MFD_NVEC is not set
diff --git a/config-arm64 b/config-arm64
index 60aa6cbbe..a9a02f81f 100644
--- a/config-arm64
+++ b/config-arm64
@@ -164,6 +164,7 @@ CONFIG_ARCH_TEGRA_210_SOC=y
CONFIG_TEGRA210_ADMA=y
CONFIG_MFD_MAX77620=y
CONFIG_REGULATOR_MAX77620=m
+# CONFIG_GPIO_TEGRA is not set
# AllWinner
CONFIG_MACH_SUN50I=y
diff --git a/config-armv7-generic b/config-armv7-generic
index 063b57e11..dbbcbc81e 100644
--- a/config-armv7-generic
+++ b/config-armv7-generic
@@ -365,7 +365,6 @@ CONFIG_INPUT_MAX8997_HAPTIC=m
CONFIG_CHARGER_MAX8997=m
CONFIG_LEDS_MAX8997=m
CONFIG_RTC_DRV_MAX8997=m
-CONFIG_RTC_DRV_MAX77686=m
CONFIG_EXTCON_MAX8997=m
# Tegra
@@ -380,6 +379,7 @@ CONFIG_SND_SOC_TEGRA_RT5677=m
CONFIG_AD525X_DPOT=m
CONFIG_AD525X_DPOT_I2C=m
CONFIG_AD525X_DPOT_SPI=m
+# CONFIG_GPIO_TEGRA is not set
# Jetson TK1
CONFIG_PINCTRL_AS3722=y
diff --git a/config-generic b/config-generic
index 32832687f..82db0f623 100644
--- a/config-generic
+++ b/config-generic
@@ -1837,13 +1837,13 @@ CONFIG_B43=m
CONFIG_B43_SDIO=y
CONFIG_B43_BCMA=y
CONFIG_B43_BCMA_PIO=y
-CONFIG_B43_DEBUG=y
+# CONFIG_B43_DEBUG is not set
CONFIG_B43_PHY_LP=y
CONFIG_B43_PHY_N=y
CONFIG_B43_PHY_HT=y
CONFIG_B43_PHY_G=y
CONFIG_B43LEGACY=m
-CONFIG_B43LEGACY_DEBUG=y
+# CONFIG_B43LEGACY_DEBUG is not set
CONFIG_B43LEGACY_DMA=y
CONFIG_B43LEGACY_PIO=y
CONFIG_B43LEGACY_DMA_AND_PIO_MODE=y
@@ -5218,7 +5218,7 @@ CONFIG_PM_DEBUG=y
# CONFIG_DPM_WATCHDOG is not set # revisit this in debug
CONFIG_PM_TRACE=y
CONFIG_PM_TRACE_RTC=y
-CONFIG_PM_TEST_SUSPEND=y
+# CONFIG_PM_TEST_SUSPEND is not set
# CONFIG_PM_OPP is not set
# CONFIG_PM_AUTOSLEEP is not set
# CONFIG_PM_WAKELOCKS is not set
diff --git a/config-nodebug b/config-nodebug
index 0dc864752..4bd461d8f 100644
--- a/config-nodebug
+++ b/config-nodebug
@@ -2,102 +2,102 @@ CONFIG_SND_VERBOSE_PRINTK=y
CONFIG_SND_DEBUG=y
CONFIG_SND_PCM_XRUN_DEBUG=y
-CONFIG_DEBUG_ATOMIC_SLEEP=y
-
-CONFIG_DEBUG_MUTEXES=y
-CONFIG_DEBUG_RT_MUTEXES=y
-CONFIG_DEBUG_LOCK_ALLOC=y
-CONFIG_LOCK_TORTURE_TEST=m
-CONFIG_PROVE_LOCKING=y
-CONFIG_DEBUG_SPINLOCK=y
-CONFIG_PROVE_RCU=y
+# CONFIG_DEBUG_ATOMIC_SLEEP is not set
+
+# CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_LOCK_TORTURE_TEST is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_PROVE_RCU is not set
# CONFIG_PROVE_RCU_REPEATEDLY is not set
-CONFIG_DEBUG_PER_CPU_MAPS=y
+# CONFIG_DEBUG_PER_CPU_MAPS is not set
CONFIG_CPUMASK_OFFSTACK=y
-CONFIG_CPU_NOTIFIER_ERROR_INJECT=m
+# CONFIG_CPU_NOTIFIER_ERROR_INJECT is not set
-CONFIG_FAULT_INJECTION=y
-CONFIG_FAILSLAB=y
-CONFIG_FAIL_PAGE_ALLOC=y
-CONFIG_FAIL_MAKE_REQUEST=y
-CONFIG_FAULT_INJECTION_DEBUG_FS=y
-CONFIG_FAULT_INJECTION_STACKTRACE_FILTER=y
-CONFIG_FAIL_IO_TIMEOUT=y
-CONFIG_FAIL_MMC_REQUEST=y
+# CONFIG_FAULT_INJECTION is not set
+# CONFIG_FAILSLAB is not set
+# CONFIG_FAIL_PAGE_ALLOC is not set
+# CONFIG_FAIL_MAKE_REQUEST is not set
+# CONFIG_FAULT_INJECTION_DEBUG_FS is not set
+# CONFIG_FAULT_INJECTION_STACKTRACE_FILTER is not set
+# CONFIG_FAIL_IO_TIMEOUT is not set
+# CONFIG_FAIL_MMC_REQUEST is not set
# CONFIG_F2FS_FAULT_INJECTION is not set
-CONFIG_LOCK_STAT=y
+# CONFIG_LOCK_STAT is not set
-CONFIG_DEBUG_STACK_USAGE=y
+# CONFIG_DEBUG_STACK_USAGE is not set
-CONFIG_ACPI_DEBUG=y
+# CONFIG_ACPI_DEBUG is not set
# CONFIG_ACPI_DEBUGGER is not set
-CONFIG_DEBUG_SG=y
-CONFIG_DEBUG_PI_LIST=y
+# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_PI_LIST is not set
# CONFIG_PAGE_EXTENSION is not set
# CONFIG_PAGE_OWNER is not set
# CONFIG_DEBUG_PAGEALLOC is not set
-CONFIG_DEBUG_OBJECTS=y
+# CONFIG_DEBUG_OBJECTS is not set
# CONFIG_DEBUG_OBJECTS_SELFTEST is not set
-CONFIG_DEBUG_OBJECTS_FREE=y
-CONFIG_DEBUG_OBJECTS_TIMERS=y
-CONFIG_DEBUG_OBJECTS_RCU_HEAD=y
+# CONFIG_DEBUG_OBJECTS_FREE is not set
+# CONFIG_DEBUG_OBJECTS_TIMERS is not set
+# CONFIG_DEBUG_OBJECTS_RCU_HEAD is not set
CONFIG_DEBUG_OBJECTS_ENABLE_DEFAULT=1
CONFIG_X86_PTDUMP=y
-CONFIG_ARM64_PTDUMP=y
-CONFIG_EFI_PGT_DUMP=y
+# CONFIG_ARM64_PTDUMP is not set
+# CONFIG_EFI_PGT_DUMP is not set
-CONFIG_CAN_DEBUG_DEVICES=y
+# CONFIG_CAN_DEBUG_DEVICES is not set
-CONFIG_MODULE_FORCE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_DEBUG_NOTIFIERS=y
+# CONFIG_DEBUG_NOTIFIERS is not set
-CONFIG_DMA_API_DEBUG=y
+# CONFIG_DMA_API_DEBUG is not set
-CONFIG_MMIOTRACE=y
+# CONFIG_MMIOTRACE is not set
-CONFIG_DEBUG_CREDENTIALS=y
+# CONFIG_DEBUG_CREDENTIALS is not set
# off in both production debug and nodebug builds,
# on in rawhide nodebug builds
-CONFIG_DEBUG_FORCE_WEAK_PER_CPU=y
+# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set
-CONFIG_EXT4_DEBUG=y
+# CONFIG_EXT4_DEBUG is not set
# CONFIG_XFS_WARN is not set
-CONFIG_DEBUG_PERF_USE_VMALLOC=y
+# CONFIG_DEBUG_PERF_USE_VMALLOC is not set
-CONFIG_JBD2_DEBUG=y
+# CONFIG_JBD2_DEBUG is not set
-CONFIG_NFSD_FAULT_INJECTION=y
+# CONFIG_NFSD_FAULT_INJECTION is not set
-CONFIG_DEBUG_BLK_CGROUP=y
+# CONFIG_DEBUG_BLK_CGROUP is not set
-CONFIG_DRBD_FAULT_INJECTION=y
+# CONFIG_DRBD_FAULT_INJECTION is not set
-CONFIG_ATH_DEBUG=y
-CONFIG_CARL9170_DEBUGFS=y
-CONFIG_IWLWIFI_DEVICE_TRACING=y
+# CONFIG_ATH_DEBUG is not set
+# CONFIG_CARL9170_DEBUGFS is not set
+# CONFIG_IWLWIFI_DEVICE_TRACING is not set
# CONFIG_RTLWIFI_DEBUG is not set
-CONFIG_DEBUG_OBJECTS_WORK=y
+# CONFIG_DEBUG_OBJECTS_WORK is not set
-CONFIG_DMADEVICES_DEBUG=y
+# CONFIG_DMADEVICES_DEBUG is not set
# CONFIG_DMADEVICES_VDEBUG is not set
CONFIG_PM_ADVANCED_DEBUG=y
-CONFIG_CEPH_LIB_PRETTYDEBUG=y
-CONFIG_QUOTA_DEBUG=y
+# CONFIG_CEPH_LIB_PRETTYDEBUG is not set
+# CONFIG_QUOTA_DEBUG is not set
CONFIG_KGDB_KDB=y
@@ -105,19 +105,19 @@ CONFIG_KDB_DEFAULT_ENABLE=0x0
CONFIG_KDB_KEYBOARD=y
CONFIG_KDB_CONTINUE_CATASTROPHIC=0
-CONFIG_DEBUG_OBJECTS_PERCPU_COUNTER=y
+# CONFIG_DEBUG_OBJECTS_PERCPU_COUNTER is not set
# CONFIG_PERCPU_TEST is not set
-CONFIG_TEST_LIST_SORT=y
+# CONFIG_TEST_LIST_SORT is not set
# CONFIG_TEST_STRING_HELPERS is not set
-CONFIG_DETECT_HUNG_TASK=y
+# CONFIG_DETECT_HUNG_TASK is not set
CONFIG_DEFAULT_HUNG_TASK_TIMEOUT=120
# CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set
-CONFIG_WQ_WATCHDOG=y
+# CONFIG_WQ_WATCHDOG is not set
-CONFIG_X86_BOOTPARAM_MEMORY_CORRUPTION_CHECK=y
+# CONFIG_X86_BOOTPARAM_MEMORY_CORRUPTION_CHECK is not set
-CONFIG_DEBUG_KMEMLEAK=y
+# CONFIG_DEBUG_KMEMLEAK is not set
CONFIG_DEBUG_KMEMLEAK_EARLY_LOG_SIZE=1024
# CONFIG_DEBUG_KMEMLEAK_TEST is not set
CONFIG_DEBUG_KMEMLEAK_DEFAULT_OFF=y
@@ -128,4 +128,4 @@ CONFIG_DEBUG_KMEMLEAK_DEFAULT_OFF=y
# CONFIG_SPI_DEBUG is not set
-CONFIG_DEBUG_VM_PGFLAGS=y
+# CONFIG_DEBUG_VM_PGFLAGS is not set
diff --git a/config-x86-generic b/config-x86-generic
index ae80650a4..8ae20bab7 100644
--- a/config-x86-generic
+++ b/config-x86-generic
@@ -381,7 +381,7 @@ CONFIG_SP5100_TCO=m
# CONFIG_MEMTEST is not set
# CONFIG_DEBUG_TLBFLUSH is not set
-CONFIG_MAXSMP=y
+# CONFIG_MAXSMP is not set
CONFIG_HP_ILO=m
diff --git a/gitrev b/gitrev
index d6453fad9..2fd16175c 100644
--- a/gitrev
+++ b/gitrev
@@ -1 +1 @@
-fa3a9f5744a92c0d7856d4e326c8d920d1d31116
+dd9506954539dcedd0294a065ff0976e61386fc6
diff --git a/kernel.spec b/kernel.spec
index c59da2ce7..db0b600dd 100644
--- a/kernel.spec
+++ b/kernel.spec
@@ -6,7 +6,7 @@ Summary: The Linux kernel
# For a stable, released kernel, released_kernel should be 1. For rawhide
# and/or a kernel built from an rc or git snapshot, released_kernel should
# be 0.
-%global released_kernel 0
+%global released_kernel 1
# Sign modules on x86. Make sure the config files match this setting if more
# architectures are added.
@@ -50,7 +50,7 @@ Summary: The Linux kernel
# base_sublevel is the kernel version we're starting with and patching
# on top of -- for example, 3.1-rc7-git1 starts with a 3.0 base,
# which yields a base_sublevel of 0.
-%define base_sublevel 6
+%define base_sublevel 7
## If this is a released kernel ##
%if 0%{?released_kernel}
@@ -75,9 +75,9 @@ Summary: The Linux kernel
# The next upstream release sublevel (base_sublevel+1)
%define upstream_sublevel %(echo $((%{base_sublevel} + 1)))
# The rc snapshot level
-%define rcrev 7
+%define rcrev 0
# The git snapshot level
-%define gitrev 3
+%define gitrev 2
# Set rpm version accordingly
%define rpmversion 4.%{upstream_sublevel}.0
%endif
@@ -133,7 +133,7 @@ Summary: The Linux kernel
# Set debugbuildsenabled to 1 for production (build separate debug kernels)
# and 0 for rawhide (all kernels are debug kernels).
# See also 'make debug' and 'make release'.
-%define debugbuildsenabled 0
+%define debugbuildsenabled 1
# Want to build a vanilla kernel build without any non-upstream patches?
%define with_vanilla %{?_without_vanilla: 0} %{?!_without_vanilla: 1}
@@ -526,16 +526,18 @@ Patch422: geekbox-v4-device-tree-support.patch
# This has major conflicts and needs to be rebased
# Patch423: Initial-AllWinner-A64-and-PINE64-support.patch
+Patch424: arm64-pcie-acpi.patch
+Patch425: arm64-pcie-quirks-xgene.patch
+
# http://www.spinics.net/lists/linux-tegra/msg26029.html
Patch426: usb-phy-tegra-Add-38.4MHz-clock-table-entry.patch
# http://patchwork.ozlabs.org/patch/587554/
Patch430: ARM-tegra-usb-no-reset.patch
-Patch432: arm-i.MX6-Utilite-device-dtb.patch
+Patch431: bcm283x-upstream-fixes.patch
-# mvebu DSA switch fixes
-# http://www.spinics.net/lists/netdev/msg370841.html http://www.spinics.net/lists/netdev/msg370842.html
+Patch432: arm-i.MX6-Utilite-device-dtb.patch
Patch460: lib-cpumask-Make-CPUMASK_OFFSTACK-usable-without-deb.patch
@@ -652,6 +654,9 @@ Patch837: drm-amdgpu-Disable-RPM-helpers-while-reprobing.patch
Patch838: drm-i915-skl-Add-support-for-the-SAGV-fix-underrun-hangs.patch
Patch839: Revert-ALSA-hda-remove-controller-dependency-on-i915.patch
+#CVE-2016-6136 rhbz 1353533 1353534
+Patch841: audit-fix-a-double-fetch-in-audit_log_single_execve_arg.patch
+
# END OF PATCH DEFINITIONS
%endif
@@ -2181,6 +2186,21 @@ fi
#
#
%changelog
+* Mon Jul 25 2016 Josh Boyer <jwboyer@fedoraproject.org>
+- CVE-2016-6136 race condition in auditsc.c (rhbz 1353533 1353534)
+
+* Mon Jul 25 2016 Laura Abbott <labbott@redhat.com> - 4.7.0-1
+- Linux v4.7
+
+* Tue Jul 19 2016 Peter Robinson <pbrobinson@fedoraproject.org>
+- Add aarch64 ACPI pci-e patches headed for 4.8
+
+* Mon Jul 18 2016 Laura Abbott <labbott@redhat.com> - 4.7.0-0.rc7.git4.1
+- Linux v4.7-rc7-92-g47ef4ad
+
+* Mon Jul 18 2016 Peter Robinson <pbrobinson@fedoraproject.org>
+- ARM config updates, update bcm238x patches
+
* Fri Jul 15 2016 Justin M. Forbes <jforbes@fedoraproject.org> - 4.7.0-0.rc7.git3.1
- Linux v4.7-rc7-78-gfa3a9f574
diff --git a/scripts/generate-perf-man.sh b/scripts/generate-perf-man.sh
new file mode 100755
index 000000000..27691fafd
--- /dev/null
+++ b/scripts/generate-perf-man.sh
@@ -0,0 +1,54 @@
+#!/bin/sh
+# Small script to generate the perf-man tarball. The script relies on having
+# LINUX_GIT set in your local .bashrc. By default the script will use the
+# the kernel version of the upstream tree set in LINUX_GIT. Use --version=x.y
+# to set a specific version.
+
+# [Default] eg. ./scritps/generate-perf-man
+# eg. ./scripts/generate-perf-man --version=4.8
+function usage(){
+ echo
+ echo "Helps generate the perf-man tarball "
+ echo "-h, --help "
+ echo
+ echo "./generate-perf-man.sh #Generates using upstream kernel version"
+ echo
+ echo "./generate-perf-man.sh --version=x.y #Generate using x.y version"
+}
+
+if [ -f ~/.bashrc ]; then
+ source ~/.bashrc
+fi
+
+if [ ! -d "$LINUX_GIT" ]; then
+ echo "Error: \$LINUX_GIT is not set to the upstream git tree."
+ exit 1
+fi
+
+BASEDIR=$(dirname "$(cd $(dirname $BASH_SOURCE[0]) && pwd)")
+pushd "$LINUX_GIT" > /dev/null
+KERNEL_VERSION=$( awk '/^VERSION =/ {print $3}' Makefile )
+KERNEL_PATCHLEVEL=$( awk '/^PATCHLEVEL =/ {print $3}' Makefile )
+
+if [ ! -z "$@" ]; then
+ for opt in "$@"; do
+ case $opt in
+ --version=*.*)
+ version="${opt#*=}"
+ KERNEL_VERSION=$( awk -F. '{print $1}' <<< $version )
+ KERNEL_PATCHLEVEL=$( awk -F. '{print $2}' <<< $version )
+ ;;
+ -h | --help)
+ usage
+ exit 0
+ ;;
+ *)
+ ;;
+ esac
+ done
+fi
+cd tools/perf/Documentation/
+make
+tar -czvf $BASEDIR/perf-man-${KERNEL_VERSION}.${KERNEL_PATCHLEVEL}.tar.gz *.1
+make clean
+popd
diff --git a/sources b/sources
index 94cde6332..cc6fb3891 100644
--- a/sources
+++ b/sources
@@ -1,4 +1,2 @@
-d2927020e24a76da4ab482a8bc3e9ef3 linux-4.6.tar.xz
-fd23b14b9d474c3dfacb6e8ee82d3a51 perf-man-4.6.tar.gz
-1ec96a040683561e53e983cfdb09bab8 patch-4.7-rc7.xz
-d53b761734ec9c20c291683f6a80df70 patch-4.7-rc7-git3.xz
+5276563eb1f39a048e4a8a887408c031 linux-4.7.tar.xz
+fe259c02c75eec61d1aa4b1211f3c853 perf-man-4.7.tar.gz
diff --git a/tcp-make-challenge-acks-less-predictable.patch b/tcp-make-challenge-acks-less-predictable.patch
deleted file mode 100644
index 6837cff0b..000000000
--- a/tcp-make-challenge-acks-less-predictable.patch
+++ /dev/null
@@ -1,81 +0,0 @@
-From 0af29b4f03b40fe0980c31d18e352f2ef19ec703 Mon Sep 17 00:00:00 2001
-From: Eric Dumazet <edumazet@google.com>
-Date: Sun, 10 Jul 2016 10:04:02 +0200
-Subject: [PATCH] tcp: make challenge acks less predictable
-
-Yue Cao claims that current host rate limiting of challenge ACKS
-(RFC 5961) could leak enough information to allow a patient attacker
-to hijack TCP sessions. He will soon provide details in an academic
-paper.
-
-This patch increases the default limit from 100 to 1000, and adds
-some randomization so that the attacker can no longer hijack
-sessions without spending a considerable amount of probes.
-
-Based on initial analysis and patch from Linus.
-
-Note that we also have per socket rate limiting, so it is tempting
-to remove the host limit in the future.
-
-v2: randomize the count of challenge acks per second, not the period.
-
-Fixes: 282f23c6ee34 ("tcp: implement RFC 5961 3.2")
-Reported-by: Yue Cao <ycao009@ucr.edu>
-Signed-off-by: Eric Dumazet <edumazet@google.com>
-Suggested-by: Linus Torvalds <torvalds@linux-foundation.org>
-Cc: Yuchung Cheng <ycheng@google.com>
-Cc: Neal Cardwell <ncardwell@google.com>
-Acked-by: Neal Cardwell <ncardwell@google.com>
-Acked-by: Yuchung Cheng <ycheng@google.com>
-Signed-off-by: David S. Miller <davem@davemloft.net>
----
- net/ipv4/tcp_input.c | 15 ++++++++++-----
- 1 file changed, 10 insertions(+), 5 deletions(-)
-
-diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
-index d6c8f4cd0800..91868bb17818 100644
---- a/net/ipv4/tcp_input.c
-+++ b/net/ipv4/tcp_input.c
-@@ -87,7 +87,7 @@ int sysctl_tcp_adv_win_scale __read_mostly = 1;
- EXPORT_SYMBOL(sysctl_tcp_adv_win_scale);
-
- /* rfc5961 challenge ack rate limiting */
--int sysctl_tcp_challenge_ack_limit = 100;
-+int sysctl_tcp_challenge_ack_limit = 1000;
-
- int sysctl_tcp_stdurg __read_mostly;
- int sysctl_tcp_rfc1337 __read_mostly;
-@@ -3458,7 +3458,7 @@ static void tcp_send_challenge_ack(struct sock *sk, const struct sk_buff *skb)
- static u32 challenge_timestamp;
- static unsigned int challenge_count;
- struct tcp_sock *tp = tcp_sk(sk);
-- u32 now;
-+ u32 count, now;
-
- /* First check our per-socket dupack rate limit. */
- if (tcp_oow_rate_limited(sock_net(sk), skb,
-@@ -3466,13 +3466,18 @@ static void tcp_send_challenge_ack(struct sock *sk, const struct sk_buff *skb)
- &tp->last_oow_ack_time))
- return;
-
-- /* Then check the check host-wide RFC 5961 rate limit. */
-+ /* Then check host-wide RFC 5961 rate limit. */
- now = jiffies / HZ;
- if (now != challenge_timestamp) {
-+ u32 half = (sysctl_tcp_challenge_ack_limit + 1) >> 1;
-+
- challenge_timestamp = now;
-- challenge_count = 0;
-+ WRITE_ONCE(challenge_count, half +
-+ prandom_u32_max(sysctl_tcp_challenge_ack_limit));
- }
-- if (++challenge_count <= sysctl_tcp_challenge_ack_limit) {
-+ count = READ_ONCE(challenge_count);
-+ if (count > 0) {
-+ WRITE_ONCE(challenge_count, count - 1);
- NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPCHALLENGEACK);
- tcp_send_ack(sk);
- }
---
-2.5.5
-