From 81c4dc55f83517f99282c822fa0def3e308414b5 Mon Sep 17 00:00:00 2001 From: Kyle McMartin Date: Tue, 11 Nov 2014 09:38:12 -0500 Subject: Re-enable kernel-arm64.patch, and fix up merge conflicts with 3.18-rc4 --- config-arm64 | 6 +- config-generic | 3 + kernel-arm64.patch | 6662 ++++++++++++++++++++++++++++++++++++++-------------- kernel.spec | 7 +- 4 files changed, 4862 insertions(+), 1816 deletions(-) diff --git a/config-arm64 b/config-arm64 index e4775a6cd..a0db86323 100644 --- a/config-arm64 +++ b/config-arm64 @@ -134,5 +134,9 @@ CONFIG_AMD_XGBE_PHY=m # CONFIG_IMX_THERMAL is not set -# temporary 2014-10-21 +# still? 2014-11-11 # CONFIG_BPF_JIT is not set + +CONFIG_DMI=y +CONFIG_DMIID=y +CONFIG_DMI_SYSFS=y diff --git a/config-generic b/config-generic index 4f2825e61..6c7199f48 100644 --- a/config-generic +++ b/config-generic @@ -5278,3 +5278,6 @@ CONFIG_FMC_CHARDEV=m # CONFIG_SBSAUART_TTY is not set # CONFIG_SERIAL_8250_FINTEK is not set + +# set in x86-generic presently +# CONFIG_TOUCHSCREEN_GOODIX is not set diff --git a/kernel-arm64.patch b/kernel-arm64.patch index 3e32005cb..f5b14ec4f 100644 --- a/kernel-arm64.patch +++ b/kernel-arm64.patch @@ -1,8 +1,123 @@ -commit 798bcf9c5057f0acd54154d09abf6fc4fc044e41 +commit ccdf75caa6a1165b8199930983596ef64cf09bd3 Author: Mark Salter -Date: Tue Oct 14 13:51:54 2014 -0400 +Date: Mon Nov 10 17:09:29 2014 -0500 - arm64: [NOT FOR UPSTREAM] fix dma_ops for ACPI and PCI devices + DO NOT UPSTREAM - pci/xgene: Provide fixup for ACPI MCFG support + + Xgene doesn't decode bus bits of mmconfig region and only + supports devfn 0 of bus 0. For other buses/devices, some + internal registers need to be poked. This patch provides + a fixup to support ACPI MCFG tables. This is a horrible + hack allowing the hardware to be used for PCI testing, but + it is not intended to be a long term patch. + + Signed-off-by: Mark Salter + +commit 4421965a8ea7caae3f50760abce1094e0186c05e +Author: Mark Salter +Date: Mon Nov 10 17:33:18 2014 -0500 + + DO NOT UPSTREAM - provide hook for MCFG fixups + + This is a temprary mechanism needed by at least one early + arm64 hardware platform with broken MCFG support. This is + not intended for upstream and will go away as soon as newer + hardware with fully compliant ECAM becomes available. + + Signed-off-by: Mark Salter + +commit dcaeb407c91845739a64fb719a8c8d34474371e8 +Author: Mark Salter +Date: Mon Nov 10 17:30:25 2014 -0500 + + arm64/pci/acpi: initial support for ACPI probing of PCI + + Signed-off-by: Mark Salter + +commit 68c8ee5c1ab7b899401750cc359912efbeb40676 +Author: Mark Salter +Date: Mon Nov 10 17:23:57 2014 -0500 + + arm64/acpi/pci: add support for parsing MCFG table + + Add support for parsing MCFG table and provide functions to read/write + PCI configuration space based on the parsed info. This provides the + low-level raw_pci_read/raw_pci_write functionality. + + Signed-off-by: Mark Salter + +commit fada05b28e93c24e8932539d94a679ce55ff332f +Author: Mark Salter +Date: Mon Nov 10 16:42:14 2014 -0500 + + DO NOT UPSTREAM - pci/xgene: workaround CRS issue + + CRS is not behaving properly for some reason. Until this + gets diagnosed properly, pretend not to support it in order + to prevent hangs in 3.18 kernel. + + Signed-off-by: Mark Salter + +commit e917d30f3febf6d88cc5001ad236ca367a211cef +Author: Duc Dang +Date: Thu Nov 6 17:14:18 2014 -0800 + + PCI: X-Gene: assign resource to bus before adding new devices + + X-Gene PCIE driver currently depends on Liviu Dudau's patch + https://lkml.org/lkml/2014/9/30/166 in order to assign resource + to root bus and endpoint devices. The patch was dropped because + it will break x86, powerpc and probably others. So X-Gene PCIE + host functionality is currently broken. + + This patch adds function calls to create and scan root_bus as well + as assign unassigned bus resource (similar to Liviu Dudau's patch + above). This will help resolve the dependency to Liviu Dudau's patch + and make X-Gene PCIE work in latest open-source kernel. + + Signed-off-by: Duc Dang + Signed-off-by: Tanmay Inamdar + +commit 6581c0591cafe4fa3b0bd9a25a84a5bf830209fd +Author: Mark Salter +Date: Mon Nov 10 16:31:05 2014 -0500 + + iommu/arm-smmu: fix NULL dereference with ACPI PCI devices + + Fix a NULL dereference in find_mmu_master which occurs when + booting with ACPI. In that case, PCI bridges with not have + an of_node. Add a check for NULL of_node and bail out if that + is the case. + + Signed-off-by: Mark Salter + +commit ae7850d2b972ee1258878ccc16824aba9d35b653 +Author: Guenter Roeck +Date: Sun Nov 2 18:19:15 2014 -0800 + + netfilter: nft_reject_bridge: Fix powerpc build error + + Fix: + net/bridge/netfilter/nft_reject_bridge.c: + In function 'nft_reject_br_send_v6_unreach': + net/bridge/netfilter/nft_reject_bridge.c:240:3: + error: implicit declaration of function 'csum_ipv6_magic' + csum_ipv6_magic(&nip6h->saddr, &nip6h->daddr, + ^ + make[3]: *** [net/bridge/netfilter/nft_reject_bridge.o] Error 1 + + Seen with powerpc:allmodconfig. + + Fixes: 523b929d5446 ("netfilter: nft_reject_bridge: don't use IP stack to reject traffic") + Cc: Pablo Neira Ayuso + Signed-off-by: Guenter Roeck + Signed-off-by: David S. Miller + +commit e2992498e4b2aad3ceac52bfb6faccfd18332236 +Author: Mark Salter +Date: Mon Nov 10 21:35:11 2014 -0500 + + DO NOT UPSTREAM - arm64: fix dma_ops for ACPI and PCI devices Commit 2189064795dc3fb4101e5: @@ -14,7 +129,7 @@ Date: Tue Oct 14 13:51:54 2014 -0400 Signed-off-by: Mark Salter -commit 4b7a879d4fe95e935a06bd5209026a2278251ce6 +commit ceb5533cf5a6b68b68dc4b8ad61f5671576bdaf2 Author: Mark Salter Date: Thu Aug 14 12:32:13 2014 -0400 @@ -33,7 +148,7 @@ Date: Thu Aug 14 12:32:13 2014 -0400 Signed-off-by: Mark Salter -commit 0e83bbc67aa2ced7b0f62bc9cdbf8026f3a83ea7 +commit 21fef5d50bb3d4465c6b644bc451c1d219967a81 Author: Wei Huang Date: Thu Sep 18 20:02:57 2014 -0400 @@ -50,7 +165,7 @@ Date: Thu Sep 18 20:02:57 2014 -0400 Signed-off-by: Wei Huang -commit b01e346d3156935d05aada065b69dbd4e8e3c38e +commit 3357db72822a2c9bc012528c6be3cf861fb3f35c Author: Wei Huang Date: Thu Sep 18 20:02:56 2014 -0400 @@ -63,7 +178,7 @@ Date: Thu Sep 18 20:02:56 2014 -0400 Signed-off-by: Wei Huang -commit 1f7fbdb23b3f616344bc6ab42d133528508b4183 +commit dc62803a26a34bb3190c9c1b5e3639ca6ebbf788 Author: Wei Huang Date: Thu Sep 18 20:02:55 2014 -0400 @@ -80,15 +195,7 @@ Date: Thu Sep 18 20:02:55 2014 -0400 Signed-off-by: Wei Huang -commit f1e1479c450a58b7fc68fec33c39b050dcc4b13d -Author: Al Stone -Date: Thu Sep 18 15:46:38 2014 -0600 - - DO NOT UPSTREAM -- patch to work around bad MAC of 0x0 - - Signed-off-by: Al Stone - -commit b97981d8eaeef88d34b68d6bf6fae3088fce76f6 +commit 18099d49d96bfac5096b8ad1d3d5c6d14f92e0a1 Author: Tom Lendacky Date: Mon Sep 15 17:02:52 2014 -0600 @@ -99,106 +206,289 @@ Date: Mon Sep 15 17:02:52 2014 -0600 Signed-off-by: Tom Lendacky -commit dd2c9edb72ff2e36152bae3bdf4f849b155c6178 +commit 7f208a9dffd58379f2e42e226052386e93d4b2dd Author: Mark Salter Date: Tue Oct 7 12:54:08 2014 -0400 xgene acpi network - first cut -commit 34f6f9c9a449fce5038a79ef74d85c0cd8aa983d -Author: Mika Westerberg -Date: Wed Oct 1 04:22:27 2014 +0200 +commit e3ce87d3414a845f8cbf71f0d80f3f3136995ce6 +Author: Geert Uytterhoeven +Date: Thu Nov 6 12:23:23 2014 +0100 - misc: at25: Add ACPI probing support + leds: leds-gpio: Fix legacy GPIO number case - Add support for matching using DT compatible string from ACPI _DSD. + In the legacy case, led_dat->gpiod is initialized correctly, but + overwritten later by template->gpiod, which is NULL, causing leds-gpio + to fail with: - Signed-off-by: Mika Westerberg + gpiod_direction_output: invalid GPIO + leds-gpio: probe of leds-gpio failed with error -22 + + Move the initialization of led_dat->gpiod from template->gpiod up, and + always use led_dat->gpiod later, to fix this. + + Fixes: 5c51277a9ababfa4 (leds: leds-gpio: Add support for GPIO descriptors) + Signed-off-by: Geert Uytterhoeven + Reviewed-by: Mika Westerberg + Signed-off-by: Rafael J. Wysocki + +commit f22bf3eef963c9fc4e58e9e96dc7e9d243042b5a +Author: Rafael J. Wysocki +Date: Wed Nov 5 00:29:07 2014 +0100 + + ACPI / property: Drop size_prop from acpi_dev_get_property_reference() + + The size_prop argument of the recently added function + acpi_dev_get_property_reference() is not used by the only current + caller of that function and is very unlikely to be used at any time + going forward. + + Namely, for a property whose value is a list of items each containing + a references to a device object possibly accompanied by some integers, + the number of items in the list can always be computed as the number + of elements of type ACPI_TYPE_LOCAL_REFERENCE in the property package. + Thus it should never be necessary to provide an additional "cells" + property with a value equal to the number of items in that list. It + also should never be necessary to provide a "cells" property specifying + how many integers are supposed to be following each reference. + + For this reason, drop the size_prop argument from + acpi_dev_get_property_reference() and update its caller accordingly. + + Link: http://marc.info/?l=linux-kernel&m=141511255610556&w=2 + Suggested-by: Grant Likely + Acked-by: Grant Likely + Acked-by: Mika Westerberg + Tested-by: Mika Westerberg Signed-off-by: Rafael J. Wysocki -commit a17b2b5016d76e752f706b5f6b04ffae8ec1728e +commit 1bb8c08673f0ca7951c0583665d2496e19368a56 Author: Mika Westerberg -Date: Wed Oct 1 04:21:18 2014 +0200 +Date: Fri Oct 31 13:40:58 2014 +0200 - misc: at25: Make use of device property API + leds: leds-gpio: Convert gpio_blink_set() to use GPIO descriptors - Make use of device property API in this driver so that both DT and ACPI - based systems can use this driver. + Commit 21f2aae91e902aad ("leds: leds-gpio: Add support for GPIO + descriptors") already converted most of the driver to use GPIO descriptors. + What is still missing is the platform specific hook gpio_blink_set() and + board files which pass legacy GPIO numbers to this driver in platform data. + + In this patch we handle the former and convert gpio_blink_set() to take + GPIO descriptor instead. In order to do this we convert the existing four + users to accept GPIO descriptor and translate it to legacy GPIO number in + the platform code. This effectively "pushes" legacy GPIO number usage from + the driver to platforms. + Also add comment to the remaining block describing that it is legacy code + path and we are getting rid of it eventually. + + Suggested-by: Linus Walleij Signed-off-by: Mika Westerberg + Acked-by: Andrew Lunn + Reviewed-by: Linus Walleij + Acked-by: Alexandre Courbot + Signed-off-by: Rafael J. Wysocki + +commit 1b8f83503e4b9b7168c5d81cabce5b66e4063607 +Author: Rafael J. Wysocki +Date: Mon Nov 3 23:39:57 2014 +0100 + + ACPI / GPIO: Document ACPI GPIO mappings API + + Document the previously introduced method that can be used by device + drivers to provide the GPIO subsystem with mappings between GPIO names + (connection IDs) and GpioIo()/GpioInt() resources in _CRS. + Signed-off-by: Rafael J. Wysocki + Reviewed-by: Mika Westerberg -commit 66442ae93d72f35bf046a6001403fdb89fbcfbdf +commit 49b5f3126e722dd0266d22a2866bb056ede2cf0a Author: Mika Westerberg -Date: Wed Oct 1 04:20:43 2014 +0200 +Date: Mon Oct 27 12:15:14 2014 +0200 - input: gpio_keys_polled - Add ACPI probing support + net: rfkill: gpio: Add default GPIO driver mappings for ACPI - Allow the driver to probe from ACPI namespace. + The driver uses devm_gpiod_get_index(..., index) so that the index refers + directly to the GpioIo resource under the ACPI device. The problem with + this is that if the ordering changes we get wrong GPIOs. + + With ACPI 5.1 _DSD we can now use names instead to reference GPIOs + analogous to Device Tree. However, we still have systems out there that do + not provide _DSD at all. These systems must be supported as well. + + Luckily we now have acpi_dev_add_driver_gpios() that can be used to provide + mappings for systems where _DSD is not provided and still take advantage of + _DSD if it exists. + + This patch changes the driver to create default GPIO mappings if we are + running on ACPI system. + + While there we can drop the indices completely and use devm_gpiod_get() + with name instead. - Signed-off-by: Aaron Lu Signed-off-by: Mika Westerberg + Reviewed-by: Johannes Berg + Acked-by: John W. Linville + Acked-by: Linus Walleij + Signed-off-by: Rafael J. Wysocki + +commit c9accb22ace8c3318e75fc0bbbca91336dab270d +Author: Rafael J. Wysocki +Date: Mon Nov 3 23:39:41 2014 +0100 + + ACPI / GPIO: Driver GPIO mappings for ACPI GPIOs + + Provide a way for device drivers using GPIOs described by ACPI + GpioIo resources in _CRS to tell the GPIO subsystem what names + (connection IDs) to associate with specific GPIO pins defined + in there. + + To do that, a driver needs to define a mapping table as a + NULL-terminated array of struct acpi_gpio_mapping objects + that each contain a name, a pointer to an array of line data + (struct acpi_gpio_params) objects and the size of that array. + + Each struct acpi_gpio_params object consists of three fields, + crs_entry_index, line_index, active_low, representing the index of + the target GpioIo()/GpioInt() resource in _CRS starting from zero, + the index of the target line in that resource starting from zero, + and the active-low flag for that line, respectively. + + Next, the mapping table needs to be passed as the second + argument to acpi_dev_add_driver_gpios() that will register it with + the ACPI device object pointed to by its first argument. That + should be done in the driver's .probe() routine. + + On removal, the driver should unregister its GPIO mapping table + by calling acpi_dev_remove_driver_gpios() on the ACPI device + object where that table was previously registered. + + Included are fixes from Mika Westerberg. + + Acked-by: Alexandre Courbot + Reviewed-by: Linus Walleij Signed-off-by: Rafael J. Wysocki -commit 7f06c354929e2325f200de26e47189a13100647e +commit 872e3713eb734e43d3001a6ef957cb67ba2349a3 Author: Aaron Lu -Date: Wed Oct 1 04:20:05 2014 +0200 +Date: Tue Oct 21 13:34:00 2014 +0200 - input: gpio_keys_polled - Make use of device property API + input: gpio_keys_polled: Make use of device property API Make use of device property API in this driver so that both OF based system and ACPI based system can use this driver. Signed-off-by: Aaron Lu Signed-off-by: Mika Westerberg + Acked-by: Dmitry Torokhov + Acked-by: Grant Likely Signed-off-by: Rafael J. Wysocki -commit 1fb6d8d9606826cf1dfdac8a75bc5e3f68e4d0de -Author: Aaron Lu -Date: Wed Oct 1 04:17:46 2014 +0200 +commit ac8ab45966dc9e98cdb44d0ca833c25772eb4745 +Author: Rafael J. Wysocki +Date: Mon Oct 27 23:30:10 2014 +0100 - input: gpio_keys_polled - Add support for GPIO descriptors + leds: leds-gpio: Make use of device property API - GPIO descriptors are the preferred way over legacy GPIO numbers - nowadays. Convert the driver to use GPIO descriptors internally but - still allow passing legacy GPIO numbers from platform data to support - existing platforms. + Make use of device property API in this driver so that both OF and ACPI + based system can use the same driver. + + This change contains material from Max Eliaser and Mika Westerberg. - Signed-off-by: Aaron Lu Signed-off-by: Mika Westerberg - Acked-by: Alexandre Courbot - Reviewed-by: Linus Walleij + Acked-by: Bryan Wu + Acked-by: Grant Likely Signed-off-by: Rafael J. Wysocki -commit 8cd8efd79a3f822db3ffc2f30f7646584b69d99f -Author: Max Eliaser -Date: Wed Oct 1 04:17:02 2014 +0200 +commit d48dca7d09f36535c2f6dba340e796b54aa6667d +Author: Mika Westerberg +Date: Tue Oct 21 13:33:59 2014 +0200 - leds: leds-gpio: Add ACPI probing support + gpio: Support for unified device properties interface + + Some drivers need to deal with only firmware representation of its + GPIOs. An example would be a GPIO button array driver where each button + is described as a separate firmware node in device tree. Typically these + child nodes do not have physical representation in the Linux device + model. - This allows the driver to probe from ACPI namespace. + In order to help device drivers to handle such firmware child nodes we + add dev[m]_get_named_gpiod_from_child() that takes a child firmware + node pointer as its second argument (the first one is the parent device + itself), finds the GPIO using whatever is the underlying firmware + method, and requests the GPIO properly. - Signed-off-by: Max Eliaser Signed-off-by: Mika Westerberg - Acked-by: Bryan Wu + Acked-by: Alexandre Courbot + Acked-by: Grant Likely Signed-off-by: Rafael J. Wysocki -commit 14144259abecb65edd35b9d5e717688800628e27 -Author: Max Eliaser -Date: Wed Oct 1 04:16:25 2014 +0200 +commit fcca136c38aa18deec3ddd3b872ea49e6d082e5a +Author: Rafael J. Wysocki +Date: Tue Nov 4 14:03:59 2014 +0100 - leds: leds-gpio: Make use of device property API + Driver core: Unified interface for firmware node properties + + Add new generic routines are provided for retrieving properties from + device description objects in the platform firmware in case there are + no struct device objects for them (either those objects have not been + created yet or they do not exist at all). + + The following functions are provided: + + fwnode_property_present() + fwnode_property_read_u8() + fwnode_property_read_u16() + fwnode_property_read_u32() + fwnode_property_read_u64() + fwnode_property_read_string() + fwnode_property_read_u8_array() + fwnode_property_read_u16_array() + fwnode_property_read_u32_array() + fwnode_property_read_u64_array() + fwnode_property_read_string_array() + + in analogy with the corresponding functions for struct device added + previously. For all of them, the first argument is a pointer to struct + fwnode_handle (new type) that allows a device description object + (depending on what platform firmware interface is in use) to be + obtained. + + Add a new macro device_for_each_child_node() for iterating over the + children of the device description object associated with a given + device and a new function device_get_child_node_count() returning the + number of a given device's child nodes. - Make use of device property API in this driver so that both OF and ACPI - based system can use the same driver. + The interface covers both ACPI and Device Trees. + + Suggested-by: Grant Likely + Acked-by: Greg Kroah-Hartman + Acked-by: Grant Likely + Signed-off-by: Rafael J. Wysocki + +commit 4ac0bb216349cce71aea75f6156d44c59fc18086 +Author: Aaron Lu +Date: Tue Oct 21 23:30:25 2014 +0200 + + input: gpio_keys_polled: Add support for GPIO descriptors + + GPIO descriptors are the preferred way over legacy GPIO numbers + nowadays. Convert the driver to use GPIO descriptors internally but + still allow passing legacy GPIO numbers from platform data to support + existing platforms. - Signed-off-by: Max Eliaser + Signed-off-by: Aaron Lu Signed-off-by: Mika Westerberg + Acked-by: Alexandre Courbot + Reviewed-by: Linus Walleij + Acked-by: Dmitry Torokhov + Acked-by: Grant Likely Signed-off-by: Rafael J. Wysocki -commit 998f66211496063e464918fcdb4e40e99fcf2501 +commit 17907d91fb1bd542b9503cc5223a070039b8d031 Author: Mika Westerberg -Date: Wed Oct 1 04:15:41 2014 +0200 +Date: Mon Oct 27 23:29:32 2014 +0100 leds: leds-gpio: Add support for GPIO descriptors @@ -210,11 +500,13 @@ Date: Wed Oct 1 04:15:41 2014 +0200 Signed-off-by: Mika Westerberg Acked-by: Alexandre Courbot Acked-by: Bryan Wu + Acked-by: Arnd Bergmann + Acked-by: Grant Likely Signed-off-by: Rafael J. Wysocki -commit ecf8d19a6019f60c567615c46bec6f4501c03c99 +commit 2781ab92fd33f2270c7b5e1628db0a180ed3ab03 Author: Mika Westerberg -Date: Wed Oct 1 04:15:01 2014 +0200 +Date: Tue Oct 21 13:33:56 2014 +0200 gpio: sch: Consolidate core and resume banks @@ -228,32 +520,12 @@ Date: Wed Oct 1 04:15:01 2014 +0200 Signed-off-by: Mika Westerberg Acked-by: Linus Walleij + Acked-by: Grant Likely Signed-off-by: Rafael J. Wysocki -commit f87218916f4a9bcd2acdf8db1a4dbf8db5592036 -Author: Mika Westerberg -Date: Wed Oct 1 04:14:20 2014 +0200 - - gpio: Support for unified device properties interface - - Some drivers need to deal with only firmware representation of its - GPIOs. An example would be a GPIO button array driver where each button - is described as a separate firmware node in device tree. Typically these - child nodes do not have physical representation in the Linux device - model. - - In order to help device drivers to handle such firmware child nodes we - add dev[m]_get_named_gpiod_from_child() that takes a child firmware - node pointer as its second argument (the first one is the parent device - itself), finds the GPIO using whatever is the underlying firmware - method, and requests the GPIO properly. - - Signed-off-by: Mika Westerberg - Signed-off-by: Rafael J. Wysocki - -commit 2edae8da3e10c8b9d679637693e9d26a0cb9440f +commit 732feab25f90c338e9ef36457a3591f322f53264 Author: Mika Westerberg -Date: Wed Oct 1 04:12:41 2014 +0200 +Date: Wed Oct 29 15:41:01 2014 +0100 gpio / ACPI: Add support for _DSD device properties @@ -311,41 +583,49 @@ Date: Wed Oct 1 04:12:41 2014 +0200 Signed-off-by: Mika Westerberg Acked-by: Linus Walleij + Acked-by: Grant Likely Signed-off-by: Rafael J. Wysocki -commit 01164a93badc2df11a1f1bfdf7d46e3253a0a6ec +commit 6b23a29f06a006a48d7fb94eef42452552144fb9 Author: Mika Westerberg -Date: Wed Oct 1 04:11:20 2014 +0200 +Date: Tue Oct 21 13:33:56 2014 +0200 - ACPI: Document ACPI device specific properties + misc: at25: Make use of device property API + + Make use of device property API in this driver so that both DT and ACPI + based systems can use this driver. - This document describes the data format and interfaces of ACPI device - specific properties. + In addition we hard-code the name of the chip to be "at25" for the + reason that there is no common mechanism to fetch name of the firmware + node. The only existing user (arch/arm/boot/dts/phy3250.dts) uses the + same name so it should continue to work. Signed-off-by: Mika Westerberg - Signed-off-by: Darren Hart + Acked-by: Grant Likely Signed-off-by: Rafael J. Wysocki -commit 1ea48df9784142befa0cdb6cb79f7fd405a7a103 +commit c901445ec7d1f37d9fd2250dd4390f395b954ef3 Author: Mika Westerberg -Date: Wed Oct 1 04:10:40 2014 +0200 +Date: Tue Oct 21 13:33:56 2014 +0200 ACPI: Allow drivers to match using Device Tree compatible property We have lots of existing Device Tree enabled drivers and allocating separate _HID for each is not feasible. Instead we allocate special _HID "PRP0001" that means that the match should be done using Device Tree - compatible property using driver's .of_match_table instead. + compatible property using driver's .of_match_table instead if the driver + is missing .acpi_match_table. If there is a need to distinguish from where the device is enumerated (DT/ACPI) driver can check dev->of_node or ACPI_COMPATION(dev). Signed-off-by: Mika Westerberg + Acked-by: Grant Likely Signed-off-by: Rafael J. Wysocki -commit f15380516841e837f8e20ed18c0039e052bb6187 +commit 7eace032b0201dfb110586080dd0628ec48c0d5c Author: Rafael J. Wysocki -Date: Wed Oct 1 04:10:03 2014 +0200 +Date: Tue Nov 4 01:28:56 2014 +0100 Driver core: Unified device properties interface for platform firmware @@ -355,34 +635,25 @@ Date: Wed Oct 1 04:10:03 2014 +0200 write portable code that won't depend on any particular platform firmware interface. - Three general helper functions, device_get_property(), - device_read_property() and device_read_property_array() are provided. - The first one allows the raw value of a given device property to be - accessed. The remaining two allow the value of a numeric or string - property and multiple numeric or string values of one array - property to be acquired, respectively. Static inline wrappers are also - provided for the various property data types that can be passed to - device_read_property() or device_read_property_array() for extra type - checking. - - In addition to that, new generic routines are provided for retrieving - properties from device description objects in the platform firmware - in case a device driver needs/wants to access properties of a child - object of a given device object. There are cases in which there is - no struct device representation of such child objects and this - additional API is useful then. Again, three functions are provided, - device_get_child_property(), device_read_child_property(), - device_read_child_property_array(), in analogy with device_get_property(), - device_read_property() and device_read_property_array() described above, - respectively, along with static inline wrappers for all of the propery - data types that can be used. For all of them, the first argument is - a struct device pointer to the parent device object and the second - argument is a (void *) pointer to the child description provided by - the platform firmware (either ACPI or FDT). - - Finally, device_for_each_child_node() is added for iterating over - the children of the device description object associated with a - given device. + The following general helper functions are added: + + device_property_present() + device_property_read_u8() + device_property_read_u16() + device_property_read_u32() + device_property_read_u64() + device_property_read_string() + device_property_read_u8_array() + device_property_read_u16_array() + device_property_read_u32_array() + device_property_read_u64_array() + device_property_read_string_array() + + The first one allows the caller to check if the given property is + present. The next 5 of them allow single-valued properties of + various types to be retrieved in a uniform way. The remaining 5 are + for reading properties with multiple values (arrays of either numbers + or strings). The interface covers both ACPI and Device Trees. @@ -390,11 +661,13 @@ Date: Wed Oct 1 04:10:03 2014 +0200 Signed-off-by: Aaron Lu Signed-off-by: Mika Westerberg + Acked-by: Greg Kroah-Hartman + Acked-by: Grant Likely Signed-off-by: Rafael J. Wysocki -commit 6b0beaa05b29a299e62293fa4ea4dad0053f31b1 +commit c2d6966e876bb42c76d03d3eb207bfa754657d8b Author: Mika Westerberg -Date: Wed Oct 1 04:08:56 2014 +0200 +Date: Tue Oct 21 13:33:55 2014 +0200 ACPI: Add support for device specific properties @@ -444,24 +717,27 @@ Date: Wed Oct 1 04:08:56 2014 +0200 Reviewed-by: Hanjun Guo Reviewed-by: Josh Triplett + Reviewed-by: Grant Likely Signed-off-by: Darren Hart Signed-off-by: Rafael J. Wysocki Signed-off-by: Mika Westerberg Signed-off-by: Rafael J. Wysocki -commit ca68950ecf22403e9d0cacdcd86fb4c245de6b9f +commit 3f675aef809d3f82bf1aa0700065ddf798d1eb86 Author: Mark Salter Date: Tue Sep 30 17:19:24 2014 -0400 - arm64: avoid need for console= to enable serial console + [NOT FOR UPSTREAM] arm64: avoid need for console= to enable serial console Tell kernel to prefer one of the serial ports on platforms pl011, 8250, or sbsa uarts. console= on command line will - override these assumed preferences. + override these assumed preferences. This is just a hack to + get the behavior we want from SPCR table support. Once SPCR + is supported, we can drop this. Signed-off-by: Mark Salter -commit 6194557254f1ed05638237a64f45f2ec08aa2523 +commit 20d7a3414d18cea0ed8982a5c538e7548bc3bb0a Author: Tom Lendacky Date: Tue Sep 9 23:33:17 2014 -0400 @@ -473,7 +749,7 @@ Date: Tue Sep 9 23:33:17 2014 -0400 Signed-off-by: Mark Salter -commit 0c9b242dd24b3ddf2e87209cb07c4bc7f5da21c4 +commit 286f94e27659e7eb45e4b54b4e3c0f9a3b9f9fd4 Author: Tom Lendacky Date: Tue Sep 9 23:34:07 2014 -0400 @@ -485,7 +761,7 @@ Date: Tue Sep 9 23:34:07 2014 -0400 Signed-off-by: Mark Salter -commit 7697f77962035de040c847f4c331eb91dc1c7c91 +commit 7e7eade04b5fe90bb30a68aa52f0881b354e7d1d Author: Graeme Gregory Date: Fri Jul 26 17:55:02 2013 +0100 @@ -495,7 +771,7 @@ Date: Fri Jul 26 17:55:02 2013 +0100 Signed-off-by: Graeme Gregory -commit 3025ec9f5711f2773be702464bf3150aa914bd66 +commit a1b37e75322dfbd359c86e51ee624511811c93b6 Author: Graeme Gregory Date: Wed Jul 24 11:29:48 2013 +0100 @@ -508,7 +784,7 @@ Date: Wed Jul 24 11:29:48 2013 +0100 Signed-off-by: Graeme Gregory -commit a41a9bd6569e079f0572d4b106ffa95d2c16ad06 +commit 29fe31c2a0e6ce57695c1341351c2579d159e446 Author: Mark Salter Date: Thu Sep 18 15:05:23 2014 -0400 @@ -521,7 +797,7 @@ Date: Thu Sep 18 15:05:23 2014 -0400 Signed-off-by: Mark Salter -commit 6e86c887dd05557830a38aa8fd93fab03a409b69 +commit 0875f7e4b6b078859a3765aac54c345980b2748c Author: Mark Salter Date: Sun Sep 14 09:44:44 2014 -0400 @@ -531,13 +807,13 @@ Date: Sun Sep 14 09:44:44 2014 -0400 Temporarily revert for backwards compatibility with rh-0.12-1 firmware -commit 81bcad4ccaf54357a6e3d51a135e07a67ce122ee +commit 31bf2a5577ffb5b318bb9f5d80a9f26224674521 Author: Mark Salter Date: Mon Aug 11 13:46:43 2014 -0400 xgene: add support for ACPI-probed serial port -commit d99f65d46bcc6a28262ff18506b0f2abd10d789e +commit f099d9ceac69d7fda70e5d3ee8200f8585f4ff88 Author: Mark Salter Date: Sat Aug 9 12:01:20 2014 -0400 @@ -545,7 +821,7 @@ Date: Sat Aug 9 12:01:20 2014 -0400 Signed-off-by: Mark Salter -commit 977b4da81b8b80d02f54f2fc799fb292b22ade12 +commit 7020f9dda064514d58da5701a351d4773a1d274f Author: Mark Salter Date: Tue Sep 9 22:59:48 2014 -0400 @@ -561,15 +837,7 @@ Date: Tue Sep 9 22:59:48 2014 -0400 Signed-off-by: Mark Salter -commit b0be9a425fd397fbed0b720a310e82d5d422f0da -Author: Mark Salter -Date: Tue Sep 23 12:35:17 2014 -0400 - - arm64/acpi: make acpi disabled by default - - Signed-off-by: Mark Salter - -commit 2dd589faf326c07b981093f73a9c7448ddf4afbf +commit 17b60c76da131d5fb9c401ec43404c911fe57f39 Author: Hanjun Guo Date: Thu Aug 28 14:26:16 2014 -0400 @@ -583,7 +851,7 @@ Date: Thu Aug 28 14:26:16 2014 -0400 [fixed up for 3.17-rc] Signed-off-by: Mark Salter -commit 1857c8d68b23fb57f6f6c64d09e3ce183244d399 +commit fc47393ae2927cb1069c2e15a7b142998702b05d Author: Al Stone Date: Thu Aug 28 13:14:16 2014 -0400 @@ -591,7 +859,7 @@ Date: Thu Aug 28 13:14:16 2014 -0400 Signed-off-by: Mark Salter -commit 4529b4dbbaa8732c742300f3abe8db83e08670e8 +commit 7100a707311becfd1cbfc26ad8298cc290877db5 Author: Suravee Suthikulpanit Date: Tue Sep 9 15:37:15 2014 -0500 @@ -617,7 +885,7 @@ Date: Tue Sep 9 15:37:15 2014 -0500 Signed-off-by: Suravee Suthikulpanit -commit 2bf2a4a102bbe2abf7b2306e89d4d59fb7ade8d2 +commit 397bc93ab853400f7146b8be14bd6cc044df9830 Author: Graeme Gregory Date: Wed Aug 13 13:47:18 2014 +0100 @@ -632,7 +900,7 @@ Date: Wed Aug 13 13:47:18 2014 +0100 Signed-off-by: Graeme Gregory -commit 5c62121c6de8268b06d563596953ce71d292733a +commit 1e6ba230a5e0c03916b0134d846204e64c477972 Author: Mark Salter Date: Mon Sep 8 11:58:46 2014 -0400 @@ -646,7 +914,7 @@ Date: Mon Sep 8 11:58:46 2014 -0400 Signed-off-by: Mark Salter -commit c4f70201c3e20f95c1a96929cf8e524a82dddf81 +commit b3ae15f9e484bab186a5ed697bb25f0244b5aa50 Author: Graeme Gregory Date: Mon Sep 8 10:36:44 2014 -0400 @@ -658,7 +926,7 @@ Date: Mon Sep 8 10:36:44 2014 -0400 Signed-off-by: Al Stone Signed-off-by: Graeme Gregory -commit e632bb50e732757dd8ac56f94785b86c300585ba +commit 4b29bf89ba430787509cb06a6aa38fafeb910b56 Author: Mark Salter Date: Mon Sep 8 17:04:28 2014 -0400 @@ -670,9 +938,9 @@ Date: Mon Sep 8 17:04:28 2014 -0400 Signed-off-by: Mark Salter -commit 51ba60203fe3cb844f1b56389dc840ecf0264817 +commit 58bb9299b1b2a87bd8002ee1bd6eb90138cc4f30 Author: Graeme Gregory -Date: Fri Sep 12 22:00:16 2014 +0800 +Date: Fri Oct 17 21:37:14 2014 +0800 Documentation: ACPI for ARM64 @@ -680,11 +948,12 @@ Date: Fri Sep 12 22:00:16 2014 +0800 on ARM64. Signed-off-by: Graeme Gregory + Signed-off-by: Al Stone Signed-off-by: Hanjun Guo -commit 49c2936aebfdc0d6fb6f8a2ed85295e4370afac7 +commit 47e5e8a11d7d0f4930c2e98671a973f3edac313f Author: Graeme Gregory -Date: Fri Sep 12 22:00:15 2014 +0800 +Date: Fri Oct 17 21:37:13 2014 +0800 ARM64 / ACPI: Enable ARM64 in Kconfig @@ -698,9 +967,9 @@ Date: Fri Sep 12 22:00:15 2014 +0800 Signed-off-by: Al Stone Signed-off-by: Hanjun Guo -commit 4a1bcc17290231af1cfbef33aa6ec77aca609389 +commit 3738397b4a8e91102db2af9ad29919a19425b3f0 Author: Al Stone -Date: Fri Sep 12 22:00:14 2014 +0800 +Date: Fri Oct 17 21:37:12 2014 +0800 ARM64 / ACPI: Select ACPI_REDUCED_HARDWARE_ONLY if ACPI is enabled on ARM64 @@ -712,9 +981,9 @@ Date: Fri Sep 12 22:00:14 2014 +0800 Signed-off-by: Al Stone Signed-off-by: Hanjun Guo -commit 2863c8dd559eaa85dbec982045ae8201bdd0216e +commit 77476629347ec5b72b13e0f3d2cf71604286298c Author: Hanjun Guo -Date: Fri Sep 12 22:00:13 2014 +0800 +Date: Fri Oct 17 21:37:11 2014 +0800 ARM64 / ACPI: Parse GTDT to initialize arch timer @@ -724,9 +993,9 @@ Date: Fri Sep 12 22:00:13 2014 +0800 Originally-by: Amit Daniel Kachhap Signed-off-by: Hanjun Guo -commit 75398d7dfd0a9bb67c70568bbc49e79d43681516 +commit 1386d5f6353e7a13d34df5302bc7e4bd1c6aae28 Author: Tomasz Nowicki -Date: Fri Sep 12 22:00:12 2014 +0800 +Date: Fri Oct 17 21:37:10 2014 +0800 ARM64 / ACPI: Add GICv2 specific ACPI boot support @@ -742,9 +1011,9 @@ Date: Fri Sep 12 22:00:12 2014 +0800 Signed-off-by: Tomasz Nowicki Signed-off-by: Hanjun Guo -commit 325e4412a370d58213bd1cd9de5a5f104dd2bab4 +commit 5213320ccc37374bbf6facc7f7e3c9246bc933c3 Author: Hanjun Guo -Date: Fri Sep 12 22:00:11 2014 +0800 +Date: Fri Oct 17 21:37:09 2014 +0800 ARM64 / ACPI: Introduce ACPI_IRQ_MODEL_GIC and register device's gsi @@ -758,9 +1027,9 @@ Date: Fri Sep 12 22:00:11 2014 +0800 Originally-by: Amit Daniel Kachhap Signed-off-by: Hanjun Guo -commit 4537275d3b1611bb1102eadfce56af2d36d1c25b +commit d1c5a9cdd33f04d4ca5f8ef1b8aed16552fc4f2d Author: Hanjun Guo -Date: Fri Sep 12 22:00:10 2014 +0800 +Date: Fri Oct 17 21:37:08 2014 +0800 ACPI / processor: Make it possible to get CPU hardware ID via GICC @@ -772,9 +1041,9 @@ Date: Fri Sep 12 22:00:10 2014 +0800 Signed-off-by: Hanjun Guo -commit 5ae8a2bbb06f1833c6494fc7a5f30931cc4b5d9a +commit 9db9a0235e80b8a80af1a000fac4127333b2a2e6 Author: Hanjun Guo -Date: Fri Sep 12 22:00:09 2014 +0800 +Date: Fri Oct 17 21:37:07 2014 +0800 ARM64 / ACPI: Parse MADT for SMP initialization @@ -791,21 +1060,29 @@ Date: Fri Sep 12 22:00:09 2014 +0800 Signed-off-by: Hanjun Guo Signed-off-by: Tomasz Nowicki -commit 4a3aed9caf1780e72030a7efc32d28a32d3ed603 +commit 1a5a392de06147924052458a6c2fd182dcd4d509 Author: Hanjun Guo -Date: Fri Sep 12 22:00:08 2014 +0800 +Date: Fri Oct 17 21:37:06 2014 +0800 ACPI / table: Print GIC information when MADT is parsed When MADT is parsed, print GIC information to make the boot - log look pretty. + log look pretty: + + ACPI: GICC (acpi_id[0x0000] address[00000000e112f000] MPDIR[0x0] enabled) + ACPI: GICC (acpi_id[0x0001] address[00000000e112f000] MPDIR[0x1] enabled) + ... + ACPI: GICC (acpi_id[0x0201] address[00000000e112f000] MPDIR[0x201] enabled) + + These information will be very helpful to bring up early systems to + see if acpi_id and MPIDR are matched or not as spec defined. Signed-off-by: Hanjun Guo Signed-off-by: Tomasz Nowicki -commit d9f88c9f5385ac2ae7c87ca0ee63e8e77a37ca09 +commit dbb10ccb37b11731a79bc004da46e482a7152be4 Author: Hanjun Guo -Date: Fri Sep 12 22:00:07 2014 +0800 +Date: Fri Oct 17 21:37:05 2014 +0800 ARM64 / ACPI: Parse FADT table to get PSCI flags for PSCI init @@ -832,9 +1109,9 @@ Date: Fri Sep 12 22:00:07 2014 +0800 Signed-off-by: Graeme Gregory Signed-off-by: Tomasz Nowicki -commit f5b32d09a98c2d5353915d2bcc3d7fa3151b6890 +commit f367d6c84f50ad7e1944ef6ec7aca8b01fd82051 Author: Hanjun Guo -Date: Fri Sep 12 22:00:06 2014 +0800 +Date: Fri Oct 17 21:37:04 2014 +0800 ARM64 / ACPI: Make PCI optional for ACPI on ARM64 @@ -847,38 +1124,40 @@ Date: Fri Sep 12 22:00:06 2014 +0800 Signed-off-by: Hanjun Guo -commit 445abae9b9e86d9bd81b3cbffc5d20e8cb375ab0 +commit 2926fd3502c857db06ab41caa8f628089287d6f4 Author: Graeme Gregory -Date: Fri Sep 12 22:00:05 2014 +0800 +Date: Fri Oct 17 21:37:03 2014 +0800 ARM64 / ACPI: If we chose to boot from acpi then disable FDT If the early boot methods of acpi are happy that we have valid ACPI - tables and acpi=off has not been passed. Then do not unflat - devicetree effectively disabling further hardware probing from DT. + tables and acpi=force has been passed, then do not unflat devicetree + effectively disabling further hardware probing from DT. Signed-off-by: Graeme Gregory Signed-off-by: Hanjun Guo -commit fad554282770ff7d0a0b002bb2c3d289ad5cc187 +commit d40d81475b41044935ee4eb455a58308e0f070ac Author: Al Stone -Date: Fri Sep 12 22:00:04 2014 +0800 +Date: Fri Oct 17 21:37:02 2014 +0800 - ARM64 / ACPI: Introduce early_param for "acpi" + ARM64 / ACPI: Introduce early_param for "acpi" and pass acpi=force to enable ACPI - Introduce one early parameters "off" for "acpi" to disable ACPI on - ARM64. + Introduce one early parameters "off" and "force" for "acpi", acpi=off + will be the default behavior for ARM64, so introduce acpi=force to + enable ACPI on ARM64. - This ensures the kernel uses the DT on a platform that provides both - ACPI tables and DT. + Disable ACPI before early parameters parsed, and enable it to pass + "acpi=force" if people want use ACPI on ARM64. This ensures DT be + the prefer one if ACPI table and DT both are provided at this moment. Signed-off-by: Al Stone Signed-off-by: Graeme Gregory Signed-off-by: Hanjun Guo -commit ed545c4a15e82373747e2ca4dd44c313a5cbfdbc +commit 19ddd869d20be9d05e37a3e867f3c1c379bc0a07 Author: Graeme Gregory -Date: Fri Sep 12 22:00:03 2014 +0800 +Date: Fri Oct 17 21:37:01 2014 +0800 ARM64 / ACPI: Introduce sleep-arm.c @@ -891,9 +1170,9 @@ Date: Fri Sep 12 22:00:03 2014 +0800 Signed-off-by: Tomasz Nowicki Signed-off-by: Hanjun Guo -commit f6b5641dd6b5bf915ee9c18bb0f44f07b858bfc2 +commit b2247b541995418caafcfc9f12e57b444fdee75d Author: Al Stone -Date: Fri Sep 12 22:00:02 2014 +0800 +Date: Fri Oct 17 21:37:00 2014 +0800 ARM64 / ACPI: Get RSDP and ACPI boot-time tables @@ -923,9 +1202,9 @@ Date: Fri Sep 12 22:00:02 2014 +0800 Signed-off-by: Tomasz Nowicki Signed-off-by: Hanjun Guo -commit 7a5a04722c2527962e4b1ebc979e185a64ed11b4 +commit ff7fee61b5c51bc24b358a6521ee9ac0c81c4ae6 Author: Tomasz Nowicki -Date: Fri Sep 12 22:00:01 2014 +0800 +Date: Fri Oct 17 21:36:59 2014 +0800 ACPI / table: Count matched and successfully parsed entries without specifying max entries @@ -938,12 +1217,13 @@ Date: Fri Sep 12 22:00:01 2014 +0800 NOTE: This change has no impact to x86 and ia64 archs since existing code checks for error occurrence only (acpi_parse_entries(...,0) < 0). + Acked-by: Grant Likely Signed-off-by: Tomasz Nowicki Signed-off-by: Hanjun Guo -commit 80eb7126770fd6b5c595e4733fb3194bda75f25b +commit 77a4d1f4423591c4f0bed7d580afb7fc7cacb082 Author: Ashwin Chaugule -Date: Fri Sep 12 22:00:00 2014 +0800 +Date: Fri Oct 17 21:36:58 2014 +0800 ACPI / table: Add new function to get table entries @@ -954,35 +1234,33 @@ Date: Fri Sep 12 22:00:00 2014 +0800 each call. e.g. as in acpi_table_parse_madt() which is normally called after acpi_table_parse(). + Acked-by: Grant Likely Signed-off-by: Ashwin Chaugule Signed-off-by: Tomasz Nowicki Signed-off-by: Hanjun Guo -commit 36633ceecab0b57354030ba4e796c3eccb0084a8 -Author: Hanjun Guo -Date: Fri Sep 12 21:59:59 2014 +0800 +commit 17a565aba814f8cb39d27afb0dbf3834be83ac41 +Author: Mark Salter +Date: Sat Nov 8 22:25:48 2014 -0500 - ARM64: Move the init of cpu_logical_map(0) before unflatten_device_tree() + arm64: use UEFI for reboot - It always make sense to initialize CPU0's logical map entry from the - hardware values, so move the initialization of cpu_logical_map(0) - before unflatten_device_tree() which is needed by ACPI code later. + Wire in support for UEFI reboot. We want UEFI reboot to have + highest priority for capsule support. - Signed-off-by: Hanjun Guo + Signed-off-by: Mark Salter -commit 1029a72c660016d7b566f9b91156068f4a86ccb7 +commit c66bae4dfb9dbf577e4692fd034cb80703f687a6 Author: Mark Salter -Date: Tue Jun 24 09:50:28 2014 -0400 +Date: Sat Nov 8 15:25:41 2014 -0500 - arm64: use EFI as last resort for reboot and poweroff + arm64: use UEFI as last resort for poweroff - Wire in support for EFI reboot and poweroff functions. We use these - only if no other mechanism has been registered with arm_pm_reboot - and/or pm_power_off respectively. + Wire in support for poweroff via UEFI. Signed-off-by: Mark Salter -commit 0fdae79847bdc64aee1a765c0bb5ee99ed95eb0e +commit ddc5d1b9a52d9c17fd975fd6ee22be7d6ce5e496 Author: Mark Salter Date: Thu Jul 17 13:34:50 2014 -0400 @@ -1000,7 +1278,7 @@ Date: Thu Jul 17 13:34:50 2014 -0400 Signed-off-by: Mark Salter -commit 6e00476b0a33370988b3fee8551c0a8d98206bd2 +commit 8675c7685ea64e0fda9cebbed08e3f30a71589cf Author: Kyle McMartin Date: Tue May 13 22:25:26 2014 -0400 @@ -1070,38 +1348,464 @@ Date: Tue May 13 22:25:26 2014 -0400 Signed-off-by: Kyle McMartin Signed-off-by: Donald Dutile - Documentation/acpi/properties.txt | 410 ++++++++++++ - Documentation/arm64/arm-acpi.txt | 218 +++++++ +commit ff46d52dc804aeff783ff55b4b6dc489da20bc11 +Author: Ard Biesheuvel +Date: Fri Nov 7 14:12:34 2014 +0000 + + arm64: kvm: eliminate literal pool entries + + Replace two instances of 'ldr xN, =(constant)' in the world switch + hot path with 'mov' instructions. + + Acked-by: Marc Zyngier + Acked-by: Christoffer Dall + Signed-off-by: Ard Biesheuvel + Signed-off-by: Will Deacon + +commit 6ddb6f9d2fe1ecab0b812b3adc4ba4bc0cf19ad8 +Author: Ard Biesheuvel +Date: Fri Nov 7 14:12:33 2014 +0000 + + arm64: ftrace: eliminate literal pool entries + + Replace ldr xN, = with adrp/add or adrp/ldr [as appropriate] + in the implementation of _mcount(), which may be called very often. + + Signed-off-by: Ard Biesheuvel + Signed-off-by: Will Deacon + +commit 35939bd2c847d742ab82049b2cc79c086e0e7130 +Author: Mark Rutland +Date: Tue Nov 4 10:50:16 2014 +0000 + + arm64: log physical ID of boot CPU + + In certain debugging scenarios it's useful to know the physical ID (i.e. + the MPIDR_EL1.Aff* fields) of the boot CPU, but we don't currently log + this as we do for 32-bit ARM kernels. + + This patch makes the kernel log the physical ID of the boot CPU early in + the boot process. The CPU logical map initialisation is folded in to + smp_setup_processor_id (which contrary to its name is also called by UP + kernels). This is called before setup_arch, so should not adversely + affect existing cpu_logical_map users. + + Acked-by: Sudeep Holla + Acked-by: Catalin Marinas + Acked-by: Lorenzo Pieralisis + Signed-off-by: Mark Rutland + Signed-off-by: Will Deacon + +commit aea6f516118cedb6f9e8d2ab23ab5a09c275e68d +Author: Ard Biesheuvel +Date: Mon Nov 3 16:50:01 2014 +0000 + + arm64/crypto: use crypto instructions to generate AES key schedule + + This patch implements the AES key schedule generation using ARMv8 + Crypto Instructions. It replaces the table based C implementation + in aes_generic.ko, which means we can drop the dependency on that + module. + + Tested-by: Steve Capper + Acked-by: Steve Capper + Signed-off-by: Ard Biesheuvel + Signed-off-by: Will Deacon + +commit 0844cddfa0ad22093ef94fdf203fe50cb92222db +Author: Geoff Levand +Date: Fri Oct 31 23:06:47 2014 +0000 + + arm64/kvm: Fix assembler compatibility of macros + + Some of the macros defined in kvm_arm.h are useful in assembly files, but are + not compatible with the assembler. Change any C language integer constant + definitions using appended U, UL, or ULL to the UL() preprocessor macro. Also, + add a preprocessor include of the asm/memory.h file which defines the UL() + macro. + + Fixes build errors like these when using kvm_arm.h in assembly + source files: + + Error: unexpected characters following instruction at operand 3 -- `and x0,x1,#((1U<<25)-1)' + + Acked-by: Mark Rutland + Signed-off-by: Geoff Levand + Signed-off-by: Will Deacon + +commit 94141ed36a5e0a2159deadfcc29a504b55bb352d +Author: Ard Biesheuvel +Date: Tue Oct 28 12:24:20 2014 +0000 + + arm64/dt: add machine name to kernel call stack dump output + + This installs the machine name as recorded by setup_machine_fdt() + as dump stack arch description. This results in the string to be + included in call stack dumps, as is shown here: + + ... + Bad mode in Synchronous Abort handler detected, code 0x84000005 + CPU: 0 PID: 1 Comm: swapper/0 Not tainted 3.18.0-rc2+ #548 + > Hardware name: linux,dummy-virt (DT) + task: ffffffc07c870000 ti: ffffffc07c878000 task.ti: ffffffc07c878000 + PC is at 0x0 + ... + + Note that systems that support DMI/SMBIOS may override this later. + + Signed-off-by: Ard Biesheuvel + Signed-off-by: Will Deacon + +commit a3b3b6027369ce53251bb381c9b87031bbd75464 +Author: Steve Capper +Date: Fri Oct 24 13:22:20 2014 +0100 + + arm64: xchg: Implement cmpxchg_double + + The arm64 architecture has the ability to exclusively load and store + a pair of registers from an address (ldxp/stxp). Also the SLUB can take + advantage of a cmpxchg_double implementation to avoid taking some + locks. + + This patch provides an implementation of cmpxchg_double for 64-bit + pairs, and activates the logic required for the SLUB to use these + functions (HAVE_ALIGNED_STRUCT_PAGE and HAVE_CMPXCHG_DOUBLE). + + Also definitions of this_cpu_cmpxchg_8 and this_cpu_cmpxchg_double_8 + are wired up to cmpxchg_local and cmpxchg_double_local (rather than the + stock implementations that perform non-atomic operations with + interrupts disabled) as they are used by the SLUB. + + On a Juno platform running on only the A57s I get quite a noticeable + performance improvement with 5 runs of hackbench on v3.17: + + Baseline | With Patch + -----------------+----------- + Mean 119.2312 | 106.1782 + StdDev 0.4919 | 0.4494 + + (times taken to complete `./hackbench 100 process 1000', in seconds) + + Signed-off-by: Steve Capper + Signed-off-by: Will Deacon + +commit e21d5b44cf03b31feac7854a5953d17ef94d76d9 +Author: Joonwoo Park +Date: Tue Oct 21 01:59:03 2014 +0100 + + arm64: optimize memcpy_{from,to}io() and memset_io() + + Optimize memcpy_{from,to}io() and memset_io() by transferring in 64 bit + as much as possible with minimized barrier usage. This simplest + optimization brings faster throughput compare to current byte-by-byte read + and write with barrier in the loop. Code's skeleton is taken from the + powerpc. + + Link: http://lkml.kernel.org/p/20141020133304.GH23751@e104818-lin.cambridge.arm.com + Reviewed-by: Catalin Marinas + Reviewed-by: Trilok Soni + Signed-off-by: Joonwoo Park + Signed-off-by: Will Deacon + +commit c8f2e7e08d50c4adb77a0fac4a2871c100ef2f51 +Author: Min-Hua Chen +Date: Thu Oct 9 16:53:10 2014 +0100 + + arm64: fix data type for physical address + + Use phys_addr_t for physical address in alloc_init_pud. Although + phys_addr_t and unsigned long are 64 bit in arm64, it is better + to use phys_addr_t to describe physical addresses. + + Signed-off-by: Min-Hua Chen + Signed-off-by: Will Deacon + +commit 674f32f5ef38c93af7a273a725a0a89b4b8a38a1 +Author: Mark Rutland +Date: Thu Oct 23 16:33:33 2014 +0100 + + efi: efi-stub: notify on DTB absence + + In the absence of a DTB configuration table, the EFI stub will happily + continue attempting to boot a kernel, despite the fact that this kernel + may not function without a description of the hardware. In this case, as + with a typo'd "dtb=" option (e.g. "dbt=") or many other possible + failures, the only output seen by the user will be the rather terse + output from the EFI stub: + + EFI stub: Booting Linux Kernel... + + To aid those attempting to debug such failures, this patch adds a notice + when no DTB is found, making the output more helpful: + + EFI stub: Booting Linux Kernel... + EFI stub: Generating empty DTB + + Additionally, a positive acknowledgement is added when a user-specified + DTB is in use: + + EFI stub: Booting Linux Kernel... + EFI stub: Using DTB from command line + + Similarly, a positive acknowledgement is added when a DTB from a + configuration table is in use: + + EFI stub: Booting Linux Kernel... + EFI stub: Using DTB from configuration table + + Signed-off-by: Mark Rutland + Acked-by: Leif Lindholm + Acked-by: Ard Biesheuvel + Acked-by: Roy Franz + Acked-by: Matt Fleming + Signed-off-by: Ard Biesheuvel + +commit 872cf856a3fc4cff5190af2f79cfc3ac410eae17 +Author: Ard Biesheuvel +Date: Wed Oct 15 09:36:50 2014 +0200 + + arm64: dmi: set DMI string as dump stack arch description + + This sets the DMI string, containing system type, serial number, + firmware version etc. as dump stack arch description, so that oopses + and other kernel stack dumps automatically have this information + included, if available. + + Tested-by: Leif Lindholm + Acked-by: Leif Lindholm + Signed-off-by: Ard Biesheuvel + +commit 2a2978d3748379bb9a0889c866b210f288c45160 +Author: Yi Li +Date: Sat Oct 4 23:46:43 2014 +0800 + + arm64: dmi: Add SMBIOS/DMI support + + SMBIOS is important for server hardware vendors. It implements a spec for + providing descriptive information about the platform. Things like serial + numbers, physical layout of the ports, build configuration data, and the like. + + Signed-off-by: Yi Li + Tested-by: Suravee Suthikulpanit + Tested-by: Leif Lindholm + Signed-off-by: Ard Biesheuvel + +commit c0f06f02f228ca722a2b850363c342f63e6214a6 +Author: Ard Biesheuvel +Date: Tue Oct 14 16:41:27 2014 +0200 + + dmi: add support for SMBIOS 3.0 64-bit entry point + + The DMTF SMBIOS reference spec v3.0.0 defines a new 64-bit entry point, + which enables support for SMBIOS structure tables residing at a physical + offset over 4 GB. This is especially important for upcoming arm64 + platforms whose system RAM resides entirely above the 4 GB boundary. + + For the UEFI case, this code attempts to detect the new SMBIOS 3.0 + header magic at the offset passed in the SMBIOS3_TABLE_GUID UEFI + configuration table. If this configuration table is not provided, or + if we fail to parse the header, we fall back to using the legacy + SMBIOS_TABLE_GUID configuration table. This is in line with the spec, + that allows both configuration tables to be provided, but mandates that + they must point to the same structure table, unless the version pointed + to by the 64-bit entry point is a superset of the 32-bit one. + + For the non-UEFI case, the detection logic is modified to look for the + SMBIOS 3.0 header magic before it looks for the legacy header magic. + + Note that this patch is based on version 3.0.0d [draft] of the + specification, which is expected not to deviate from the final version + in ways that would affect the correctness of this implementation. + + Tested-by: Suravee Suthikulpanit + Acked-by: Leif Lindholm + Tested-by: Leif Lindholm + Cc: Andrew Morton + Cc: Tony Luck + Acked-by: Matt Fleming + Signed-off-by: Ard Biesheuvel + +commit 4ebf40f890ebad9458abc56e00d4814bc881fb9d +Author: Ard Biesheuvel +Date: Tue Oct 14 16:34:47 2014 +0200 + + efi: dmi: add support for SMBIOS 3.0 UEFI configuration table + + This adds support to the UEFI side for detecting the presence of + a SMBIOS 3.0 64-bit entry point. This allows the actual SMBIOS + structure table to reside at a physical offset over 4 GB, which + cannot be supported by the legacy SMBIOS 32-bit entry point. + + Since the firmware can legally provide both entry points, store + the SMBIOS 3.0 entry point in a separate variable, and let the + DMI decoding layer decide which one will be used. + + Tested-by: Suravee Suthikulpanit + Acked-by: Leif Lindholm + Acked-by: Matt Fleming + Signed-off-by: Ard Biesheuvel + +commit 90c66a6923311d477c68543f945f543558b91eec +Author: Ard Biesheuvel +Date: Fri Oct 17 12:44:11 2014 +0200 + + arm64/efi: drop redundant set_bit(EFI_CONFIG_TABLES) + + The EFI_CONFIG_TABLES bit already gets set by efi_config_init(), + so there is no reason to set it again after this function returns + successfully. + + Acked-by: Will Deacon + Signed-off-by: Ard Biesheuvel + +commit bbc705f61c1aebddb5bf80f75964b6da40c55ca9 +Author: Ard Biesheuvel +Date: Mon Oct 20 15:31:57 2014 +0200 + + arm64/efi: invert UEFI memory region reservation logic + + Instead of reserving the memory regions based on which types we know + need to be reserved, consider only regions of the following types as + free for general use by the OS: + + EFI_LOADER_CODE + EFI_LOADER_DATA + EFI_BOOT_SERVICES_CODE + EFI_BOOT_SERVICES_DATA + EFI_CONVENTIONAL_MEMORY + + Note that this also fixes a problem with the original code, which would + misidentify a EFI_RUNTIME_SERVICES_DATA region as not reserved if it + does not have the EFI_MEMORY_RUNTIME attribute set. However, it is + perfectly legal for the firmware not to request a virtual mapping for + EFI_RUNTIME_SERVICES_DATA regions that contain configuration tables, in + which case the EFI_MEMORY_RUNTIME attribute would not be set. + + Acked-by: Roy Franz + Signed-off-by: Ard Biesheuvel + +commit d6e4e04244cb7b4670759bd83679ead21df55a8a +Author: Ard Biesheuvel +Date: Fri Oct 10 18:42:55 2014 +0200 + + arm64/efi: set PE/COFF file alignment to 512 bytes + + Change our PE/COFF header to use the minimum file alignment of + 512 bytes (0x200), as mandated by the PE/COFF spec v8.3 + + Also update the linker script so that the Image file itself is also a + round multiple of FileAlignment. + + Acked-by: Catalin Marinas + Acked-by: Roy Franz + Signed-off-by: Ard Biesheuvel + +commit e9e7422d7035c64a16771d47dcd9f907adc5070d +Author: Ard Biesheuvel +Date: Fri Oct 10 11:25:24 2014 +0200 + + arm64/efi: set PE/COFF section alignment to 4 KB + + Position independent AArch64 code needs to be linked and loaded at the + same relative offset from a 4 KB boundary, or adrp/add and adrp/ldr + pairs will not work correctly. (This is how PC relative symbol + references with a 4 GB reach are emitted) + + We need to declare this in the PE/COFF header, otherwise the PE/COFF + loader may load the Image and invoke the stub at an offset which + violates this rule. + + Reviewed-by: Roy Franz + Acked-by: Mark Rutland + Signed-off-by: Ard Biesheuvel + +commit 2d2346a11e6ac9be30ac5590a7ec4b47bda35870 +Author: Ard Biesheuvel +Date: Wed Oct 8 16:11:27 2014 +0200 + + arm64/efi: efistub: jump to 'stext' directly, not through the header + + After the EFI stub has done its business, it jumps into the kernel by + branching to offset #0 of the loaded Image, which is where it expects + to find the header containing a 'branch to stext' instruction. + + However, the UEFI spec 2.1.1 states the following regarding PE/COFF + image loading: + "A UEFI image is loaded into memory through the LoadImage() Boot + Service. This service loads an image with a PE32+ format into memory. + This PE32+ loader is required to load all sections of the PE32+ image + into memory." + + In other words, it is /not/ required to load parts of the image that are + not covered by a PE/COFF section, so it may not have loaded the header + at the expected offset, as it is not covered by any PE/COFF section. + + So instead, jump to 'stext' directly, which is at the base of the + PE/COFF .text section, by supplying a symbol 'stext_offset' to + efi-entry.o which contains the relative offset of stext into the Image. + Also replace other open coded calculations of the same value with a + reference to 'stext_offset' + + Acked-by: Mark Rutland + Acked-by: Roy Franz + Signed-off-by: Ard Biesheuvel + + Documentation/acpi/gpio-properties.txt | 96 +++ + Documentation/arm64/arm-acpi.txt | 323 ++++++++++ + Documentation/gpio/consumer.txt | 18 + Documentation/kernel-parameters.txt | 3 +- - arch/arm64/Kconfig | 6 + + arch/arm/mach-s3c24xx/h1940-bluetooth.c | 4 +- + arch/arm/mach-s3c24xx/h1940.h | 4 +- + arch/arm/mach-s3c24xx/mach-h1940.c | 3 +- + arch/arm/mach-s3c24xx/mach-rx1950.c | 3 +- + arch/arm/plat-orion/gpio.c | 3 +- + arch/arm/plat-orion/include/plat/orion-gpio.h | 5 +- + arch/arm64/Kconfig | 22 + arch/arm64/Makefile | 1 + + arch/arm64/crypto/Kconfig | 5 +- + arch/arm64/crypto/aes-ce-ccm-glue.c | 4 +- + arch/arm64/crypto/aes-ce-cipher.c | 112 +++- + arch/arm64/crypto/aes-ce-setkey.h | 5 + + arch/arm64/crypto/aes-glue.c | 18 +- arch/arm64/include/asm/acenv.h | 18 + - arch/arm64/include/asm/acpi.h | 99 +++ + arch/arm64/include/asm/acpi.h | 102 +++ + arch/arm64/include/asm/cmpxchg.h | 71 +++ arch/arm64/include/asm/cpu_ops.h | 1 + + arch/arm64/include/asm/dmi.h | 31 + arch/arm64/include/asm/elf.h | 3 +- + arch/arm64/include/asm/kvm_arm.h | 21 +- + arch/arm64/include/asm/pci.h | 51 ++ arch/arm64/include/asm/psci.h | 3 +- arch/arm64/include/asm/smp.h | 10 +- arch/arm64/kernel/Makefile | 4 +- - arch/arm64/kernel/acpi.c | 397 ++++++++++++ + arch/arm64/kernel/acpi.c | 398 ++++++++++++ arch/arm64/kernel/cpu_ops.c | 8 +- - arch/arm64/kernel/efi.c | 11 + - arch/arm64/kernel/process.c | 6 + + arch/arm64/kernel/efi-entry.S | 3 +- + arch/arm64/kernel/efi.c | 74 ++- + arch/arm64/kernel/entry-ftrace.S | 21 +- + arch/arm64/kernel/head.S | 24 +- + arch/arm64/kernel/io.c | 66 +- + arch/arm64/kernel/pci.c | 97 ++- arch/arm64/kernel/psci.c | 78 ++- - arch/arm64/kernel/setup.c | 64 +- + arch/arm64/kernel/setup.c | 67 +- arch/arm64/kernel/smp.c | 2 +- arch/arm64/kernel/smp_parking_protocol.c | 110 ++++ arch/arm64/kernel/time.c | 7 + + arch/arm64/kernel/vmlinux.lds.S | 17 + + arch/arm64/kvm/hyp.S | 4 +- arch/arm64/mm/dma-mapping.c | 103 +++ - arch/arm64/pci/Makefile | 1 + - arch/arm64/pci/pci.c | 28 + + arch/arm64/mm/mmu.c | 2 +- + arch/arm64/pci/Makefile | 2 + + arch/arm64/pci/mmconfig.c | 292 +++++++++ + arch/arm64/pci/pci.c | 461 ++++++++++++++ drivers/acpi/Kconfig | 6 +- drivers/acpi/Makefile | 7 +- drivers/acpi/bus.c | 3 + drivers/acpi/internal.h | 11 + drivers/acpi/osl.c | 6 +- drivers/acpi/processor_core.c | 37 ++ - drivers/acpi/property.c | 586 +++++++++++++++++ - drivers/acpi/scan.c | 93 ++- + drivers/acpi/property.c | 551 ++++++++++++++++ + drivers/acpi/scan.c | 129 +++- drivers/acpi/sleep-arm.c | 28 + drivers/acpi/tables.c | 115 +++- drivers/acpi/utils.c | 26 + @@ -1109,23 +1813,27 @@ Date: Tue May 13 22:25:26 2014 -0400 drivers/ata/ahci_platform.c | 13 + drivers/ata/ahci_xgene.c | 30 +- drivers/base/Makefile | 2 +- - drivers/base/property.c | 235 +++++++ - drivers/clocksource/arm_arch_timer.c | 131 +++- - drivers/gpio/devres.c | 34 + + drivers/base/property.c | 431 +++++++++++++ + drivers/clocksource/arm_arch_timer.c | 120 +++- + drivers/firmware/dmi_scan.c | 79 ++- + drivers/firmware/efi/efi.c | 4 + + drivers/firmware/efi/libstub/arm-stub.c | 11 +- + drivers/gpio/devres.c | 32 + drivers/gpio/gpio-sch.c | 293 ++++----- - drivers/gpio/gpiolib-acpi.c | 78 ++- - drivers/gpio/gpiolib.c | 86 ++- + drivers/gpio/gpiolib-acpi.c | 117 +++- + drivers/gpio/gpiolib.c | 85 ++- drivers/gpio/gpiolib.h | 7 +- - drivers/input/keyboard/gpio_keys_polled.c | 163 ++--- + drivers/input/keyboard/gpio_keys_polled.c | 112 ++-- + drivers/iommu/arm-smmu.c | 8 +- drivers/irqchip/irq-gic-v3.c | 10 + drivers/irqchip/irq-gic.c | 116 ++++ drivers/irqchip/irqchip.c | 3 + - drivers/leds/leds-gpio.c | 185 +++--- - drivers/misc/eeprom/at25.c | 41 +- + drivers/leds/leds-gpio.c | 140 ++-- + drivers/misc/eeprom/at25.c | 34 +- drivers/net/ethernet/amd/Kconfig | 2 +- drivers/net/ethernet/amd/xgbe/xgbe-dev.c | 16 +- drivers/net/ethernet/amd/xgbe/xgbe-drv.c | 3 + - drivers/net/ethernet/amd/xgbe/xgbe-main.c | 294 +++++++-- + drivers/net/ethernet/amd/xgbe/xgbe-main.c | 289 +++++++-- drivers/net/ethernet/amd/xgbe/xgbe-mdio.c | 20 +- drivers/net/ethernet/amd/xgbe/xgbe-ptp.c | 4 +- drivers/net/ethernet/amd/xgbe/xgbe.h | 13 + @@ -1135,471 +1843,166 @@ Date: Tue May 13 22:25:26 2014 -0400 drivers/net/ethernet/smsc/smc91x.c | 10 + drivers/net/phy/Kconfig | 2 +- drivers/net/phy/amd-xgbe-phy.c | 777 ++++++++++++----------- - drivers/of/base.c | 186 ++++++ + drivers/of/base.c | 33 + + drivers/pci/host/pci-xgene.c | 174 ++++- drivers/pnp/resource.c | 2 + drivers/tty/Kconfig | 6 + drivers/tty/Makefile | 1 + drivers/tty/sbsauart.c | 355 +++++++++++ drivers/tty/serial/8250/8250_dw.c | 9 + drivers/virtio/virtio_mmio.c | 12 +- - include/acpi/acpi_bus.h | 10 + + drivers/xen/efi.c | 1 + + include/acpi/acpi_bus.h | 30 + include/acpi/acpi_io.h | 6 + + include/asm-generic/vmlinux.lds.h | 7 + include/kvm/arm_vgic.h | 20 +- - include/linux/acpi.h | 95 ++- + include/linux/acpi.h | 141 +++- include/linux/clocksource.h | 6 + - include/linux/gpio/consumer.h | 5 + + include/linux/efi.h | 6 +- + include/linux/gpio/consumer.h | 7 + include/linux/gpio_keys.h | 3 + include/linux/irqchip/arm-gic-acpi.h | 31 + include/linux/irqchip/arm-gic.h | 2 + - include/linux/leds.h | 1 + - include/linux/of.h | 37 ++ + include/linux/leds.h | 3 +- + include/linux/of.h | 34 + include/linux/pci.h | 37 +- - include/linux/property.h | 207 ++++++ + include/linux/property.h | 143 +++++ + net/bridge/netfilter/nft_reject_bridge.c | 1 + + net/rfkill/rfkill-gpio.c | 18 +- virt/kvm/arm/arch_timer.c | 108 ++-- virt/kvm/arm/vgic-v2.c | 75 ++- virt/kvm/arm/vgic-v3.c | 8 +- virt/kvm/arm/vgic.c | 32 +- - 89 files changed, 5425 insertions(+), 1054 deletions(-) + 123 files changed, 6825 insertions(+), 1116 deletions(-) -diff --git a/Documentation/acpi/properties.txt b/Documentation/acpi/properties.txt +diff --git a/Documentation/acpi/gpio-properties.txt b/Documentation/acpi/gpio-properties.txt new file mode 100644 -index 0000000..13a93c5 +index 0000000..ae36fcf --- /dev/null -+++ b/Documentation/acpi/properties.txt -@@ -0,0 +1,410 @@ -+ACPI device properties -+====================== -+This document describes the format and interfaces of ACPI device -+properties as specified in "Device Properties UUID For _DSD" available -+here: -+ -+http://www.uefi.org/sites/default/files/resources/_DSD-device-properties-UUID.pdf -+ -+1. Introduction -+--------------- -+In systems that use ACPI and want to take advantage of device specific -+properties, there needs to be a standard way to return and extract -+name-value pairs for a given ACPI device. -+ -+An ACPI device that wants to export its properties must implement a -+static name called _DSD that takes no arguments and returns a package of -+packages: -+ -+ Name (_DSD, Package () { -+ ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"), -+ Package () { -+ Package () {"name1", }, -+ Package () {"name2", } -+ } -+ }) -+ -+The UUID identifies contents of the following package. In case of ACPI -+device properties it is daffd814-6eba-4d8c-8a91-bc9bbf4aa301. -+ -+In each returned package, the first item is the name and must be a string. -+The corresponding value can be a string, integer, reference, or package. If -+a package it may only contain strings, integers, and references. -+ -+An example device where we might need properties is a device that uses -+GPIOs. In addition to the GpioIo/GpioInt resources the driver needs to -+know which GPIO is used for which purpose. -+ -+To solve this we add the following ACPI device properties to the device: -+ -+ Device (DEV0) -+ { -+ Name (_CRS, ResourceTemplate () { -+ GpioIo (Exclusive, PullUp, 0, 0, IoRestrictionInputOnly, -+ "\\_SB.PCI0.LPC", 0, ResourceConsumer) {0} -+ GpioIo (Exclusive, PullUp, 0, 0, IoRestrictionInputOnly, -+ "\\_SB.PCI0.LPC", 0, ResourceConsumer) {1} -+ ... -+ }) -+ -+ Name (_DSD, Package () { -+ ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"), -+ Package () { -+ Package () {"reset-gpio", {^DEV0, 0, 0, 0}}, -+ Package () {"shutdown-gpio", {^DEV0, 1, 0, 0}}, -+ } -+ }) -+ } -+ -+Now the device driver can reference the GPIOs using names instead of -+using indexes. -+ -+If there is an existing Device Tree binding for a device, it is expected -+that the same bindings are used with ACPI properties, so that the driver -+dealing with the device needs only minor modifications if any. -+ -+2. Formal definition of properties -+---------------------------------- -+The following chapters define the currently supported properties. For -+these there exists a helper function that can be used to extract the -+property value. -+ -+2.1 Integer types -+----------------- -+ACPI integers are always 64-bit. However, for drivers the full range is -+typically not needed so we provide a set of functions which convert the -+64-bit integer to a smaller Linux integer type. -+ -+An integer property looks like this: -+ -+ Package () {"i2c-sda-hold-time-ns", 300}, -+ Package () {"clock-frequency", 400000}, -+ -+To read a property value, use a unified property accessor as shown -+below: -+ -+ u32 val; -+ int ret; -+ -+ ret = device_property_read_u32(dev, "clock-frequency", &val); -+ if (ret) -+ /* Handle error */ -+ -+The function returns 0 if the property is copied to 'val' or negative -+errno if something went wrong (or the property does not exist). -+ -+2.2 Integer arrays -+------------------ -+An integer array is a package holding only integers. Arrays can be used to -+represent different things like Linux input key codes to GPIO mappings, pin -+control settings, dma request lines, etc. -+ -+An integer array looks like this: -+ -+ Package () { -+ "max8952,dvs-mode-microvolt", -+ Package () { -+ 1250000, -+ 1200000, -+ 1050000, -+ 950000, -+ } -+ } -+ -+The above array property can be accessed like: -+ -+ u32 voltages[4]; -+ int ret; -+ -+ ret = device_property_read_u32_array(dev, "max8952,dvs-mode-microvolt", -+ voltages, ARRAY_SIZE(voltages)); -+ if (ret) -+ /* Handle error */ -+ -+ -+All functions copy the resulting values cast to a requested type to the -+caller supplied array. If you pass NULL in the value pointer ('voltages' in -+this case), the function returns number of items in the array. This can be -+useful if caller does not know size of the array beforehand. -+ -+2.3 Strings -+----------- -+String properties can be used to describe many things like labels for GPIO -+buttons, compability ids, etc. -+ -+A string property looks like this: -+ -+ Package () {"pwm-names", "backlight"}, -+ Package () {"label", "Status-LED"}, -+ -+You can use device_property_read_string() to extract strings: -+ -+ const char *val; -+ int ret; -+ -+ ret = device_property_read_string(dev, "label", &val); -+ if (ret) -+ /* Handle error */ -+ -+Note that the function does not copy the returned string but instead the -+value is modified to point to the string property itself. -+ -+The memory is owned by the associated ACPI device object and released -+when it is removed. The user need not free the associated memory. -+ -+2.4 String arrays -+----------------- -+String arrays can be useful in describing a list of labels, names for -+DMA channels, etc. -+ -+A string array property looks like this: -+ -+ Package () {"dma-names", Package () {"tx", "rx", "rx-tx"}}, -+ Package () {"clock-output-names", Package () {"pll", "pll-switched"}}, -+ -+And these can be read in similar way that the integer arrrays: -+ -+ const char *dma_names[3]; -+ int ret; -+ -+ ret = device_property_read_string_array(dev, "dma-names", dma_names, -+ ARRAY_SIZE(dma_names)); -+ if (ret) -+ /* Handle error */ -+ -+The memory management rules follow what is specified for single strings. -+Specifically the returned pointers should be treated as constant and not to -+be freed. That is done automatically when the correspondig ACPI device -+object is released. -+ -+2.5 Object references -+--------------------- -+An ACPI object reference is used to refer to some object in the -+namespace. For example, if a device has dependencies with some other -+object, an object reference can be used. -+ -+An object reference looks like this: -+ -+ Package () {"dev0", \_SB.DEV0}, -+ -+At the time of writing this, there is no unified device_property_* accessor -+for references so one needs to use the following ACPI helper function: -+ -+ int acpi_dev_get_property_reference(struct acpi_device *adev, -+ const char *name, -+ const char *size_prop, int index, -+ struct acpi_reference_args *args); -+ -+The referenced ACPI device is returned in args->adev if found. -+ -+In addition to simple object references it is also possible to have object -+references with arguments. These are represented in ASL as follows: -+ -+ Device (\_SB.PCI0.PWM) -+ { -+ Name (_DSD, Package () { -+ ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"), -+ Package () { -+ Package () {"#pwm-cells", 2} -+ } -+ }) -+ } -+ -+ Device (\_SB.PCI0.BL) -+ { -+ Name (_DSD, Package () { -+ ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"), -+ Package () { -+ Package () { -+ "pwms", -+ Package () { -+ \_SB.PCI0.PWM, 0, 5000000, -+ \_SB.PCI0.PWM, 1, 4500000, -+ } -+ } -+ } -+ }) -+ } -+ -+In the above example, the referenced device declares a property that -+returns the number of expected arguments (here it is "#pwm-cells"). If -+no such property is given we assume that all the integers following the -+reference are arguments. -+ -+In the above example PWM device expects 2 additional arguments. This -+will be validated by the ACPI property core. -+ -+The additional arguments must be integers. Nothing else is supported. -+ -+It is possible, as in the above example, to have multiple references -+with varying number of integer arguments. It is up to the referenced -+device to declare how many arguments it expects. The 'index' parameter -+selects which reference is returned. -+ -+One can use acpi_dev_get_property_reference() as well to extract the -+information in additional parameters: -+ -+ struct acpi_reference_args args; -+ struct acpi_device *adev = /* this will point to the BL device */ -+ int ret; -+ -+ /* extract the first reference */ -+ acpi_dev_get_property_reference(adev, "pwms", "#pwm-cells", 0, &args); -+ -+ BUG_ON(args.nargs != 2); -+ BUG_ON(args.args[0] != 0); -+ BUG_ON(args.args[1] != 5000000); -+ -+ /* extract the second reference */ -+ acpi_dev_get_property_reference(adev, "pwms", "#pwm-cells", 1, &args); -+ -+ BUG_ON(args.nargs != 2); -+ BUG_ON(args.args[0] != 1); -+ BUG_ON(args.args[1] != 4500000); -+ -+In addition to arguments, args.adev now points to the ACPI device that -+corresponds to \_SB.PCI0.PWM. -+ -+It is intended that this function is not used directly but instead -+subsystems like pwm implement their ACPI support on top of this function -+in such way that it is hidden from the client drivers, such as via -+pwm_get(). -+ -+3. Device property hierarchies -+------------------------------ -+Devices are organized in a tree within the Linux kernel. It follows that -+the configuration data would also be hierarchical. In order to reach -+equivalence with Device Tree, the ACPI mechanism must also provide some -+sort of tree-like representation. Fortunately, the ACPI namespace is -+already such a structure. -+ -+For example, we could have the following device in ACPI namespace. The -+KEYS device is much like gpio_keys_polled.c in that it includes "pseudo" -+devices for each GPIO: -+ -+ Device (KEYS) -+ { -+ Name (_CRS, ResourceTemplate () { -+ GpioIo (Exclusive, PullUp, 0, 0, IoRestrictionInputOnly, -+ "\\_SB.PCI0.LPC", 0, ResourceConsumer) {0} -+ GpioIo (Exclusive, PullUp, 0, 0, IoRestrictionInputOnly, -+ "\\_SB.PCI0.LPC", 0, ResourceConsumer) {1} -+ ... -+ }) -+ -+ // "pseudo" devices declared under the parent device -+ Device (BTN0) { -+ Name (_DSD, Package () { -+ ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"), -+ Package () { -+ Package () {"label", "minnow_btn0"} -+ Package () {"gpios", Package () {^KEYS, 0, 0, 1}} -+ } -+ }) -+ } -+ -+ Device (BTN1) { -+ Name (_DSD, Package () { -+ ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"), -+ Package () { -+ Package () {"label", "minnow_btn1"} -+ Package () {"gpios", Package () {^KEYS, 1, 0, 1}} -+ } -+ }) -+ } -+ } -+ -+We can extract the above in gpio_keys_polled.c like: -+ -+ static int gpio_keys_polled_create_button(struct device *dev, void *child, -+ void *data) -+ { -+ struct button_data *bdata = data; -+ const char *label = NULL; -+ -+ /* -+ * We need to use device_child_ variant here to access -+ * properties of the child. -+ */ -+ device_child_property_read_string(dev, child, "label", &label); -+ /* and so on */ -+ } -+ -+ static void gpio_keys_polled_probe(struct device *dev) -+ { -+ /* Properties for the KEYS device itself */ -+ device_property_read(dev, ...); -+ -+ /* -+ * Iterate over button devices and extract their -+ * firmware configuration. -+ */ -+ ret = device_for_each_child_node(dev, gpio_keys_polled_create_button, -+ &bdata); -+ if (ret) -+ /* Handle error */ -+ } -+ -+Note that you still need proper error handling which is omitted in the -+above example. -+ -+4. Existing Device Tree enabled drivers -+--------------------------------------- -+At the time of writing this, there are ~250 existing DT enabled drivers. -+Allocating _HID/_CID for each would not be feasible. To make sure that -+those drivers can still be used on ACPI systems, we provide an -+alternative way to get these matched. -+ -+There is a special _HID "PRP0001" which means that use the DT bindings -+for matching this device to a driver. The driver needs to have -+.of_match_table filled in even when !CONFIG_OF. -+ -+An example device would be leds that can be controlled via GPIOs. This -+is represented as "leds-gpio" device and looks like this in the ACPI -+namespace: -+ -+ Device (LEDS) -+ { -+ Name (_DSD, Package () { -+ ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"), -+ Package () { -+ Package () {"compatible", Package () {"gpio-leds"}}, -+ } -+ }) -+ ... -+ } -+ -+In order to get the existing drivers/leds/leds-gpio.c bound to this -+device, we take advantage of "PRP0001": -+ -+ /* Following already exists in the driver */ -+ static const struct of_device_id of_gpio_leds_match[] = { -+ { .compatible = "gpio-leds", }, -+ {}, -+ }; -+ MODULE_DEVICE_TABLE(of, of_gpio_leds_match); -+ -+ /* This we add to the driver to get it probed */ -+ static const struct acpi_device_id acpi_gpio_leds_match[] = { -+ { "PRP0001" }, /* Device Tree shoehorned into ACPI */ -+ {}, -+ }; -+ MODULE_DEVICE_TABLE(acpi, acpi_gpio_leds_match); -+ -+ static struct platform_driver gpio_led_driver = { -+ .driver = { -+ /* -+ * No of_match_ptr() here because we want this -+ * table to be visible even when !CONFIG_OF to -+ * match against "compatible" in _DSD. -+ */ -+ .of_match_table = of_gpio_leds_match, -+ .acpi_match_table = acpi_gpio_leds_match, -+ }, -+ }; -+ -+Once ACPI core sees "PRP0001" and that the device has "compatible" -+property it will do the match using .of_match_table instead. ++++ b/Documentation/acpi/gpio-properties.txt +@@ -0,0 +1,96 @@ ++_DSD Device Properties Related to GPIO ++-------------------------------------- ++ ++With the release of ACPI 5.1 and the _DSD configuration objecte names ++can finally be given to GPIOs (and other things as well) returned by ++_CRS. Previously, we were only able to use an integer index to find ++the corresponding GPIO, which is pretty error prone (it depends on ++the _CRS output ordering, for example). ++ ++With _DSD we can now query GPIOs using a name instead of an integer ++index, like the ASL example below shows: ++ ++ // Bluetooth device with reset and shutdown GPIOs ++ Device (BTH) ++ { ++ Name (_HID, ...) ++ ++ Name (_CRS, ResourceTemplate () ++ { ++ GpioIo (Exclusive, PullUp, 0, 0, IoRestrictionInputOnly, ++ "\\_SB.GPO0", 0, ResourceConsumer) {15} ++ GpioIo (Exclusive, PullUp, 0, 0, IoRestrictionInputOnly, ++ "\\_SB.GPO0", 0, ResourceConsumer) {27, 31} ++ }) ++ ++ Name (_DSD, Package () ++ { ++ ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"), ++ Package () ++ { ++ Package () {"reset-gpio", Package() {^BTH, 1, 1, 0 }}, ++ Package () {"shutdown-gpio", Package() {^BTH, 0, 0, 0 }}, ++ } ++ }) ++ } ++ ++The format of the supported GPIO property is: ++ ++ Package () { "name", Package () { ref, index, pin, active_low }} ++ ++ ref - The device that has _CRS containing GpioIo()/GpioInt() resources, ++ typically this is the device itself (BTH in our case). ++ index - Index of the GpioIo()/GpioInt() resource in _CRS starting from zero. ++ pin - Pin in the GpioIo()/GpioInt() resource. Typically this is zero. ++ active_low - If 1 the GPIO is marked as active_low. ++ ++Since ACPI GpioIo() resource does not have a field saying whether it is ++active low or high, the "active_low" argument can be used here. Setting ++it to 1 marks the GPIO as active low. ++ ++In our Bluetooth example the "reset-gpio" refers to the second GpioIo() ++resource, second pin in that resource with the GPIO number of 31. ++ ++ACPI GPIO Mappings Provided by Drivers ++-------------------------------------- ++ ++There are systems in which the ACPI tables do not contain _DSD but provide _CRS ++with GpioIo()/GpioInt() resources and device drivers still need to work with ++them. ++ ++In those cases ACPI device identification objects, _HID, _CID, _CLS, _SUB, _HRV, ++available to the driver can be used to identify the device and that is supposed ++to be sufficient to determine the meaning and purpose of all of the GPIO lines ++listed by the GpioIo()/GpioInt() resources returned by _CRS. In other words, ++the driver is supposed to know what to use the GpioIo()/GpioInt() resources for ++once it has identified the device. Having done that, it can simply assign names ++to the GPIO lines it is going to use and provide the GPIO subsystem with a ++mapping between those names and the ACPI GPIO resources corresponding to them. ++ ++To do that, the driver needs to define a mapping table as a NULL-terminated ++array of struct acpi_gpio_mapping objects that each contain a name, a pointer ++to an array of line data (struct acpi_gpio_params) objects and the size of that ++array. Each struct acpi_gpio_params object consists of three fields, ++crs_entry_index, line_index, active_low, representing the index of the target ++GpioIo()/GpioInt() resource in _CRS starting from zero, the index of the target ++line in that resource starting from zero, and the active-low flag for that line, ++respectively, in analogy with the _DSD GPIO property format specified above. ++ ++For the example Bluetooth device discussed previously the data structures in ++question would look like this: ++ ++static const struct acpi_gpio_params reset_gpio = { 1, 1, false }; ++static const struct acpi_gpio_params shutdown_gpio = { 0, 0, false }; ++ ++static const struct acpi_gpio_mapping bluetooth_acpi_gpios[] = { ++ { "reset-gpio", &reset_gpio, 1 }, ++ { "shutdown-gpio", &shutdown_gpio, 1 }, ++ { }, ++}; + -+It is preferred that new devices get a proper _HID allocated for them -+instead of inventing new DT "compatible" devices. ++Next, the mapping table needs to be passed as the second argument to ++acpi_dev_add_driver_gpios() that will register it with the ACPI device object ++pointed to by its first argument. That should be done in the driver's .probe() ++routine. On removal, the driver should unregister its GPIO mapping table by ++calling acpi_dev_remove_driver_gpios() on the ACPI device object where that ++table was previously registered. diff --git a/Documentation/arm64/arm-acpi.txt b/Documentation/arm64/arm-acpi.txt new file mode 100644 -index 0000000..b7dc826 +index 0000000..17cf96d --- /dev/null +++ b/Documentation/arm64/arm-acpi.txt -@@ -0,0 +1,218 @@ +@@ -0,0 +1,323 @@ +ACPI on ARMv8 Servers +--------------------- -+ +ACPI can be used for ARMv8 general purpose servers designed to follow -+the SBSA specification (currently available to people with an ARM login at -+http://silver.arm.com). ++the ARM SBSA (Server Base System Architecture) specification, currently ++available to those with an ARM login at http://silver.arm.com. + -+The kernel will implement minimum ACPI version is 5.1 + errata as released by -+the UEFI Forum, which is available at . ++The ARMv8 kernel implements the reduced hardware model of ACPI version ++5.1 and its corresponding errata. Links to the specification and all ++external documents it refers to are managed by the UEFI Forum. The ++specification is available at http://www.uefi.org/specifications and ++external documents can be found via http://www.uefi.org/acpi. ++ ++If an ARMv8 system does not meet the requirements of the SBSA, or cannot ++be described using the mechanisms defined in the required ACPI specifications, ++then it is likely that Device Tree (DT) is more suitable than ACPI for the ++hardware. + -+If the machine does not meet the requirements of the SBSA, or cannot be -+described in the required ACPI specifications then it is likely that Device Tree -+(DT) is more suitable for the hardware. + +Relationship with Device Tree +----------------------------- -+ +ACPI support in drivers and subsystems for ARMv8 should never be mutually +exclusive with DT support at compile time. + @@ -1610,131 +2013,226 @@ index 0000000..b7dc826 +of booting with either scheme (in kernels with both schemes enabled at compile +time). + -+When booting using ACPI tables the /chosen node in DT will still be parsed -+to extract the kernel command line and initrd path. No other section of -+the DT will be used. ++When booting using ACPI tables, the /chosen node in DT will still be parsed ++to extract the kernel command line and initrd path. No other section of the ++DT will be used. ++ + +Booting using ACPI tables +------------------------- -+ -+Currently, the only defined method to pass ACPI tables to the kernel on ARMv8 ++The only defined method for passing ACPI tables to the kernel on ARMv8 +is via the UEFI system configuration table. + -+The UEFI implementation MUST set the ACPI_20_TABLE_GUID to point to the -+RSDP table (the table with the ACPI signature "RSD PTR "). ++Processing of ACPI tables may be disabled by passing acpi=off on the kernel ++command line; this is the default behavior. If acpi=force is used, the kernel ++will ONLY use device configuration information contained in the ACPI tables. + -+The pointer to the RSDP table will be retrieved from EFI by the ACPI core. ++In order for the kernel to load and use ACPI tables, the UEFI implementation ++MUST set the ACPI_20_TABLE_GUID to point to the RSDP table (the table with ++the ACPI signature "RSD PTR "). If this pointer is incorrect and acpi=force ++is used, the kernel will disable ACPI and try to use DT to boot. + -+Processing of ACPI tables may be disabled by passing acpi=off on the kernel -+command line. ++If the pointer to the RSDP table is correct, the table will be mapped into ++the kernel by the ACPI core, using the address provided by UEFI. + -+DO use an XSDT; RSDTs are deprecated and should not be used on arm64. They -+only allow for 32-bit addresses. ++The ACPI core will then locate and map in all other ACPI tables provided by ++using the addresses in the RSDP table to find the XSDT (eXtended System ++Description Table). The XSDT in turn provides the addresses to all other ++ACPI tables provided by the system firmware; the ACPI core will then traverse ++this table and map in the tables listed. + -+DO NOT use the 32-bit address fields in the FADT; they are deprecated. The -+64-bit alternatives MUST be used. ++The ACPI core will ignore any provided RSDT (Root System Description Table). ++RSDTs have been deprecated and are ignored on arm64 since they only allow ++for 32-bit addresses. + -+The minimum set of tables MUST include RSDP, XSDT, FACS, FADT, DSDT, MADT -+and GTDT. If PCI is used the MCFG table MUST also be present. ++Further, the ACPI core will only use the 64-bit address fields in the FADT ++(Fixed ACPI Description Table). Any 32-bit address fields in the FADT will ++be ignored on arm64. + -+ACPI Detection -+-------------- ++Hardware reduced mode (see Section 4.1 of the ACPI 5.1 specification) will ++be enforced by the ACPI core on arm64. Doing so allows the ACPI core to ++run less complex code since it no longer has to provide support for legacy ++hardware from other architectures. + -+Drivers should determine their probe() type by checking for ACPI_HANDLE, -+or .of_node, or other information in the device structure. This is -+detailed further in the "Driver Recommendations" section. ++For the ACPI core to operate properly, and in turn provide the information ++the kernel needs to configure devices, it expects to find the following ++tables (all section numbers refer to the ACPI 5.1 specfication): + -+In non-driver code If the presence of ACPI needs to be detected at runtime, -+then check the value of acpi_disabled. If CONFIG_ACPI is not set, -+acpi_disabled will always be 1. ++ -- RSDP (Root System Description Pointer), section 5.2.5 + -+Device Enumeration -+------------------ ++ -- XSDT (eXtended System Description Table), section 5.2.8 + -+Device descriptions in ACPI should use standard recognized ACPI interfaces. -+These are far simpler than the information provided via Device Tree. Drivers -+should take into account this simplicity and work with sensible defaults. ++ -- FACS (Firmware ACPI Control Structure), section 5.2.10 ++ ++ -- FADT (Fixed ACPI Description Table), section 5.2.9 + -+On no account should a Device Tree attempt to be replicated in ASL using such -+constructs as Name(KEY0, "Value1") type constructs. Additional driver specific -+data should be represented with the appropriate _DSD (ACPI Section 6.2.5) -+structure. _DSM (ACPI Section 9.14.1) should only be used if _DSD cannot -+represent the data required. ++ -- DSDT (Differentiated System Description Table), section ++ 5.2.11.1 + -+This data should be rare and not OS specific. For x86 ACPI has taken to -+identifying itself as Windows because it was found that only one path was -+routinely tested. For ARMv8 it would be preferable to have only one well -+tested path. ++ -- MADT (Multiple APIC Description Table), section 5.2.12 + -+_DSD covers more than the generic server case and care should be taken not to -+replicate highly specific embedded behaviour from DT into generic servers. ++ -- GTDT (Generic Timer Description Table), section 5.2.24 + -+Common _DSD bindings should be submitted to ASWG to be included in the -+document :- ++ -- If PCI is supported, the MCFG (Memory mapped ConFiGuration ++ Table), section 5.2.6, specifically Table 5-31. + -+http://www.uefi.org/sites/default/files/resources/_DSD-implementation-guide-toplevel.htm ++If the above tables are not all present, the kernel may or may not be ++able to boot properly since it may not be able to configure all of the ++devices available. ++ ++ ++ACPI Detection ++-------------- ++Drivers should determine their probe() type by checking for a null ++value for ACPI_HANDLE, or checking .of_node, or other information in ++the device structure. This is detailed further in the "Driver ++Recommendations" section. ++ ++In non-driver code, if the presence of ACPI needs to be detected at ++runtime, then check the value of acpi_disabled. If CONFIG_ACPI is not ++set, acpi_disabled will always be 1. ++ ++ ++Device Enumeration ++------------------ ++Device descriptions in ACPI should use standard recognized ACPI interfaces. ++These can contain less information than is typically provided via a Device ++Tree description for the same device. This is also one of the reasons that ++ACPI can be useful -- the driver takes into account that it may have less ++detailed information about the device and uses sensible defaults instead. ++If done properly in the driver, the hardware can change and improve over ++time without the driver having to change at all. ++ ++Clocks provide an excellent example. In DT, clocks need to be specified ++and the drivers need to take them into account. In ACPI, the assumption ++is that UEFI will leave the device in a reasonable default state, including ++any clock settings. If for some reason the driver needs to change a clock ++value, this can be done in an ACPI method; all the driver needs to do is ++invoke the method and not concern itself with what the method needs to do ++to change the clock. Changing the hardware can then take place over time ++by changing what the ACPI method does, and not the driver. ++ ++ACPI drivers should only look at one specific ASL object -- the _DSD object ++-- for device driver parameters (known in DT as "bindings", or "Device ++Properties" in ACPI). Not all DT bindings will be recognized. The UEFI ++Forum provides a mechanism for registering such bindings [URL TBD by ASWG] ++so that they may be used on any operating system supporting ACPI. Device ++properties that have not been registered with the UEFI Forum should not be ++used. ++ ++Drivers should look for device properties in the _DSD object ONLY; the _DSD ++object is described in the ACPI specification section 6.2.5, but more ++specifically, use the _DSD Device Properties UUID: ++ ++ -- UUID: daffd814-6eba-4d8c-8a91-bc9bbf4aa301 ++ ++ -- http://www.uefi.org/sites/default/files/resources/_DSD-device-properties-UUID.pdf) ++ ++The kernel has an interface for looking up device properties in a manner ++independent of whether DT or ACPI is being used and that interface should ++be used; it can eliminate some duplication of code paths in driver probing ++functions and discourage divergence between DT bindings and ACPI device ++properties. ++ ++ACPI tables are described with a formal language called ASL, the ACPI ++Source Language (section 19 of the specification). This means that there ++are always multiple ways to describe the same thing -- including device ++properties. For example, device properties could use an ASL construct ++that looks like this: Name(KEY0, "value0"). An ACPI device driver would ++then retrieve the value of the property by evaluating the KEY0 object. ++However, using Name() this way has multiple problems: (1) ACPI limits ++names ("KEY0") to four characters unlike DT; (2) there is no industry ++wide registry that maintains a list of names, minimzing re-use; (3) ++there is also no registry for the definition of property values ("value0"), ++again making re-use difficult; and (4) how does one maintain backward ++compatibility as new hardware comes out? The _DSD method was created ++to solve precisely these sorts of problems; Linux drivers should ALWAYS ++use the _DSD method for device properties and nothing else. ++ ++The _DSM object (ACPI Section 9.14.1) could also be used for conveying ++device properties to a driver. Linux drivers should only expect it to ++be used if _DSD cannot represent the data required, and there is no way ++to create a new UUID for the _DSD object. Note that there is even less ++regulation of the use of _DSM than there is of _DSD. Drivers that depend ++on the contents of _DSM objects will be more difficult to maintain over ++time because of this. ++ ++The _DSD object is a very flexible mechanism in ACPI, as are the registered ++Device Properties. This flexibility allows _DSD to cover more than just the ++generic server case and care should be taken in device drivers not to expect ++it to replicate highly specific embedded behaviour from DT. ++ ++Both DT bindings and ACPI device properties for device drivers have review ++processes. Use them. And, before creating new device properties, check to ++be sure that they have not been defined before and either registered in the ++Linux kernel documentation or the UEFI Forum. If the device drivers supports ++ACPI and DT, please make sure the device properties are consistent in both ++places. + -+If these bindings are mirrored from DT care should be taken to ensure they are -+reviewed as DT bindings before submission to limit divergance in bindings. + +Programmable Power Control Resources +------------------------------------ -+ +Programmable power control resources include such resources as voltage/current +providers (regulators) and clock sources. + -+For power control of these resources they should be represented with Power -+Resource Objects (ACPI Section 7.1). The ACPI core will then handle correctly -+enabling/disabling of resources as they are needed. ++The kernel assumes that power control of these resources is represented with ++Power Resource Objects (ACPI section 7.1). The ACPI core will then handle ++correctly enabling and disabling resources as they are needed. In order to ++get that to work, ACPI assumes each device has defined D-states and that these ++can be controlled through the optional ACPI methods _PS0, _PS1, _PS2, and _PS3; ++in ACPI, _PS0 is the method to invoke to turn a device full on, and _PS3 is for ++turning a device full off. ++ ++The kernel ACPI code will also assume that the _PS? methods follow the normal ++ACPI rules for such methods: + -+The ACPI 5.1 specification does not contain any standard binding for these -+objects to enable programmable levels or rates so this should be avoided if -+possible and the resources set to appropriate levels by the firmware. If this is -+not possible then any manipulation should be abstracted in ASL. ++ -- If either _PS0 or _PS3 is implemented, then the other method must also ++ be implemented. + -+Each device in ACPI has D-states and these can be controlled through -+the optional methods _PS0..._PS3 where _PS0 is full on and _PS3 is full off. ++ -- If a device requires usage or setup of a power resource when on, the ASL ++ should organize that it is allocated/enabled using the _PS0 method. + -+If either _PS0 or _PS3 is implemented, then the other method must also be -+implemented. ++ -- Resources allocated or enabled in the _PS0 method should be disabled ++ or de-allocated in the _PS3 method. + -+If a device requires usage or setup of a power resource when on, the ASL -+should organize that it is allocated/enabled using the _PS0 method. ++ -- Firmware will leave the resources in a reasonable state before handing ++ over control to the kernel. + -+Resources allocated/enabled in the _PS0 method should be disabled/de-allocated -+in the _PS3 method. ++Such code in _PS? methods will of course be very platform specific. But, ++this allows the driver to abstract out the interface for operating the device ++and avoid having to read special non-standard values from ACPI tables. Further, ++abstracting the use of these resources allows the hardware to change over time ++without requiring updates to the driver. + -+Such code in _PS? methods will of course be very platform specific but -+should allow the driver to operate the device without special non-standard -+values being read from ASL. Further, abstracting the use of these resources -+allows hardware revisions without requiring updates to the kernel. + +Clocks +------ ++ACPI makes the assumption that clocks are initialized by the firmware -- ++UEFI, in this case -- to some working value before control is handed over ++to the kernel. This has implications for devices such as UARTs, or SoC ++driven LCD displays, for example. + -+Like clocks that are part of the power resources there is no standard way -+to represent a clock tree in ACPI 5.1 in a similar manner to how it is -+described in DT. ++When the kernel boots, the clock is assumed to be set to reasonable ++working value. If for some reason the frequency needs to change -- e.g., ++throttling for power management -- the device driver should expect that ++process to be abstracted out into some ACPI method that can be invoked ++(please see the ACPI specification for further recommendations on standard ++methods to be expected). If is not, there is no direct way for ACPI to ++control the clocks. + -+Devices affected by this include things like UARTs, SoC driven LCD displays, -+etc. -+ -+The firmware (for example, UEFI) should initialize these clocks to fixed working -+values before the kernel is executed. + +Driver Recommendations +---------------------- ++DO NOT remove any DT handling when adding ACPI support for a driver. The ++same device may be used on many different systems. + -+DO NOT remove any FDT handling when adding ACPI support for a driver. Different -+systems may use the same device. -+ -+DO try and keep complex sections of ACPI and DT functionality separate. This -+may mean a patch to break out some complex DT to another function before -+the patch to add ACPI. This may happen in other functions but is most likely -+in probe function. This gives a clearer flow of data for reviewing driver -+source. -+ -+probe() :- ++DO try to structure the driver so that it is data driven. That is, set up ++a struct containing internal per-device state based on defaults and whatever ++else must be discovered by the driver probe function. Then, have the rest ++of the driver operate off of the contents of that struct. Doing so should ++allow most divergence between ACPI and DT functionality to be kept local to ++the probe function instead of being scattered throughout the driver. For ++example: + +static int device_probe_dt(struct platform_device *pdev) +{ @@ -1765,10 +2263,9 @@ index 0000000..b7dc826 + ... +} + -+DO keep the MODULE_DEVICE_TABLE entries together in the driver to make it clear -+the different names the driver is probed for, both from DT and from ACPI. -+ -+module device tables :- ++DO keep the MODULE_DEVICE_TABLE entries together in the driver to make it ++clear the different names the driver is probed for, both from DT and from ++ACPI: + +static struct of_device_id virtio_mmio_match[] = { + { .compatible = "virtio,mmio", }, @@ -1782,27 +2279,64 @@ index 0000000..b7dc826 +}; +MODULE_DEVICE_TABLE(acpi, virtio_mmio_acpi_match); + ++ +ASWG +---- -+ -+The following areas are not yet well defined for ARM in the current ACPI -+specification and are expected to be worked through in the UEFI ACPI -+Specification Working Group (ASWG) . -+Participation in this group is open to all UEFI members. -+ -+ - ACPI based CPU topology -+ - ACPI based Power management -+ - CPU idle control based on PSCI -+ - CPU performance control (CPPC) -+ - ACPI based SMMU -+ - ITS support for GIC in MADT -+ -+No code shall be accepted into the kernel unless it complies with the released -+standards from UEFI ASWG. If there are features missing from ACPI to make it -+function on a platform, ECRs should be submitted to ASWG and go through the -+approval process. ++The following areas are not yet fully defined for ARM in the 5.1 version ++of the ACPI specification and are expected to be worked through in the ++UEFI ACPI Specification Working Group (ASWG): ++ ++ -- ACPI based CPU topology ++ -- ACPI based Power management ++ -- CPU idle control based on PSCI ++ -- CPU performance control (CPPC) ++ -- ACPI based SMMU ++ -- ITS support for GIC in MADT ++ ++Participation in this group is open to all UEFI members. Please see ++http://www.uefi.org/workinggroup for details on group membership. ++ ++It is the intent of the ARMv8 ACPI kernel code to follow the ACPI specification ++as closely as possible, and to only implement functionality that complies with ++the released standards from UEFI ASWG. As a practical matter, there will be ++vendors that provide bad ACPI tables or violate the standards in some way. ++If this is because of errors, quirks and fixups may be necessary, but will ++be avoided if possible. If there are features missing from ACPI that preclude ++it from being used on a platform, ECRs (Engineering Change Requests) should be ++submitted to ASWG and go through the normal approval process; for those that ++are not UEFI members, many other members of the Linux community are and would ++likely be willing to assist in submitting ECRs. +diff --git a/Documentation/gpio/consumer.txt b/Documentation/gpio/consumer.txt +index 6ce5441..859918d 100644 +--- a/Documentation/gpio/consumer.txt ++++ b/Documentation/gpio/consumer.txt +@@ -219,6 +219,24 @@ part of the IRQ interface, e.g. IRQF_TRIGGER_FALLING, as are system wakeup + capabilities. + + ++GPIOs and ACPI ++============== ++ ++On ACPI systems, GPIOs are described by GpioIo()/GpioInt() resources listed by ++the _CRS configuration objects of devices. Those resources do not provide ++connection IDs (names) for GPIOs, so it is necessary to use an additional ++mechanism for this purpose. ++ ++Systems compliant with ACPI 5.1 or newer may provide a _DSD configuration object ++which, among other things, may be used to provide connection IDs for specific ++GPIOs described by the GpioIo()/GpioInt() resources in _CRS. If that is the ++case, it will be handled by the GPIO subsystem automatically. However, if the ++_DSD is not present, the mappings between GpioIo()/GpioInt() resources and GPIO ++connection IDs need to be provided by device drivers. ++ ++For details refer to Documentation/acpi/gpio-properties.txt ++ ++ + Interacting With the Legacy GPIO Subsystem + ========================================== + Many kernel subsystems still handle GPIOs using the legacy integer-based diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt -index 7dbe5ec..bb69b63 100644 +index 479f332..6187d9b 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -165,7 +165,7 @@ multipliers 'Kilo', 'Mega', and 'Giga', equalling 2^10, 2^20, and 2^30 @@ -1810,7 +2344,7 @@ index 7dbe5ec..bb69b63 100644 - acpi= [HW,ACPI,X86] -+ acpi= [HW,ACPI,X86,ARM] ++ acpi= [HW,ACPI,X86,ARM64] Advanced Configuration and Power Interface Format: { force | off | strict | noirq | rsdt } force -- enable ACPI if default was off @@ -1818,22 +2352,157 @@ index 7dbe5ec..bb69b63 100644 strictly ACPI specification compliant. rsdt -- prefer RSDT over (default) XSDT copy_dsdt -- copy DSDT to memory -+ For ARM64, ONLY "acpi=off" is available. ++ For ARM64, ONLY "acpi=off" or "acpi=force" are available See also Documentation/power/runtime_pm.txt, pci=noacpi +diff --git a/arch/arm/mach-s3c24xx/h1940-bluetooth.c b/arch/arm/mach-s3c24xx/h1940-bluetooth.c +index b4d14b8..9c8b127 100644 +--- a/arch/arm/mach-s3c24xx/h1940-bluetooth.c ++++ b/arch/arm/mach-s3c24xx/h1940-bluetooth.c +@@ -41,7 +41,7 @@ static void h1940bt_enable(int on) + mdelay(10); + gpio_set_value(S3C2410_GPH(1), 0); + +- h1940_led_blink_set(-EINVAL, GPIO_LED_BLINK, NULL, NULL); ++ h1940_led_blink_set(NULL, GPIO_LED_BLINK, NULL, NULL); + } + else { + gpio_set_value(S3C2410_GPH(1), 1); +@@ -50,7 +50,7 @@ static void h1940bt_enable(int on) + mdelay(10); + gpio_set_value(H1940_LATCH_BLUETOOTH_POWER, 0); + +- h1940_led_blink_set(-EINVAL, GPIO_LED_NO_BLINK_LOW, NULL, NULL); ++ h1940_led_blink_set(NULL, GPIO_LED_NO_BLINK_LOW, NULL, NULL); + } + } + +diff --git a/arch/arm/mach-s3c24xx/h1940.h b/arch/arm/mach-s3c24xx/h1940.h +index 2950cc4..596d9f6 100644 +--- a/arch/arm/mach-s3c24xx/h1940.h ++++ b/arch/arm/mach-s3c24xx/h1940.h +@@ -19,8 +19,10 @@ + #define H1940_SUSPEND_RESUMEAT (0x30081000) + #define H1940_SUSPEND_CHECK (0x30080000) + ++struct gpio_desc; ++ + extern void h1940_pm_return(void); +-extern int h1940_led_blink_set(unsigned gpio, int state, ++extern int h1940_led_blink_set(struct gpio_desc *desc, int state, + unsigned long *delay_on, + unsigned long *delay_off); + +diff --git a/arch/arm/mach-s3c24xx/mach-h1940.c b/arch/arm/mach-s3c24xx/mach-h1940.c +index d35ddc1..d40d4f5 100644 +--- a/arch/arm/mach-s3c24xx/mach-h1940.c ++++ b/arch/arm/mach-s3c24xx/mach-h1940.c +@@ -359,10 +359,11 @@ static struct platform_device h1940_battery = { + + static DEFINE_SPINLOCK(h1940_blink_spin); + +-int h1940_led_blink_set(unsigned gpio, int state, ++int h1940_led_blink_set(struct gpio_desc *desc, int state, + unsigned long *delay_on, unsigned long *delay_off) + { + int blink_gpio, check_gpio1, check_gpio2; ++ int gpio = desc ? desc_to_gpio(desc) : -EINVAL; + + switch (gpio) { + case H1940_LATCH_LED_GREEN: +diff --git a/arch/arm/mach-s3c24xx/mach-rx1950.c b/arch/arm/mach-s3c24xx/mach-rx1950.c +index c3f2682..1d35ff3 100644 +--- a/arch/arm/mach-s3c24xx/mach-rx1950.c ++++ b/arch/arm/mach-s3c24xx/mach-rx1950.c +@@ -250,9 +250,10 @@ static void rx1950_disable_charger(void) + + static DEFINE_SPINLOCK(rx1950_blink_spin); + +-static int rx1950_led_blink_set(unsigned gpio, int state, ++static int rx1950_led_blink_set(struct gpio_desc *desc, int state, + unsigned long *delay_on, unsigned long *delay_off) + { ++ int gpio = desc_to_gpio(desc); + int blink_gpio, check_gpio; + + switch (gpio) { +diff --git a/arch/arm/plat-orion/gpio.c b/arch/arm/plat-orion/gpio.c +index b61a3bc..b357053 100644 +--- a/arch/arm/plat-orion/gpio.c ++++ b/arch/arm/plat-orion/gpio.c +@@ -306,9 +306,10 @@ EXPORT_SYMBOL(orion_gpio_set_blink); + + #define ORION_BLINK_HALF_PERIOD 100 /* ms */ + +-int orion_gpio_led_blink_set(unsigned gpio, int state, ++int orion_gpio_led_blink_set(struct gpio_desc *desc, int state, + unsigned long *delay_on, unsigned long *delay_off) + { ++ unsigned gpio = desc_to_gpio(desc); + + if (delay_on && delay_off && !*delay_on && !*delay_off) + *delay_on = *delay_off = ORION_BLINK_HALF_PERIOD; +diff --git a/arch/arm/plat-orion/include/plat/orion-gpio.h b/arch/arm/plat-orion/include/plat/orion-gpio.h +index e763988..e856b07 100644 +--- a/arch/arm/plat-orion/include/plat/orion-gpio.h ++++ b/arch/arm/plat-orion/include/plat/orion-gpio.h +@@ -14,12 +14,15 @@ + #include + #include + #include ++ ++struct gpio_desc; ++ + /* + * Orion-specific GPIO API extensions. + */ + void orion_gpio_set_unused(unsigned pin); + void orion_gpio_set_blink(unsigned pin, int blink); +-int orion_gpio_led_blink_set(unsigned gpio, int state, ++int orion_gpio_led_blink_set(struct gpio_desc *desc, int state, + unsigned long *delay_on, unsigned long *delay_off); + + #define GPIO_INPUT_OK (1 << 0) diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig -index ac9afde..14423f3 100644 +index 9532f8d..80a82ac 100644 --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig -@@ -1,5 +1,6 @@ - config ARM64 - def_bool y -+ select ACPI_REDUCED_HARDWARE_ONLY if ACPI - select ARCH_BINFMT_ELF_RANDOMIZE_PIE +@@ -4,6 +4,7 @@ config ARM64 select ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE select ARCH_HAS_SG_CHAIN -@@ -267,6 +268,9 @@ config SMP + select ARCH_HAS_TICK_BROADCAST if GENERIC_CLOCKEVENTS_BROADCAST ++ select ACPI_REDUCED_HARDWARE_ONLY if ACPI + select ARCH_USE_CMPXCHG_LOCKREF + select ARCH_SUPPORTS_ATOMIC_RMW + select ARCH_WANT_OPTIONAL_GPIOLIB +@@ -34,6 +35,7 @@ config ARM64 + select GENERIC_TIME_VSYSCALL + select HANDLE_DOMAIN_IRQ + select HARDIRQS_SW_RESEND ++ select HAVE_ALIGNED_STRUCT_PAGE if SLUB + select HAVE_ARCH_AUDITSYSCALL + select HAVE_ARCH_JUMP_LABEL + select HAVE_ARCH_KGDB +@@ -41,6 +43,7 @@ config ARM64 + select HAVE_BPF_JIT + select HAVE_C_RECORDMCOUNT + select HAVE_CC_STACKPROTECTOR ++ select HAVE_CMPXCHG_DOUBLE + select HAVE_DEBUG_BUGVERBOSE + select HAVE_DEBUG_KMEMLEAK + select HAVE_DMA_API_DEBUG +@@ -185,6 +188,9 @@ config PCI_DOMAINS_GENERIC + config PCI_SYSCALL + def_bool PCI + ++config PCI_MMCONFIG ++ def_bool y if PCI && ACPI ++ + source "drivers/pci/Kconfig" + source "drivers/pci/pcie/Kconfig" + source "drivers/pci/hotplug/Kconfig" +@@ -268,6 +274,9 @@ config SMP If you don't know what to do here, say N. @@ -1843,7 +2512,25 @@ index ac9afde..14423f3 100644 config SCHED_MC bool "Multi-core scheduler support" depends on SMP -@@ -453,6 +457,8 @@ source "drivers/Kconfig" +@@ -401,6 +410,17 @@ config EFI + allow the kernel to be booted as an EFI application. This + is only useful on systems that have UEFI firmware. + ++config DMI ++ bool "Enable support for SMBIOS (DMI) tables" ++ depends on EFI ++ default y ++ help ++ This enables SMBIOS/DMI feature for systems. ++ ++ This option is only useful on systems that have UEFI firmware. ++ However, even with this option, the resultant kernel should ++ continue to boot on existing non-UEFI platforms. ++ + endmenu + + menu "Userspace binary formats" +@@ -454,6 +474,8 @@ source "drivers/Kconfig" source "drivers/firmware/Kconfig" @@ -1864,6 +2551,271 @@ index 20901ff..983d72a 100644 libs-y := arch/arm64/lib/ $(libs-y) libs-y += $(LIBGCC) libs-$(CONFIG_EFI_STUB) += drivers/firmware/efi/libstub/ +diff --git a/arch/arm64/crypto/Kconfig b/arch/arm64/crypto/Kconfig +index 5562652..a38b02c 100644 +--- a/arch/arm64/crypto/Kconfig ++++ b/arch/arm64/crypto/Kconfig +@@ -27,20 +27,19 @@ config CRYPTO_AES_ARM64_CE + tristate "AES core cipher using ARMv8 Crypto Extensions" + depends on ARM64 && KERNEL_MODE_NEON + select CRYPTO_ALGAPI +- select CRYPTO_AES + + config CRYPTO_AES_ARM64_CE_CCM + tristate "AES in CCM mode using ARMv8 Crypto Extensions" + depends on ARM64 && KERNEL_MODE_NEON + select CRYPTO_ALGAPI +- select CRYPTO_AES ++ select CRYPTO_AES_ARM64_CE + select CRYPTO_AEAD + + config CRYPTO_AES_ARM64_CE_BLK + tristate "AES in ECB/CBC/CTR/XTS modes using ARMv8 Crypto Extensions" + depends on ARM64 && KERNEL_MODE_NEON + select CRYPTO_BLKCIPHER +- select CRYPTO_AES ++ select CRYPTO_AES_ARM64_CE + select CRYPTO_ABLK_HELPER + + config CRYPTO_AES_ARM64_NEON_BLK +diff --git a/arch/arm64/crypto/aes-ce-ccm-glue.c b/arch/arm64/crypto/aes-ce-ccm-glue.c +index 9e6cdde..0ac73b8 100644 +--- a/arch/arm64/crypto/aes-ce-ccm-glue.c ++++ b/arch/arm64/crypto/aes-ce-ccm-glue.c +@@ -16,6 +16,8 @@ + #include + #include + ++#include "aes-ce-setkey.h" ++ + static int num_rounds(struct crypto_aes_ctx *ctx) + { + /* +@@ -48,7 +50,7 @@ static int ccm_setkey(struct crypto_aead *tfm, const u8 *in_key, + struct crypto_aes_ctx *ctx = crypto_aead_ctx(tfm); + int ret; + +- ret = crypto_aes_expand_key(ctx, in_key, key_len); ++ ret = ce_aes_expandkey(ctx, in_key, key_len); + if (!ret) + return 0; + +diff --git a/arch/arm64/crypto/aes-ce-cipher.c b/arch/arm64/crypto/aes-ce-cipher.c +index 2075e1a..ce47792 100644 +--- a/arch/arm64/crypto/aes-ce-cipher.c ++++ b/arch/arm64/crypto/aes-ce-cipher.c +@@ -14,6 +14,8 @@ + #include + #include + ++#include "aes-ce-setkey.h" ++ + MODULE_DESCRIPTION("Synchronous AES cipher using ARMv8 Crypto Extensions"); + MODULE_AUTHOR("Ard Biesheuvel "); + MODULE_LICENSE("GPL v2"); +@@ -124,6 +126,114 @@ static void aes_cipher_decrypt(struct crypto_tfm *tfm, u8 dst[], u8 const src[]) + kernel_neon_end(); + } + ++/* ++ * aes_sub() - use the aese instruction to perform the AES sbox substitution ++ * on each byte in 'input' ++ */ ++static u32 aes_sub(u32 input) ++{ ++ u32 ret; ++ ++ __asm__("dup v1.4s, %w[in] ;" ++ "movi v0.16b, #0 ;" ++ "aese v0.16b, v1.16b ;" ++ "umov %w[out], v0.4s[0] ;" ++ ++ : [out] "=r"(ret) ++ : [in] "r"(input) ++ : "v0","v1"); ++ ++ return ret; ++} ++ ++int ce_aes_expandkey(struct crypto_aes_ctx *ctx, const u8 *in_key, ++ unsigned int key_len) ++{ ++ /* ++ * The AES key schedule round constants ++ */ ++ static u8 const rcon[] = { ++ 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, ++ }; ++ ++ u32 kwords = key_len / sizeof(u32); ++ struct aes_block *key_enc, *key_dec; ++ int i, j; ++ ++ if (key_len != AES_KEYSIZE_128 && ++ key_len != AES_KEYSIZE_192 && ++ key_len != AES_KEYSIZE_256) ++ return -EINVAL; ++ ++ memcpy(ctx->key_enc, in_key, key_len); ++ ctx->key_length = key_len; ++ ++ kernel_neon_begin_partial(2); ++ for (i = 0; i < sizeof(rcon); i++) { ++ u32 *rki = ctx->key_enc + (i * kwords); ++ u32 *rko = rki + kwords; ++ ++ rko[0] = ror32(aes_sub(rki[kwords - 1]), 8) ^ rcon[i] ^ rki[0]; ++ rko[1] = rko[0] ^ rki[1]; ++ rko[2] = rko[1] ^ rki[2]; ++ rko[3] = rko[2] ^ rki[3]; ++ ++ if (key_len == AES_KEYSIZE_192) { ++ if (i >= 7) ++ break; ++ rko[4] = rko[3] ^ rki[4]; ++ rko[5] = rko[4] ^ rki[5]; ++ } else if (key_len == AES_KEYSIZE_256) { ++ if (i >= 6) ++ break; ++ rko[4] = aes_sub(rko[3]) ^ rki[4]; ++ rko[5] = rko[4] ^ rki[5]; ++ rko[6] = rko[5] ^ rki[6]; ++ rko[7] = rko[6] ^ rki[7]; ++ } ++ } ++ ++ /* ++ * Generate the decryption keys for the Equivalent Inverse Cipher. ++ * This involves reversing the order of the round keys, and applying ++ * the Inverse Mix Columns transformation on all but the first and ++ * the last one. ++ */ ++ key_enc = (struct aes_block *)ctx->key_enc; ++ key_dec = (struct aes_block *)ctx->key_dec; ++ j = num_rounds(ctx); ++ ++ key_dec[0] = key_enc[j]; ++ for (i = 1, j--; j > 0; i++, j--) ++ __asm__("ld1 {v0.16b}, %[in] ;" ++ "aesimc v1.16b, v0.16b ;" ++ "st1 {v1.16b}, %[out] ;" ++ ++ : [out] "=Q"(key_dec[i]) ++ : [in] "Q"(key_enc[j]) ++ : "v0","v1"); ++ key_dec[i] = key_enc[0]; ++ ++ kernel_neon_end(); ++ return 0; ++} ++EXPORT_SYMBOL(ce_aes_expandkey); ++ ++int ce_aes_setkey(struct crypto_tfm *tfm, const u8 *in_key, ++ unsigned int key_len) ++{ ++ struct crypto_aes_ctx *ctx = crypto_tfm_ctx(tfm); ++ int ret; ++ ++ ret = ce_aes_expandkey(ctx, in_key, key_len); ++ if (!ret) ++ return 0; ++ ++ tfm->crt_flags |= CRYPTO_TFM_RES_BAD_KEY_LEN; ++ return -EINVAL; ++} ++EXPORT_SYMBOL(ce_aes_setkey); ++ + static struct crypto_alg aes_alg = { + .cra_name = "aes", + .cra_driver_name = "aes-ce", +@@ -135,7 +245,7 @@ static struct crypto_alg aes_alg = { + .cra_cipher = { + .cia_min_keysize = AES_MIN_KEY_SIZE, + .cia_max_keysize = AES_MAX_KEY_SIZE, +- .cia_setkey = crypto_aes_set_key, ++ .cia_setkey = ce_aes_setkey, + .cia_encrypt = aes_cipher_encrypt, + .cia_decrypt = aes_cipher_decrypt + } +diff --git a/arch/arm64/crypto/aes-ce-setkey.h b/arch/arm64/crypto/aes-ce-setkey.h +new file mode 100644 +index 0000000..f08a647 +--- /dev/null ++++ b/arch/arm64/crypto/aes-ce-setkey.h +@@ -0,0 +1,5 @@ ++ ++int ce_aes_setkey(struct crypto_tfm *tfm, const u8 *in_key, ++ unsigned int key_len); ++int ce_aes_expandkey(struct crypto_aes_ctx *ctx, const u8 *in_key, ++ unsigned int key_len); +diff --git a/arch/arm64/crypto/aes-glue.c b/arch/arm64/crypto/aes-glue.c +index 79cd911..801aae3 100644 +--- a/arch/arm64/crypto/aes-glue.c ++++ b/arch/arm64/crypto/aes-glue.c +@@ -16,9 +16,13 @@ + #include + #include + ++#include "aes-ce-setkey.h" ++ + #ifdef USE_V8_CRYPTO_EXTENSIONS + #define MODE "ce" + #define PRIO 300 ++#define aes_setkey ce_aes_setkey ++#define aes_expandkey ce_aes_expandkey + #define aes_ecb_encrypt ce_aes_ecb_encrypt + #define aes_ecb_decrypt ce_aes_ecb_decrypt + #define aes_cbc_encrypt ce_aes_cbc_encrypt +@@ -30,6 +34,8 @@ MODULE_DESCRIPTION("AES-ECB/CBC/CTR/XTS using ARMv8 Crypto Extensions"); + #else + #define MODE "neon" + #define PRIO 200 ++#define aes_setkey crypto_aes_set_key ++#define aes_expandkey crypto_aes_expand_key + #define aes_ecb_encrypt neon_aes_ecb_encrypt + #define aes_ecb_decrypt neon_aes_ecb_decrypt + #define aes_cbc_encrypt neon_aes_cbc_encrypt +@@ -79,10 +85,10 @@ static int xts_set_key(struct crypto_tfm *tfm, const u8 *in_key, + struct crypto_aes_xts_ctx *ctx = crypto_tfm_ctx(tfm); + int ret; + +- ret = crypto_aes_expand_key(&ctx->key1, in_key, key_len / 2); ++ ret = aes_expandkey(&ctx->key1, in_key, key_len / 2); + if (!ret) +- ret = crypto_aes_expand_key(&ctx->key2, &in_key[key_len / 2], +- key_len / 2); ++ ret = aes_expandkey(&ctx->key2, &in_key[key_len / 2], ++ key_len / 2); + if (!ret) + return 0; + +@@ -288,7 +294,7 @@ static struct crypto_alg aes_algs[] = { { + .min_keysize = AES_MIN_KEY_SIZE, + .max_keysize = AES_MAX_KEY_SIZE, + .ivsize = AES_BLOCK_SIZE, +- .setkey = crypto_aes_set_key, ++ .setkey = aes_setkey, + .encrypt = ecb_encrypt, + .decrypt = ecb_decrypt, + }, +@@ -306,7 +312,7 @@ static struct crypto_alg aes_algs[] = { { + .min_keysize = AES_MIN_KEY_SIZE, + .max_keysize = AES_MAX_KEY_SIZE, + .ivsize = AES_BLOCK_SIZE, +- .setkey = crypto_aes_set_key, ++ .setkey = aes_setkey, + .encrypt = cbc_encrypt, + .decrypt = cbc_decrypt, + }, +@@ -324,7 +330,7 @@ static struct crypto_alg aes_algs[] = { { + .min_keysize = AES_MIN_KEY_SIZE, + .max_keysize = AES_MAX_KEY_SIZE, + .ivsize = AES_BLOCK_SIZE, +- .setkey = crypto_aes_set_key, ++ .setkey = aes_setkey, + .encrypt = ctr_encrypt, + .decrypt = ctr_encrypt, + }, diff --git a/arch/arm64/include/asm/acenv.h b/arch/arm64/include/asm/acenv.h new file mode 100644 index 0000000..b49166f @@ -1890,10 +2842,10 @@ index 0000000..b49166f +#endif /* _ASM_ACENV_H */ diff --git a/arch/arm64/include/asm/acpi.h b/arch/arm64/include/asm/acpi.h new file mode 100644 -index 0000000..7f6cd91 +index 0000000..6e692f4 --- /dev/null +++ b/arch/arm64/include/asm/acpi.h -@@ -0,0 +1,99 @@ +@@ -0,0 +1,102 @@ +/* + * Copyright (C) 2013-2014, Linaro Ltd. + * Author: Al Stone @@ -1936,23 +2888,27 @@ index 0000000..7f6cd91 + acpi_noirq = 1; +} + -+/* MPIDR value provided in GICC structure is 64 bits, but -+ * the acpi processor driver use the 32 bits cpu hardware -+ * ID (apic_id on intel platform) everywhere, it is pretty -+ * hard to modify the acpi processor driver to accept the -+ * 64 bits MPIDR value, at the same time, only 32 bits of -+ * the MPIDR is used in the 64 bits MPIDR, just pack the -+ * Affx fields into a single 32 bit identifier to accommodate -+ * the acpi processor drivers. ++static inline void enable_acpi(void) ++{ ++ acpi_disabled = 0; ++ acpi_pci_disabled = 0; ++ acpi_noirq = 0; ++} ++ ++/* MPIDR value provided in GICC structure is 64 bits, but the ++ * existing apic_id (CPU hardware ID) using in acpi processor ++ * driver is 32-bit, to conform to the same datatype we need ++ * to repack the GICC structure MPIDR. ++ * ++ * Only 32 bits of MPIDR are used: ++ * ++ * Bits [0:7] Aff0; ++ * Bits [8:15] Aff1; ++ * Bits [16:23] Aff2; ++ * Bits [32:39] Aff3; + */ -+static inline u32 pack_mpidr_into_32_bits(u64 mpidr) ++static inline u32 pack_mpidr(u64 mpidr) +{ -+ /* -+ * Bits [0:7] Aff0; -+ * Bits [8:15] Aff1; -+ * Bits [16:23] Aff2; -+ * Bits [32:39] Aff3; -+ */ + return (u32) ((mpidr & 0xff00000000) >> 8) | mpidr; +} + @@ -1964,7 +2920,7 @@ index 0000000..7f6cd91 + * cpu_logical_map(cpu) is the mapping of MPIDR and the logical cpu, + * and MPIDR is the cpu hardware ID we needed to pack. + */ -+#define cpu_physical_id(cpu) pack_mpidr_into_32_bits(cpu_logical_map(cpu)) ++#define cpu_physical_id(cpu) pack_mpidr(cpu_logical_map(cpu)) + +/* + * It's used from ACPI core in kdump to boot UP system with SMP kernel, @@ -1984,15 +2940,110 @@ index 0000000..7f6cd91 +extern int acpi_get_cpu_parked_address(int cpu, u64 *addr); + +#else -+ ++static inline void disable_acpi(void) { } +static inline bool acpi_psci_present(void) { return false; } +static inline bool acpi_psci_use_hvc(void) { return false; } +static inline void acpi_smp_init_cpus(void) { } +static inline int acpi_get_cpu_parked_address(int cpu, u64 *addr) { return -EOPNOTSUPP; } -+ +#endif /* CONFIG_ACPI */ + +#endif /*_ASM_ACPI_H*/ +diff --git a/arch/arm64/include/asm/cmpxchg.h b/arch/arm64/include/asm/cmpxchg.h +index ddb9d78..89e397b 100644 +--- a/arch/arm64/include/asm/cmpxchg.h ++++ b/arch/arm64/include/asm/cmpxchg.h +@@ -19,6 +19,7 @@ + #define __ASM_CMPXCHG_H + + #include ++#include + + #include + +@@ -152,6 +153,51 @@ static inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old, + return oldval; + } + ++#define system_has_cmpxchg_double() 1 ++ ++static inline int __cmpxchg_double(volatile void *ptr1, volatile void *ptr2, ++ unsigned long old1, unsigned long old2, ++ unsigned long new1, unsigned long new2, int size) ++{ ++ unsigned long loop, lost; ++ ++ switch (size) { ++ case 8: ++ VM_BUG_ON((unsigned long *)ptr2 - (unsigned long *)ptr1 != 1); ++ do { ++ asm volatile("// __cmpxchg_double8\n" ++ " ldxp %0, %1, %2\n" ++ " eor %0, %0, %3\n" ++ " eor %1, %1, %4\n" ++ " orr %1, %0, %1\n" ++ " mov %w0, #0\n" ++ " cbnz %1, 1f\n" ++ " stxp %w0, %5, %6, %2\n" ++ "1:\n" ++ : "=&r"(loop), "=&r"(lost), "+Q" (*(u64 *)ptr1) ++ : "r" (old1), "r"(old2), "r"(new1), "r"(new2)); ++ } while (loop); ++ break; ++ default: ++ BUILD_BUG(); ++ } ++ ++ return !lost; ++} ++ ++static inline int __cmpxchg_double_mb(volatile void *ptr1, volatile void *ptr2, ++ unsigned long old1, unsigned long old2, ++ unsigned long new1, unsigned long new2, int size) ++{ ++ int ret; ++ ++ smp_mb(); ++ ret = __cmpxchg_double(ptr1, ptr2, old1, old2, new1, new2, size); ++ smp_mb(); ++ ++ return ret; ++} ++ + static inline unsigned long __cmpxchg_mb(volatile void *ptr, unsigned long old, + unsigned long new, int size) + { +@@ -182,6 +228,31 @@ static inline unsigned long __cmpxchg_mb(volatile void *ptr, unsigned long old, + __ret; \ + }) + ++#define cmpxchg_double(ptr1, ptr2, o1, o2, n1, n2) \ ++({\ ++ int __ret;\ ++ __ret = __cmpxchg_double_mb((ptr1), (ptr2), (unsigned long)(o1), \ ++ (unsigned long)(o2), (unsigned long)(n1), \ ++ (unsigned long)(n2), sizeof(*(ptr1)));\ ++ __ret; \ ++}) ++ ++#define cmpxchg_double_local(ptr1, ptr2, o1, o2, n1, n2) \ ++({\ ++ int __ret;\ ++ __ret = __cmpxchg_double((ptr1), (ptr2), (unsigned long)(o1), \ ++ (unsigned long)(o2), (unsigned long)(n1), \ ++ (unsigned long)(n2), sizeof(*(ptr1)));\ ++ __ret; \ ++}) ++ ++#define this_cpu_cmpxchg_8(ptr, o, n) \ ++ cmpxchg_local(raw_cpu_ptr(&(ptr)), o, n) ++ ++#define this_cpu_cmpxchg_double_8(ptr1, ptr2, o1, o2, n1, n2) \ ++ cmpxchg_double_local(raw_cpu_ptr(&(ptr1)), raw_cpu_ptr(&(ptr2)), \ ++ o1, o2, n1, n2) ++ + #define cmpxchg64(ptr,o,n) cmpxchg((ptr),(o),(n)) + #define cmpxchg64_local(ptr,o,n) cmpxchg_local((ptr),(o),(n)) + diff --git a/arch/arm64/include/asm/cpu_ops.h b/arch/arm64/include/asm/cpu_ops.h index 6f8e2ef..978f567 100644 --- a/arch/arm64/include/asm/cpu_ops.h @@ -2005,10 +3056,47 @@ index 6f8e2ef..978f567 100644 int __init cpu_read_ops(struct device_node *dn, int cpu); void __init cpu_read_bootcpu_ops(void); -diff --git a/arch/arm64/include/asm/elf.h b/arch/arm64/include/asm/elf.h -index 01d3aab..8186df6 100644 ---- a/arch/arm64/include/asm/elf.h -+++ b/arch/arm64/include/asm/elf.h +diff --git a/arch/arm64/include/asm/dmi.h b/arch/arm64/include/asm/dmi.h +new file mode 100644 +index 0000000..69d37d8 +--- /dev/null ++++ b/arch/arm64/include/asm/dmi.h +@@ -0,0 +1,31 @@ ++/* ++ * arch/arm64/include/asm/dmi.h ++ * ++ * Copyright (C) 2013 Linaro Limited. ++ * Written by: Yi Li (yi.li@linaro.org) ++ * ++ * based on arch/ia64/include/asm/dmi.h ++ * ++ * This file is subject to the terms and conditions of the GNU General Public ++ * License. See the file "COPYING" in the main directory of this archive ++ * for more details. ++ */ ++ ++#ifndef __ASM_DMI_H ++#define __ASM_DMI_H ++ ++#include ++#include ++ ++/* ++ * According to section 2.3.6 of the UEFI spec, the firmware should not ++ * request a virtual mapping for configuration tables such as SMBIOS. ++ * This means we have to map them before use. ++ */ ++#define dmi_early_remap(x, l) ioremap_cache(x, l) ++#define dmi_early_unmap(x, l) iounmap(x) ++#define dmi_remap(x, l) ioremap_cache(x, l) ++#define dmi_unmap(x) iounmap(x) ++#define dmi_alloc(l) kzalloc(l, GFP_KERNEL) ++ ++#endif +diff --git a/arch/arm64/include/asm/elf.h b/arch/arm64/include/asm/elf.h +index 1f65be3..c0f89a0 100644 +--- a/arch/arm64/include/asm/elf.h ++++ b/arch/arm64/include/asm/elf.h @@ -114,7 +114,8 @@ typedef struct user_fpsimd_state elf_fpregset_t; */ #define elf_check_arch(x) ((x)->e_machine == EM_AARCH64) @@ -2019,6 +3107,130 @@ index 01d3aab..8186df6 100644 #define CORE_DUMP_USE_REGSET #define ELF_EXEC_PAGESIZE PAGE_SIZE +diff --git a/arch/arm64/include/asm/kvm_arm.h b/arch/arm64/include/asm/kvm_arm.h +index 7fd3e27..8afb863 100644 +--- a/arch/arm64/include/asm/kvm_arm.h ++++ b/arch/arm64/include/asm/kvm_arm.h +@@ -18,6 +18,7 @@ + #ifndef __ARM64_KVM_ARM_H__ + #define __ARM64_KVM_ARM_H__ + ++#include + #include + + /* Hyp Configuration Register (HCR) bits */ +@@ -160,9 +161,9 @@ + #endif + + #define VTTBR_BADDR_SHIFT (VTTBR_X - 1) +-#define VTTBR_BADDR_MASK (((1LLU << (PHYS_MASK_SHIFT - VTTBR_X)) - 1) << VTTBR_BADDR_SHIFT) +-#define VTTBR_VMID_SHIFT (48LLU) +-#define VTTBR_VMID_MASK (0xffLLU << VTTBR_VMID_SHIFT) ++#define VTTBR_BADDR_MASK (((UL(1) << (PHYS_MASK_SHIFT - VTTBR_X)) - 1) << VTTBR_BADDR_SHIFT) ++#define VTTBR_VMID_SHIFT (UL(48)) ++#define VTTBR_VMID_MASK (UL(0xFF) << VTTBR_VMID_SHIFT) + + /* Hyp System Trap Register */ + #define HSTR_EL2_TTEE (1 << 16) +@@ -185,13 +186,13 @@ + + /* Exception Syndrome Register (ESR) bits */ + #define ESR_EL2_EC_SHIFT (26) +-#define ESR_EL2_EC (0x3fU << ESR_EL2_EC_SHIFT) +-#define ESR_EL2_IL (1U << 25) ++#define ESR_EL2_EC (UL(0x3f) << ESR_EL2_EC_SHIFT) ++#define ESR_EL2_IL (UL(1) << 25) + #define ESR_EL2_ISS (ESR_EL2_IL - 1) + #define ESR_EL2_ISV_SHIFT (24) +-#define ESR_EL2_ISV (1U << ESR_EL2_ISV_SHIFT) ++#define ESR_EL2_ISV (UL(1) << ESR_EL2_ISV_SHIFT) + #define ESR_EL2_SAS_SHIFT (22) +-#define ESR_EL2_SAS (3U << ESR_EL2_SAS_SHIFT) ++#define ESR_EL2_SAS (UL(3) << ESR_EL2_SAS_SHIFT) + #define ESR_EL2_SSE (1 << 21) + #define ESR_EL2_SRT_SHIFT (16) + #define ESR_EL2_SRT_MASK (0x1f << ESR_EL2_SRT_SHIFT) +@@ -205,16 +206,16 @@ + #define ESR_EL2_FSC_TYPE (0x3c) + + #define ESR_EL2_CV_SHIFT (24) +-#define ESR_EL2_CV (1U << ESR_EL2_CV_SHIFT) ++#define ESR_EL2_CV (UL(1) << ESR_EL2_CV_SHIFT) + #define ESR_EL2_COND_SHIFT (20) +-#define ESR_EL2_COND (0xfU << ESR_EL2_COND_SHIFT) ++#define ESR_EL2_COND (UL(0xf) << ESR_EL2_COND_SHIFT) + + + #define FSC_FAULT (0x04) + #define FSC_PERM (0x0c) + + /* Hyp Prefetch Fault Address Register (HPFAR/HDFAR) */ +-#define HPFAR_MASK (~0xFUL) ++#define HPFAR_MASK (~UL(0xf)) + + #define ESR_EL2_EC_UNKNOWN (0x00) + #define ESR_EL2_EC_WFI (0x01) +diff --git a/arch/arm64/include/asm/pci.h b/arch/arm64/include/asm/pci.h +index 872ba93..2f287a6 100644 +--- a/arch/arm64/include/asm/pci.h ++++ b/arch/arm64/include/asm/pci.h +@@ -33,5 +33,56 @@ static inline int pci_proc_domain(struct pci_bus *bus) + } + #endif /* CONFIG_PCI */ + ++/* "PCI MMCONFIG %04x [bus %02x-%02x]" */ ++#define PCI_MMCFG_RESOURCE_NAME_LEN (22 + 4 + 2 + 2) ++ ++#define PCI_MMCFG_BUS_OFFSET(bus) ((bus) << 20) ++ ++struct acpi_device; ++ ++struct pci_sysdata { ++ int domain; /* PCI domain */ ++ int node; /* NUMA node */ ++ struct acpi_device *companion; /* ACPI companion device */ ++ void *iommu; /* IOMMU private data */ ++}; ++ ++struct acpi_pci_root; ++struct pci_mmcfg_region; ++ ++typedef int (*acpi_mcfg_fixup_t)(struct acpi_pci_root *root, ++ struct pci_mmcfg_region *cfg); ++ ++struct pci_mmcfg_region { ++ struct list_head list; ++ struct resource res; ++ int (*read)(struct pci_mmcfg_region *cfg, unsigned int bus, ++ unsigned int devfn, int reg, int len, u32 *value); ++ int (*write)(struct pci_mmcfg_region *cfg, unsigned int bus, ++ unsigned int devfn, int reg, int len, u32 value); ++ acpi_mcfg_fixup_t fixup; ++ void *data; ++ u64 address; ++ char __iomem *virt; ++ u16 segment; ++ u8 start_bus; ++ u8 end_bus; ++ char name[PCI_MMCFG_RESOURCE_NAME_LEN]; ++}; ++ ++struct acpi_mcfg_fixup { ++ char oem_id[7]; ++ char oem_table_id[9]; ++ acpi_mcfg_fixup_t hook; ++}; ++ ++/* Designate a routine to fix up buggy MCFG */ ++#define DECLARE_ACPI_MCFG_FIXUP(oem_id, table_id, hook) \ ++ static const struct acpi_mcfg_fixup __acpi_fixup_##hook __used \ ++ __attribute__((__section__(".acpi_fixup_mcfg"), aligned((sizeof(void *))))) \ ++ = { {oem_id}, {table_id}, hook }; ++ ++extern struct pci_mmcfg_region *pci_mmconfig_lookup(int segment, int bus); ++ + #endif /* __KERNEL__ */ + #endif /* __ASM_PCI_H */ diff --git a/arch/arm64/include/asm/psci.h b/arch/arm64/include/asm/psci.h index e5312ea..2454bc5 100644 --- a/arch/arm64/include/asm/psci.h @@ -2085,10 +3297,10 @@ index 5bd029b..f4ba4fe 100644 obj-m += $(arm64-obj-m) diff --git a/arch/arm64/kernel/acpi.c b/arch/arm64/kernel/acpi.c new file mode 100644 -index 0000000..5486426 +index 0000000..06a96be --- /dev/null +++ b/arch/arm64/kernel/acpi.c -@@ -0,0 +1,397 @@ +@@ -0,0 +1,398 @@ +/* + * ARM64 Specific Low-Level ACPI Boot Support + * @@ -2119,10 +3331,8 @@ index 0000000..5486426 +#include +#include + -+#define ARM64_ACPI_DISABLED_DEFAULT 1 -+ +int acpi_noirq; /* skip ACPI IRQ initialization */ -+int acpi_disabled = ARM64_ACPI_DISABLED_DEFAULT; ++int acpi_disabled; +EXPORT_SYMBOL(acpi_disabled); + +int acpi_pci_disabled; /* skip ACPI PCI scan and IRQ initialization */ @@ -2172,7 +3382,7 @@ index 0000000..5486426 + int cpu; + + if (mpidr == INVALID_HWID) { -+ pr_info("Skip invalid cpu hardware ID\n"); ++ pr_info("Skip MADT cpu entry with invalid MPIDR\n"); + return -EINVAL; + } + @@ -2196,7 +3406,7 @@ index 0000000..5486426 + for_each_possible_cpu(cpu) { + if (cpu_logical_map(cpu) == mpidr) { + pr_err("Firmware bug, duplicate CPU MPIDR: 0x%llx in MADT\n", -+ mpidr); ++ mpidr); + return -EINVAL; + } + } @@ -2204,7 +3414,10 @@ index 0000000..5486426 + /* allocate a logical cpu id for the new comer */ + cpu = cpumask_next_zero(-1, cpu_possible_mask); + } else { -+ /* First GICC entry must be BSP as ACPI spec said */ ++ /* ++ * First GICC entry must be BSP as ACPI spec said ++ * in section 5.2.12.15 ++ */ + if (cpu_logical_map(0) != mpidr) { + pr_err("First GICC entry with MPIDR 0x%llx is not BSP\n", + mpidr); @@ -2360,7 +3573,7 @@ index 0000000..5486426 + /* + * Revision in table header is the FADT Major revision, + * and there is a minor revision of FADT which was introduced -+ * by ACPI 5.1, we only deal with ACPI 5.1 or higher revision ++ * by ACPI 5.1, we only deal with ACPI 5.1 or newer revision + * to get arm boot flags, or we will disable ACPI. + */ + if (table->revision > 5 || @@ -2378,7 +3591,7 @@ index 0000000..5486426 + boot_method = "parking-protocol"; + + if (!boot_method) -+ pr_warn("has no boot support, will not bring up secondary CPUs\n"); ++ pr_warn("No boot method, will not bring up secondary CPUs\n"); + return -EOPNOTSUPP; + } + @@ -2457,9 +3670,9 @@ index 0000000..5486426 + + /* "acpi=off" disables both ACPI table parsing and interpreter */ + if (strcmp(arg, "off") == 0) -+ acpi_disabled = 1; -+ else if (strcmp(arg, "on") == 0) -+ acpi_disabled = 0; ++ disable_acpi(); ++ else if (strcmp(arg, "force") == 0) /* force ACPI to be enabled */ ++ enable_acpi(); + else + return -EINVAL; /* Core will print when we return error */ + @@ -2516,51 +3729,456 @@ index cce9524..1d90f31 100644 { const struct cpu_operations **ops = supported_cpu_ops; +diff --git a/arch/arm64/kernel/efi-entry.S b/arch/arm64/kernel/efi-entry.S +index 619b1dd..a0016d3 100644 +--- a/arch/arm64/kernel/efi-entry.S ++++ b/arch/arm64/kernel/efi-entry.S +@@ -61,7 +61,8 @@ ENTRY(efi_stub_entry) + */ + mov x20, x0 // DTB address + ldr x0, [sp, #16] // relocated _text address +- mov x21, x0 ++ ldr x21, =stext_offset ++ add x21, x0, x21 + + /* + * Flush dcache covering current runtime addresses diff --git a/arch/arm64/kernel/efi.c b/arch/arm64/kernel/efi.c -index 03aaa99..6c4de44 100644 +index 95c49eb..f9de195 100644 --- a/arch/arm64/kernel/efi.c +++ b/arch/arm64/kernel/efi.c -@@ -479,3 +479,14 @@ err_unmap: +@@ -11,6 +11,7 @@ + * + */ + ++#include + #include + #include + #include +@@ -112,8 +113,6 @@ static int __init uefi_init(void) + efi.systab->hdr.revision & 0xffff, vendor); + + retval = efi_config_init(NULL); +- if (retval == 0) +- set_bit(EFI_CONFIG_TABLES, &efi.flags); + + out: + early_memunmap(efi.systab, sizeof(efi_system_table_t)); +@@ -125,17 +124,17 @@ out: + */ + static __init int is_reserve_region(efi_memory_desc_t *md) + { +- if (!is_normal_ram(md)) ++ switch (md->type) { ++ case EFI_LOADER_CODE: ++ case EFI_LOADER_DATA: ++ case EFI_BOOT_SERVICES_CODE: ++ case EFI_BOOT_SERVICES_DATA: ++ case EFI_CONVENTIONAL_MEMORY: + return 0; +- +- if (md->attribute & EFI_MEMORY_RUNTIME) +- return 1; +- +- if (md->type == EFI_ACPI_RECLAIM_MEMORY || +- md->type == EFI_RESERVED_TYPE) +- return 1; +- +- return 0; ++ default: ++ break; ++ } ++ return is_normal_ram(md); + } + + static __init void reserve_regions(void) +@@ -471,3 +470,54 @@ err_unmap: return -1; } early_initcall(arm64_enter_virtual_mode); + ++static int __init arm64_dmi_init(void) ++{ ++ /* ++ * On arm64, DMI depends on UEFI, and dmi_scan_machine() needs to ++ * be called early because dmi_id_init(), which is an arch_initcall ++ * itself, depends on dmi_scan_machine() having been called already. ++ */ ++ dmi_scan_machine(); ++ if (dmi_available) ++ dmi_set_dump_stack_arch_desc(); ++ return 0; ++} ++core_initcall(arm64_dmi_init); ++ +/* + * If nothing else is handling pm_power_off, use EFI + * -+ * This is called from a late_initcall after other mechanisms -+ * have had a chance to register a handler. ++ * When Guenter Roeck's power-off handler call chain patches land, ++ * we just need to return true unconditionally. + */ +bool efi_poweroff_required(void) +{ + return pm_power_off == NULL; +} -diff --git a/arch/arm64/kernel/process.c b/arch/arm64/kernel/process.c -index c3065db..99edd1f 100644 ---- a/arch/arm64/kernel/process.c -+++ b/arch/arm64/kernel/process.c -@@ -43,6 +43,7 @@ - #include - #include - #include -+#include - - #include - #include -@@ -157,6 +158,11 @@ void machine_restart(char *cmd) - do_kernel_restart(cmd); - - /* -+ * If all else fails, try EFI -+ */ ++ ++static int arm64_efi_restart(struct notifier_block *this, ++ unsigned long mode, void *cmd) ++{ + efi_reboot(reboot_mode, cmd); ++ return NOTIFY_DONE; ++} ++ ++static struct notifier_block arm64_efi_restart_nb = { ++ .notifier_call = arm64_efi_restart, ++ .priority = INT_MAX, ++}; ++ ++static int __init arm64_register_efi_restart(void) ++{ ++ int ret = 0; ++ ++ if (efi_enabled(EFI_RUNTIME_SERVICES)) { ++ ret = register_restart_handler(&arm64_efi_restart_nb); ++ if (ret) ++ pr_err("%s: cannot register restart handler, %d\n", ++ __func__, ret); ++ } ++ return ret; ++} ++late_initcall(arm64_register_efi_restart); +diff --git a/arch/arm64/kernel/entry-ftrace.S b/arch/arm64/kernel/entry-ftrace.S +index 38e704e..08cafc5 100644 +--- a/arch/arm64/kernel/entry-ftrace.S ++++ b/arch/arm64/kernel/entry-ftrace.S +@@ -98,8 +98,8 @@ + ENTRY(_mcount) + mcount_enter + +- ldr x0, =ftrace_trace_function +- ldr x2, [x0] ++ adrp x0, ftrace_trace_function ++ ldr x2, [x0, #:lo12:ftrace_trace_function] + adr x0, ftrace_stub + cmp x0, x2 // if (ftrace_trace_function + b.eq skip_ftrace_call // != ftrace_stub) { +@@ -115,14 +115,15 @@ skip_ftrace_call: // return; + mcount_exit // return; + // } + skip_ftrace_call: +- ldr x1, =ftrace_graph_return +- ldr x2, [x1] // if ((ftrace_graph_return +- cmp x0, x2 // != ftrace_stub) +- b.ne ftrace_graph_caller +- +- ldr x1, =ftrace_graph_entry // || (ftrace_graph_entry +- ldr x2, [x1] // != ftrace_graph_entry_stub)) +- ldr x0, =ftrace_graph_entry_stub ++ adrp x1, ftrace_graph_return ++ ldr x2, [x1, #:lo12:ftrace_graph_return] ++ cmp x0, x2 // if ((ftrace_graph_return ++ b.ne ftrace_graph_caller // != ftrace_stub) ++ ++ adrp x1, ftrace_graph_entry // || (ftrace_graph_entry ++ adrp x0, ftrace_graph_entry_stub // != ftrace_graph_entry_stub)) ++ ldr x2, [x1, #:lo12:ftrace_graph_entry] ++ add x0, x0, #:lo12:ftrace_graph_entry_stub + cmp x0, x2 + b.ne ftrace_graph_caller // ftrace_graph_caller(); + +diff --git a/arch/arm64/kernel/head.S b/arch/arm64/kernel/head.S +index 0a6e4f9..5a76e3a 100644 +--- a/arch/arm64/kernel/head.S ++++ b/arch/arm64/kernel/head.S +@@ -132,6 +132,8 @@ efi_head: + #endif + + #ifdef CONFIG_EFI ++ .globl stext_offset ++ .set stext_offset, stext - efi_head + .align 3 + pe_header: + .ascii "PE" +@@ -155,12 +157,12 @@ optional_header: + .long 0 // SizeOfInitializedData + .long 0 // SizeOfUninitializedData + .long efi_stub_entry - efi_head // AddressOfEntryPoint +- .long stext - efi_head // BaseOfCode ++ .long stext_offset // BaseOfCode + + extra_header_fields: + .quad 0 // ImageBase +- .long 0x20 // SectionAlignment +- .long 0x8 // FileAlignment ++ .long 0x1000 // SectionAlignment ++ .long PECOFF_FILE_ALIGNMENT // FileAlignment + .short 0 // MajorOperatingSystemVersion + .short 0 // MinorOperatingSystemVersion + .short 0 // MajorImageVersion +@@ -172,7 +174,7 @@ extra_header_fields: + .long _end - efi_head // SizeOfImage + + // Everything before the kernel image is considered part of the header +- .long stext - efi_head // SizeOfHeaders ++ .long stext_offset // SizeOfHeaders + .long 0 // CheckSum + .short 0xa // Subsystem (EFI application) + .short 0 // DllCharacteristics +@@ -217,16 +219,24 @@ section_table: + .byte 0 + .byte 0 // end of 0 padding of section name + .long _end - stext // VirtualSize +- .long stext - efi_head // VirtualAddress ++ .long stext_offset // VirtualAddress + .long _edata - stext // SizeOfRawData +- .long stext - efi_head // PointerToRawData ++ .long stext_offset // PointerToRawData + + .long 0 // PointerToRelocations (0 for executables) + .long 0 // PointerToLineNumbers (0 for executables) + .short 0 // NumberOfRelocations (0 for executables) + .short 0 // NumberOfLineNumbers (0 for executables) + .long 0xe0500020 // Characteristics (section flags) +- .align 5 + + /* - * Whoops - the architecture was unable to reboot. - */ - printk("Reboot failed -- System halted\n"); ++ * EFI will load stext onwards at the 4k section alignment ++ * described in the PE/COFF header. To ensure that instruction ++ * sequences using an adrp and a :lo12: immediate will function ++ * correctly at this alignment, we must ensure that stext is ++ * placed at a 4k boundary in the Image to begin with. ++ */ ++ .align 12 + #endif + + ENTRY(stext) +diff --git a/arch/arm64/kernel/io.c b/arch/arm64/kernel/io.c +index 7d37ead..354be2a 100644 +--- a/arch/arm64/kernel/io.c ++++ b/arch/arm64/kernel/io.c +@@ -25,12 +25,26 @@ + */ + void __memcpy_fromio(void *to, const volatile void __iomem *from, size_t count) + { +- unsigned char *t = to; +- while (count) { ++ while (count && (!IS_ALIGNED((unsigned long)from, 8) || ++ !IS_ALIGNED((unsigned long)to, 8))) { ++ *(u8 *)to = __raw_readb(from); ++ from++; ++ to++; + count--; +- *t = readb(from); +- t++; ++ } ++ ++ while (count >= 8) { ++ *(u64 *)to = __raw_readq(from); ++ from += 8; ++ to += 8; ++ count -= 8; ++ } ++ ++ while (count) { ++ *(u8 *)to = __raw_readb(from); + from++; ++ to++; ++ count--; + } + } + EXPORT_SYMBOL(__memcpy_fromio); +@@ -40,12 +54,26 @@ EXPORT_SYMBOL(__memcpy_fromio); + */ + void __memcpy_toio(volatile void __iomem *to, const void *from, size_t count) + { +- const unsigned char *f = from; +- while (count) { ++ while (count && (!IS_ALIGNED((unsigned long)to, 8) || ++ !IS_ALIGNED((unsigned long)from, 8))) { ++ __raw_writeb(*(volatile u8 *)from, to); ++ from++; ++ to++; + count--; +- writeb(*f, to); +- f++; ++ } ++ ++ while (count >= 8) { ++ __raw_writeq(*(volatile u64 *)from, to); ++ from += 8; ++ to += 8; ++ count -= 8; ++ } ++ ++ while (count) { ++ __raw_writeb(*(volatile u8 *)from, to); ++ from++; + to++; ++ count--; + } + } + EXPORT_SYMBOL(__memcpy_toio); +@@ -55,10 +83,28 @@ EXPORT_SYMBOL(__memcpy_toio); + */ + void __memset_io(volatile void __iomem *dst, int c, size_t count) + { +- while (count) { ++ u64 qc = (u8)c; ++ ++ qc |= qc << 8; ++ qc |= qc << 16; ++ qc |= qc << 32; ++ ++ while (count && !IS_ALIGNED((unsigned long)dst, 8)) { ++ __raw_writeb(c, dst); ++ dst++; + count--; +- writeb(c, dst); ++ } ++ ++ while (count >= 8) { ++ __raw_writeq(qc, dst); ++ dst += 8; ++ count -= 8; ++ } ++ ++ while (count) { ++ __raw_writeb(c, dst); + dst++; ++ count--; + } + } + EXPORT_SYMBOL(__memset_io); +diff --git a/arch/arm64/kernel/pci.c b/arch/arm64/kernel/pci.c +index ce5836c..978cd21 100644 +--- a/arch/arm64/kernel/pci.c ++++ b/arch/arm64/kernel/pci.c +@@ -17,6 +17,8 @@ + #include + #include + #include ++#include ++#include + + #include + +@@ -37,34 +39,99 @@ resource_size_t pcibios_align_resource(void *data, const struct resource *res, + return res->start; + } + ++int pcibios_root_bridge_prepare(struct pci_host_bridge *bridge) ++{ ++ struct pci_sysdata *sd; ++ ++ if (!acpi_disabled) { ++ sd = bridge->bus->sysdata; ++ ACPI_COMPANION_SET(&bridge->dev, sd->companion); ++ } ++ return 0; ++} ++ + /* + * Try to assign the IRQ number from DT when adding a new device + */ + int pcibios_add_device(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); + + return 0; + } + ++void pcibios_add_bus(struct pci_bus *bus) ++{ ++ if (!acpi_disabled) ++ acpi_pci_add_bus(bus); ++} + +-#ifdef CONFIG_PCI_DOMAINS_GENERIC +-static bool dt_domain_found = false; ++void pcibios_remove_bus(struct pci_bus *bus) ++{ ++ if (!acpi_disabled) ++ acpi_pci_remove_bus(bus); ++} ++ ++int pcibios_enable_irq(struct pci_dev *dev) ++{ ++ if (!acpi_disabled && !pci_dev_msi_enabled(dev)) ++ acpi_pci_irq_enable(dev); ++ return 0; ++} ++ ++int pcibios_disable_irq(struct pci_dev *dev) ++{ ++ if (!acpi_disabled && !pci_dev_msi_enabled(dev)) ++ acpi_pci_irq_disable(dev); ++ return 0; ++} + ++int pcibios_enable_device(struct pci_dev *dev, int bars) ++{ ++ int err; ++ ++ err = pci_enable_resources(dev, bars); ++ if (err < 0) ++ return err; ++ ++ if (!pci_dev_msi_enabled(dev)) ++ return pcibios_enable_irq(dev); ++ return 0; ++} ++ ++#ifdef CONFIG_PCI_DOMAINS_GENERIC + void pci_bus_assign_domain_nr(struct pci_bus *bus, struct device *parent) + { +- int domain = of_get_pci_domain_nr(parent->of_node); +- +- if (domain >= 0) { +- dt_domain_found = true; +- } else if (dt_domain_found == true) { +- dev_err(parent, "Node %s is missing \"linux,pci-domain\" property in DT\n", +- parent->of_node->full_name); +- return; +- } else { +- domain = pci_get_new_domain_nr(); +- } ++ int domain = -1; + +- bus->domain_nr = domain; ++ if (acpi_disabled) ++ domain = of_get_pci_domain_nr(parent->of_node); ++ else { ++ struct pci_sysdata *sd = bus->sysdata; ++ ++ domain = sd->domain; ++ } ++ if (domain >= 0) ++ bus->domain_nr = domain; + } + #endif ++ ++static int __init pcibios_assign_resources(void) ++{ ++ struct pci_bus *root_bus; ++ ++ if (acpi_disabled) ++ return 0; ++ ++ list_for_each_entry(root_bus, &pci_root_buses, node) { ++ pcibios_resource_survey_bus(root_bus); ++ pci_assign_unassigned_root_bus_resources(root_bus); ++ } ++ return 0; ++} ++/* ++ * fs_initcall comes after subsys_initcall, so we know acpi scan ++ * has run. ++ */ ++fs_initcall(pcibios_assign_resources); diff --git a/arch/arm64/kernel/psci.c b/arch/arm64/kernel/psci.c -index 866c1c8..f8a981e 100644 +index 663da77..2d0deda 100644 --- a/arch/arm64/kernel/psci.c +++ b/arch/arm64/kernel/psci.c @@ -15,6 +15,7 @@ @@ -2684,7 +4302,7 @@ index 866c1c8..f8a981e 100644 static int __init cpu_psci_cpu_init(struct device_node *dn, unsigned int cpu) diff --git a/arch/arm64/kernel/setup.c b/arch/arm64/kernel/setup.c -index 2437196..c1144a1 100644 +index 2437196..4c7029d 100644 --- a/arch/arm64/kernel/setup.c +++ b/arch/arm64/kernel/setup.c @@ -43,6 +43,7 @@ @@ -2706,13 +4324,41 @@ index 2437196..c1144a1 100644 unsigned int processor_id; EXPORT_SYMBOL(processor_id); -@@ -386,22 +391,34 @@ void __init setup_arch(char **cmdline_p) +@@ -116,12 +121,16 @@ void __init early_print(const char *str, ...) + + void __init smp_setup_processor_id(void) + { ++ u64 mpidr = read_cpuid_mpidr() & MPIDR_HWID_BITMASK; ++ cpu_logical_map(0) = mpidr; ++ + /* + * clear __my_cpu_offset on boot CPU to avoid hang caused by + * using percpu variable early, for example, lockdep will + * access percpu variable inside lock_release */ - local_async_enable(); + set_my_cpu_offset(0); ++ pr_info("Booting Linux on physical CPU 0x%lx\n", (unsigned long)mpidr); + } -+ if (acpi_disabled) -+ disable_acpi(); + bool arch_match_cpu_phys_id(int cpu, u64 phys_id) +@@ -312,6 +321,7 @@ static void __init setup_machine_fdt(phys_addr_t dt_phys) + } + + machine_name = of_flat_dt_get_machine_name(); ++ dump_stack_set_arch_desc("%s (DT)", machine_name); + } + + /* +@@ -378,6 +388,8 @@ void __init setup_arch(char **cmdline_p) + + early_ioremap_init(); + ++ disable_acpi(); + + parse_early_param(); + + /* +@@ -389,19 +401,27 @@ void __init setup_arch(char **cmdline_p) efi_init(); arm64_memblock_init(); @@ -2727,9 +4373,6 @@ index 2437196..c1144a1 100644 - unflatten_device_tree(); - - psci_init(); -- - cpu_logical_map(0) = read_cpuid_mpidr() & MPIDR_HWID_BITMASK; -- cpu_read_bootcpu_ops(); + if (acpi_disabled) { + unflatten_device_tree(); + psci_dt_init(); @@ -2741,13 +4384,15 @@ index 2437196..c1144a1 100644 + psci_acpi_init(); + acpi_smp_init_cpus(); + } -+ + +- cpu_logical_map(0) = read_cpuid_mpidr() & MPIDR_HWID_BITMASK; +- cpu_read_bootcpu_ops(); #ifdef CONFIG_SMP - smp_init_cpus(); smp_build_mpidr_hash(); #endif -@@ -414,6 +431,19 @@ void __init setup_arch(char **cmdline_p) +@@ -414,6 +434,19 @@ void __init setup_arch(char **cmdline_p) #endif } @@ -2767,7 +4412,7 @@ index 2437196..c1144a1 100644 static int __init arm64_device_init(void) { of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL); -@@ -506,3 +536,25 @@ const struct seq_operations cpuinfo_op = { +@@ -506,3 +539,25 @@ const struct seq_operations cpuinfo_op = { .stop = c_stop, .show = c_show }; @@ -2947,8 +4592,60 @@ index 1a7125c..42f9195 100644 arch_timer_rate = arch_timer_get_rate(); if (!arch_timer_rate) panic("Unable to initialise architected timer.\n"); +diff --git a/arch/arm64/kernel/vmlinux.lds.S b/arch/arm64/kernel/vmlinux.lds.S +index edf8715..4596f46 100644 +--- a/arch/arm64/kernel/vmlinux.lds.S ++++ b/arch/arm64/kernel/vmlinux.lds.S +@@ -32,6 +32,22 @@ jiffies = jiffies_64; + *(.hyp.text) \ + VMLINUX_SYMBOL(__hyp_text_end) = .; + ++/* ++ * The size of the PE/COFF section that covers the kernel image, which ++ * runs from stext to _edata, must be a round multiple of the PE/COFF ++ * FileAlignment, which we set to its minimum value of 0x200. 'stext' ++ * itself is 4 KB aligned, so padding out _edata to a 0x200 aligned ++ * boundary should be sufficient. ++ */ ++PECOFF_FILE_ALIGNMENT = 0x200; ++ ++#ifdef CONFIG_EFI ++#define PECOFF_EDATA_PADDING \ ++ .pecoff_edata_padding : { BYTE(0); . = ALIGN(PECOFF_FILE_ALIGNMENT); } ++#else ++#define PECOFF_EDATA_PADDING ++#endif ++ + SECTIONS + { + /* +@@ -103,6 +119,7 @@ SECTIONS + _data = .; + _sdata = .; + RW_DATA_SECTION(64, PAGE_SIZE, THREAD_SIZE) ++ PECOFF_EDATA_PADDING + _edata = .; + + BSS_SECTION(0, 0, 0) +diff --git a/arch/arm64/kvm/hyp.S b/arch/arm64/kvm/hyp.S +index b72aa9f..fbe909f 100644 +--- a/arch/arm64/kvm/hyp.S ++++ b/arch/arm64/kvm/hyp.S +@@ -761,10 +761,10 @@ + .macro activate_traps + ldr x2, [x0, #VCPU_HCR_EL2] + msr hcr_el2, x2 +- ldr x2, =(CPTR_EL2_TTA) ++ mov x2, #CPTR_EL2_TTA + msr cptr_el2, x2 + +- ldr x2, =(1 << 15) // Trap CP15 Cr=15 ++ mov x2, #(1 << 15) // Trap CP15 Cr=15 + msr hstr_el2, x2 + + mrs x2, mdcr_el2 diff --git a/arch/arm64/mm/dma-mapping.c b/arch/arm64/mm/dma-mapping.c -index d920942..fda70ab 100644 +index d920942..705a9ce 100644 --- a/arch/arm64/mm/dma-mapping.c +++ b/arch/arm64/mm/dma-mapping.c @@ -23,8 +23,14 @@ @@ -3015,7 +4712,7 @@ index d920942..fda70ab 100644 + status = acpi_check_coherency(ACPI_HANDLE(dev), + &coherent); + if (ACPI_FAILURE(status) || coherent) -+ set_dma_ops(dev, &coherent_swiotlb_dma_ops); ++ set_dma_ops(_dev, &coherent_swiotlb_dma_ops); + break; + } + dev = dev->parent; @@ -3055,68 +4752,813 @@ index d920942..fda70ab 100644 +}; +#endif + - static int __init swiotlb_late_init(void) - { - size_t swiotlb_size = min(SZ_64M, MAX_ORDER_NR_PAGES << PAGE_SHIFT); - -+ /* -+ * These must be registered before of_platform_populate(). -+ */ -+#ifdef CONFIG_ACPI -+ bus_register_notifier(&platform_bus_type, &platform_bus_nb); -+ bus_register_notifier(&amba_bustype, &amba_bus_nb); -+#endif + static int __init swiotlb_late_init(void) + { + size_t swiotlb_size = min(SZ_64M, MAX_ORDER_NR_PAGES << PAGE_SHIFT); + ++ /* ++ * These must be registered before of_platform_populate(). ++ */ ++#ifdef CONFIG_ACPI ++ bus_register_notifier(&platform_bus_type, &platform_bus_nb); ++ bus_register_notifier(&amba_bustype, &amba_bus_nb); ++#endif ++ ++#ifdef CONFIG_PCI ++ bus_register_notifier(&pci_bus_type, &pci_bus_nb); ++#endif ++ + dma_ops = &noncoherent_swiotlb_dma_ops; + + return swiotlb_late_init_with_default_size(swiotlb_size); +diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c +index 0bf90d2..f4f8b50 100644 +--- a/arch/arm64/mm/mmu.c ++++ b/arch/arm64/mm/mmu.c +@@ -202,7 +202,7 @@ static void __init alloc_init_pmd(pud_t *pud, unsigned long addr, + } + + static void __init alloc_init_pud(pgd_t *pgd, unsigned long addr, +- unsigned long end, unsigned long phys, ++ unsigned long end, phys_addr_t phys, + int map_io) + { + pud_t *pud; +diff --git a/arch/arm64/pci/Makefile b/arch/arm64/pci/Makefile +new file mode 100644 +index 0000000..7038b51 +--- /dev/null ++++ b/arch/arm64/pci/Makefile +@@ -0,0 +1,2 @@ ++obj-y += pci.o ++obj-$(CONFIG_ACPI) += mmconfig.o +diff --git a/arch/arm64/pci/mmconfig.c b/arch/arm64/pci/mmconfig.c +new file mode 100644 +index 0000000..e83e0d5 +--- /dev/null ++++ b/arch/arm64/pci/mmconfig.c +@@ -0,0 +1,292 @@ ++/* ++ * mmconfig.c - Low-level direct PCI config space access via MMCONFIG ++ * ++ * Borrowed heavily from x86 ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define PREFIX "PCI: " ++ ++/* Indicate if the mmcfg resources have been placed into the resource table. */ ++static bool pci_mmcfg_running_state; ++static bool pci_mmcfg_arch_init_failed; ++static DEFINE_MUTEX(pci_mmcfg_lock); ++ ++LIST_HEAD(pci_mmcfg_list); ++ ++struct pci_mmcfg_region *pci_mmconfig_lookup(int segment, int bus) ++{ ++ struct pci_mmcfg_region *cfg; ++ ++ list_for_each_entry_rcu(cfg, &pci_mmcfg_list, list) ++ if (cfg->segment == segment && ++ cfg->start_bus <= bus && bus <= cfg->end_bus) ++ return cfg; ++ ++ return NULL; ++} ++ ++static void __iomem *mcfg_ioremap(struct pci_mmcfg_region *cfg) ++{ ++ void __iomem *addr; ++ u64 start, size; ++ int num_buses; ++ ++ start = cfg->address + PCI_MMCFG_BUS_OFFSET(cfg->start_bus); ++ num_buses = cfg->end_bus - cfg->start_bus + 1; ++ size = PCI_MMCFG_BUS_OFFSET(num_buses); ++ addr = ioremap_nocache(start, size); ++ if (addr) ++ addr -= PCI_MMCFG_BUS_OFFSET(cfg->start_bus); ++ return addr; ++} ++ ++void pci_mmcfg_arch_unmap(struct pci_mmcfg_region *cfg) ++{ ++ if (cfg && cfg->virt) { ++ iounmap(cfg->virt + PCI_MMCFG_BUS_OFFSET(cfg->start_bus)); ++ cfg->virt = NULL; ++ } ++} ++ ++void __init pci_mmcfg_arch_free(void) ++{ ++ struct pci_mmcfg_region *cfg; ++ ++ list_for_each_entry(cfg, &pci_mmcfg_list, list) ++ pci_mmcfg_arch_unmap(cfg); ++} ++ ++int pci_mmcfg_arch_map(struct pci_mmcfg_region *cfg) ++{ ++ cfg->virt = mcfg_ioremap(cfg); ++ if (!cfg->virt) { ++ pr_err(PREFIX "can't map MMCONFIG at %pR\n", &cfg->res); ++ return -ENOMEM; ++ } ++ ++ return 0; ++} ++ ++static void __init pci_mmconfig_remove(struct pci_mmcfg_region *cfg) ++{ ++ if (cfg->res.parent) ++ release_resource(&cfg->res); ++ list_del(&cfg->list); ++ kfree(cfg); ++} ++ ++static void __init free_all_mmcfg(void) ++{ ++ struct pci_mmcfg_region *cfg, *tmp; ++ ++ pci_mmcfg_arch_free(); ++ list_for_each_entry_safe(cfg, tmp, &pci_mmcfg_list, list) ++ pci_mmconfig_remove(cfg); ++} ++ ++static void list_add_sorted(struct pci_mmcfg_region *new) ++{ ++ struct pci_mmcfg_region *cfg; ++ ++ /* keep list sorted by segment and starting bus number */ ++ list_for_each_entry_rcu(cfg, &pci_mmcfg_list, list) { ++ if (cfg->segment > new->segment || ++ (cfg->segment == new->segment && ++ cfg->start_bus >= new->start_bus)) { ++ list_add_tail_rcu(&new->list, &cfg->list); ++ return; ++ } ++ } ++ list_add_tail_rcu(&new->list, &pci_mmcfg_list); ++} ++ ++static struct pci_mmcfg_region *pci_mmconfig_alloc(int segment, int start, ++ int end, u64 addr) ++{ ++ struct pci_mmcfg_region *new; ++ struct resource *res; ++ ++ if (addr == 0) ++ return NULL; ++ ++ new = kzalloc(sizeof(*new), GFP_KERNEL); ++ if (!new) ++ return NULL; ++ ++ new->address = addr; ++ new->segment = segment; ++ new->start_bus = start; ++ new->end_bus = end; ++ ++ res = &new->res; ++ res->start = addr + PCI_MMCFG_BUS_OFFSET(start); ++ res->end = addr + PCI_MMCFG_BUS_OFFSET(end + 1) - 1; ++ res->flags = IORESOURCE_MEM | IORESOURCE_BUSY; ++ snprintf(new->name, PCI_MMCFG_RESOURCE_NAME_LEN, ++ "PCI MMCONFIG %04x [bus %02x-%02x]", segment, start, end); ++ res->name = new->name; ++ ++ return new; ++} ++ ++static struct pci_mmcfg_region *__init pci_mmconfig_add(int segment, int start, ++ int end, u64 addr) ++{ ++ struct pci_mmcfg_region *new; ++ ++ new = pci_mmconfig_alloc(segment, start, end, addr); ++ if (new) { ++ mutex_lock(&pci_mmcfg_lock); ++ list_add_sorted(new); ++ mutex_unlock(&pci_mmcfg_lock); ++ ++ pr_info(PREFIX ++ "MMCONFIG for domain %04x [bus %02x-%02x] at %pR " ++ "(base %#lx)\n", ++ segment, start, end, &new->res, (unsigned long)addr); ++ } ++ ++ return new; ++} ++ ++extern struct acpi_mcfg_fixup __start_acpi_mcfg_fixups[]; ++extern struct acpi_mcfg_fixup __end_acpi_mcfg_fixups[]; ++ ++static int __init pci_parse_mcfg(struct acpi_table_header *header) ++{ ++ struct acpi_table_mcfg *mcfg; ++ struct acpi_mcfg_allocation *cfg_table, *cfg; ++ struct acpi_mcfg_fixup *fixup; ++ struct pci_mmcfg_region *new; ++ unsigned long i; ++ int entries; ++ ++ if (!header) ++ return -EINVAL; ++ ++ mcfg = (struct acpi_table_mcfg *)header; ++ ++ /* how many config structures do we have */ ++ free_all_mmcfg(); ++ entries = 0; ++ i = header->length - sizeof(struct acpi_table_mcfg); ++ while (i >= sizeof(struct acpi_mcfg_allocation)) { ++ entries++; ++ i -= sizeof(struct acpi_mcfg_allocation); ++ } ++ if (entries == 0) { ++ pr_err(PREFIX "MMCONFIG has no entries\n"); ++ return -ENODEV; ++ } ++ ++ fixup = __start_acpi_mcfg_fixups; ++ while (fixup < __end_acpi_mcfg_fixups) { ++ if (!strncmp(fixup->oem_id, header->oem_id, 6) && ++ !strncmp(fixup->oem_table_id, header->oem_table_id, 8)) ++ break; ++ ++fixup; ++ } ++ ++ cfg_table = (struct acpi_mcfg_allocation *) &mcfg[1]; ++ for (i = 0; i < entries; i++) { ++ cfg = &cfg_table[i]; ++ ++ new = pci_mmconfig_add(cfg->pci_segment, cfg->start_bus_number, ++ cfg->end_bus_number, cfg->address); ++ if (!new) { ++ pr_warn(PREFIX "no memory for MCFG entries\n"); ++ free_all_mmcfg(); ++ return -ENOMEM; ++ } ++ if (fixup < __end_acpi_mcfg_fixups) ++ new->fixup = fixup->hook; ++ } ++ ++ return 0; ++} ++ ++int __init pci_mmcfg_arch_init(void) ++{ ++ struct pci_mmcfg_region *cfg; ++ ++ list_for_each_entry(cfg, &pci_mmcfg_list, list) ++ if (pci_mmcfg_arch_map(cfg)) { ++ pci_mmcfg_arch_free(); ++ return 0; ++ } ++ ++ return 1; ++} ++ ++static void __init __pci_mmcfg_init(int early) ++{ ++ if (list_empty(&pci_mmcfg_list)) { ++ pr_info("No MCFG table found!\n"); ++ pci_mmcfg_arch_init_failed = true; ++ return; ++ } ++ ++ if (!pci_mmcfg_arch_init()) { ++ pr_info("pci_mmcfg_arch_init failed!\n"); ++ free_all_mmcfg(); ++ pci_mmcfg_arch_init_failed = true; ++ } ++} ++ ++void __init pci_mmcfg_early_init(void) ++{ ++ acpi_table_parse(ACPI_SIG_MCFG, pci_parse_mcfg); ++ ++ __pci_mmcfg_init(1); ++} ++ ++static int __init pci_mmcfg_init(void) ++{ ++ pci_mmcfg_early_init(); ++ return 0; ++} ++arch_initcall(pci_mmcfg_init); ++ ++void __init pci_mmcfg_late_init(void) ++{ ++ /* MMCONFIG hasn't been enabled yet, try again */ ++ if (pci_mmcfg_arch_init_failed) { ++ acpi_table_parse(ACPI_SIG_MCFG, pci_parse_mcfg); ++ __pci_mmcfg_init(0); ++ } ++} ++ ++static int __init pci_mmcfg_late_insert_resources(void) ++{ ++ struct pci_mmcfg_region *cfg; ++ ++ pci_mmcfg_running_state = true; ++ ++ /* ++ * Attempt to insert the mmcfg resources but not with the busy flag ++ * marked so it won't cause request errors when __request_region is ++ * called. ++ */ ++ list_for_each_entry(cfg, &pci_mmcfg_list, list) ++ if (!cfg->res.parent) ++ insert_resource(&iomem_resource, &cfg->res); ++ ++ return 0; ++} ++ ++/* ++ * Perform MMCONFIG resource insertion after PCI initialization to allow for ++ * misprogrammed MCFG tables that state larger sizes but actually conflict ++ * with other system resources. ++ */ ++late_initcall(pci_mmcfg_late_insert_resources); +diff --git a/arch/arm64/pci/pci.c b/arch/arm64/pci/pci.c +new file mode 100644 +index 0000000..0166475 +--- /dev/null ++++ b/arch/arm64/pci/pci.c +@@ -0,0 +1,461 @@ ++#include ++#include ++#include ++#include ++#include ++ ++struct pci_root_info { ++ struct acpi_device *bridge; ++ char name[16]; ++ unsigned int res_num; ++ struct resource *res; ++ resource_size_t *res_offset; ++ struct pci_sysdata sd; ++ u16 segment; ++ u8 start_bus; ++ u8 end_bus; ++}; ++ ++static char __iomem *pci_dev_base(struct pci_mmcfg_region *cfg, ++ unsigned int bus, unsigned int devfn) ++{ ++ return cfg->virt + (PCI_MMCFG_BUS_OFFSET(bus) | (devfn << 12)); ++} ++ ++static int __raw_pci_read(struct pci_mmcfg_region *cfg, unsigned int bus, ++ unsigned int devfn, int reg, int len, u32 *value) ++{ ++ char __iomem *addr = pci_dev_base(cfg, bus, devfn) + (reg & ~3); ++ int shift = (reg & 3) * 8; ++ u32 v; ++ ++ v = readl(addr) >> shift; ++ switch (len) { ++ case 1: ++ *value = v & 0xff; ++ break; ++ case 2: ++ *value = v & 0xffff; ++ break; ++ case 4: ++ *value = v; ++ break; ++ } ++ return 0; ++} ++ ++static int __raw_pci_write(struct pci_mmcfg_region *cfg, unsigned int bus, ++ unsigned int devfn, int reg, int len, u32 value) ++{ ++ char __iomem *addr = pci_dev_base(cfg, bus, devfn) + (reg & ~3); ++ int mask = 0, shift = (reg & 3) * 8; ++ u32 v; ++ ++ switch (len) { ++ case 1: ++ mask = 0xff << shift; ++ break; ++ case 2: ++ mask = 0xffff << shift; ++ break; ++ } ++ ++ if (mask) { ++ v = readl(addr) & ~mask; ++ writel(v | (value << shift), addr); ++ } else ++ writel(value, addr); ++ ++ return 0; ++} ++ ++/* ++ * raw_pci_read/write - Platform-specific PCI config space access. ++ */ ++int raw_pci_read(unsigned int domain, unsigned int bus, ++ unsigned int devfn, int reg, int len, u32 *val) ++{ ++ struct pci_mmcfg_region *cfg; ++ int ret; ++ ++ if (unlikely((bus > 255) || (devfn > 255) || (reg > 4095))) { ++err: *val = -1; ++ return -EINVAL; ++ } ++ ++ rcu_read_lock(); ++ cfg = pci_mmconfig_lookup(domain, bus); ++ if (!cfg || !cfg->virt) { ++ rcu_read_unlock(); ++ goto err; ++ } ++ ++ if (cfg->read) ++ ret = (*cfg->read)(cfg, bus, devfn, reg, len, val); ++ else ++ ret = __raw_pci_read(cfg, bus, devfn, reg, len, val); ++ ++ rcu_read_unlock(); ++ ++ return ret; ++} ++ ++int raw_pci_write(unsigned int domain, unsigned int bus, ++ unsigned int devfn, int reg, int len, u32 val) ++{ ++ struct pci_mmcfg_region *cfg; ++ int ret; ++ ++ if (unlikely((bus > 255) || (devfn > 255) || (reg > 4095))) ++ return -EINVAL; ++ ++ rcu_read_lock(); ++ cfg = pci_mmconfig_lookup(domain, bus); ++ if (!cfg || !cfg->virt) { ++ rcu_read_unlock(); ++ return -EINVAL; ++ } ++ ++ if (cfg->write) ++ ret = (*cfg->write)(cfg, bus, devfn, reg, len, val); ++ else ++ ret = __raw_pci_write(cfg, bus, devfn, reg, len, val); ++ ++ rcu_read_unlock(); ++ ++ return ret; ++} ++ ++#ifdef CONFIG_ACPI ++static int pci_read(struct pci_bus *bus, unsigned int devfn, int where, ++ int size, u32 *value) ++{ ++ return raw_pci_read(pci_domain_nr(bus), bus->number, ++ devfn, where, size, value); ++} ++ ++static int pci_write(struct pci_bus *bus, unsigned int devfn, int where, ++ int size, u32 value) ++{ ++ return raw_pci_write(pci_domain_nr(bus), bus->number, ++ devfn, where, size, value); ++} ++ ++struct pci_ops pci_root_ops = { ++ .read = pci_read, ++ .write = pci_write, ++}; ++ ++static acpi_status resource_to_addr(struct acpi_resource *resource, ++ struct acpi_resource_address64 *addr) ++{ ++ acpi_status status; ++ ++ memset(addr, 0, sizeof(*addr)); ++ switch (resource->type) { ++ case ACPI_RESOURCE_TYPE_ADDRESS16: ++ case ACPI_RESOURCE_TYPE_ADDRESS32: ++ case ACPI_RESOURCE_TYPE_ADDRESS64: ++ status = acpi_resource_to_address64(resource, addr); ++ if (ACPI_SUCCESS(status) && ++ (addr->resource_type == ACPI_MEMORY_RANGE || ++ addr->resource_type == ACPI_IO_RANGE) && ++ addr->address_length > 0) { ++ return AE_OK; ++ } ++ break; ++ } ++ return AE_ERROR; ++} ++ ++static acpi_status count_resource(struct acpi_resource *acpi_res, void *data) ++{ ++ struct pci_root_info *info = data; ++ struct acpi_resource_address64 addr; ++ acpi_status status; ++ ++ status = resource_to_addr(acpi_res, &addr); ++ if (ACPI_SUCCESS(status)) ++ info->res_num++; ++ return AE_OK; ++} ++ ++static acpi_status setup_resource(struct acpi_resource *acpi_res, void *data) ++{ ++ struct pci_root_info *info = data; ++ struct resource *res; ++ struct acpi_resource_address64 addr; ++ acpi_status status; ++ unsigned long flags; ++ u64 start, end; ++ ++ status = resource_to_addr(acpi_res, &addr); ++ if (!ACPI_SUCCESS(status)) ++ return AE_OK; ++ ++ if (addr.resource_type == ACPI_MEMORY_RANGE) { ++ flags = IORESOURCE_MEM; ++ if (addr.info.mem.caching == ACPI_PREFETCHABLE_MEMORY) ++ flags |= IORESOURCE_PREFETCH; ++ } else if (addr.resource_type == ACPI_IO_RANGE) { ++ flags = IORESOURCE_IO; ++ } else ++ return AE_OK; ++ ++ start = addr.minimum + addr.translation_offset; ++ end = addr.maximum + addr.translation_offset; ++ ++ res = &info->res[info->res_num]; ++ res->name = info->name; ++ res->flags = flags; ++ res->start = start; ++ res->end = end; ++ ++ if (flags & IORESOURCE_IO) { ++ unsigned long port; ++ int err; ++ ++ err = pci_register_io_range(start, addr.address_length); ++ if (err) ++ return AE_OK; ++ ++ port = pci_address_to_pio(start); ++ if (port == (unsigned long)-1) { ++ res->start = -1; ++ res->end = -1; ++ return AE_OK; ++ } ++ ++ res->start = port; ++ res->end = res->start + addr.address_length - 1; ++ ++ if (pci_remap_iospace(res, start) < 0) ++ return AE_OK; ++ ++ info->res_offset[info->res_num] = 0; ++ } else ++ info->res_offset[info->res_num] = addr.translation_offset; ++ ++ info->res_num++; ++ ++ return AE_OK; ++} ++ ++static void coalesce_windows(struct pci_root_info *info, unsigned long type) ++{ ++ int i, j; ++ struct resource *res1, *res2; ++ ++ for (i = 0; i < info->res_num; i++) { ++ res1 = &info->res[i]; ++ if (!(res1->flags & type)) ++ continue; ++ ++ for (j = i + 1; j < info->res_num; j++) { ++ res2 = &info->res[j]; ++ if (!(res2->flags & type)) ++ continue; ++ ++ /* ++ * I don't like throwing away windows because then ++ * our resources no longer match the ACPI _CRS, but ++ * the kernel resource tree doesn't allow overlaps. ++ */ ++ if (resource_overlaps(res1, res2)) { ++ res2->start = min(res1->start, res2->start); ++ res2->end = max(res1->end, res2->end); ++ dev_info(&info->bridge->dev, ++ "host bridge window expanded to %pR; %pR ignored\n", ++ res2, res1); ++ res1->flags = 0; ++ } ++ } ++ } ++} ++ ++static void add_resources(struct pci_root_info *info, ++ struct list_head *resources) ++{ ++ int i; ++ struct resource *res, *root, *conflict; ++ ++ coalesce_windows(info, IORESOURCE_MEM); ++ coalesce_windows(info, IORESOURCE_IO); ++ ++ for (i = 0; i < info->res_num; i++) { ++ res = &info->res[i]; ++ ++ if (res->flags & IORESOURCE_MEM) ++ root = &iomem_resource; ++ else if (res->flags & IORESOURCE_IO) ++ root = &ioport_resource; ++ else ++ continue; ++ ++ conflict = insert_resource_conflict(root, res); ++ if (conflict) ++ dev_info(&info->bridge->dev, ++ "ignoring host bridge window %pR (conflicts with %s %pR)\n", ++ res, conflict->name, conflict); ++ else ++ pci_add_resource_offset(resources, res, ++ info->res_offset[i]); ++ } ++} ++ ++static void free_pci_root_info_res(struct pci_root_info *info) ++{ ++ kfree(info->res); ++ info->res = NULL; ++ kfree(info->res_offset); ++ info->res_offset = NULL; ++ info->res_num = 0; ++} ++ ++static void __release_pci_root_info(struct pci_root_info *info) ++{ ++ int i; ++ struct resource *res; ++ ++ for (i = 0; i < info->res_num; i++) { ++ res = &info->res[i]; ++ ++ if (!res->parent) ++ continue; ++ ++ if (!(res->flags & (IORESOURCE_MEM | IORESOURCE_IO))) ++ continue; ++ ++ release_resource(res); ++ } + -+#ifdef CONFIG_PCI -+ bus_register_notifier(&pci_bus_type, &pci_bus_nb); -+#endif ++ free_pci_root_info_res(info); + - dma_ops = &noncoherent_swiotlb_dma_ops; - - return swiotlb_late_init_with_default_size(swiotlb_size); -diff --git a/arch/arm64/pci/Makefile b/arch/arm64/pci/Makefile -new file mode 100644 -index 0000000..b8d5dbd ---- /dev/null -+++ b/arch/arm64/pci/Makefile -@@ -0,0 +1 @@ -+obj-y += pci.o -diff --git a/arch/arm64/pci/pci.c b/arch/arm64/pci/pci.c -new file mode 100644 -index 0000000..b03b0eb ---- /dev/null -+++ b/arch/arm64/pci/pci.c -@@ -0,0 +1,28 @@ -+#include -+#include -+#include -+#include ++ kfree(info); ++} + -+/** -+ * raw_pci_read - Platform-specific PCI config space access. -+ * -+ * Default empty implementation. Replace with an architecture-specific setup -+ * routine, if necessary. -+ */ -+int __weak raw_pci_read(unsigned int domain, unsigned int bus, -+ unsigned int devfn, int reg, int len, u32 *val) ++static void release_pci_root_info(struct pci_host_bridge *bridge) +{ -+ return -EINVAL; ++ struct pci_root_info *info = bridge->release_data; ++ ++ __release_pci_root_info(info); +} + -+int __weak raw_pci_write(unsigned int domain, unsigned int bus, -+ unsigned int devfn, int reg, int len, u32 val) ++static void probe_pci_root_info(struct pci_root_info *info, ++ struct acpi_device *device, ++ int busnum, int domain) +{ -+ return -EINVAL; ++ size_t size; ++ ++ sprintf(info->name, "PCI Bus %04x:%02x", domain, busnum); ++ info->bridge = device; ++ ++ info->res_num = 0; ++ acpi_walk_resources(device->handle, METHOD_NAME__CRS, count_resource, ++ info); ++ if (!info->res_num) ++ return; ++ ++ size = sizeof(*info->res) * info->res_num; ++ info->res = kzalloc_node(size, GFP_KERNEL, info->sd.node); ++ if (!info->res) { ++ info->res_num = 0; ++ return; ++ } ++ ++ size = sizeof(*info->res_offset) * info->res_num; ++ info->res_num = 0; ++ info->res_offset = kzalloc_node(size, GFP_KERNEL, info->sd.node); ++ if (!info->res_offset) { ++ kfree(info->res); ++ info->res = NULL; ++ return; ++ } ++ ++ acpi_walk_resources(device->handle, METHOD_NAME__CRS, setup_resource, ++ info); +} + +/* Root bridge scanning */ +struct pci_bus *pci_acpi_scan_root(struct acpi_pci_root *root) +{ -+ return NULL; ++ struct acpi_device *device = root->device; ++ struct pci_mmcfg_region *mcfg; ++ struct pci_root_info *info; ++ int domain = root->segment; ++ int busnum = root->secondary.start; ++ LIST_HEAD(resources); ++ struct pci_bus *bus; ++ struct pci_sysdata *sd; ++ int node; ++ ++ /* we need mmconfig */ ++ mcfg = pci_mmconfig_lookup(domain, busnum); ++ if (!mcfg) { ++ pr_err("pci_bus %04x:%02x has no MCFG table\n", ++ domain, busnum); ++ return NULL; ++ } ++ ++ /* temporary hack */ ++ if (mcfg->fixup) ++ (*mcfg->fixup)(root, mcfg); ++ ++ if (domain && !pci_domains_supported) { ++ pr_warn("PCI %04x:%02x: multiple domains not supported.\n", ++ domain, busnum); ++ return NULL; ++ } ++ ++ node = NUMA_NO_NODE; ++ ++ info = kzalloc_node(sizeof(*info), GFP_KERNEL, node); ++ if (!info) { ++ pr_warn("PCI %04x:%02x: ignored (out of memory)\n", ++ domain, busnum); ++ return NULL; ++ } ++ info->segment = domain; ++ info->start_bus = busnum; ++ info->end_bus = root->secondary.end; ++ ++ sd = &info->sd; ++ sd->domain = domain; ++ sd->node = node; ++ sd->companion = device; ++ ++ probe_pci_root_info(info, device, busnum, domain); ++ ++ /* insert busn res at first */ ++ pci_add_resource(&resources, &root->secondary); ++ ++ /* then _CRS resources */ ++ add_resources(info, &resources); ++ ++ bus = pci_create_root_bus(NULL, busnum, &pci_root_ops, sd, &resources); ++ if (bus) { ++ pci_scan_child_bus(bus); ++ pci_set_host_bridge_release(to_pci_host_bridge(bus->bridge), ++ release_pci_root_info, info); ++ } else { ++ pci_free_resource_list(&resources); ++ __release_pci_root_info(info); ++ } ++ ++ /* After the PCI-E bus has been walked and all devices discovered, ++ * configure any settings of the fabric that might be necessary. ++ */ ++ if (bus) { ++ struct pci_bus *child; ++ ++ list_for_each_entry(child, &bus->children, node) ++ pcie_bus_configure_settings(child); ++ } ++ ++ if (bus && node != NUMA_NO_NODE) ++ dev_printk(KERN_DEBUG, &bus->dev, "on NUMA node %d\n", node); ++ ++ return bus; +} ++ ++#endif /* CONFIG_ACPI */ diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig -index d0f3265..3343080 100644 +index b23fe37..555e226 100644 --- a/drivers/acpi/Kconfig +++ b/drivers/acpi/Kconfig @@ -5,8 +5,7 @@ @@ -3147,7 +5589,7 @@ index d0f3265..3343080 100644 help This driver creates entries in /sys/bus/pci/slots/ for all PCI diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile -index 505d4d7..252d0ff 100644 +index c3b2fcb..5a21476 100644 --- a/drivers/acpi/Makefile +++ b/drivers/acpi/Makefile @@ -23,7 +23,11 @@ acpi-y += nvs.o @@ -3162,7 +5604,7 @@ index 505d4d7..252d0ff 100644 acpi-y += device_pm.o acpi-$(CONFIG_ACPI_SLEEP) += proc.o -@@ -39,13 +43,14 @@ acpi-y += processor_core.o +@@ -39,7 +43,7 @@ acpi-y += processor_core.o acpi-$(CONFIG_ARCH_MIGHT_HAVE_ACPI_PDC) += processor_pdc.o acpi-y += ec.o acpi-$(CONFIG_ACPI_DOCK) += dock.o @@ -3171,13 +5613,14 @@ index 505d4d7..252d0ff 100644 acpi-y += acpi_lpss.o acpi-y += acpi_platform.o acpi-y += acpi_pnp.o - acpi-y += int340x_thermal.o +@@ -47,6 +51,7 @@ acpi-y += int340x_thermal.o acpi-y += power.o acpi-y += event.o acpi-y += sysfs.o +acpi-y += property.o acpi-$(CONFIG_X86) += acpi_cmos_rtc.o acpi-$(CONFIG_DEBUG_FS) += debugfs.o + acpi-$(CONFIG_ACPI_NUMA) += numa.o diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index 8b67bd0..c412fdb 100644 --- a/drivers/acpi/bus.c @@ -3193,7 +5636,7 @@ index 8b67bd0..c412fdb 100644 message = "platform specific model"; break; diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h -index 4c5cf77..926ca5c 100644 +index 447f6d6..c5ff8ba 100644 --- a/drivers/acpi/internal.h +++ b/drivers/acpi/internal.h @@ -26,8 +26,13 @@ @@ -3210,7 +5653,7 @@ index 4c5cf77..926ca5c 100644 void acpi_processor_init(void); void acpi_platform_init(void); void acpi_pnp_init(void); -@@ -181,4 +186,10 @@ struct platform_device *acpi_create_platform_device(struct acpi_device *adev); +@@ -173,4 +178,10 @@ static inline void suspend_nvs_restore(void) {} bool acpi_osi_is_win8(void); #endif @@ -3304,10 +5747,10 @@ index ef58f46..5c84e0d 100644 exit: diff --git a/drivers/acpi/property.c b/drivers/acpi/property.c new file mode 100644 -index 0000000..ff53eb8 +index 0000000..0d08373 --- /dev/null +++ b/drivers/acpi/property.c -@@ -0,0 +1,586 @@ +@@ -0,0 +1,551 @@ +/* + * ACPI device specific properties support. + * @@ -3391,6 +5834,7 @@ index 0000000..ff53eb8 + const union acpi_object *of_compatible; + struct acpi_hardware_id *hwid; + bool acpi_of = false; ++ int ret; + + /* + * Check if the special PRP0001 ACPI ID is present and in that @@ -3407,13 +5851,17 @@ index 0000000..ff53eb8 + if (!acpi_of) + return; + -+ if (acpi_dev_get_property_array(adev, "compatible", ACPI_TYPE_STRING, -+ &of_compatible)) { -+ acpi_handle_warn(adev->handle, -+ "PRP0001 requires compatible property\n"); -+ return; ++ ret = acpi_dev_get_property_array(adev, "compatible", ACPI_TYPE_STRING, ++ &of_compatible); ++ if (ret) { ++ ret = acpi_dev_get_property(adev, "compatible", ++ ACPI_TYPE_STRING, &of_compatible); ++ if (ret) { ++ acpi_handle_warn(adev->handle, ++ "PRP0001 requires compatible property\n"); ++ return; ++ } + } -+ + adev->data.of_compatible = of_compatible; +} + @@ -3578,25 +6026,21 @@ index 0000000..ff53eb8 + * acpi_dev_get_property_reference - returns handle to the referenced object + * @adev: ACPI device to get property + * @name: Name of the property -+ * @size_prop: Name of the "size" property in referenced object + * @index: Index of the reference to return + * @args: Location to store the returned reference with optional arguments + * + * Find property with @name, verifify that it is a package containing at least + * one object reference and if so, store the ACPI device object pointer to the -+ * target object in @args->adev. ++ * target object in @args->adev. If the reference includes arguments, store ++ * them in the @args->args[] array. + * -+ * If the reference includes arguments (@size_prop is not %NULL) follow the -+ * reference and check whether or not there is an integer property @size_prop -+ * under the target object and if so, whether or not its value matches the -+ * number of arguments that follow the reference. If there's more than one -+ * reference in the property value package, @index is used to select the one to -+ * return. ++ * If there's more than one reference in the property value package, @index is ++ * used to select the one to return. + * + * Return: %0 on success, negative error code on failure. + */ -+int acpi_dev_get_property_reference(struct acpi_device *adev, const char *name, -+ const char *size_prop, size_t index, ++int acpi_dev_get_property_reference(struct acpi_device *adev, ++ const char *name, size_t index, + struct acpi_reference_args *args) +{ + const union acpi_object *element, *end; @@ -3613,7 +6057,7 @@ index 0000000..ff53eb8 + * return that reference then. + */ + if (obj->type == ACPI_TYPE_LOCAL_REFERENCE) { -+ if (size_prop || index) ++ if (index) + return -EINVAL; + + ret = acpi_bus_get_device(obj->reference.handle, &device); @@ -3653,42 +6097,16 @@ index 0000000..ff53eb8 + element++; + nargs = 0; + -+ if (size_prop) { -+ const union acpi_object *prop; ++ /* assume following integer elements are all args */ ++ for (i = 0; element + i < end; i++) { ++ int type = element[i].type; + -+ /* -+ * Find out how many arguments the refenced object -+ * expects by reading its size_prop property. -+ */ -+ ret = acpi_dev_get_property(device, size_prop, -+ ACPI_TYPE_INTEGER, &prop); -+ if (ret) -+ return ret; -+ -+ nargs = prop->integer.value; -+ if (nargs > MAX_ACPI_REFERENCE_ARGS -+ || element + nargs > end) ++ if (type == ACPI_TYPE_INTEGER) ++ nargs++; ++ else if (type == ACPI_TYPE_LOCAL_REFERENCE) ++ break; ++ else + return -EPROTO; -+ -+ /* -+ * Skip to the start of the arguments and verify -+ * that they all are in fact integers. -+ */ -+ for (i = 0; i < nargs; i++) -+ if (element[i].type != ACPI_TYPE_INTEGER) -+ return -EPROTO; -+ } else { -+ /* assume following integer elements are all args */ -+ for (i = 0; element + i < end; i++) { -+ int type = element[i].type; -+ -+ if (type == ACPI_TYPE_INTEGER) -+ nargs++; -+ else if (type == ACPI_TYPE_LOCAL_REFERENCE) -+ break; -+ else -+ return -EPROTO; -+ } + } + + if (idx++ == index) { @@ -3714,11 +6132,11 @@ index 0000000..ff53eb8 + (const union acpi_object **)valptr); +} + -+int acpi_dev_prop_read(struct acpi_device *adev, const char *propname, -+ enum dev_prop_type proptype, void *val) ++int acpi_dev_prop_read_single(struct acpi_device *adev, const char *propname, ++ enum dev_prop_type proptype, void *val) +{ + const union acpi_object *obj; -+ int ret = -EINVAL; ++ int ret; + + if (!val) + return -EINVAL; @@ -3754,6 +6172,8 @@ index 0000000..ff53eb8 + return ret; + + *(char **)val = obj->string.pointer; ++ } else { ++ ret = -EINVAL; + } + return ret; +} @@ -3834,23 +6254,30 @@ index 0000000..ff53eb8 + return 0; +} + -+int acpi_dev_prop_read_array(struct acpi_device *adev, const char *propname, -+ enum dev_prop_type proptype, void *val, -+ size_t nval) ++int acpi_dev_prop_read(struct acpi_device *adev, const char *propname, ++ enum dev_prop_type proptype, void *val, size_t nval) +{ + const union acpi_object *obj; + const union acpi_object *items; + int ret; + ++ if (val && nval == 1) { ++ ret = acpi_dev_prop_read_single(adev, propname, proptype, val); ++ if (!ret) ++ return ret; ++ } ++ + ret = acpi_dev_get_property_array(adev, propname, ACPI_TYPE_ANY, &obj); + if (ret) + return ret; + + if (!val) + return obj->package.count; ++ else if (nval <= 0) ++ return -EINVAL; + + if (nval > obj->package.count) -+ nval = obj->package.count; ++ return -EOVERFLOW; + + items = obj->package.elements; + switch (proptype) { @@ -3875,49 +6302,17 @@ index 0000000..ff53eb8 + } + return ret; +} -+ -+int acpi_for_each_child_node(struct device *dev, -+ int (*fn)(struct device *dev, void *child, void *data), -+ void *data) -+{ -+ struct acpi_device *adev = ACPI_COMPANION(dev); -+ struct acpi_device *child; -+ int ret = 0; -+ -+ if (!adev) -+ return -EINVAL; -+ -+ list_for_each_entry(child, &adev->children, node) { -+ ret = fn(dev, child, data); -+ if (ret) -+ break; -+ } -+ return ret; -+} diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c -index ae44d86..4da55d8 100644 +index 0476e90..9cb5cca 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c -@@ -124,17 +124,43 @@ static int create_modalias(struct acpi_device *acpi_dev, char *modalias, +@@ -124,17 +124,56 @@ static int create_modalias(struct acpi_device *acpi_dev, char *modalias, if (list_empty(&acpi_dev->pnp.ids)) return 0; - len = snprintf(modalias, size, "acpi:"); - size -= len; -+ /* -+ * If the device has PRP0001 we expose DT compatible modalias -+ * instead. -+ */ -+ if (acpi_dev->data.of_compatible) { -+ const union acpi_object *of_compatible, *obj; -+ int i; -+ -+ len = snprintf(modalias, size, "of:Nprp0001Tacpi"); -+ -+ of_compatible = acpi_dev->data.of_compatible; -+ for (i = 0; i < of_compatible->package.count; i++) { -+ obj = &of_compatible->package.elements[i]; - +- - list_for_each_entry(id, &acpi_dev->pnp.ids, list) { - count = snprintf(&modalias[len], size, "%s:", id->id); - if (count < 0) @@ -3926,6 +6321,33 @@ index ae44d86..4da55d8 100644 - return -ENOMEM; - len += count; - size -= count; ++ /* ++ * If the device has PRP0001 we expose DT compatible modalias ++ * instead in form of of:NnameTCcompatible. ++ */ ++ if (acpi_dev->data.of_compatible) { ++ struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER }; ++ const union acpi_object *of_compatible, *obj; ++ int i, nval; ++ char *c; ++ ++ acpi_get_name(acpi_dev->handle, ACPI_SINGLE_NAME, &buf); ++ /* DT strings are all in lower case */ ++ for (c = buf.pointer; *c != '\0'; c++) ++ *c = tolower(*c); ++ ++ len = snprintf(modalias, size, "of:N%sT", (char *)buf.pointer); ++ ACPI_FREE(buf.pointer); ++ ++ of_compatible = acpi_dev->data.of_compatible; ++ if (of_compatible->type == ACPI_TYPE_PACKAGE) { ++ nval = of_compatible->package.count; ++ obj = of_compatible->package.elements; ++ } else { /* Must be ACPI_TYPE_STRING. */ ++ nval = 1; ++ obj = of_compatible; ++ } ++ for (i = 0; i < nval; i++, obj++) { + count = snprintf(&modalias[len], size, "C%s", + obj->string.pointer); + if (count < 0) @@ -3952,33 +6374,36 @@ index ae44d86..4da55d8 100644 } modalias[len] = '\0'; -@@ -864,6 +890,51 @@ int acpi_match_device_ids(struct acpi_device *device, +@@ -902,6 +941,51 @@ int acpi_match_device_ids(struct acpi_device *device, } EXPORT_SYMBOL(acpi_match_device_ids); -+/* Performs match for special "PRP0001" shoehorn ACPI ID */ ++/* Performs match against special "PRP0001" shoehorn ACPI ID */ +static bool acpi_of_driver_match_device(struct device *dev, + const struct device_driver *drv) +{ -+ struct acpi_device *adev = ACPI_COMPANION(dev); -+ const union acpi_object *of_compatible; -+ int i; ++ const union acpi_object *of_compatible, *obj; ++ struct acpi_device *adev; ++ int i, nval; ++ ++ adev = ACPI_COMPANION(dev); ++ if (!adev) ++ return false; + -+ /* -+ * If the ACPI device does not have corresponding compatible -+ * property or the driver in question does not have DT matching -+ * table we consider the match succesful (matches the ACPI ID). -+ */ + of_compatible = adev->data.of_compatible; + if (!drv->of_match_table || !of_compatible) -+ return true; ++ return false; + ++ if (of_compatible->type == ACPI_TYPE_PACKAGE) { ++ nval = of_compatible->package.count; ++ obj = of_compatible->package.elements; ++ } else { /* Must be ACPI_TYPE_STRING. */ ++ nval = 1; ++ obj = of_compatible; ++ } + /* Now we can look for the driver DT compatible strings */ -+ for (i = 0; i < of_compatible->package.count; i++) { ++ for (i = 0; i < nval; i++, obj++) { + const struct of_device_id *id; -+ const union acpi_object *obj; -+ -+ obj = &of_compatible->package.elements[i]; + + for (id = drv->of_match_table; id->compatible[0]; id++) + if (!strcasecmp(obj->string.pointer, id->compatible)) @@ -3991,20 +6416,17 @@ index ae44d86..4da55d8 100644 +bool acpi_driver_match_device(struct device *dev, + const struct device_driver *drv) +{ -+ const struct acpi_device_id *id; -+ -+ id = acpi_match_device(drv->acpi_match_table, dev); -+ if (!id) -+ return false; ++ if (!drv->acpi_match_table) ++ return acpi_of_driver_match_device(dev, drv); + -+ return acpi_of_driver_match_device(dev, drv); ++ return !!acpi_match_device(drv->acpi_match_table, dev); +} +EXPORT_SYMBOL_GPL(acpi_driver_match_device); + static void acpi_free_power_resources_lists(struct acpi_device *device) { int i; -@@ -884,6 +955,7 @@ static void acpi_device_release(struct device *dev) +@@ -922,6 +1006,7 @@ static void acpi_device_release(struct device *dev) { struct acpi_device *acpi_dev = to_acpi_device(dev); @@ -4012,7 +6434,38 @@ index ae44d86..4da55d8 100644 acpi_free_pnp_ids(&acpi_dev->pnp); acpi_free_power_resources_lists(acpi_dev); kfree(acpi_dev); -@@ -1888,6 +1960,7 @@ void acpi_init_device_object(struct acpi_device *device, acpi_handle handle, +@@ -1304,6 +1389,26 @@ int acpi_device_add(struct acpi_device *device, + return result; + } + ++struct acpi_device *acpi_get_next_child(struct device *dev, ++ struct acpi_device *child) ++{ ++ struct acpi_device *adev = ACPI_COMPANION(dev); ++ struct list_head *head, *next; ++ ++ if (!adev) ++ return NULL; ++ ++ head = &adev->children; ++ if (list_empty(head)) ++ return NULL; ++ ++ if (!child) ++ return list_first_entry(head, struct acpi_device, node); ++ ++ next = child->node.next; ++ return next == head ? NULL : list_entry(next, struct acpi_device, node); ++} ++ + /* -------------------------------------------------------------------------- + Driver Management + -------------------------------------------------------------------------- */ +@@ -1923,9 +2028,11 @@ void acpi_init_device_object(struct acpi_device *device, acpi_handle handle, + device->device_type = type; + device->handle = handle; + device->parent = acpi_bus_get_parent(handle); ++ device->fwnode.type = FWNODE_ACPI; acpi_set_device_status(device, sta); acpi_device_get_busid(device); acpi_set_pnp_ids(handle, &device->pnp, type); @@ -4225,10 +6678,10 @@ index 6d5a6cd..47f36d4 100644 int __init diff --git a/drivers/acpi/utils.c b/drivers/acpi/utils.c -index 834f35c..b163f73 100644 +index 371ac12..af325a7 100644 --- a/drivers/acpi/utils.c +++ b/drivers/acpi/utils.c -@@ -697,3 +697,29 @@ bool acpi_check_dsm(acpi_handle handle, const u8 *uuid, int rev, u64 funcs) +@@ -723,3 +723,29 @@ bool acpi_check_dsm(acpi_handle handle, const u8 *uuid, int rev, u64 funcs) return false; } EXPORT_SYMBOL(acpi_check_dsm); @@ -4407,10 +6860,10 @@ index 6922cd6..53c3fe1 100644 obj-y += power/ diff --git a/drivers/base/property.c b/drivers/base/property.c new file mode 100644 -index 0000000..7bf5708 +index 0000000..c458458 --- /dev/null +++ b/drivers/base/property.c -@@ -0,0 +1,235 @@ +@@ -0,0 +1,431 @@ +/* + * property.c - Unified device property interface. + * @@ -4418,221 +6871,414 @@ index 0000000..7bf5708 + * Authors: Rafael J. Wysocki + * Mika Westerberg + * -+ * 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 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. ++ */ ++ ++#include ++#include ++#include ++#include ++ ++/** ++ * device_property_present - check if a property of a device is present ++ * @dev: Device whose property is being checked ++ * @propname: Name of the property ++ * ++ * Check if property @propname is present in the device firmware description. ++ */ ++bool device_property_present(struct device *dev, const char *propname) ++{ ++ if (IS_ENABLED(CONFIG_OF) && dev->of_node) ++ return of_property_read_bool(dev->of_node, propname); ++ ++ return !acpi_dev_prop_get(ACPI_COMPANION(dev), propname, NULL); ++} ++EXPORT_SYMBOL_GPL(device_property_present); ++ ++/** ++ * fwnode_property_present - check if a property of a firmware node is present ++ * @fwnode: Firmware node whose property to check ++ * @propname: Name of the property ++ */ ++bool fwnode_property_present(struct fwnode_handle *fwnode, const char *propname) ++{ ++ if (is_of_node(fwnode)) ++ return of_property_read_bool(of_node(fwnode), propname); ++ else if (is_acpi_node(fwnode)) ++ return !acpi_dev_prop_get(acpi_node(fwnode), propname, NULL); ++ ++ return false; ++} ++EXPORT_SYMBOL_GPL(fwnode_property_present); ++ ++#define OF_DEV_PROP_READ_ARRAY(node, propname, type, val, nval) \ ++ (val) ? of_property_read_##type##_array((node), (propname), (val), (nval)) \ ++ : of_property_count_elems_of_size((node), (propname), sizeof(type)) ++ ++#define DEV_PROP_READ_ARRAY(_dev_, _propname_, _type_, _proptype_, _val_, _nval_) \ ++ IS_ENABLED(CONFIG_OF) && _dev_->of_node ? \ ++ (OF_DEV_PROP_READ_ARRAY(_dev_->of_node, _propname_, _type_, \ ++ _val_, _nval_)) : \ ++ acpi_dev_prop_read(ACPI_COMPANION(_dev_), _propname_, \ ++ _proptype_, _val_, _nval_) ++ ++/** ++ * device_property_read_u8_array - return a u8 array property of a device ++ * @dev: Device to get the property of ++ * @propname: Name of the property ++ * @val: The values are stored here ++ * @nval: Size of the @val array ++ * ++ * Function reads an array of u8 properties with @propname from the device ++ * firmware description and stores them to @val if found. ++ * ++ * Return: %0 if the property was found (success), ++ * %-EINVAL if given arguments are not valid, ++ * %-ENODATA if the property does not have a value, ++ * %-EPROTO if the property is not an array of numbers, ++ * %-EOVERFLOW if the size of the property is not as expected. ++ */ ++int device_property_read_u8_array(struct device *dev, const char *propname, ++ u8 *val, size_t nval) ++{ ++ return DEV_PROP_READ_ARRAY(dev, propname, u8, DEV_PROP_U8, val, nval); ++} ++EXPORT_SYMBOL_GPL(device_property_read_u8_array); ++ ++/** ++ * device_property_read_u16_array - return a u16 array property of a device ++ * @dev: Device to get the property of ++ * @propname: Name of the property ++ * @val: The values are stored here ++ * @nval: Size of the @val array ++ * ++ * Function reads an array of u16 properties with @propname from the device ++ * firmware description and stores them to @val if found. ++ * ++ * Return: %0 if the property was found (success), ++ * %-EINVAL if given arguments are not valid, ++ * %-ENODATA if the property does not have a value, ++ * %-EPROTO if the property is not an array of numbers, ++ * %-EOVERFLOW if the size of the property is not as expected. ++ */ ++int device_property_read_u16_array(struct device *dev, const char *propname, ++ u16 *val, size_t nval) ++{ ++ return DEV_PROP_READ_ARRAY(dev, propname, u16, DEV_PROP_U16, val, nval); ++} ++EXPORT_SYMBOL_GPL(device_property_read_u16_array); ++ ++/** ++ * device_property_read_u32_array - return a u32 array property of a device ++ * @dev: Device to get the property of ++ * @propname: Name of the property ++ * @val: The values are stored here ++ * @nval: Size of the @val array ++ * ++ * Function reads an array of u32 properties with @propname from the device ++ * firmware description and stores them to @val if found. ++ * ++ * Return: %0 if the property was found (success), ++ * %-EINVAL if given arguments are not valid, ++ * %-ENODATA if the property does not have a value, ++ * %-EPROTO if the property is not an array of numbers, ++ * %-EOVERFLOW if the size of the property is not as expected. ++ */ ++int device_property_read_u32_array(struct device *dev, const char *propname, ++ u32 *val, size_t nval) ++{ ++ return DEV_PROP_READ_ARRAY(dev, propname, u32, DEV_PROP_U32, val, nval); ++} ++EXPORT_SYMBOL_GPL(device_property_read_u32_array); ++ ++/** ++ * device_property_read_u64_array - return a u64 array property of a device ++ * @dev: Device to get the property of ++ * @propname: Name of the property ++ * @val: The values are stored here ++ * @nval: Size of the @val array ++ * ++ * Function reads an array of u64 properties with @propname from the device ++ * firmware description and stores them to @val if found. ++ * ++ * Return: %0 if the property was found (success), ++ * %-EINVAL if given arguments are not valid, ++ * %-ENODATA if the property does not have a value, ++ * %-EPROTO if the property is not an array of numbers, ++ * %-EOVERFLOW if the size of the property is not as expected. ++ */ ++int device_property_read_u64_array(struct device *dev, const char *propname, ++ u64 *val, size_t nval) ++{ ++ return DEV_PROP_READ_ARRAY(dev, propname, u64, DEV_PROP_U64, val, nval); ++} ++EXPORT_SYMBOL_GPL(device_property_read_u64_array); ++ ++/** ++ * device_property_read_string_array - return a string array property of device ++ * @dev: Device to get the property of ++ * @propname: Name of the property ++ * @val: The values are stored here ++ * @nval: Size of the @val array ++ * ++ * Function reads an array of string properties with @propname from the device ++ * firmware description and stores them to @val if found. ++ * ++ * Return: %0 if the property was found (success), ++ * %-EINVAL if given arguments are not valid, ++ * %-ENODATA if the property does not have a value, ++ * %-EPROTO or %-EILSEQ if the property is not an array of strings, ++ * %-EOVERFLOW if the size of the property is not as expected. + */ -+ -+#include -+#include -+#include -+#include ++int device_property_read_string_array(struct device *dev, const char *propname, ++ const char **val, size_t nval) ++{ ++ return IS_ENABLED(CONFIG_OF) && dev->of_node ? ++ of_property_read_string_array(dev->of_node, propname, val, nval) : ++ acpi_dev_prop_read(ACPI_COMPANION(dev), propname, ++ DEV_PROP_STRING, val, nval); ++} ++EXPORT_SYMBOL_GPL(device_property_read_string_array); + +/** -+ * device_get_property - return a raw property of a device -+ * @dev: Device get the property of ++ * device_property_read_string - return a string property of a device ++ * @dev: Device to get the property of + * @propname: Name of the property -+ * @valptr: The raw property value is stored here ++ * @val: The value is stored here + * + * Function reads property @propname from the device firmware description and -+ * stores the raw value into @valptr if found. Otherwise returns a negative -+ * errno as specified below. ++ * stores the value into @val if found. The value is checked to be a string. + * + * Return: %0 if the property was found (success), + * %-EINVAL if given arguments are not valid, -+ * %-ENODATA if the property does not exist. ++ * %-ENODATA if the property does not have a value, ++ * %-EPROTO or %-EILSEQ if the property type is not a string. + */ -+int device_get_property(struct device *dev, const char *propname, void **valptr) -+{ -+ if (IS_ENABLED(CONFIG_OF) && dev->of_node) -+ return of_dev_prop_get(dev->of_node, propname, valptr); -+ -+ return acpi_dev_prop_get(ACPI_COMPANION(dev), propname, valptr); -+} -+EXPORT_SYMBOL_GPL(device_get_property); ++int device_property_read_string(struct device *dev, const char *propname, ++ const char **val) ++{ ++ return IS_ENABLED(CONFIG_OF) && dev->of_node ? ++ of_property_read_string(dev->of_node, propname, val) : ++ acpi_dev_prop_read(ACPI_COMPANION(dev), propname, ++ DEV_PROP_STRING, val, 1); ++} ++EXPORT_SYMBOL_GPL(device_property_read_string); ++ ++#define FWNODE_PROP_READ_ARRAY(_fwnode_, _propname_, _type_, _proptype_, _val_, _nval_) \ ++({ \ ++ int _ret_; \ ++ if (is_of_node(_fwnode_)) \ ++ _ret_ = OF_DEV_PROP_READ_ARRAY(of_node(_fwnode_), _propname_, \ ++ _type_, _val_, _nval_); \ ++ else if (is_acpi_node(_fwnode_)) \ ++ _ret_ = acpi_dev_prop_read(acpi_node(_fwnode_), _propname_, \ ++ _proptype_, _val_, _nval_); \ ++ else \ ++ _ret_ = -ENXIO; \ ++ _ret_; \ ++}) + +/** -+ * device_get_child_property - return a raw property of a device's child -+ * @dev: Parent device -+ * @child: Child to get a property of ++ * fwnode_property_read_u8_array - return a u8 array property of firmware node ++ * @fwnode: Firmware node to get the property of + * @propname: Name of the property -+ * @valptr: The raw property value is stored here ++ * @val: The values are stored here ++ * @nval: Size of the @val array + * -+ * Function reads property @propname from the firmware description of @child and -+ * stores the raw value into @valptr if found. Otherwise returns a negative -+ * errno as specified below. ++ * Read an array of u8 properties with @propname from @fwnode and stores them to ++ * @val if found. + * + * Return: %0 if the property was found (success), + * %-EINVAL if given arguments are not valid, -+ * %-ENODATA if the property does not exist. ++ * %-ENODATA if the property does not have a value, ++ * %-EPROTO if the property is not an array of numbers, ++ * %-EOVERFLOW if the size of the property is not as expected, ++ * %-ENXIO if no suitable firmware interface is present. + */ -+int device_get_child_property(struct device *dev, void *child, -+ const char *propname, void **valptr) ++int fwnode_property_read_u8_array(struct fwnode_handle *fwnode, ++ const char *propname, u8 *val, size_t nval) +{ -+ if (!child) -+ return -EINVAL; -+ -+ if (IS_ENABLED(CONFIG_OF) && dev->of_node) -+ return of_dev_prop_get(child, propname, valptr); -+ else if (ACPI_COMPANION(dev)) -+ return acpi_dev_prop_get(child, propname, valptr); -+ -+ return -ENODATA; ++ return FWNODE_PROP_READ_ARRAY(fwnode, propname, u8, DEV_PROP_U8, ++ val, nval); +} -+EXPORT_SYMBOL_GPL(device_get_child_property); ++EXPORT_SYMBOL_GPL(fwnode_property_read_u8_array); + +/** -+ * device_read_property - read a typed property of a device -+ * @dev: Device to get the property of ++ * fwnode_property_read_u16_array - return a u16 array property of firmware node ++ * @fwnode: Firmware node to get the property of + * @propname: Name of the property -+ * @proptype: Type of the property -+ * @val: The value is stored here ++ * @val: The values are stored here ++ * @nval: Size of the @val array + * -+ * Function reads property @propname from the device firmware description and -+ * stores the value into @val if found. The value is checked to be of type -+ * @proptype. ++ * Read an array of u16 properties with @propname from @fwnode and store them to ++ * @val if found. + * + * Return: %0 if the property was found (success), + * %-EINVAL if given arguments are not valid, -+ * %-ENODATA if the property does not exist, -+ * %-EPROTO if the property type does not match @proptype, -+ * %-EOVERFLOW if the property value is out of bounds of @proptype. ++ * %-ENODATA if the property does not have a value, ++ * %-EPROTO if the property is not an array of numbers, ++ * %-EOVERFLOW if the size of the property is not as expected, ++ * %-ENXIO if no suitable firmware interface is present. + */ -+int device_read_property(struct device *dev, const char *propname, -+ enum dev_prop_type proptype, void *val) ++int fwnode_property_read_u16_array(struct fwnode_handle *fwnode, ++ const char *propname, u16 *val, size_t nval) +{ -+ if (IS_ENABLED(CONFIG_OF) && dev->of_node) -+ return of_dev_prop_read(dev->of_node, propname, proptype, val); -+ -+ return acpi_dev_prop_read(ACPI_COMPANION(dev), propname, proptype, val); ++ return FWNODE_PROP_READ_ARRAY(fwnode, propname, u16, DEV_PROP_U16, ++ val, nval); +} -+EXPORT_SYMBOL_GPL(device_read_property); ++EXPORT_SYMBOL_GPL(fwnode_property_read_u16_array); + +/** -+ * device_read_child_property - read a typed property of a device's child -+ * @dev: Parent device -+ * @child: Child to read a property of ++ * fwnode_property_read_u32_array - return a u32 array property of firmware node ++ * @fwnode: Firmware node to get the property of + * @propname: Name of the property -+ * @proptype: Type of the property -+ * @val: The value is stored here ++ * @val: The values are stored here ++ * @nval: Size of the @val array + * -+ * Function reads property @propname from the firmware description of @child and -+ * stores the value into @val if found. The value is checked to be of type -+ * @proptype. ++ * Read an array of u32 properties with @propname from @fwnode store them to ++ * @val if found. + * + * Return: %0 if the property was found (success), + * %-EINVAL if given arguments are not valid, -+ * %-ENODATA if the property does not exist, -+ * %-EPROTO if the property type does not match @proptype, -+ * %-EOVERFLOW if the property value is out of bounds of @proptype. ++ * %-ENODATA if the property does not have a value, ++ * %-EPROTO if the property is not an array of numbers, ++ * %-EOVERFLOW if the size of the property is not as expected, ++ * %-ENXIO if no suitable firmware interface is present. + */ -+int device_read_child_property(struct device *dev, void *child, -+ const char *propname, enum dev_prop_type proptype, -+ void *val) ++int fwnode_property_read_u32_array(struct fwnode_handle *fwnode, ++ const char *propname, u32 *val, size_t nval) +{ -+ if (!child) -+ return -EINVAL; -+ -+ if (IS_ENABLED(CONFIG_OF) && dev->of_node) -+ return of_dev_prop_read(child, propname, proptype, val); -+ else if (ACPI_COMPANION(dev)) -+ return acpi_dev_prop_read(child, propname, proptype, val); -+ -+ return -ENODATA; ++ return FWNODE_PROP_READ_ARRAY(fwnode, propname, u32, DEV_PROP_U32, ++ val, nval); +} -+EXPORT_SYMBOL_GPL(device_read_child_property); ++EXPORT_SYMBOL_GPL(fwnode_property_read_u32_array); + +/** -+ * device_read_property_array - read an array property of a device -+ * @dev: Device to get the property of ++ * fwnode_property_read_u64_array - return a u64 array property firmware node ++ * @fwnode: Firmware node to get the property of + * @propname: Name of the property -+ * @proptype: Type of the property + * @val: The values are stored here + * @nval: Size of the @val array + * -+ * Function reads an array of properties with @propname from the device -+ * firmware description and stores them to @val if found. All the values -+ * in the array must be of type @proptype. ++ * Read an array of u64 properties with @propname from @fwnode and store them to ++ * @val if found. + * + * Return: %0 if the property was found (success), + * %-EINVAL if given arguments are not valid, -+ * %-ENODATA if the property does not exist, -+ * %-EPROTO if the property type does not match @proptype, -+ * %-EOVERFLOW if the property value is out of bounds of @proptype. ++ * %-ENODATA if the property does not have a value, ++ * %-EPROTO if the property is not an array of numbers, ++ * %-EOVERFLOW if the size of the property is not as expected, ++ * %-ENXIO if no suitable firmware interface is present. + */ -+int device_read_property_array(struct device *dev, const char *propname, -+ enum dev_prop_type proptype, void *val, -+ size_t nval) ++int fwnode_property_read_u64_array(struct fwnode_handle *fwnode, ++ const char *propname, u64 *val, size_t nval) +{ -+ if (IS_ENABLED(CONFIG_OF) && dev->of_node) -+ return of_dev_prop_read_array(dev->of_node, propname, proptype, -+ val, nval); -+ -+ return acpi_dev_prop_read_array(ACPI_COMPANION(dev), propname, proptype, -+ val, nval); ++ return FWNODE_PROP_READ_ARRAY(fwnode, propname, u64, DEV_PROP_U64, ++ val, nval); +} -+EXPORT_SYMBOL_GPL(device_read_property_array); ++EXPORT_SYMBOL_GPL(fwnode_property_read_u64_array); + +/** -+ * device_read_child_property_array - read an array property of a device's child -+ * @dev: Parent device -+ * @child: Child to get the property of ++ * fwnode_property_read_string_array - return string array property of a node ++ * @fwnode: Firmware node to get the property of + * @propname: Name of the property -+ * @proptype: Type of the property + * @val: The values are stored here + * @nval: Size of the @val array + * -+ * Function reads an array of properties with @propname from the firmware -+ * description of @child and stores them to @val if found. All the values -+ * in the array must be of type @proptype. ++ * Read an string list property @propname from the given firmware node and store ++ * them to @val if found. + * + * Return: %0 if the property was found (success), + * %-EINVAL if given arguments are not valid, -+ * %-ENODATA if the property does not exist, -+ * %-EPROTO if the property type does not match @proptype, -+ * %-EOVERFLOW if the property value is out of bounds of @proptype. ++ * %-ENODATA if the property does not have a value, ++ * %-EPROTO if the property is not an array of strings, ++ * %-EOVERFLOW if the size of the property is not as expected, ++ * %-ENXIO if no suitable firmware interface is present. + */ -+int device_read_child_property_array(struct device *dev, void *child, -+ const char *propname, -+ enum dev_prop_type proptype, void *val, -+ size_t nval) ++int fwnode_property_read_string_array(struct fwnode_handle *fwnode, ++ const char *propname, const char **val, ++ size_t nval) +{ -+ if (!child) -+ return -EINVAL; ++ if (is_of_node(fwnode)) ++ return of_property_read_string_array(of_node(fwnode), propname, ++ val, nval); ++ else if (is_acpi_node(fwnode)) ++ return acpi_dev_prop_read(acpi_node(fwnode), propname, ++ DEV_PROP_STRING, val, nval); + -+ if (IS_ENABLED(CONFIG_OF) && dev->of_node) -+ return of_dev_prop_read_array(child, propname, proptype, -+ val, nval); -+ else if (ACPI_COMPANION(dev)) -+ return acpi_dev_prop_read_array(child, propname, proptype, -+ val, nval); ++ return -ENXIO; ++} ++EXPORT_SYMBOL_GPL(fwnode_property_read_string_array); + -+ return -ENODATA; ++/** ++ * fwnode_property_read_string - return a string property of a firmware node ++ * @fwnode: Firmware node to get the property of ++ * @propname: Name of the property ++ * @val: The value is stored here ++ * ++ * Read property @propname from the given firmware node and store the value into ++ * @val if found. The value is checked to be a string. ++ * ++ * Return: %0 if the property was found (success), ++ * %-EINVAL if given arguments are not valid, ++ * %-ENODATA if the property does not have a value, ++ * %-EPROTO or %-EILSEQ if the property is not a string, ++ * %-ENXIO if no suitable firmware interface is present. ++ */ ++int fwnode_property_read_string(struct fwnode_handle *fwnode, ++ const char *propname, const char **val) ++{ ++ if (is_of_node(fwnode)) ++ return of_property_read_string(of_node(fwnode),propname, val); ++ else if (is_acpi_node(fwnode)) ++ return acpi_dev_prop_read(acpi_node(fwnode), propname, ++ DEV_PROP_STRING, val, 1); ++ ++ return -ENXIO; +} -+EXPORT_SYMBOL_GPL(device_read_child_property_array); ++EXPORT_SYMBOL_GPL(fwnode_property_read_string); + +/** -+ * device_for_each_child_node - execute function for each child node of device -+ * @dev: Device to run the function for -+ * @fn: Function to run -+ * @data: Additional data to pass to the function ++ * device_get_next_child_node - Return the next child node handle for a device ++ * @dev: Device to find the next child node for. ++ * @child: Handle to one of the device's child nodes or a null handle. + */ -+int device_for_each_child_node(struct device *dev, -+ int (*fn)(struct device *dev, void *child, void *data), -+ void *data) ++struct fwnode_handle *device_get_next_child_node(struct device *dev, ++ struct fwnode_handle *child) +{ -+ if (IS_ENABLED(CONFIG_OF) && dev->of_node) -+ return of_for_each_child_node(dev, fn, data); ++ if (IS_ENABLED(CONFIG_OF) && dev->of_node) { ++ struct device_node *node; ++ ++ node = of_get_next_available_child(dev->of_node, of_node(child)); ++ if (node) ++ return &node->fwnode; ++ } else if (IS_ENABLED(CONFIG_ACPI)) { ++ struct acpi_device *node; + -+ return acpi_for_each_child_node(dev, fn, data); ++ node = acpi_get_next_child(dev, acpi_node(child)); ++ if (node) ++ return acpi_fwnode_handle(node); ++ } ++ return NULL; +} -+EXPORT_SYMBOL_GPL(device_for_each_child_node); ++EXPORT_SYMBOL_GPL(device_get_next_child_node); + -+static int increment_count(struct device *dev, void *child, void *data) ++/** ++ * fwnode_handle_put - Drop reference to a device node ++ * @fwnode: Pointer to the device node to drop the reference to. ++ * ++ * This has to be used when terminating device_for_each_child_node() iteration ++ * with break or return to prevent stale device node references from being left ++ * behind. ++ */ ++void fwnode_handle_put(struct fwnode_handle *fwnode) +{ -+ *((unsigned int *)data) += 1; -+ return 0; ++ if (is_of_node(fwnode)) ++ of_node_put(of_node(fwnode)); +} ++EXPORT_SYMBOL_GPL(fwnode_handle_put); + +/** + * device_get_child_node_count - return the number of child nodes for device @@ -4640,14 +7286,17 @@ index 0000000..7bf5708 + */ +unsigned int device_get_child_node_count(struct device *dev) +{ ++ struct fwnode_handle *child; + unsigned int count = 0; + -+ device_for_each_child_node(dev, increment_count, &count); ++ device_for_each_child_node(dev, child) ++ count++; ++ + return count; +} +EXPORT_SYMBOL_GPL(device_get_child_node_count); diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c -index 2133f9d..b73392b 100644 +index 43005d4..c9411e6 100644 --- a/drivers/clocksource/arm_arch_timer.c +++ b/drivers/clocksource/arm_arch_timer.c @@ -21,6 +21,7 @@ @@ -4683,8 +7332,7 @@ index 2133f9d..b73392b 100644 if (cntbase) arch_timer_rate = readl_relaxed(cntbase + CNTFRQ); else - -@@ -687,20 +694,8 @@ static void __init arch_timer_common_init(void) +@@ -687,20 +693,8 @@ static void __init arch_timer_common_init(void) arch_timer_arch_init(); } @@ -4706,7 +7354,7 @@ index 2133f9d..b73392b 100644 /* * If HYP mode is available, we know that the physical timer * has been configured to be accessible from PL1. Use it, so -@@ -719,13 +714,31 @@ static void __init arch_timer_init(struct device_node *np) +@@ -719,13 +713,31 @@ static void __init arch_timer_init(struct device_node *np) } } @@ -4742,7 +7390,7 @@ index 2133f9d..b73392b 100644 static void __init arch_timer_mem_init(struct device_node *np) { -@@ -792,3 +805,71 @@ static void __init arch_timer_mem_init(struct device_node *np) +@@ -792,3 +804,71 @@ static void __init arch_timer_mem_init(struct device_node *np) } CLOCKSOURCE_OF_DECLARE(armv7_arch_timer_mem, "arm,armv7-timer-mem", arch_timer_mem_init); @@ -4814,25 +7462,207 @@ index 2133f9d..b73392b 100644 + acpi_table_parse(ACPI_SIG_GTDT, arch_timer_acpi_init); +} +#endif +diff --git a/drivers/firmware/dmi_scan.c b/drivers/firmware/dmi_scan.c +index 17afc51..c5f7b4e 100644 +--- a/drivers/firmware/dmi_scan.c ++++ b/drivers/firmware/dmi_scan.c +@@ -93,6 +93,12 @@ static void dmi_table(u8 *buf, int len, int num, + const struct dmi_header *dm = (const struct dmi_header *)data; + + /* ++ * 7.45 End-of-Table (Type 127) [SMBIOS reference spec v3.0.0] ++ */ ++ if (dm->type == DMI_ENTRY_END_OF_TABLE) ++ break; ++ ++ /* + * We want to know the total length (formatted area and + * strings) before decoding to make sure we won't run off the + * table in dmi_decode or dmi_string +@@ -107,7 +113,7 @@ static void dmi_table(u8 *buf, int len, int num, + } + } + +-static u32 dmi_base; ++static phys_addr_t dmi_base; + static u16 dmi_len; + static u16 dmi_num; + +@@ -467,7 +473,7 @@ static int __init dmi_present(const u8 *buf) + + if (memcmp(buf, "_SM_", 4) == 0 && + buf[5] < 32 && dmi_checksum(buf, buf[5])) { +- smbios_ver = (buf[6] << 8) + buf[7]; ++ smbios_ver = get_unaligned_be16(buf + 6); + + /* Some BIOS report weird SMBIOS version, fix that up */ + switch (smbios_ver) { +@@ -489,10 +495,9 @@ static int __init dmi_present(const u8 *buf) + buf += 16; + + if (memcmp(buf, "_DMI_", 5) == 0 && dmi_checksum(buf, 15)) { +- dmi_num = (buf[13] << 8) | buf[12]; +- dmi_len = (buf[7] << 8) | buf[6]; +- dmi_base = (buf[11] << 24) | (buf[10] << 16) | +- (buf[9] << 8) | buf[8]; ++ dmi_num = get_unaligned_le16(buf + 12); ++ dmi_len = get_unaligned_le16(buf + 6); ++ dmi_base = get_unaligned_le32(buf + 8); + + if (dmi_walk_early(dmi_decode) == 0) { + if (smbios_ver) { +@@ -514,12 +519,72 @@ static int __init dmi_present(const u8 *buf) + return 1; + } + ++/* ++ * Check for the SMBIOS 3.0 64-bit entry point signature. Unlike the legacy ++ * 32-bit entry point, there is no embedded DMI header (_DMI_) in here. ++ */ ++static int __init dmi_smbios3_present(const u8 *buf) ++{ ++ if (memcmp(buf, "_SM3_", 5) == 0 && ++ buf[6] < 32 && dmi_checksum(buf, buf[6])) { ++ dmi_ver = get_unaligned_be16(buf + 7); ++ dmi_len = get_unaligned_le32(buf + 12); ++ dmi_base = get_unaligned_le64(buf + 16); ++ ++ /* ++ * The 64-bit SMBIOS 3.0 entry point no longer has a field ++ * containing the number of structures present in the table. ++ * Instead, it defines the table size as a maximum size, and ++ * relies on the end-of-table structure type (#127) to be used ++ * to signal the end of the table. ++ * So let's define dmi_num as an upper bound as well: each ++ * structure has a 4 byte header, so dmi_len / 4 is an upper ++ * bound for the number of structures in the table. ++ */ ++ dmi_num = dmi_len / 4; ++ ++ if (dmi_walk_early(dmi_decode) == 0) { ++ pr_info("SMBIOS %d.%d present.\n", ++ dmi_ver >> 8, dmi_ver & 0xFF); ++ dmi_format_ids(dmi_ids_string, sizeof(dmi_ids_string)); ++ pr_debug("DMI: %s\n", dmi_ids_string); ++ return 0; ++ } ++ } ++ return 1; ++} ++ + void __init dmi_scan_machine(void) + { + char __iomem *p, *q; + char buf[32]; + + if (efi_enabled(EFI_CONFIG_TABLES)) { ++ /* ++ * According to the DMTF SMBIOS reference spec v3.0.0, it is ++ * allowed to define both the 64-bit entry point (smbios3) and ++ * the 32-bit entry point (smbios), in which case they should ++ * either both point to the same SMBIOS structure table, or the ++ * table pointed to by the 64-bit entry point should contain a ++ * superset of the table contents pointed to by the 32-bit entry ++ * point (section 5.2) ++ * This implies that the 64-bit entry point should have ++ * precedence if it is defined and supported by the OS. If we ++ * have the 64-bit entry point, but fail to decode it, fall ++ * back to the legacy one (if available) ++ */ ++ if (efi.smbios3 != EFI_INVALID_TABLE_ADDR) { ++ p = dmi_early_remap(efi.smbios3, 32); ++ if (p == NULL) ++ goto error; ++ memcpy_fromio(buf, p, 32); ++ dmi_early_unmap(p, 32); ++ ++ if (!dmi_smbios3_present(buf)) { ++ dmi_available = 1; ++ goto out; ++ } ++ } + if (efi.smbios == EFI_INVALID_TABLE_ADDR) + goto error; + +@@ -552,7 +617,7 @@ void __init dmi_scan_machine(void) + memset(buf, 0, 16); + for (q = p; q < p + 0x10000; q += 16) { + memcpy_fromio(buf + 16, q, 16); +- if (!dmi_present(buf)) { ++ if (!dmi_smbios3_present(buf) || !dmi_present(buf)) { + dmi_available = 1; + dmi_early_unmap(p, 0x10000); + goto out; +diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c +index 8590099..9035c1b 100644 +--- a/drivers/firmware/efi/efi.c ++++ b/drivers/firmware/efi/efi.c +@@ -30,6 +30,7 @@ struct efi __read_mostly efi = { + .acpi = EFI_INVALID_TABLE_ADDR, + .acpi20 = EFI_INVALID_TABLE_ADDR, + .smbios = EFI_INVALID_TABLE_ADDR, ++ .smbios3 = EFI_INVALID_TABLE_ADDR, + .sal_systab = EFI_INVALID_TABLE_ADDR, + .boot_info = EFI_INVALID_TABLE_ADDR, + .hcdp = EFI_INVALID_TABLE_ADDR, +@@ -86,6 +87,8 @@ static ssize_t systab_show(struct kobject *kobj, + str += sprintf(str, "ACPI=0x%lx\n", efi.acpi); + if (efi.smbios != EFI_INVALID_TABLE_ADDR) + str += sprintf(str, "SMBIOS=0x%lx\n", efi.smbios); ++ if (efi.smbios3 != EFI_INVALID_TABLE_ADDR) ++ str += sprintf(str, "SMBIOS3=0x%lx\n", efi.smbios3); + if (efi.hcdp != EFI_INVALID_TABLE_ADDR) + str += sprintf(str, "HCDP=0x%lx\n", efi.hcdp); + if (efi.boot_info != EFI_INVALID_TABLE_ADDR) +@@ -260,6 +263,7 @@ static __initdata efi_config_table_type_t common_tables[] = { + {MPS_TABLE_GUID, "MPS", &efi.mps}, + {SAL_SYSTEM_TABLE_GUID, "SALsystab", &efi.sal_systab}, + {SMBIOS_TABLE_GUID, "SMBIOS", &efi.smbios}, ++ {SMBIOS3_TABLE_GUID, "SMBIOS 3.0", &efi.smbios3}, + {UGA_IO_PROTOCOL_GUID, "UGA", &efi.uga}, + {NULL_GUID, NULL, NULL}, + }; +diff --git a/drivers/firmware/efi/libstub/arm-stub.c b/drivers/firmware/efi/libstub/arm-stub.c +index 75ee059..eb48a1a 100644 +--- a/drivers/firmware/efi/libstub/arm-stub.c ++++ b/drivers/firmware/efi/libstub/arm-stub.c +@@ -247,9 +247,18 @@ unsigned long __init efi_entry(void *handle, efi_system_table_t *sys_table, + goto fail_free_cmdline; + } + } +- if (!fdt_addr) ++ ++ if (fdt_addr) { ++ pr_efi(sys_table, "Using DTB from command line\n"); ++ } else { + /* Look for a device tree configuration table entry. */ + fdt_addr = (uintptr_t)get_fdt(sys_table); ++ if (fdt_addr) ++ pr_efi(sys_table, "Using DTB from configuration table\n"); ++ } ++ ++ if (!fdt_addr) ++ pr_efi(sys_table, "Generating empty DTB\n"); + + status = handle_cmdline_files(sys_table, image, cmdline_ptr, + "initrd=", dram_base + SZ_512M, diff --git a/drivers/gpio/devres.c b/drivers/gpio/devres.c -index 954b9f6..a1f7e55 100644 +index 954b9f6..13dbd3d 100644 --- a/drivers/gpio/devres.c +++ b/drivers/gpio/devres.c -@@ -109,6 +109,40 @@ struct gpio_desc *__must_check __devm_gpiod_get_index(struct device *dev, +@@ -109,6 +109,38 @@ struct gpio_desc *__must_check __devm_gpiod_get_index(struct device *dev, EXPORT_SYMBOL(__devm_gpiod_get_index); /** -+ * devm_get_named_gpiod_from_child - managed dev_get_named_gpiod_from_child() ++ * devm_get_gpiod_from_child - get a GPIO descriptor from a device's child node + * @dev: GPIO consumer + * @child: firmware node (child of @dev) -+ * @propname: name of the firmware property -+ * @index: index of the GPIO in the property value in case of many + * + * GPIO descriptors returned from this function are automatically disposed on + * driver detach. + */ -+struct gpio_desc *devm_get_named_gpiod_from_child(struct device *dev, void *child, -+ const char *propname, int index) ++struct gpio_desc *devm_get_gpiod_from_child(struct device *dev, ++ struct fwnode_handle *child) +{ + struct gpio_desc **dr; + struct gpio_desc *desc; @@ -4842,7 +7672,7 @@ index 954b9f6..a1f7e55 100644 + if (!dr) + return ERR_PTR(-ENOMEM); + -+ desc = dev_get_named_gpiod_from_child(dev, child, propname, index); ++ desc = fwnode_get_named_gpiod(child, "gpios"); + if (IS_ERR(desc)) { + devres_free(dr); + return desc; @@ -4853,7 +7683,7 @@ index 954b9f6..a1f7e55 100644 + + return desc; +} -+EXPORT_SYMBOL(devm_get_named_gpiod_from_child); ++EXPORT_SYMBOL(devm_get_gpiod_from_child); + +/** * devm_gpiod_get_index_optional - Resource-managed gpiod_get_index_optional() @@ -5267,10 +8097,48 @@ index 41e91d7..99720c8 100644 } diff --git a/drivers/gpio/gpiolib-acpi.c b/drivers/gpio/gpiolib-acpi.c -index 05c6275..8aa6ca4 100644 +index 05c6275..ba98bb5 100644 --- a/drivers/gpio/gpiolib-acpi.c +++ b/drivers/gpio/gpiolib-acpi.c -@@ -290,6 +290,7 @@ void acpi_gpiochip_free_interrupts(struct gpio_chip *chip) +@@ -287,9 +287,45 @@ void acpi_gpiochip_free_interrupts(struct gpio_chip *chip) + } + } + ++int acpi_dev_add_driver_gpios(struct acpi_device *adev, ++ const struct acpi_gpio_mapping *gpios) ++{ ++ if (adev && gpios) { ++ adev->driver_gpios = gpios; ++ return 0; ++ } ++ return -EINVAL; ++} ++EXPORT_SYMBOL_GPL(acpi_dev_add_driver_gpios); ++ ++static bool acpi_get_driver_gpio_data(struct acpi_device *adev, ++ const char *name, int index, ++ struct acpi_reference_args *args) ++{ ++ const struct acpi_gpio_mapping *gm; ++ ++ if (!adev->driver_gpios) ++ return false; ++ ++ for (gm = adev->driver_gpios; gm->name; gm++) ++ if (!strcmp(name, gm->name) && gm->data && index < gm->size) { ++ const struct acpi_gpio_params *par = gm->data + index; ++ ++ args->adev = adev; ++ args->args[0] = par->crs_entry_index; ++ args->args[1] = par->line_index; ++ args->args[2] = par->active_low; ++ args->nargs = 3; ++ return true; ++ } ++ ++ return false; ++} ++ struct acpi_gpio_lookup { struct acpi_gpio_info info; int index; @@ -5278,7 +8146,7 @@ index 05c6275..8aa6ca4 100644 struct gpio_desc *desc; int n; }; -@@ -303,13 +304,24 @@ static int acpi_find_gpio(struct acpi_resource *ares, void *data) +@@ -303,13 +339,24 @@ static int acpi_find_gpio(struct acpi_resource *ares, void *data) if (lookup->n++ == lookup->index && !lookup->desc) { const struct acpi_resource_gpio *agpio = &ares->data.gpio; @@ -5306,7 +8174,7 @@ index 05c6275..8aa6ca4 100644 } return 1; -@@ -317,40 +329,75 @@ static int acpi_find_gpio(struct acpi_resource *ares, void *data) +@@ -317,40 +364,79 @@ static int acpi_find_gpio(struct acpi_resource *ares, void *data) /** * acpi_get_gpiod_by_index() - get a GPIO descriptor from device resources @@ -5361,10 +8229,14 @@ index 05c6275..8aa6ca4 100644 + dev_dbg(&adev->dev, "GPIO: looking up %s\n", propname); + + memset(&args, 0, sizeof(args)); -+ ret = acpi_dev_get_property_reference(adev, propname, NULL, ++ ret = acpi_dev_get_property_reference(adev, propname, + index, &args); -+ if (ret) -+ return ERR_PTR(ret); ++ if (ret) { ++ bool found = acpi_get_driver_gpio_data(adev, propname, ++ index, &args); ++ if (!found) ++ return ERR_PTR(ret); ++ } + + /* + * The property was found and resolved so need to @@ -5392,7 +8264,7 @@ index 05c6275..8aa6ca4 100644 INIT_LIST_HEAD(&resource_list); ret = acpi_dev_get_resources(adev, &resource_list, acpi_find_gpio, &lookup); -@@ -359,8 +406,11 @@ struct gpio_desc *acpi_get_gpiod_by_index(struct device *dev, int index, +@@ -359,8 +445,11 @@ struct gpio_desc *acpi_get_gpiod_by_index(struct device *dev, int index, acpi_dev_free_resource_list(&resource_list); @@ -5406,7 +8278,7 @@ index 05c6275..8aa6ca4 100644 return lookup.desc ? lookup.desc : ERR_PTR(-ENOENT); } diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c -index e8e98ca..0fa5f79 100644 +index e8e98ca..58659db 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -1505,14 +1505,36 @@ static struct gpio_desc *acpi_find_gpio(struct device *dev, const char *con_id, @@ -5433,7 +8305,7 @@ index e8e98ca..0fa5f79 100644 + suffixes[i]); + } + -+ desc = acpi_get_gpiod_by_index(adev, propname, 0, &info); ++ desc = acpi_get_gpiod_by_index(adev, propname, idx, &info); + if (!IS_ERR(desc) || (PTR_ERR(desc) == -EPROBE_DEFER)) + break; + } @@ -5450,19 +8322,16 @@ index e8e98ca..0fa5f79 100644 *flags |= GPIO_ACTIVE_LOW; return desc; -@@ -1713,6 +1735,62 @@ struct gpio_desc *__must_check __gpiod_get_index(struct device *dev, +@@ -1713,6 +1735,61 @@ struct gpio_desc *__must_check __gpiod_get_index(struct device *dev, EXPORT_SYMBOL_GPL(__gpiod_get_index); /** -+ * dev_get_named_gpiod_from_child - obtain a GPIO from firmware node -+ * @dev: parent device -+ * @child: firmware node (child of @dev) -+ * @propname: name of the firmware property -+ * @idx: index of the GPIO in the property value in case of many ++ * fwnode_get_named_gpiod - obtain a GPIO from firmware node ++ * @fwnode: handle of the firmware node ++ * @propname: name of the firmware property representing the GPIO + * + * This function can be used for drivers that get their configuration -+ * from firmware in such a way that some properties are described as child -+ * nodes for the parent device in DT or ACPI. ++ * from firmware. + * + * Function properly finds the corresponding GPIO using whatever is the + * underlying firmware interface and then makes sure that the GPIO @@ -5470,26 +8339,28 @@ index e8e98ca..0fa5f79 100644 + * + * In case of error an ERR_PTR() is returned. + */ -+struct gpio_desc *dev_get_named_gpiod_from_child(struct device *dev, void *child, -+ const char *propname, int index) ++struct gpio_desc *fwnode_get_named_gpiod(struct fwnode_handle *fwnode, ++ const char *propname) +{ + struct gpio_desc *desc = ERR_PTR(-ENODEV); + bool active_low = false; + int ret; + -+ if (!child) ++ if (!fwnode) + return ERR_PTR(-EINVAL); + -+ if (IS_ENABLED(CONFIG_OF) && dev->of_node) { ++ if (is_of_node(fwnode)) { + enum of_gpio_flags flags; + -+ desc = of_get_named_gpiod_flags(child, propname, index, &flags); ++ desc = of_get_named_gpiod_flags(of_node(fwnode), propname, 0, ++ &flags); + if (!IS_ERR(desc)) + active_low = flags & OF_GPIO_ACTIVE_LOW; -+ } else if (ACPI_COMPANION(dev)) { ++ } else if (is_acpi_node(fwnode)) { + struct acpi_gpio_info info; + -+ desc = acpi_get_gpiod_by_index(child, propname, index, &info); ++ desc = acpi_get_gpiod_by_index(acpi_node(fwnode), propname, 0, ++ &info); + if (!IS_ERR(desc)) + active_low = info.active_low; + } @@ -5507,7 +8378,7 @@ index e8e98ca..0fa5f79 100644 + + return desc; +} -+EXPORT_SYMBOL_GPL(dev_get_named_gpiod_from_child); ++EXPORT_SYMBOL_GPL(fwnode_get_named_gpiod); + +/** * gpiod_get_index_optional - obtain an optional GPIO from a multi-index GPIO @@ -5539,7 +8410,7 @@ index 9db2b6a..e3a5211 100644 return ERR_PTR(-ENOSYS); } diff --git a/drivers/input/keyboard/gpio_keys_polled.c b/drivers/input/keyboard/gpio_keys_polled.c -index 432d363..3563850 100644 +index 432d363..c9c1c8c 100644 --- a/drivers/input/keyboard/gpio_keys_polled.c +++ b/drivers/input/keyboard/gpio_keys_polled.c @@ -23,10 +23,9 @@ @@ -5574,59 +8445,17 @@ index 432d363..3563850 100644 input_sync(input); bdata->count = 0; bdata->last_state = state; -@@ -102,21 +100,57 @@ static void gpio_keys_polled_close(struct input_polled_dev *dev) +@@ -102,21 +100,15 @@ static void gpio_keys_polled_close(struct input_polled_dev *dev) pdata->disable(bdev->dev); } -#ifdef CONFIG_OF -+static int gpio_keys_polled_get_button(struct device *dev, void *child, -+ void *data) -+{ -+ struct gpio_keys_platform_data *pdata = data; -+ struct gpio_keys_button *button; -+ struct gpio_desc *desc; -+ -+ desc = devm_get_named_gpiod_from_child(dev, child, "gpios", 0); -+ if (IS_ERR(desc)) { -+ int err = PTR_ERR(desc); -+ -+ if (err != -EPROBE_DEFER) -+ dev_err(dev, "Failed to get gpio flags, error: %d\n", -+ err); -+ return err; -+ } -+ -+ button = &pdata->buttons[pdata->nbuttons++]; -+ button->gpiod = desc; -+ -+ if (device_child_property_read_u32(dev, child, "linux,code", -+ &button->code)) { -+ dev_err(dev, "Button without keycode: %d\n", -+ pdata->nbuttons - 1); -+ return -EINVAL; -+ } -+ -+ device_child_property_read_string(dev, child, "label", &button->desc); -+ -+ if (device_child_property_read_u32(dev, child, "linux,input-type", -+ &button->type)) -+ button->type = EV_KEY; -+ -+ button->wakeup = !device_get_child_property(dev, child, -+ "gpio-key,wakeup", NULL); -+ -+ if (device_child_property_read_u32(dev, child, "debounce-interval", -+ &button->debounce_interval)) -+ button->debounce_interval = 5; -+ -+ return 0; -+} -+ static struct gpio_keys_platform_data *gpio_keys_polled_get_devtree_pdata(struct device *dev) { - struct device_node *node, *pp; struct gpio_keys_platform_data *pdata; struct gpio_keys_button *button; ++ struct fwnode_handle *child; int error; int nbuttons; - int i; @@ -5640,7 +8469,7 @@ index 432d363..3563850 100644 if (nbuttons == 0) return NULL; -@@ -126,54 +160,14 @@ static struct gpio_keys_platform_data *gpio_keys_polled_get_devtree_pdata(struct +@@ -126,52 +118,44 @@ static struct gpio_keys_platform_data *gpio_keys_polled_get_devtree_pdata(struct return ERR_PTR(-ENOMEM); pdata->buttons = (struct gpio_keys_button *)(pdata + 1); @@ -5648,14 +8477,16 @@ index 432d363..3563850 100644 - pdata->rep = !!of_get_property(node, "autorepeat", NULL); - of_property_read_u32(node, "poll-interval", &pdata->poll_interval); -+ pdata->rep = !device_get_property(dev, "autorepeat", NULL); ++ pdata->rep = device_property_present(dev, "autorepeat"); + device_property_read_u32(dev, "poll-interval", &pdata->poll_interval); - i = 0; - for_each_child_of_node(node, pp) { - int gpio; - enum of_gpio_flags flags; -- ++ device_for_each_child_node(dev, child) { ++ struct gpio_desc *desc; + - if (!of_find_property(pp, "gpios", NULL)) { - pdata->nbuttons--; - dev_warn(dev, "Found button without gpios\n"); @@ -5665,43 +8496,53 @@ index 432d363..3563850 100644 - gpio = of_get_gpio_flags(pp, 0, &flags); - if (gpio < 0) { - error = gpio; -- if (error != -EPROBE_DEFER) -- dev_err(dev, -- "Failed to get gpio flags, error: %d\n", -- error); -- return ERR_PTR(error); -- } -- ++ desc = devm_get_gpiod_from_child(dev, child); ++ if (IS_ERR(desc)) { ++ error = PTR_ERR(desc); + if (error != -EPROBE_DEFER) + dev_err(dev, + "Failed to get gpio flags, error: %d\n", + error); ++ fwnode_handle_put(child); + return ERR_PTR(error); + } + - button = &pdata->buttons[i++]; - - button->gpio = gpio; - button->active_low = flags & OF_GPIO_ACTIVE_LOW; -- ++ button = &pdata->buttons[pdata->nbuttons++]; ++ button->gpiod = desc; + - if (of_property_read_u32(pp, "linux,code", &button->code)) { - dev_err(dev, "Button without keycode: 0x%x\n", - button->gpio); -- return ERR_PTR(-EINVAL); -- } -- ++ if (fwnode_property_read_u32(child, "linux,code", &button->code)) { ++ dev_err(dev, "Button without keycode: %d\n", ++ pdata->nbuttons - 1); ++ fwnode_handle_put(child); + return ERR_PTR(-EINVAL); + } + - button->desc = of_get_property(pp, "label", NULL); -- ++ fwnode_property_read_string(child, "label", &button->desc); + - if (of_property_read_u32(pp, "linux,input-type", &button->type)) -- button->type = EV_KEY; -- ++ if (fwnode_property_read_u32(child, "linux,input-type", ++ &button->type)) + button->type = EV_KEY; + - button->wakeup = !!of_get_property(pp, "gpio-key,wakeup", NULL); -- ++ button->wakeup = fwnode_property_present(child, "gpio-key,wakeup"); + - if (of_property_read_u32(pp, "debounce-interval", - &button->debounce_interval)) -- button->debounce_interval = 5; -- } -+ error = device_for_each_child_node(dev, gpio_keys_polled_get_button, -+ pdata); -+ if (error) -+ return ERR_PTR(error); - - if (pdata->nbuttons == 0) - return ERR_PTR(-EINVAL); -@@ -187,14 +181,11 @@ static const struct of_device_id gpio_keys_polled_of_match[] = { ++ if (fwnode_property_read_u32(child, "debounce-interval", ++ &button->debounce_interval)) + button->debounce_interval = 5; + } + +@@ -187,15 +171,6 @@ static const struct of_device_id gpio_keys_polled_of_match[] = { }; MODULE_DEVICE_TABLE(of, gpio_keys_polled_of_match); @@ -5713,15 +8554,11 @@ index 432d363..3563850 100644 - return NULL; -} -#endif -+static const struct acpi_device_id gpio_keys_polled_acpi_match[] = { -+ { "PRP0001" }, /* Device Tree shoehorned into ACPI */ -+ { }, -+}; -+MODULE_DEVICE_TABLE(acpi, gpio_keys_polled_acpi_match); - +- static int gpio_keys_polled_probe(struct platform_device *pdev) { -@@ -259,7 +250,6 @@ static int gpio_keys_polled_probe(struct platform_device *pdev) + struct device *dev = &pdev->dev; +@@ -259,7 +234,6 @@ static int gpio_keys_polled_probe(struct platform_device *pdev) for (i = 0; i < pdata->nbuttons; i++) { struct gpio_keys_button *button = &pdata->buttons[i]; struct gpio_keys_button_data *bdata = &bdev->data[i]; @@ -5729,7 +8566,7 @@ index 432d363..3563850 100644 unsigned int type = button->type ?: EV_KEY; if (button->wakeup) { -@@ -267,15 +257,31 @@ static int gpio_keys_polled_probe(struct platform_device *pdev) +@@ -267,15 +241,31 @@ static int gpio_keys_polled_probe(struct platform_device *pdev) return -EINVAL; } @@ -5768,16 +8605,41 @@ index 432d363..3563850 100644 bdata->last_state = -1; bdata->threshold = DIV_ROUND_UP(button->debounce_interval, pdata->poll_interval); -@@ -308,7 +314,8 @@ static struct platform_driver gpio_keys_polled_driver = { +@@ -308,7 +298,7 @@ static struct platform_driver gpio_keys_polled_driver = { .driver = { .name = DRV_NAME, .owner = THIS_MODULE, - .of_match_table = of_match_ptr(gpio_keys_polled_of_match), + .of_match_table = gpio_keys_polled_of_match, -+ .acpi_match_table = gpio_keys_polled_acpi_match, }, }; module_platform_driver(gpio_keys_polled_driver); +diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c +index 60558f7..3b92862 100644 +--- a/drivers/iommu/arm-smmu.c ++++ b/drivers/iommu/arm-smmu.c +@@ -444,7 +444,10 @@ static struct device_node *dev_get_dev_node(struct device *dev) + + while (!pci_is_root_bus(bus)) + bus = bus->parent; +- return bus->bridge->parent->of_node; ++ if (bus->bridge->parent) ++ return bus->bridge->parent->of_node; ++ else ++ return NULL; + } + + return dev->of_node; +@@ -560,6 +563,9 @@ static struct arm_smmu_device *find_smmu_for_device(struct device *dev) + struct arm_smmu_master *master = NULL; + struct device_node *dev_node = dev_get_dev_node(dev); + ++ if (!dev_node) ++ return NULL; ++ + spin_lock(&arm_smmu_devices_lock); + list_for_each_entry(smmu, &arm_smmu_devices, list) { + master = find_smmu_master(smmu, dev_node); diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c index aa17ae8..d330dab 100644 --- a/drivers/irqchip/irq-gic-v3.c @@ -5973,10 +8835,11 @@ index 0fe2f71..9106c6d 100644 + acpi_gic_init(); } diff --git a/drivers/leds/leds-gpio.c b/drivers/leds/leds-gpio.c -index 57ff20f..681efd5 100644 +index b4518c8..b3c5d9d 100644 --- a/drivers/leds/leds-gpio.c +++ b/drivers/leds/leds-gpio.c -@@ -13,22 +13,20 @@ +@@ -12,25 +12,23 @@ + */ #include #include +#include @@ -6000,22 +8863,20 @@ index 57ff20f..681efd5 100644 u8 can_sleep; - u8 active_low; u8 blinking; - int (*platform_gpio_blink_set)(unsigned gpio, int state, +- int (*platform_gpio_blink_set)(unsigned gpio, int state, ++ int (*platform_gpio_blink_set)(struct gpio_desc *desc, int state, unsigned long *delay_on, unsigned long *delay_off); -@@ -40,12 +38,16 @@ static void gpio_led_work(struct work_struct *work) + }; + +@@ -40,12 +38,11 @@ static void gpio_led_work(struct work_struct *work) container_of(work, struct gpio_led_data, work); if (led_dat->blinking) { - led_dat->platform_gpio_blink_set(led_dat->gpio, - led_dat->new_level, - NULL, NULL); -+ int gpio = desc_to_gpio(led_dat->gpiod); -+ int level = led_dat->new_level; -+ -+ if (gpiod_is_active_low(led_dat->gpiod)) -+ level = !level; -+ -+ led_dat->platform_gpio_blink_set(gpio, level, NULL, NULL); ++ led_dat->platform_gpio_blink_set(led_dat->gpiod, ++ led_dat->new_level, NULL, NULL); led_dat->blinking = 0; } else - gpio_set_value_cansleep(led_dat->gpio, led_dat->new_level); @@ -6023,7 +8884,7 @@ index 57ff20f..681efd5 100644 } static void gpio_led_set(struct led_classdev *led_cdev, -@@ -60,9 +62,6 @@ static void gpio_led_set(struct led_classdev *led_cdev, +@@ -60,9 +57,6 @@ static void gpio_led_set(struct led_classdev *led_cdev, else level = 1; @@ -6033,19 +8894,13 @@ index 57ff20f..681efd5 100644 /* Setting GPIOs with I2C/etc requires a task context, and we don't * seem to have a reliable way to know if we're already in one; so * let's just assume the worst. -@@ -72,11 +71,16 @@ static void gpio_led_set(struct led_classdev *led_cdev, +@@ -72,11 +66,11 @@ static void gpio_led_set(struct led_classdev *led_cdev, schedule_work(&led_dat->work); } else { if (led_dat->blinking) { - led_dat->platform_gpio_blink_set(led_dat->gpio, level, -- NULL, NULL); -+ int gpio = desc_to_gpio(led_dat->gpiod); -+ -+ if (gpiod_is_active_low(led_dat->gpiod)) -+ level = !level; -+ -+ led_dat->platform_gpio_blink_set(gpio, level, NULL, -+ NULL); ++ led_dat->platform_gpio_blink_set(led_dat->gpiod, level, + NULL, NULL); led_dat->blinking = 0; } else - gpio_set_value(led_dat->gpio, level); @@ -6053,25 +8908,39 @@ index 57ff20f..681efd5 100644 } } -@@ -85,9 +89,10 @@ static int gpio_blink_set(struct led_classdev *led_cdev, - { - struct gpio_led_data *led_dat = +@@ -87,34 +81,49 @@ static int gpio_blink_set(struct led_classdev *led_cdev, container_of(led_cdev, struct gpio_led_data, cdev); -+ int gpio = desc_to_gpio(led_dat->gpiod); led_dat->blinking = 1; - return led_dat->platform_gpio_blink_set(led_dat->gpio, GPIO_LED_BLINK, -+ return led_dat->platform_gpio_blink_set(gpio, GPIO_LED_BLINK, ++ return led_dat->platform_gpio_blink_set(led_dat->gpiod, GPIO_LED_BLINK, delay_on, delay_off); } -@@ -97,24 +102,33 @@ static int create_gpio_led(const struct gpio_led *template, + static int create_gpio_led(const struct gpio_led *template, + struct gpio_led_data *led_dat, struct device *parent, +- int (*blink_set)(unsigned, int, unsigned long *, unsigned long *)) ++ int (*blink_set)(struct gpio_desc *, int, unsigned long *, ++ unsigned long *)) { int ret, state; - led_dat->gpio = -1; -+ if (!template->gpiod) { ++ led_dat->gpiod = template->gpiod; ++ if (!led_dat->gpiod) { ++ /* ++ * This is the legacy code path for platform code that ++ * still uses GPIO numbers. Ultimately we would like to get ++ * rid of this block completely. ++ */ + unsigned long flags = 0; ++ ++ /* skip leds that aren't available */ ++ if (!gpio_is_valid(template->gpio)) { ++ dev_info(parent, "Skipping unavailable LED gpio %d (%s)\n", ++ template->gpio, template->name); ++ return 0; ++ } - /* skip leds that aren't available */ - if (!gpio_is_valid(template->gpio)) { @@ -6079,19 +8948,12 @@ index 57ff20f..681efd5 100644 - template->gpio, template->name); - return 0; - } -+ /* skip leds that aren't available */ -+ if (!gpio_is_valid(template->gpio)) { -+ dev_info(parent, "Skipping unavailable LED gpio %d (%s)\n", -+ template->gpio, template->name); -+ return 0; -+ } ++ if (template->active_low) ++ flags |= GPIOF_ACTIVE_LOW; - ret = devm_gpio_request(parent, template->gpio, template->name); - if (ret < 0) - return ret; -+ if (template->active_low) -+ flags |= GPIOF_ACTIVE_LOW; -+ + ret = devm_gpio_request_one(parent, template->gpio, flags, + template->name); + if (ret < 0) @@ -6107,12 +8969,11 @@ index 57ff20f..681efd5 100644 - led_dat->gpio = template->gpio; - led_dat->can_sleep = gpio_cansleep(template->gpio); - led_dat->active_low = template->active_low; -+ led_dat->gpiod = template->gpiod; -+ led_dat->can_sleep = gpiod_cansleep(template->gpiod); ++ led_dat->can_sleep = gpiod_cansleep(led_dat->gpiod); led_dat->blinking = 0; if (blink_set) { led_dat->platform_gpio_blink_set = blink_set; -@@ -122,30 +136,24 @@ static int create_gpio_led(const struct gpio_led *template, +@@ -122,30 +131,24 @@ static int create_gpio_led(const struct gpio_led *template, } led_dat->cdev.brightness_set = gpio_led_set; if (template->default_state == LEDS_GPIO_DEFSTATE_KEEP) @@ -6146,54 +9007,24 @@ index 57ff20f..681efd5 100644 led_classdev_unregister(&led->cdev); cancel_work_sync(&led->work); } -@@ -161,65 +169,59 @@ static inline int sizeof_gpio_leds_priv(int num_leds) +@@ -161,40 +164,37 @@ static inline int sizeof_gpio_leds_priv(int num_leds) (sizeof(struct gpio_led_data) * num_leds); } -/* Code to create from OpenFirmware platform devices */ -#ifdef CONFIG_OF_GPIO -static struct gpio_leds_priv *gpio_leds_create_of(struct platform_device *pdev) -+static int gpio_leds_create_led(struct device *dev, void *child, void *data) -+{ -+ struct gpio_leds_priv *priv = data; -+ struct gpio_led led = {}; -+ const char *state = NULL; -+ -+ led.gpiod = devm_get_named_gpiod_from_child(dev, child, "gpios", 0); -+ if (IS_ERR(led.gpiod)) -+ return PTR_ERR(led.gpiod); -+ -+ device_child_property_read_string(dev, child, "label", &led.name); -+ device_child_property_read_string(dev, child, "linux,default-trigger", -+ &led.default_trigger); -+ -+ device_child_property_read_string(dev, child, "linux,default_state", -+ &state); -+ if (state) { -+ if (!strcmp(state, "keep")) -+ led.default_state = LEDS_GPIO_DEFSTATE_KEEP; -+ else if (!strcmp(state, "on")) -+ led.default_state = LEDS_GPIO_DEFSTATE_ON; -+ else -+ led.default_state = LEDS_GPIO_DEFSTATE_OFF; -+ } -+ -+ if (!device_get_child_property(dev, child, "retain-state-suspended", NULL)) -+ led.retain_state_suspended = 1; -+ -+ return create_gpio_led(&led, &priv->leds[priv->num_leds++], dev, NULL); -+} -+ +static struct gpio_leds_priv *gpio_leds_create(struct platform_device *pdev) { - struct device_node *np = pdev->dev.of_node, *child; ++ struct device *dev = &pdev->dev; ++ struct fwnode_handle *child; struct gpio_leds_priv *priv; -- int count, ret; -+ int ret, count; + int count, ret; - /* count LEDs in this device, so we know how much to allocate */ - count = of_get_available_child_count(np); -+ count = device_get_child_node_count(&pdev->dev); ++ count = device_get_child_node_count(dev); if (!count) return ERR_PTR(-ENODEV); @@ -6201,13 +9032,15 @@ index 57ff20f..681efd5 100644 - if (of_get_gpio(child, 0) == -EPROBE_DEFER) - return ERR_PTR(-EPROBE_DEFER); - - priv = devm_kzalloc(&pdev->dev, sizeof_gpio_leds_priv(count), - GFP_KERNEL); +- priv = devm_kzalloc(&pdev->dev, sizeof_gpio_leds_priv(count), +- GFP_KERNEL); ++ priv = devm_kzalloc(dev, sizeof_gpio_leds_priv(count), GFP_KERNEL); if (!priv) return ERR_PTR(-ENOMEM); - for_each_available_child_of_node(np, child) { -- struct gpio_led led = {}; ++ device_for_each_child_node(dev, child) { + struct gpio_led led = {}; - enum of_gpio_flags flags; - const char *state; - @@ -6218,40 +9051,41 @@ index 57ff20f..681efd5 100644 - of_get_property(child, "linux,default-trigger", NULL); - state = of_get_property(child, "default-state", NULL); - if (state) { -- if (!strcmp(state, "keep")) -- led.default_state = LEDS_GPIO_DEFSTATE_KEEP; -- else if (!strcmp(state, "on")) -- led.default_state = LEDS_GPIO_DEFSTATE_ON; -- else -- led.default_state = LEDS_GPIO_DEFSTATE_OFF; -- } -- ++ const char *state = NULL; ++ ++ led.gpiod = devm_get_gpiod_from_child(dev, child); ++ if (IS_ERR(led.gpiod)) { ++ fwnode_handle_put(child); ++ goto err; ++ } ++ ++ fwnode_property_read_string(child, "label", &led.name); ++ fwnode_property_read_string(child, "linux,default-trigger", ++ &led.default_trigger); ++ ++ if (!fwnode_property_read_string(child, "linux,default_state", ++ &state)) { + if (!strcmp(state, "keep")) + led.default_state = LEDS_GPIO_DEFSTATE_KEEP; + else if (!strcmp(state, "on")) +@@ -203,13 +203,13 @@ static struct gpio_leds_priv *gpio_leds_create_of(struct platform_device *pdev) + led.default_state = LEDS_GPIO_DEFSTATE_OFF; + } + - if (of_get_property(child, "retain-state-suspended", NULL)) -- led.retain_state_suspended = 1; -- -- ret = create_gpio_led(&led, &priv->leds[priv->num_leds++], ++ if (fwnode_property_present(child, "retain-state-suspended")) + led.retain_state_suspended = 1; + + ret = create_gpio_led(&led, &priv->leds[priv->num_leds++], - &pdev->dev, NULL); -- if (ret < 0) { ++ dev, NULL); + if (ret < 0) { - of_node_put(child); -- goto err; -- } -+ ret = device_for_each_child_node(&pdev->dev, gpio_leds_create_led, priv); -+ if (ret) { -+ for (count = priv->num_leds - 2; count >= 0; count--) -+ delete_gpio_led(&priv->leds[count]); -+ return ERR_PTR(ret); ++ fwnode_handle_put(child); + goto err; + } } - - return priv; -- --err: -- for (count = priv->num_leds - 2; count >= 0; count--) -- delete_gpio_led(&priv->leds[count]); -- return ERR_PTR(-ENODEV); - } - - static const struct of_device_id of_gpio_leds_match[] = { -@@ -228,12 +228,13 @@ static const struct of_device_id of_gpio_leds_match[] = { +@@ -228,12 +228,6 @@ static const struct of_device_id of_gpio_leds_match[] = { }; MODULE_DEVICE_TABLE(of, of_gpio_leds_match); @@ -6261,17 +9095,10 @@ index 57ff20f..681efd5 100644 - return ERR_PTR(-ENODEV); -} -#endif /* CONFIG_OF_GPIO */ -+ -+static const struct acpi_device_id acpi_gpio_leds_match[] = { -+ { "PRP0001" }, /* Device Tree shoehorned into ACPI */ -+ {}, -+}; -+ -+MODULE_DEVICE_TABLE(acpi, acpi_gpio_leds_match); static int gpio_led_probe(struct platform_device *pdev) { -@@ -263,7 +265,7 @@ static int gpio_led_probe(struct platform_device *pdev) +@@ -261,7 +255,7 @@ static int gpio_led_probe(struct platform_device *pdev) } } } else { @@ -6280,18 +9107,17 @@ index 57ff20f..681efd5 100644 if (IS_ERR(priv)) return PTR_ERR(priv); } -@@ -290,7 +292,8 @@ static struct platform_driver gpio_led_driver = { +@@ -288,7 +282,7 @@ static struct platform_driver gpio_led_driver = { .driver = { .name = "leds-gpio", .owner = THIS_MODULE, - .of_match_table = of_match_ptr(of_gpio_leds_match), + .of_match_table = of_gpio_leds_match, -+ .acpi_match_table = acpi_gpio_leds_match, }, }; diff --git a/drivers/misc/eeprom/at25.c b/drivers/misc/eeprom/at25.c -index 634f729..1a760cd 100644 +index 634f729..0a1af93 100644 --- a/drivers/misc/eeprom/at25.c +++ b/drivers/misc/eeprom/at25.c @@ -18,7 +18,7 @@ @@ -6352,7 +9178,7 @@ index 634f729..1a760cd 100644 return -ENODEV; } - if (of_find_property(np, "read-only", NULL)) -+ if (!device_get_property(dev, "read-only", NULL)) ++ if (device_property_present(dev, "read-only")) chip->flags |= EE_READONLY; } return 0; @@ -6378,28 +9204,9 @@ index 634f729..1a760cd 100644 + err = at25_fw_to_chip(&spi->dev, &chip); + if (err) + return err; - } else - chip = *(struct spi_eeprom *)spi->dev.platform_data; - -@@ -467,11 +459,18 @@ static const struct of_device_id at25_of_match[] = { - }; - MODULE_DEVICE_TABLE(of, at25_of_match); - -+static const struct acpi_device_id at25_acpi_match[] = { -+ { "PRP0001" }, -+ { } -+}; -+MODULE_DEVICE_TABLE(acpi, at25_acpi_match); -+ - static struct spi_driver at25_driver = { - .driver = { - .name = "at25", - .owner = THIS_MODULE, - .of_match_table = at25_of_match, -+ .acpi_match_table = at25_acpi_match, - }, - .probe = at25_probe, - .remove = at25_remove, + } else + chip = *(struct spi_eeprom *)spi->dev.platform_data; + diff --git a/drivers/net/ethernet/amd/Kconfig b/drivers/net/ethernet/amd/Kconfig index 8319c99..6feb6ef3 100644 --- a/drivers/net/ethernet/amd/Kconfig @@ -6455,7 +9262,7 @@ index 9da3a03..a34cad2 100644 * management interface uses indirect addressing to access the MMD * register sets. This requires accessing of the PCS register in two diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c -index 2955499..423ae3d 100644 +index 2349ea9..a04b18b 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c +++ b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c @@ -425,6 +425,9 @@ void xgbe_get_all_hw_features(struct xgbe_prv_data *pdata) @@ -6469,7 +9276,7 @@ index 2955499..423ae3d 100644 } diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-main.c b/drivers/net/ethernet/amd/xgbe/xgbe-main.c -index f5a8fa0..db29dec 100644 +index f5a8fa0..338c0ed 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-main.c +++ b/drivers/net/ethernet/amd/xgbe/xgbe-main.c @@ -124,6 +124,7 @@ @@ -6480,7 +9287,7 @@ index f5a8fa0..db29dec 100644 #include "xgbe.h" #include "xgbe-common.h" -@@ -215,6 +216,210 @@ static void xgbe_init_all_fptrs(struct xgbe_prv_data *pdata) +@@ -215,6 +216,205 @@ static void xgbe_init_all_fptrs(struct xgbe_prv_data *pdata) xgbe_init_function_ptrs_desc(&pdata->desc_if); } @@ -6567,12 +9374,7 @@ index f5a8fa0..db29dec 100644 + if (!is_valid_ether_addr(pdata->mac_addr)) { + dev_err(dev, "invalid %s acpi property\n", + XGBE_ACPI_MAC_ADDR); -+#if 0 + return -EINVAL; -+#else -+ dev_err(dev, "invalid MAC address, using random address\n"); -+ eth_random_addr(pdata->mac_addr); -+#endif + } + + /* Retrieve the PHY mode - it must be "xgmii" */ @@ -6691,7 +9493,7 @@ index f5a8fa0..db29dec 100644 static int xgbe_probe(struct platform_device *pdev) { struct xgbe_prv_data *pdata; -@@ -222,8 +427,6 @@ static int xgbe_probe(struct platform_device *pdev) +@@ -222,8 +422,6 @@ static int xgbe_probe(struct platform_device *pdev) struct xgbe_desc_if *desc_if; struct net_device *netdev; struct device *dev = &pdev->dev; @@ -6700,7 +9502,7 @@ index f5a8fa0..db29dec 100644 int ret; DBGPR("--> xgbe_probe\n"); -@@ -239,6 +442,7 @@ static int xgbe_probe(struct platform_device *pdev) +@@ -239,6 +437,7 @@ static int xgbe_probe(struct platform_device *pdev) pdata = netdev_priv(netdev); pdata->netdev = netdev; pdata->pdev = pdev; @@ -6708,7 +9510,7 @@ index f5a8fa0..db29dec 100644 pdata->dev = dev; platform_set_drvdata(pdev, netdev); -@@ -264,40 +468,13 @@ static int xgbe_probe(struct platform_device *pdev) +@@ -264,40 +463,13 @@ static int xgbe_probe(struct platform_device *pdev) goto err_io; } @@ -6755,7 +9557,7 @@ index f5a8fa0..db29dec 100644 /* Set the DMA mask */ if (!dev->dma_mask) -@@ -308,23 +485,16 @@ static int xgbe_probe(struct platform_device *pdev) +@@ -308,23 +480,16 @@ static int xgbe_probe(struct platform_device *pdev) goto err_io; } @@ -6782,7 +9584,7 @@ index f5a8fa0..db29dec 100644 /* Set all the function pointers */ xgbe_init_all_fptrs(pdata); -@@ -337,23 +507,6 @@ static int xgbe_probe(struct platform_device *pdev) +@@ -337,23 +502,6 @@ static int xgbe_probe(struct platform_device *pdev) /* Populate the hardware features */ xgbe_get_all_hw_features(pdata); @@ -6806,7 +9608,7 @@ index f5a8fa0..db29dec 100644 /* Set default configuration data */ xgbe_default_config(pdata); -@@ -531,10 +684,22 @@ static int xgbe_resume(struct device *dev) +@@ -531,10 +679,22 @@ static int xgbe_resume(struct device *dev) } #endif /* CONFIG_PM */ @@ -6829,7 +9631,7 @@ index f5a8fa0..db29dec 100644 MODULE_DEVICE_TABLE(of, xgbe_of_match); static SIMPLE_DEV_PM_OPS(xgbe_pm_ops, xgbe_suspend, xgbe_resume); -@@ -542,7 +707,12 @@ static SIMPLE_DEV_PM_OPS(xgbe_pm_ops, xgbe_suspend, xgbe_resume); +@@ -542,7 +702,12 @@ static SIMPLE_DEV_PM_OPS(xgbe_pm_ops, xgbe_suspend, xgbe_resume); static struct platform_driver xgbe_driver = { .driver = { .name = "amd-xgbe", @@ -7272,10 +10074,10 @@ index 874e5a0..8b7e2cf 100644 #define XGENE_DRV_VERSION "v1.0" diff --git a/drivers/net/ethernet/smsc/smc91x.c b/drivers/net/ethernet/smsc/smc91x.c -index 5e94d00..a6131a9 100644 +index 2c62208..98e22544 100644 --- a/drivers/net/ethernet/smsc/smc91x.c +++ b/drivers/net/ethernet/smsc/smc91x.c -@@ -81,6 +81,7 @@ static const char version[] = +@@ -82,6 +82,7 @@ static const char version[] = #include #include #include @@ -7283,7 +10085,7 @@ index 5e94d00..a6131a9 100644 #include #include -@@ -2405,6 +2406,14 @@ static struct dev_pm_ops smc_drv_pm_ops = { +@@ -2463,6 +2464,14 @@ static struct dev_pm_ops smc_drv_pm_ops = { .resume = smc_drv_resume, }; @@ -7298,7 +10100,7 @@ index 5e94d00..a6131a9 100644 static struct platform_driver smc_driver = { .probe = smc_drv_probe, .remove = smc_drv_remove, -@@ -2413,6 +2422,7 @@ static struct platform_driver smc_driver = { +@@ -2471,6 +2480,7 @@ static struct platform_driver smc_driver = { .owner = THIS_MODULE, .pm = &smc_drv_pm_ops, .of_match_table = of_match_ptr(smc91x_match), @@ -8472,7 +11274,7 @@ index c456559..d852c6e 100644 devm_kfree(dev, priv); } diff --git a/drivers/of/base.c b/drivers/of/base.c -index 2305dc0..43999a8 100644 +index 3823edf..4c2ccde 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c @@ -1250,6 +1250,39 @@ int of_property_read_u64(const struct device_node *np, const char *propname, @@ -8515,170 +11317,215 @@ index 2305dc0..43999a8 100644 * of_property_read_string - Find and read a string from a property * @np: device node from which the property value is to be read. * @propname: name of the property to be searched. -@@ -1397,6 +1430,49 @@ int of_property_count_strings(struct device_node *np, const char *propname) +diff --git a/drivers/pci/host/pci-xgene.c b/drivers/pci/host/pci-xgene.c +index 9ecabfa..9029d59c 100644 +--- a/drivers/pci/host/pci-xgene.c ++++ b/drivers/pci/host/pci-xgene.c +@@ -29,6 +29,7 @@ + #include + #include + #include ++#include + + #define PCIECORE_CTLANDSTATUS 0x50 + #define PIM1_1L 0x80 +@@ -235,6 +236,13 @@ static int xgene_pcie_read_config(struct pci_bus *bus, unsigned int devfn, + break; + case 2: + xgene_pcie_cfg_in16(addr, offset, val); ++ /* FIXME. ++ * Something wrong with Configuration Request Retry Status ++ * on this hw. Pretend it isn't supported until the problem ++ * gets sorted out properly. ++ */ ++ if (pci_is_root_bus(bus) && offset == (0x40 + PCI_EXP_RTCAP)) ++ *val &= ~PCI_EXP_RTCAP_CRSVIS; + break; + default: + xgene_pcie_cfg_in32(addr, offset, val); +@@ -600,6 +608,165 @@ static int xgene_pcie_setup(struct xgene_pcie_port *port, + return 0; } - EXPORT_SYMBOL_GPL(of_property_count_strings); -+/** -+ * of_property_read_string_array - Find and read an array of strings -+ * from a multiple strings property. -+ * @np: device node from which the property value is to be read. -+ * @propname: name of the property to be searched. -+ * @out_string: pointer to null terminated return string, modified only if -+ * return value is 0. -+ * @sz: number of array elements to read -+ * -+ * Search for a property in a device tree node and retrieve a list of -+ * terminated string value (pointer to data, not a copy) in that property. -+ * Returns 0 on success, -EINVAL if the property does not exist, -ENODATA if -+ * property does not have a value, and -EOVERFLOW if the string is not -+ * null-terminated within the length of the property data. -+ * -+ * The out_string pointer is modified only if a valid string can be decoded. ++#ifdef CONFIG_ACPI ++struct xgene_mcfg_info { ++ void __iomem *csr_base; ++}; ++ ++/* ++ * When the address bit [17:16] is 2'b01, the Configuration access will be ++ * treated as Type 1 and it will be forwarded to external PCIe device. + */ -+int of_property_read_string_array(struct device_node *np, const char *propname, -+ char **output, size_t sz) ++static void __iomem *__get_cfg_base(struct pci_mmcfg_region *cfg, ++ unsigned int bus) +{ -+ struct property *prop = of_find_property(np, propname, NULL); -+ int i = 0; -+ size_t l = 0, total = 0; -+ char *p; ++ if (bus > cfg->start_bus) ++ return cfg->virt + AXI_EP_CFG_ACCESS; + -+ if (!prop) -+ return -EINVAL; -+ -+ if (!prop->value) -+ return -ENODATA; -+ -+ if (strnlen(prop->value, prop->length) >= prop->length) -+ return -EOVERFLOW; -+ -+ p = prop->value; -+ -+ for (i = 0; total < prop->length; total += l, p += l) { -+ output[i++] = p; -+ l = strlen(p) + 1; -+ } -+ return 0; ++ return cfg->virt; +} + - void of_print_phandle_args(const char *msg, const struct of_phandle_args *args) - { - int i; -@@ -2186,3 +2262,113 @@ struct device_node *of_graph_get_remote_port(const struct device_node *node) - return of_get_next_parent(np); - } - EXPORT_SYMBOL(of_graph_get_remote_port); -+ -+int of_dev_prop_get(struct device_node *dn, const char *propname, void **valptr) ++/* ++ * For Configuration request, RTDID register is used as Bus Number, ++ * Device Number and Function number of the header fields. ++ */ ++static void __set_rtdid_reg(struct pci_mmcfg_region *cfg, ++ unsigned int bus, unsigned int devfn) +{ -+ struct property *pp = of_find_property(dn, propname, NULL); ++ struct xgene_mcfg_info *info = cfg->data; ++ unsigned int b, d, f; ++ u32 rtdid_val = 0; + -+ if (!pp) -+ return -ENODATA; ++ b = bus; ++ d = PCI_SLOT(devfn); ++ f = PCI_FUNC(devfn); + -+ if (valptr) -+ *valptr = pp->value; -+ return 0; ++ if (bus != cfg->start_bus) ++ rtdid_val = (b << 8) | (d << 3) | f; ++ ++ writel(rtdid_val, info->csr_base + RTDID); ++ /* read the register back to ensure flush */ ++ readl(info->csr_base + RTDID); +} + -+int of_dev_prop_read(struct device_node *dn, const char *propname, -+ enum dev_prop_type proptype, void *val) ++static int xgene_raw_pci_read(struct pci_mmcfg_region *cfg, unsigned int bus, ++ unsigned int devfn, int offset, int len, u32 *val) +{ -+ void *value; -+ int ret = of_dev_prop_get(dn, propname, &value); -+ -+ if (ret) -+ return ret; ++ void __iomem *addr; + -+ if (proptype >= DEV_PROP_U8 && proptype <= DEV_PROP_U64) { -+ switch (proptype) { -+ case DEV_PROP_U8: { -+ *(u8 *)val = *(u8 *)value; -+ break; ++ if (bus == cfg->start_bus) { ++ if (devfn != 0) { ++ *val = 0xffffffff; ++ return PCIBIOS_DEVICE_NOT_FOUND; + } -+ case DEV_PROP_U16: -+ *(u16 *)val = *(u16 *)value; -+ break; -+ case DEV_PROP_U32: -+ *(u32 *)val = *(u32 *)value; -+ break; -+ default: -+ *(u64 *)val = *(u64 *)value; -+ break; ++ ++ /* see xgene_pcie_hide_rc_bars() above */ ++ if (offset == PCI_BASE_ADDRESS_0 || ++ offset == PCI_BASE_ADDRESS_1) { ++ *val = 0; ++ return PCIBIOS_SUCCESSFUL; + } -+ } else if (proptype == DEV_PROP_STRING) { -+ *(char **)val = value; + } -+ return ret; + ++ __set_rtdid_reg(cfg, bus, devfn); ++ addr = __get_cfg_base(cfg, bus); ++ switch (len) { ++ case 1: ++ xgene_pcie_cfg_in8(addr, offset, val); ++ break; ++ case 2: ++ xgene_pcie_cfg_in16(addr, offset, val); ++ /* FIXME. ++ * Something wrong with Configuration Request Retry Status ++ * on this hw. Pretend it isn't supported until the problem ++ * gets sorted out properly. ++ */ ++ if (bus == cfg->start_bus && offset == (0x40 + PCI_EXP_RTCAP)) ++ *val &= ~PCI_EXP_RTCAP_CRSVIS; ++ break; ++ default: ++ xgene_pcie_cfg_in32(addr, offset, val); ++ break; ++ } ++ return PCIBIOS_SUCCESSFUL; +} + -+int of_dev_prop_read_array(struct device_node *dn, const char *propname, -+ enum dev_prop_type proptype, void *val, size_t nval) ++static int xgene_raw_pci_write(struct pci_mmcfg_region *cfg, unsigned int bus, ++ unsigned int devfn, int offset, int len, u32 val) +{ -+ int ret, elem_size; ++ void __iomem *addr; + -+ if (!val) { -+ switch (proptype) { -+ case DEV_PROP_U8: -+ elem_size = sizeof(u8); -+ break; -+ case DEV_PROP_U16: -+ elem_size = sizeof(u16); -+ break; -+ case DEV_PROP_U32: -+ elem_size = sizeof(u32); -+ break; -+ case DEV_PROP_U64: -+ elem_size = sizeof(u64); -+ break; -+ case DEV_PROP_STRING: -+ return of_property_count_strings(dn, propname); -+ default: -+ return -EINVAL; -+ } -+ return of_property_count_elems_of_size(dn, propname, elem_size); -+ } ++ if (bus == cfg->start_bus && devfn != 0) ++ return PCIBIOS_DEVICE_NOT_FOUND; + -+ switch (proptype) { -+ case DEV_PROP_U8: -+ ret = of_property_read_u8_array(dn, propname, (u8 *)val, nval); -+ break; -+ case DEV_PROP_U16: -+ ret = of_property_read_u16_array(dn, propname, (u16 *)val, nval); -+ break; -+ case DEV_PROP_U32: -+ ret = of_property_read_u32_array(dn, propname, (u32 *)val, nval); -+ break; -+ case DEV_PROP_U64: -+ ret = of_property_read_u64_array(dn, propname, (u64 *)val, nval); ++ __set_rtdid_reg(cfg, bus, devfn); ++ addr = __get_cfg_base(cfg, bus); ++ switch (len) { ++ case 1: ++ xgene_pcie_cfg_out8(addr, offset, (u8)val); + break; -+ case DEV_PROP_STRING: -+ ret = of_property_read_string_array(dn, propname, -+ (char **)val, nval); ++ case 2: ++ xgene_pcie_cfg_out16(addr, offset, (u16)val); + break; + default: -+ ret = -EINVAL; ++ xgene_pcie_cfg_out32(addr, offset, val); + break; + } -+ return ret; ++ return PCIBIOS_SUCCESSFUL; +} + -+int of_for_each_child_node(struct device *dev, -+ int (*fn)(struct device *dev, void *child, void *data), -+ void *data) ++static acpi_status find_csr_base(struct acpi_resource *acpi_res, void *data) +{ -+ struct device_node *child; -+ int ret = 0; ++ struct pci_mmcfg_region *cfg = data; ++ struct xgene_mcfg_info *info = cfg->data; ++ struct acpi_resource_fixed_memory32 *fixed32; + -+ for_each_child_of_node(dev->of_node, child) { -+ ret = fn(dev, child, data); -+ if (ret) -+ break; ++ if (acpi_res->type == ACPI_RESOURCE_TYPE_FIXED_MEMORY32) { ++ fixed32 = &acpi_res->data.fixed_memory32; ++ info->csr_base = ioremap(fixed32->address, ++ fixed32->address_length); ++ return AE_CTRL_TERMINATE; + } -+ return ret; ++ return AE_OK; ++} ++ ++static int xgene_mcfg_fixup(struct acpi_pci_root *root, ++ struct pci_mmcfg_region *cfg) ++{ ++ struct acpi_device *device = root->device; ++ struct xgene_mcfg_info *info; ++ ++ info = kzalloc(sizeof(*info), GFP_KERNEL); ++ if (info == NULL) ++ return -ENOMEM; ++ ++ cfg->data = info; ++ ++ acpi_walk_resources(device->handle, METHOD_NAME__CRS, ++ find_csr_base, cfg); ++ ++ if (!info->csr_base) { ++ kfree(info); ++ cfg->data = NULL; ++ return -ENODEV; ++ } ++ ++ cfg->read = xgene_raw_pci_read; ++ cfg->write = xgene_raw_pci_write; ++ ++ /* actual last bus reachable through this mmconfig */ ++ cfg->end_bus = root->secondary.end; ++ ++ /* firmware should have done this */ ++ xgene_raw_pci_write(cfg, cfg->start_bus, 0, PCI_PRIMARY_BUS, 4, ++ cfg->start_bus | ((cfg->start_bus + 1) << 8) | ++ (cfg->end_bus << 16)); ++ ++ return 0; +} ++DECLARE_ACPI_MCFG_FIXUP("APM ", "XGENE ", xgene_mcfg_fixup); ++#endif /* CONFIG_ACPI */ ++ + static int xgene_pcie_probe_bridge(struct platform_device *pdev) + { + struct device_node *dn = pdev->dev.of_node; +@@ -631,10 +798,15 @@ static int xgene_pcie_probe_bridge(struct platform_device *pdev) + if (ret) + return ret; + +- bus = pci_scan_root_bus(&pdev->dev, 0, &xgene_pcie_ops, port, &res); ++ bus = pci_create_root_bus(&pdev->dev, 0, ++ &xgene_pcie_ops, port, &res); + if (!bus) + return -ENOMEM; + ++ pci_scan_child_bus(bus); ++ pci_assign_unassigned_bus_resources(bus); ++ pci_bus_add_devices(bus); ++ + platform_set_drvdata(pdev, port); + return 0; + } diff --git a/drivers/pnp/resource.c b/drivers/pnp/resource.c index 782e822..d952462 100644 --- a/drivers/pnp/resource.c @@ -9154,11 +12001,31 @@ index ef9a165..9f1939c 100644 }, }; +diff --git a/drivers/xen/efi.c b/drivers/xen/efi.c +index 1f850c9..f745db2 100644 +--- a/drivers/xen/efi.c ++++ b/drivers/xen/efi.c +@@ -294,6 +294,7 @@ static const struct efi efi_xen __initconst = { + .acpi = EFI_INVALID_TABLE_ADDR, + .acpi20 = EFI_INVALID_TABLE_ADDR, + .smbios = EFI_INVALID_TABLE_ADDR, ++ .smbios3 = EFI_INVALID_TABLE_ADDR, + .sal_systab = EFI_INVALID_TABLE_ADDR, + .boot_info = EFI_INVALID_TABLE_ADDR, + .hcdp = EFI_INVALID_TABLE_ADDR, diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h -index 57ee052..a1ef42f 100644 +index f34a083..04d02fc 100644 --- a/include/acpi/acpi_bus.h +++ b/include/acpi/acpi_bus.h -@@ -68,6 +68,8 @@ bool acpi_check_dsm(acpi_handle handle, const u8 *uuid, int rev, u64 funcs); +@@ -27,6 +27,7 @@ + #define __ACPI_BUS_H__ + + #include ++#include + + /* TBD: Make dynamic */ + #define ACPI_MAX_HANDLES 10 +@@ -68,6 +69,8 @@ bool acpi_check_dsm(acpi_handle handle, const u8 *uuid, int rev, u64 funcs); union acpi_object *acpi_evaluate_dsm(acpi_handle handle, const u8 *uuid, int rev, int func, union acpi_object *argv4); @@ -9167,7 +12034,7 @@ index 57ee052..a1ef42f 100644 static inline union acpi_object * acpi_evaluate_dsm_typed(acpi_handle handle, const u8 *uuid, int rev, int func, union acpi_object *argv4, acpi_object_type type) -@@ -337,6 +339,13 @@ struct acpi_device_physical_node { +@@ -337,10 +340,20 @@ struct acpi_device_physical_node { bool put_online:1; }; @@ -9177,11 +12044,18 @@ index 57ee052..a1ef42f 100644 + const union acpi_object *properties; + const union acpi_object *of_compatible; +}; ++ ++struct acpi_gpio_mapping; + /* Device */ struct acpi_device { int device_type; -@@ -353,6 +362,7 @@ struct acpi_device { + acpi_handle handle; /* no handle for fixed hardware */ ++ struct fwnode_handle fwnode; + struct acpi_device *parent; + struct list_head children; + struct list_head node; +@@ -353,9 +366,11 @@ struct acpi_device { struct acpi_device_wakeup wakeup; struct acpi_device_perf performance; struct acpi_device_dir dir; @@ -9189,6 +12063,32 @@ index 57ee052..a1ef42f 100644 struct acpi_scan_handler *handler; struct acpi_hotplug_context *hp; struct acpi_driver *driver; ++ const struct acpi_gpio_mapping *driver_gpios; + void *driver_data; + struct device dev; + unsigned int physical_node_count; +@@ -364,6 +379,21 @@ struct acpi_device { + void (*remove)(struct acpi_device *); + }; + ++static inline bool is_acpi_node(struct fwnode_handle *fwnode) ++{ ++ return fwnode && fwnode->type == FWNODE_ACPI; ++} ++ ++static inline struct acpi_device *acpi_node(struct fwnode_handle *fwnode) ++{ ++ return fwnode ? container_of(fwnode, struct acpi_device, fwnode) : NULL; ++} ++ ++static inline struct fwnode_handle *acpi_fwnode_handle(struct acpi_device *adev) ++{ ++ return &adev->fwnode; ++} ++ + static inline void *acpi_driver_data(struct acpi_device *d) + { + return d->driver_data; diff --git a/include/acpi/acpi_io.h b/include/acpi/acpi_io.h index 444671e..9d573db 100644 --- a/include/acpi/acpi_io.h @@ -9211,6 +12111,24 @@ index 444671e..9d573db 100644 return ioremap_cache(phys, size); } +diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h +index aa70cbd..1261fef 100644 +--- a/include/asm-generic/vmlinux.lds.h ++++ b/include/asm-generic/vmlinux.lds.h +@@ -275,6 +275,13 @@ + VMLINUX_SYMBOL(__end_pci_fixups_suspend_late) = .; \ + } \ + \ ++ /* ACPI 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/kvm/arm_vgic.h b/include/kvm/arm_vgic.h index 206dcc3..660dbfc 100644 --- a/include/kvm/arm_vgic.h @@ -9245,7 +12163,7 @@ index 206dcc3..660dbfc 100644 return -ENODEV; } diff --git a/include/linux/acpi.h b/include/linux/acpi.h -index b7926bb..6c22abf 100644 +index 407a12f..de81de3 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h @@ -28,6 +28,7 @@ @@ -9290,10 +12208,64 @@ index b7926bb..6c22abf 100644 int acpi_device_uevent_modalias(struct device *, struct kobj_uevent_env *); int acpi_device_modalias(struct device *, char *, int); -@@ -658,4 +660,85 @@ do { \ +@@ -443,6 +445,23 @@ struct platform_device *acpi_create_platform_device(struct acpi_device *); + #define ACPI_COMPANION_SET(dev, adev) do { } while (0) + #define ACPI_HANDLE(dev) (NULL) + ++struct fwnode_handle; ++ ++static inline bool is_acpi_node(struct fwnode_handle *fwnode) ++{ ++ return false; ++} ++ ++static inline struct acpi_device *acpi_node(struct fwnode_handle *fwnode) ++{ ++ return NULL; ++} ++ ++static inline struct fwnode_handle *acpi_fwnode_handle(struct acpi_device *adev) ++{ ++ return NULL; ++} ++ + static inline const char *acpi_dev_name(struct acpi_device *adev) + { + return NULL; +@@ -659,4 +678,114 @@ do { \ #endif #endif ++struct acpi_gpio_params { ++ unsigned int crs_entry_index; ++ unsigned int line_index; ++ bool active_low; ++}; ++ ++struct acpi_gpio_mapping { ++ const char *name; ++ const struct acpi_gpio_params *data; ++ unsigned int size; ++}; ++ ++#if defined(CONFIG_ACPI) && defined(CONFIG_GPIOLIB) ++int acpi_dev_add_driver_gpios(struct acpi_device *adev, ++ const struct acpi_gpio_mapping *gpios); ++ ++static inline void acpi_dev_remove_driver_gpios(struct acpi_device *adev) ++{ ++ if (adev) ++ adev->driver_gpios = NULL; ++} ++#else ++static inline int acpi_dev_add_driver_gpios(struct acpi_device *adev, ++ const struct acpi_gpio_mapping *gpios) ++{ ++ return -ENXIO; ++} ++static inline void acpi_dev_remove_driver_gpios(struct acpi_device *adev) {} ++#endif ++ +/* Device properties */ + +#define MAX_ACPI_REFERENCE_ARGS 8 @@ -9309,20 +12281,19 @@ index b7926bb..6c22abf 100644 +int acpi_dev_get_property_array(struct acpi_device *adev, const char *name, + acpi_object_type type, + const union acpi_object **obj); -+int acpi_dev_get_property_reference(struct acpi_device *adev, const char *name, -+ const char *cells_name, size_t index, ++int acpi_dev_get_property_reference(struct acpi_device *adev, ++ const char *name, size_t index, + struct acpi_reference_args *args); + +int acpi_dev_prop_get(struct acpi_device *adev, const char *propname, + void **valptr); ++int acpi_dev_prop_read_single(struct acpi_device *adev, const char *propname, ++ enum dev_prop_type proptype, void *val); +int acpi_dev_prop_read(struct acpi_device *adev, const char *propname, -+ enum dev_prop_type proptype, void *val); -+int acpi_dev_prop_read_array(struct acpi_device *adev, const char *propname, -+ enum dev_prop_type proptype, void *val, -+ size_t nval); -+int acpi_for_each_child_node(struct device *dev, -+ int (*fn)(struct device *dev, void *child, void *data), -+ void *data); ++ enum dev_prop_type proptype, void *val, size_t nval); ++ ++struct acpi_device *acpi_get_next_child(struct device *dev, ++ struct acpi_device *child); +#else +static inline int acpi_dev_get_property(struct acpi_device *adev, + const char *name, acpi_object_type type, @@ -9351,33 +12322,33 @@ index b7926bb..6c22abf 100644 + return -ENXIO; +} + -+static inline int acpi_dev_prop_read(struct acpi_device *adev, -+ const char *propname, -+ enum dev_prop_type proptype, void *val) ++static inline int acpi_dev_prop_read_single(struct acpi_device *adev, ++ const char *propname, ++ enum dev_prop_type proptype, ++ void *val) +{ + return -ENXIO; +} + -+static inline int acpi_dev_prop_read_array(struct acpi_device *adev, -+ const char *propname, -+ enum dev_prop_type proptype, -+ void *val, size_t nval) ++static inline int acpi_dev_prop_read(struct acpi_device *adev, ++ const char *propname, ++ enum dev_prop_type proptype, ++ void *val, size_t nval) +{ + return -ENXIO; +} + -+static inline int acpi_for_each_child_node(struct device *dev, -+ int (*fn)(struct device *dev, void *child, void *data), -+ void *data) ++static inline struct acpi_device *acpi_get_next_child(struct device *dev, ++ struct acpi_device *child) +{ -+ return -ENXIO; ++ return NULL; +} + +#endif + #endif /*_LINUX_ACPI_H*/ diff --git a/include/linux/clocksource.h b/include/linux/clocksource.h -index 653f0e2..5839f98 100644 +index abcafaa..4f5caa1 100644 --- a/include/linux/clocksource.h +++ b/include/linux/clocksource.h @@ -346,4 +346,10 @@ extern void clocksource_of_init(void); @@ -9391,19 +12362,45 @@ index 653f0e2..5839f98 100644 +#endif + #endif /* _LINUX_CLOCKSOURCE_H */ +diff --git a/include/linux/efi.h b/include/linux/efi.h +index 0949f9c..0238d61 100644 +--- a/include/linux/efi.h ++++ b/include/linux/efi.h +@@ -547,6 +547,9 @@ void efi_native_runtime_setup(void); + #define SMBIOS_TABLE_GUID \ + EFI_GUID( 0xeb9d2d31, 0x2d88, 0x11d3, 0x9a, 0x16, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d ) + ++#define SMBIOS3_TABLE_GUID \ ++ EFI_GUID( 0xf2fd1544, 0x9794, 0x4a2c, 0x99, 0x2e, 0xe5, 0xbb, 0xcf, 0x20, 0xe3, 0x94 ) ++ + #define SAL_SYSTEM_TABLE_GUID \ + EFI_GUID( 0xeb9d2d32, 0x2d88, 0x11d3, 0x9a, 0x16, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d ) + +@@ -810,7 +813,8 @@ extern struct efi { + unsigned long mps; /* MPS table */ + unsigned long acpi; /* ACPI table (IA64 ext 0.71) */ + unsigned long acpi20; /* ACPI table (ACPI 2.0) */ +- unsigned long smbios; /* SM BIOS table */ ++ unsigned long smbios; /* SMBIOS table (32 bit entry point) */ ++ unsigned long smbios3; /* SMBIOS table (64 bit entry point) */ + unsigned long sal_systab; /* SAL system table */ + unsigned long boot_info; /* boot info table */ + unsigned long hcdp; /* HCDP table */ diff --git a/include/linux/gpio/consumer.h b/include/linux/gpio/consumer.h -index 12f146f..033d2fd 100644 +index 12f146f..00b1b70 100644 --- a/include/linux/gpio/consumer.h +++ b/include/linux/gpio/consumer.h -@@ -94,6 +94,11 @@ int gpiod_to_irq(const struct gpio_desc *desc); +@@ -94,6 +94,13 @@ int gpiod_to_irq(const struct gpio_desc *desc); struct gpio_desc *gpio_to_desc(unsigned gpio); int desc_to_gpio(const struct gpio_desc *desc); +/* Child properties interface */ -+struct gpio_desc *dev_get_named_gpiod_from_child(struct device *dev, void *child, -+ const char *propname, int index); -+struct gpio_desc *devm_get_named_gpiod_from_child(struct device *dev, void *child, -+ const char *propname, int index); ++struct fwnode_handle; ++ ++struct gpio_desc *fwnode_get_named_gpiod(struct fwnode_handle *fwnode, ++ const char *propname); ++struct gpio_desc *devm_get_gpiod_from_child(struct device *dev, ++ struct fwnode_handle *child); #else /* CONFIG_GPIOLIB */ static inline struct gpio_desc *__must_check __gpiod_get(struct device *dev, @@ -9486,19 +12483,28 @@ index 13eed92..dc9cb5f 100644 #define GICH_VTR 0x4 #define GICH_VMCR 0x8 diff --git a/include/linux/leds.h b/include/linux/leds.h -index e436864..879a113 100644 +index a57611d..361101f 100644 --- a/include/linux/leds.h +++ b/include/linux/leds.h -@@ -246,6 +246,7 @@ struct led_platform_data { - struct gpio_led { - const char *name; - const char *default_trigger; -+ struct gpio_desc *gpiod; - unsigned gpio; - unsigned active_low : 1; +@@ -261,6 +261,7 @@ struct gpio_led { unsigned retain_state_suspended : 1; + unsigned default_state : 2; + /* default_state should be one of LEDS_GPIO_DEFSTATE_(ON|OFF|KEEP) */ ++ struct gpio_desc *gpiod; + }; + #define LEDS_GPIO_DEFSTATE_OFF 0 + #define LEDS_GPIO_DEFSTATE_ON 1 +@@ -273,7 +274,7 @@ struct gpio_led_platform_data { + #define GPIO_LED_NO_BLINK_LOW 0 /* No blink GPIO state low */ + #define GPIO_LED_NO_BLINK_HIGH 1 /* No blink GPIO state high */ + #define GPIO_LED_BLINK 2 /* Please, blink */ +- int (*gpio_blink_set)(unsigned gpio, int state, ++ int (*gpio_blink_set)(struct gpio_desc *desc, int state, + unsigned long *delay_on, + unsigned long *delay_off); + }; diff --git a/include/linux/of.h b/include/linux/of.h -index 6545e7a..9962b70 100644 +index 29f0adc..cf79be1 100644 --- a/include/linux/of.h +++ b/include/linux/of.h @@ -23,6 +23,7 @@ @@ -9509,56 +12515,81 @@ index 6545e7a..9962b70 100644 #include #include -@@ -355,6 +356,15 @@ const char *of_prop_next_string(struct property *prop, const char *cur); +@@ -49,6 +50,7 @@ struct device_node { + const char *type; + phandle phandle; + const char *full_name; ++ struct fwnode_handle fwnode; + + struct property *properties; + struct property *deadprops; /* removed properties */ +@@ -79,6 +81,7 @@ extern struct kobj_type of_node_ktype; + static inline void of_node_init(struct device_node *node) + { + kobject_init(&node->kobj, &of_node_ktype); ++ node->fwnode.type = FWNODE_OF; + } - bool of_console_check(struct device_node *dn, char *name, int index); + /* true when node is initialized */ +@@ -114,6 +117,16 @@ extern struct device_node *of_aliases; + extern struct device_node *of_stdout; + extern raw_spinlock_t devtree_lock; -+int of_dev_prop_get(struct device_node *dn, const char *propname, void **valptr); -+int of_dev_prop_read(struct device_node *dn, const char *propname, -+ enum dev_prop_type proptype, void *val); -+int of_dev_prop_read_array(struct device_node *dn, const char *propname, -+ enum dev_prop_type proptype, void *val, size_t nval); -+int of_for_each_child_node(struct device *dev, -+ int (*fn)(struct device *dev, void *child, void *data), -+ void *data); ++static inline bool is_of_node(struct fwnode_handle *fwnode) ++{ ++ return fwnode && fwnode->type == FWNODE_OF; ++} + - #else /* CONFIG_OF */ - - static inline const char* of_node_full_name(const struct device_node *np) -@@ -582,6 +592,33 @@ static inline const char *of_prop_next_string(struct property *prop, - return NULL; - } - -+static inline int of_dev_prop_get(struct device_node *dn, const char *propname, -+ void **valptr) ++static inline struct device_node *of_node(struct fwnode_handle *fwnode) +{ -+ return -ENXIO; ++ return fwnode ? container_of(fwnode, struct device_node, fwnode) : NULL; +} + -+static inline int of_dev_prop_read(struct device_node *dn, const char *propname, -+ enum dev_prop_type proptype, void *val) + static inline bool of_have_populated_dt(void) + { + return of_allnodes != NULL; +@@ -263,6 +276,10 @@ extern int of_property_read_u32_array(const struct device_node *np, + size_t sz); + extern int of_property_read_u64(const struct device_node *np, + const char *propname, u64 *out_value); ++extern int of_property_read_u64_array(const struct device_node *np, ++ const char *propname, ++ u64 *out_values, ++ size_t sz); + + extern int of_property_read_string(struct device_node *np, + const char *propname, +@@ -355,6 +372,16 @@ bool of_console_check(struct device_node *dn, char *name, int index); + + #else /* CONFIG_OF */ + ++static inline bool is_of_node(struct fwnode_handle *fwnode) +{ -+ return -ENXIO; ++ return false; +} + -+static inline int of_dev_prop_read_array(struct device_node *dn, -+ const char *propname, -+ enum dev_prop_type proptype, -+ void *val, size_t nval) ++static inline struct device_node *of_node(struct fwnode_handle *fwnode) +{ -+ return -ENXIO; ++ return NULL; +} + -+static inline int of_for_each_child_node(struct device *dev, -+ int (*fn)(struct device *dev, void *child, void *data), -+ void *data) + static inline const char* of_node_full_name(const struct device_node *np) + { + return ""; +@@ -477,6 +504,13 @@ static inline int of_property_read_u32_array(const struct device_node *np, + return -ENOSYS; + } + ++static inline int of_property_read_u64_array(const struct device_node *np, ++ const char *propname, ++ u64 *out_values, size_t sz) +{ -+ return -ENXIO; ++ return -ENOSYS; +} + - #define of_match_ptr(_ptr) NULL - #define of_match_node(_matches, _node) NULL - #endif /* CONFIG_OF */ + static inline int of_property_read_string(struct device_node *np, + const char *propname, + const char **out_string) diff --git a/include/linux/pci.h b/include/linux/pci.h index 5be8db4..6afba72 100644 --- a/include/linux/pci.h @@ -9630,10 +12661,10 @@ index 5be8db4..6afba72 100644 extern struct dev_pm_ops pcibios_pm_ops; diff --git a/include/linux/property.h b/include/linux/property.h new file mode 100644 -index 0000000..1a42878 +index 0000000..a6a3d98 --- /dev/null +++ b/include/linux/property.h -@@ -0,0 +1,207 @@ +@@ -0,0 +1,143 @@ +/* + * property.h - Unified device property interface. + * @@ -9649,7 +12680,9 @@ index 0000000..1a42878 +#ifndef _LINUX_PROPERTY_H_ +#define _LINUX_PROPERTY_H_ + -+#include ++#include ++ ++struct device; + +enum dev_prop_type { + DEV_PROP_U8, @@ -9660,187 +12693,190 @@ index 0000000..1a42878 + DEV_PROP_MAX, +}; + -+int device_get_property(struct device *dev, const char *propname, -+ void **valptr); -+int device_read_property(struct device *dev, const char *propname, -+ enum dev_prop_type proptype, void *val); -+int device_read_property_array(struct device *dev, const char *propname, -+ enum dev_prop_type proptype, void *val, -+ size_t nval); -+int device_get_child_property(struct device *dev, void *child, -+ const char *propname, void **valptr); -+int device_read_child_property(struct device *dev, void *child, -+ const char *propname, -+ enum dev_prop_type proptype, void *val); -+int device_read_child_property_array(struct device *dev, void *child, -+ const char *propname, -+ enum dev_prop_type proptype, void *val, -+ size_t nval); -+int device_for_each_child_node(struct device *dev, -+ int (*fn)(struct device *dev, void *child, void *data), -+ void *data); -+unsigned int device_get_child_node_count(struct device *dev); -+ -+static inline int device_property_read_u8(struct device *dev, -+ const char *propname, u8 *out_value) -+{ -+ return device_read_property(dev, propname, DEV_PROP_U8, out_value); -+} -+ -+static inline int device_property_read_u16(struct device *dev, -+ const char *propname, u16 *out_value) -+{ -+ return device_read_property(dev, propname, DEV_PROP_U16, out_value); -+} -+ -+static inline int device_property_read_u32(struct device *dev, -+ const char *propname, u32 *out_value) -+{ -+ return device_read_property(dev, propname, DEV_PROP_U32, out_value); -+} ++bool device_property_present(struct device *dev, const char *propname); ++int device_property_read_u8_array(struct device *dev, const char *propname, ++ u8 *val, size_t nval); ++int device_property_read_u16_array(struct device *dev, const char *propname, ++ u16 *val, size_t nval); ++int device_property_read_u32_array(struct device *dev, const char *propname, ++ u32 *val, size_t nval); ++int device_property_read_u64_array(struct device *dev, const char *propname, ++ u64 *val, size_t nval); ++int device_property_read_string_array(struct device *dev, const char *propname, ++ const char **val, size_t nval); ++int device_property_read_string(struct device *dev, const char *propname, ++ const char **val); ++ ++enum fwnode_type { ++ FWNODE_INVALID = 0, ++ FWNODE_OF, ++ FWNODE_ACPI, ++}; + -+static inline int device_property_read_u64(struct device *dev, -+ const char *propname, u64 *out_value) -+{ -+ return device_read_property(dev, propname, DEV_PROP_U64, out_value); -+} ++struct fwnode_handle { ++ enum fwnode_type type; ++}; + -+static inline int device_property_read_u8_array(struct device *dev, -+ const char *propname, -+ u8 *val, size_t nval) -+{ -+ return device_read_property_array(dev, propname, DEV_PROP_U8, val, -+ nval); -+} ++bool fwnode_property_present(struct fwnode_handle *fwnode, const char *propname); ++int fwnode_property_read_u8_array(struct fwnode_handle *fwnode, ++ const char *propname, u8 *val, ++ size_t nval); ++int fwnode_property_read_u16_array(struct fwnode_handle *fwnode, ++ const char *propname, u16 *val, ++ size_t nval); ++int fwnode_property_read_u32_array(struct fwnode_handle *fwnode, ++ const char *propname, u32 *val, ++ size_t nval); ++int fwnode_property_read_u64_array(struct fwnode_handle *fwnode, ++ const char *propname, u64 *val, ++ size_t nval); ++int fwnode_property_read_string_array(struct fwnode_handle *fwnode, ++ const char *propname, const char **val, ++ size_t nval); ++int fwnode_property_read_string(struct fwnode_handle *fwnode, ++ const char *propname, const char **val); ++ ++struct fwnode_handle *device_get_next_child_node(struct device *dev, ++ struct fwnode_handle *child); ++ ++#define device_for_each_child_node(dev, child) \ ++ for (child = device_get_next_child_node(dev, NULL); child; \ ++ child = device_get_next_child_node(dev, child)) ++ ++void fwnode_handle_put(struct fwnode_handle *fwnode); + -+static inline int device_property_read_u16_array(struct device *dev, -+ const char *propname, -+ u16 *val, size_t nval) -+{ -+ return device_read_property_array(dev, propname, DEV_PROP_U16, val, -+ nval); -+} ++unsigned int device_get_child_node_count(struct device *dev); + -+static inline int device_property_read_u32_array(struct device *dev, -+ const char *propname, -+ u32 *val, size_t nval) ++static inline bool device_property_read_bool(struct device *dev, ++ const char *propname) +{ -+ return device_read_property_array(dev, propname, DEV_PROP_U32, val, -+ nval); ++ return device_property_present(dev, propname); +} + -+static inline int device_property_read_u64_array(struct device *dev, -+ const char *propname, -+ u64 *val, size_t nval) ++static inline int device_property_read_u8(struct device *dev, ++ const char *propname, u8 *val) +{ -+ return device_read_property_array(dev, propname, DEV_PROP_U64, val, -+ nval); ++ return device_property_read_u8_array(dev, propname, val, 1); +} + -+static inline int device_property_read_string(struct device *dev, -+ const char *propname, -+ const char **out_string) ++static inline int device_property_read_u16(struct device *dev, ++ const char *propname, u16 *val) +{ -+ return device_read_property(dev, propname, DEV_PROP_STRING, out_string); ++ return device_property_read_u16_array(dev, propname, val, 1); +} + -+static inline int device_property_read_string_array(struct device *dev, -+ const char *propname, -+ const char **out_strings, -+ size_t nstrings) ++static inline int device_property_read_u32(struct device *dev, ++ const char *propname, u32 *val) +{ -+ return device_read_property_array(dev, propname, DEV_PROP_STRING, -+ out_strings, nstrings); ++ return device_property_read_u32_array(dev, propname, val, 1); +} + -+static inline int device_child_property_read_u8(struct device *dev, void *child, -+ const char *propname, -+ u8 *out_value) ++static inline int device_property_read_u64(struct device *dev, ++ const char *propname, u64 *val) +{ -+ return device_read_child_property(dev, child, propname, DEV_PROP_U8, -+ out_value); ++ return device_property_read_u64_array(dev, propname, val, 1); +} + -+static inline int device_child_property_read_u16(struct device *dev, void *child, -+ const char *propname, -+ u16 *out_value) ++static inline bool fwnode_property_read_bool(struct fwnode_handle *fwnode, ++ const char *propname) +{ -+ return device_read_child_property(dev, child, propname, DEV_PROP_U16, -+ out_value); ++ return fwnode_property_present(fwnode, propname); +} + -+static inline int device_child_property_read_u32(struct device *dev, void *child, -+ const char *propname, -+ u32 *out_value) ++static inline int fwnode_property_read_u8(struct fwnode_handle *fwnode, ++ const char *propname, u8 *val) +{ -+ return device_read_child_property(dev, child, propname, DEV_PROP_U32, -+ out_value); ++ return fwnode_property_read_u8_array(fwnode, propname, val, 1); +} + -+static inline int device_child_property_read_u64(struct device *dev, void *child, -+ const char *propname, -+ u64 *out_value) ++static inline int fwnode_property_read_u16(struct fwnode_handle *fwnode, ++ const char *propname, u16 *val) +{ -+ return device_read_child_property(dev, child, propname, DEV_PROP_U64, -+ out_value); ++ return fwnode_property_read_u16_array(fwnode, propname, val, 1); +} + -+static inline int device_child_property_read_u8_array(struct device *dev, -+ void *child, -+ const char *propname, -+ u8 *val, size_t nval) ++static inline int fwnode_property_read_u32(struct fwnode_handle *fwnode, ++ const char *propname, u32 *val) +{ -+ return device_read_child_property_array(dev, child, propname, -+ DEV_PROP_U8, val, nval); ++ return fwnode_property_read_u32_array(fwnode, propname, val, 1); +} + -+static inline int device_child_property_read_u16_array(struct device *dev, -+ void *child, -+ const char *propname, -+ u16 *val, size_t nval) ++static inline int fwnode_property_read_u64(struct fwnode_handle *fwnode, ++ const char *propname, u64 *val) +{ -+ return device_read_child_property_array(dev, child, propname, -+ DEV_PROP_U16, val, nval); ++ return fwnode_property_read_u64_array(fwnode, propname, val, 1); +} + -+static inline int device_child_property_read_u32_array(struct device *dev, -+ void *child, -+ const char *propname, -+ u32 *val, size_t nval) -+{ -+ return device_read_child_property_array(dev, child, propname, -+ DEV_PROP_U32, val, nval); -+} ++#endif /* _LINUX_PROPERTY_H_ */ +diff --git a/net/bridge/netfilter/nft_reject_bridge.c b/net/bridge/netfilter/nft_reject_bridge.c +index 654c901..48da2c5 100644 +--- a/net/bridge/netfilter/nft_reject_bridge.c ++++ b/net/bridge/netfilter/nft_reject_bridge.c +@@ -18,6 +18,7 @@ + #include + #include + #include ++#include + #include + #include "../br_private.h" + +diff --git a/net/rfkill/rfkill-gpio.c b/net/rfkill/rfkill-gpio.c +index 0f62326..2a47179 100644 +--- a/net/rfkill/rfkill-gpio.c ++++ b/net/rfkill/rfkill-gpio.c +@@ -63,6 +63,15 @@ static const struct rfkill_ops rfkill_gpio_ops = { + .set_block = rfkill_gpio_set_power, + }; + ++static const struct acpi_gpio_params reset_gpios = { 0, 0, false }; ++static const struct acpi_gpio_params shutdown_gpios = { 1, 0, false }; + -+static inline int device_child_property_read_u64_array(struct device *dev, -+ void *child, -+ const char *propname, -+ u64 *val, size_t nval) -+{ -+ return device_read_child_property_array(dev, child, propname, -+ DEV_PROP_U64, val, nval); -+} ++static const struct acpi_gpio_mapping acpi_rfkill_default_gpios[] = { ++ { "reset-gpios", &reset_gpios, 1 }, ++ { "shutdown-gpios", &shutdown_gpios, 1 }, ++ { }, ++}; + -+static inline int device_child_property_read_string(struct device *dev, -+ void *child, -+ const char *propname, -+ const char **out_string) -+{ -+ return device_read_child_property(dev, child, propname, DEV_PROP_STRING, -+ out_string); -+} + static int rfkill_gpio_acpi_probe(struct device *dev, + struct rfkill_gpio_data *rfkill) + { +@@ -75,7 +84,8 @@ static int rfkill_gpio_acpi_probe(struct device *dev, + rfkill->name = dev_name(dev); + rfkill->type = (unsigned)id->driver_data; + +- return 0; ++ return acpi_dev_add_driver_gpios(ACPI_COMPANION(dev), ++ acpi_rfkill_default_gpios); + } + + static int rfkill_gpio_probe(struct platform_device *pdev) +@@ -102,7 +112,7 @@ static int rfkill_gpio_probe(struct platform_device *pdev) + + rfkill->clk = devm_clk_get(&pdev->dev, NULL); + +- gpio = devm_gpiod_get_index(&pdev->dev, "reset", 0); ++ gpio = devm_gpiod_get(&pdev->dev, "reset"); + if (!IS_ERR(gpio)) { + ret = gpiod_direction_output(gpio, 0); + if (ret) +@@ -110,7 +120,7 @@ static int rfkill_gpio_probe(struct platform_device *pdev) + rfkill->reset_gpio = gpio; + } + +- gpio = devm_gpiod_get_index(&pdev->dev, "shutdown", 1); ++ gpio = devm_gpiod_get(&pdev->dev, "shutdown"); + if (!IS_ERR(gpio)) { + ret = gpiod_direction_output(gpio, 0); + if (ret) +@@ -150,6 +160,8 @@ static int rfkill_gpio_remove(struct platform_device *pdev) + rfkill_unregister(rfkill->rfkill_dev); + rfkill_destroy(rfkill->rfkill_dev); + ++ acpi_dev_remove_driver_gpios(ACPI_COMPANION(&pdev->dev)); + -+static inline int device_child_property_read_string_array(struct device *dev, -+ void *child, -+ const char *propname, -+ const char **out_strings, -+ size_t nstrings) -+{ -+ return device_read_child_property_array(dev, child, propname, -+ DEV_PROP_STRING, -+ out_strings, nstrings); -+} -+#endif /* _LINUX_PROPERTY_H_ */ + return 0; + } + diff --git a/virt/kvm/arm/arch_timer.c b/virt/kvm/arm/arch_timer.c index 22fa819..9cd5dbd 100644 --- a/virt/kvm/arm/arch_timer.c diff --git a/kernel.spec b/kernel.spec index 2cc619949..83f1b4c7d 100644 --- a/kernel.spec +++ b/kernel.spec @@ -8,7 +8,7 @@ Summary: The Linux kernel # be 0. %global released_kernel 0 -%global aarch64patches 0 +%global aarch64patches 1 # Sign modules on x86. Make sure the config files match this setting if more # architectures are added. @@ -42,7 +42,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 1 +%global baserelease 2 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -2215,6 +2215,9 @@ fi # ||----w | # || || %changelog +* Tue Nov 11 2014 Kyle McMartin - 3.18.0-0.rc4.git0.2 +- Re-enable kernel-arm64.patch, and fix up merge conflicts with 3.18-rc4 + * Mon Nov 10 2014 Josh Boyer - Fix Samsung pci-e SSD handling on some macbooks (rhbz 1161805) -- cgit