summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPeter Robinson <pbrobinson@gmail.com>2017-07-12 10:22:44 +0100
committerPeter Robinson <pbrobinson@gmail.com>2017-07-12 10:22:44 +0100
commit87fc2a45ad81705dc8559e93d608720c963f334c (patch)
treea23cfd78e8d10a59b35daea33bf9bccf2e01c920
parent272a38dcb88cb85ea5d34fdd5134f38da10cc7ad (diff)
downloadkernel-87fc2a45ad81705dc8559e93d608720c963f334c.tar.gz
kernel-87fc2a45ad81705dc8559e93d608720c963f334c.tar.xz
kernel-87fc2a45ad81705dc8559e93d608720c963f334c.zip
add missing patches from the 4.12 GA commit
-rw-r--r--0001-platform-x86-Add-driver-for-ACPI-INT0002-Virtual-GPI.patch339
-rw-r--r--0002-mfd-Add-Cherry-Trail-Whiskey-Cove-PMIC-driver.patch355
-rw-r--r--0003-power-supply-core-Add-support-for-supplied-from-devi.patch57
-rw-r--r--0004-platform-x86-intel_cht_int33fe-Set-supplied-from-pro.patch48
-rw-r--r--0005-ACPI-PMIC-xpower-Add-support-for-the-GPI1-regulator-.patch80
-rw-r--r--0006-Input-axp20x-pek-Add-wakeup-support.patch67
-rw-r--r--0007-platform-x86-silead_dmi-Add-touchscreen-info-for-GP-.patch56
-rw-r--r--0008-platform-x86-silead_dmi-Add-touchscreen-info-for-PoV.patch59
-rw-r--r--0009-platform-x86-silead_dmi-Add-touchscreen-info-for-Pip.patch57
-rw-r--r--0010-Input-silead-Add-support-for-capactive-home-button-f.patch114
-rw-r--r--0011-Input-goodix-Add-support-for-capacitive-home-button.patch53
-rw-r--r--0012-Input-gpio_keys-Do-not-report-wake-button-presses-as.patch150
-rw-r--r--0013-iio-accel-bmc150-Add-support-for-BOSC0200-ACPI-devic.patch32
-rw-r--r--0014-mmc-sdhci-acpi-Workaround-conflict-with-PCI-wifi-on-.patch143
-rw-r--r--0015-i2c-cht-wc-Add-Intel-Cherry-Trail-Whiskey-Cove-SMBUS.patch410
-rw-r--r--0016-Input-silead-Do-not-try-to-directly-access-the-GPIO-.patch54
-rw-r--r--KEYS-Allow-unrestricted-boot-time-addition-of-keys-t.patch95
-rw-r--r--RFC-audit-fix-a-race-condition-with-the-auditd-tracking-code.patch156
-rw-r--r--arm-dts-boneblack-wireless-add-WL1835-Bluetooth-device-node.patch40
-rw-r--r--bcm2835-clk-audio-jitter-issues.patch206
-rw-r--r--bcm2835-fix-potential-null-pointer-dereferences.patch70
-rw-r--r--bcm283x-vc4-fix-vblank.patch123
-rw-r--r--qcom-msm89xx-fixes.patch285
23 files changed, 3049 insertions, 0 deletions
diff --git a/0001-platform-x86-Add-driver-for-ACPI-INT0002-Virtual-GPI.patch b/0001-platform-x86-Add-driver-for-ACPI-INT0002-Virtual-GPI.patch
new file mode 100644
index 000000000..a0b6ff03e
--- /dev/null
+++ b/0001-platform-x86-Add-driver-for-ACPI-INT0002-Virtual-GPI.patch
@@ -0,0 +1,339 @@
+From 3bbfe49a1d965b951527cde0da48f5d7677db264 Mon Sep 17 00:00:00 2001
+From: Hans de Goede <hdegoede@redhat.com>
+Date: Sun, 21 May 2017 13:15:11 +0200
+Subject: [PATCH 01/16] platform/x86: Add driver for ACPI INT0002 Virtual GPIO
+ device
+
+Some peripherals on Bay Trail and Cherry Trail platforms signal a
+Power Management Event (PME) to the Power Management Controller (PMC)
+to wakeup the system. When this happens software needs to explicitly
+clear the PME bus 0 status bit in the GPE0a_STS register to avoid an
+IRQ storm on IRQ 9.
+
+This is modelled in ACPI through the INT0002 ACPI device, which is
+called a "Virtual GPIO controller" in ACPI because it defines the
+event handler to call when the PME triggers through _AEI and _L02
+methods as would be done for a real GPIO interrupt in ACPI.
+
+This commit adds a driver which registers the Virtual GPIOs expected
+by the DSDT on these devices, letting gpiolib-acpi claim the
+virtual GPIO and install a GPIO-interrupt handler which call the _L02
+handler as it would for a real GPIO controller.
+
+Cc: joeyli <jlee@suse.com>
+Cc: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+Acked-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
+---
+Changes in v2:
+-Remove dev_err after malloc failure
+-Remove unused empty runtime pm callbacks
+-s/GPE0A_PME_/GPE0A_PME_B0_/
+-Fixed some checkpatch warnings (I forgot to run checkpatch on v1)
+
+Changes in v3:
+-Rewrite as gpiochip driver letting gpiolib-acpi deal with claiming the pin
+ 0x0002 and calling the _L02 event handler when the virtual gpio-irq triggers
+-Rebase on 4.12-rc1
+
+Changes in v4:
+-Drop device_init_wakeup() from _probe(), use pm_system_wakeup() instead
+ of pm_wakeup_hard_event(chip->parent)
+-Improve commit message
+
+Changes in v5:
+-Use BIT() macro for FOO_BIT defines
+-Drop unneeded ACPI_PTR macro usage
+
+Changes in v6:
+-Move back to drivers/platform/x86
+-Expand certain acronyms (PME, PMC)
+-Use linux/gpio/driver.h include instead of linux/gpio.h
+-Document why the get / set / direction_output functions are dummys
+-No functional changes
+
+Changes in v7:
+-Some minor cleanups from Andy:
+ -Move asm/ includes below linux/ includes
+ -s/APCI/ACPI/
+ -Use bitmap_clear on chip->irq_valid_mask
+-Add Linus Walleij's Reviewed-by
+---
+ drivers/platform/x86/Kconfig | 19 +++
+ drivers/platform/x86/Makefile | 1 +
+ drivers/platform/x86/intel_int0002_vgpio.c | 219 +++++++++++++++++++++++++++++
+ 3 files changed, 239 insertions(+)
+ create mode 100644 drivers/platform/x86/intel_int0002_vgpio.c
+
+diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig
+index 8489020ecf44..a3ccc3c795a5 100644
+--- a/drivers/platform/x86/Kconfig
++++ b/drivers/platform/x86/Kconfig
+@@ -794,6 +794,25 @@ config INTEL_CHT_INT33FE
+ This driver instantiates i2c-clients for these, so that standard
+ i2c drivers for these chips can bind to the them.
+
++config INTEL_INT0002_VGPIO
++ tristate "Intel ACPI INT0002 Virtual GPIO driver"
++ depends on GPIOLIB && ACPI
++ select GPIOLIB_IRQCHIP
++ ---help---
++ Some peripherals on Bay Trail and Cherry Trail platforms signal a
++ Power Management Event (PME) to the Power Management Controller (PMC)
++ to wakeup the system. When this happens software needs to explicitly
++ clear the PME bus 0 status bit in the GPE0a_STS register to avoid an
++ IRQ storm on IRQ 9.
++
++ This is modelled in ACPI through the INT0002 ACPI device, which is
++ called a "Virtual GPIO controller" in ACPI because it defines the
++ event handler to call when the PME triggers through _AEI and _L02
++ methods as would be done for a real GPIO interrupt in ACPI.
++
++ To compile this driver as a module, choose M here: the module will
++ be called intel_int0002_vgpio.
++
+ config INTEL_HID_EVENT
+ tristate "INTEL HID Event"
+ depends on ACPI
+diff --git a/drivers/platform/x86/Makefile b/drivers/platform/x86/Makefile
+index 182a3ed6605a..ab22ce77fb66 100644
+--- a/drivers/platform/x86/Makefile
++++ b/drivers/platform/x86/Makefile
+@@ -46,6 +46,7 @@ obj-$(CONFIG_TOSHIBA_BT_RFKILL) += toshiba_bluetooth.o
+ obj-$(CONFIG_TOSHIBA_HAPS) += toshiba_haps.o
+ obj-$(CONFIG_TOSHIBA_WMI) += toshiba-wmi.o
+ obj-$(CONFIG_INTEL_CHT_INT33FE) += intel_cht_int33fe.o
++obj-$(CONFIG_INTEL_INT0002_VGPIO) += intel_int0002_vgpio.o
+ obj-$(CONFIG_INTEL_HID_EVENT) += intel-hid.o
+ obj-$(CONFIG_INTEL_VBTN) += intel-vbtn.o
+ obj-$(CONFIG_INTEL_SCU_IPC) += intel_scu_ipc.o
+diff --git a/drivers/platform/x86/intel_int0002_vgpio.c b/drivers/platform/x86/intel_int0002_vgpio.c
+new file mode 100644
+index 000000000000..92dc230ef5b2
+--- /dev/null
++++ b/drivers/platform/x86/intel_int0002_vgpio.c
+@@ -0,0 +1,219 @@
++/*
++ * Intel INT0002 "Virtual GPIO" driver
++ *
++ * Copyright (C) 2017 Hans de Goede <hdegoede@redhat.com>
++ *
++ * Loosely based on android x86 kernel code which is:
++ *
++ * Copyright (c) 2014, Intel Corporation.
++ *
++ * Author: Dyut Kumar Sil <dyut.k.sil@intel.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * Some peripherals on Bay Trail and Cherry Trail platforms signal a Power
++ * Management Event (PME) to the Power Management Controller (PMC) to wakeup
++ * the system. When this happens software needs to clear the PME bus 0 status
++ * bit in the GPE0a_STS register to avoid an IRQ storm on IRQ 9.
++ *
++ * This is modelled in ACPI through the INT0002 ACPI device, which is
++ * called a "Virtual GPIO controller" in ACPI because it defines the event
++ * handler to call when the PME triggers through _AEI and _L02 / _E02
++ * methods as would be done for a real GPIO interrupt in ACPI. Note this
++ * is a hack to define an AML event handler for the PME while using existing
++ * ACPI mechanisms, this is not a real GPIO at all.
++ *
++ * This driver will bind to the INT0002 device, and register as a GPIO
++ * controller, letting gpiolib-acpi.c call the _L02 handler as it would
++ * for a real GPIO controller.
++ */
++
++#include <linux/acpi.h>
++#include <linux/bitmap.h>
++#include <linux/gpio/driver.h>
++#include <linux/interrupt.h>
++#include <linux/io.h>
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/platform_device.h>
++#include <linux/slab.h>
++#include <linux/suspend.h>
++
++#include <asm/cpu_device_id.h>
++#include <asm/intel-family.h>
++
++#define DRV_NAME "INT0002 Virtual GPIO"
++
++/* For some reason the virtual GPIO pin tied to the GPE is numbered pin 2 */
++#define GPE0A_PME_B0_VIRT_GPIO_PIN 2
++
++#define GPE0A_PME_B0_STS_BIT BIT(13)
++#define GPE0A_PME_B0_EN_BIT BIT(13)
++#define GPE0A_STS_PORT 0x420
++#define GPE0A_EN_PORT 0x428
++
++#define ICPU(model) { X86_VENDOR_INTEL, 6, model, X86_FEATURE_ANY, }
++
++static const struct x86_cpu_id int0002_cpu_ids[] = {
++/*
++ * Limit ourselves to Cherry Trail for now, until testing shows we
++ * need to handle the INT0002 device on Baytrail too.
++ * ICPU(INTEL_FAM6_ATOM_SILVERMONT1), * Valleyview, Bay Trail *
++ */
++ ICPU(INTEL_FAM6_ATOM_AIRMONT), /* Braswell, Cherry Trail */
++ {}
++};
++
++/*
++ * As this is not a real GPIO at all, but just a hack to model an event in
++ * ACPI the get / set functions are dummy functions.
++ */
++
++static int int0002_gpio_get(struct gpio_chip *chip, unsigned int offset)
++{
++ return 0;
++}
++
++static void int0002_gpio_set(struct gpio_chip *chip, unsigned int offset,
++ int value)
++{
++}
++
++static int int0002_gpio_direction_output(struct gpio_chip *chip,
++ unsigned int offset, int value)
++{
++ return 0;
++}
++
++static void int0002_irq_ack(struct irq_data *data)
++{
++ outl(GPE0A_PME_B0_STS_BIT, GPE0A_STS_PORT);
++}
++
++static void int0002_irq_unmask(struct irq_data *data)
++{
++ u32 gpe_en_reg;
++
++ gpe_en_reg = inl(GPE0A_EN_PORT);
++ gpe_en_reg |= GPE0A_PME_B0_EN_BIT;
++ outl(gpe_en_reg, GPE0A_EN_PORT);
++}
++
++static void int0002_irq_mask(struct irq_data *data)
++{
++ u32 gpe_en_reg;
++
++ gpe_en_reg = inl(GPE0A_EN_PORT);
++ gpe_en_reg &= ~GPE0A_PME_B0_EN_BIT;
++ outl(gpe_en_reg, GPE0A_EN_PORT);
++}
++
++static irqreturn_t int0002_irq(int irq, void *data)
++{
++ struct gpio_chip *chip = data;
++ u32 gpe_sts_reg;
++
++ gpe_sts_reg = inl(GPE0A_STS_PORT);
++ if (!(gpe_sts_reg & GPE0A_PME_B0_STS_BIT))
++ return IRQ_NONE;
++
++ generic_handle_irq(irq_find_mapping(chip->irqdomain,
++ GPE0A_PME_B0_VIRT_GPIO_PIN));
++
++ pm_system_wakeup();
++
++ return IRQ_HANDLED;
++}
++
++static struct irq_chip int0002_irqchip = {
++ .name = DRV_NAME,
++ .irq_ack = int0002_irq_ack,
++ .irq_mask = int0002_irq_mask,
++ .irq_unmask = int0002_irq_unmask,
++};
++
++static int int0002_probe(struct platform_device *pdev)
++{
++ struct device *dev = &pdev->dev;
++ const struct x86_cpu_id *cpu_id;
++ struct gpio_chip *chip;
++ int irq, ret;
++
++ /* Menlow has a different INT0002 device? <sigh> */
++ cpu_id = x86_match_cpu(int0002_cpu_ids);
++ if (!cpu_id)
++ return -ENODEV;
++
++ irq = platform_get_irq(pdev, 0);
++ if (irq < 0) {
++ dev_err(dev, "Error getting IRQ: %d\n", irq);
++ return irq;
++ }
++
++ chip = devm_kzalloc(dev, sizeof(*chip), GFP_KERNEL);
++ if (!chip)
++ return -ENOMEM;
++
++ chip->label = DRV_NAME;
++ chip->parent = dev;
++ chip->owner = THIS_MODULE;
++ chip->get = int0002_gpio_get;
++ chip->set = int0002_gpio_set;
++ chip->direction_input = int0002_gpio_get;
++ chip->direction_output = int0002_gpio_direction_output;
++ chip->base = -1;
++ chip->ngpio = GPE0A_PME_B0_VIRT_GPIO_PIN + 1;
++ chip->irq_need_valid_mask = true;
++
++ ret = devm_gpiochip_add_data(&pdev->dev, chip, NULL);
++ if (ret) {
++ dev_err(dev, "Error adding gpio chip: %d\n", ret);
++ return ret;
++ }
++
++ bitmap_clear(chip->irq_valid_mask, 0, GPE0A_PME_B0_VIRT_GPIO_PIN);
++
++ /*
++ * We manually request the irq here instead of passing a flow-handler
++ * to gpiochip_set_chained_irqchip, because the irq is shared.
++ */
++ ret = devm_request_irq(dev, irq, int0002_irq,
++ IRQF_SHARED | IRQF_NO_THREAD, "INT0002", chip);
++ if (ret) {
++ dev_err(dev, "Error requesting IRQ %d: %d\n", irq, ret);
++ return ret;
++ }
++
++ ret = gpiochip_irqchip_add(chip, &int0002_irqchip, 0, handle_edge_irq,
++ IRQ_TYPE_NONE);
++ if (ret) {
++ dev_err(dev, "Error adding irqchip: %d\n", ret);
++ return ret;
++ }
++
++ gpiochip_set_chained_irqchip(chip, &int0002_irqchip, irq, NULL);
++
++ return 0;
++}
++
++static const struct acpi_device_id int0002_acpi_ids[] = {
++ { "INT0002", 0 },
++ { },
++};
++MODULE_DEVICE_TABLE(acpi, int0002_acpi_ids);
++
++static struct platform_driver int0002_driver = {
++ .driver = {
++ .name = DRV_NAME,
++ .acpi_match_table = int0002_acpi_ids,
++ },
++ .probe = int0002_probe,
++};
++
++module_platform_driver(int0002_driver);
++
++MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>");
++MODULE_DESCRIPTION("Intel INT0002 Virtual GPIO driver");
++MODULE_LICENSE("GPL");
+--
+2.13.0
+
diff --git a/0002-mfd-Add-Cherry-Trail-Whiskey-Cove-PMIC-driver.patch b/0002-mfd-Add-Cherry-Trail-Whiskey-Cove-PMIC-driver.patch
new file mode 100644
index 000000000..49975811b
--- /dev/null
+++ b/0002-mfd-Add-Cherry-Trail-Whiskey-Cove-PMIC-driver.patch
@@ -0,0 +1,355 @@
+From c0f9254fdd0703ade018b2ff3a8cca433f781a11 Mon Sep 17 00:00:00 2001
+From: Hans de Goede <hdegoede@redhat.com>
+Date: Sun, 26 Feb 2017 21:07:29 +0100
+Subject: [PATCH 02/16] mfd: Add Cherry Trail Whiskey Cove PMIC driver
+
+Add mfd driver for Intel CHT Whiskey Cove PMIC, based on various non
+upstreamed CHT Whiskey Cove PMIC patches.
+
+This is a somewhat minimal version which adds irqchip support and cells
+for: ACPI PMIC opregion support, the i2c-controller driving the external
+charger irc and the pwrsrc/extcon block.
+
+Further cells can be added in the future if/when drivers are upstreamed
+for them.
+
+Cc: Bin Gao <bin.gao@intel.com>
+Cc: Felipe Balbi <felipe.balbi@linux.intel.com>
+Cc: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+---
+Changes in v2:
+-Since this uses plain mfd and not the intel_soc_pmic stuff give it
+ its own Kconfig and allow this to be built as a module
+-Add missing #include <acpi/acpi_bus.h>
+
+Changes in v3:
+-Drop #include <acpi/acpi_bus.h> again, not the right fix for the build errors
+-Error out when the upper byte of the register-address passed to the regmap
+ functions is 0 rather then hardcoding an address in that case
+-Various minor style tweaks / cleanups
+-Move defines of regulator register addresses to intel_pmic_chtwc.c,
+ it is the only place where they are used
+-Drop now empty include/linux/mfd/intel_chtwc.h
+-Rename intel_soc_pmic_chtwc.c to intel_cht_wc.c to match Kconfig option name
+-Add irqchip support
+-Add external charger cell
+-Add pwrsrc cell
+
+Changes in v4:
+-Use PLATFORM_DEVID_NONE
+
+Changes in v5:
+-Change Kconfig option from tristate to boolean and add a select for the
+ i2c-bus driver, this is necessary because the chtwc PMIC provides an ACPI
+ OPRegion handler, which must be available before other drivers using it
+ are loaded, which can only be ensured if the mfd, opregion and i2c-bus
+ drivers are built in. This fixes errors like these during boot:
+ mmc0: SDHCI controller on ACPI [80860F14:00] using ADMA
+ ACPI Error: No handler for Region [REGS] (ffff93543b0cc3a8) [UserDefinedRegion] (20170119/evregion-166)
+ ACPI Error: Region UserDefinedRegion (ID=143) has no handler (20170119/exfldio-299)
+ ACPI Error: Method parse/execution failed [\_SB.PCI0.I2C7.PMI5.GET] (Node ffff93543b0cde10), AE_NOT_EXIST (20170119/psparse-543)
+ ACPI Error: Method parse/execution failed [\_SB.PCI0.SHC1._PS0] (Node ffff93543b0b5cd0), AE_NOT_EXIST (20170119/psparse-543)
+ acpi 80860F14:02: Failed to change power state to D0
+-Some minor style and capitalization fixes from review by Lee Jones
+
+Changes in v6:
+-Fix Kconfig depends and selects to fix warning reported by kbuild test robot
+
+Changes in v7:
+-Add explanation why this is a bool and why it selects i2c-designwaree
+ to the help text rather then as comments in the Kconfig
+
+Changes in v8:
+-Remove MODULE macros, etc. now that this driver is a bool in Kconfig
+
+Changes in v9:
+-Some whitespace tweaks
+-Return -EINVAL from probe on invalid irq
+-Use probe_new i2c_driver callback
+---
+ drivers/mfd/Kconfig | 16 +++
+ drivers/mfd/Makefile | 1 +
+ drivers/mfd/intel_soc_pmic_chtwc.c | 230 +++++++++++++++++++++++++++++++++++++
+ 3 files changed, 247 insertions(+)
+ create mode 100644 drivers/mfd/intel_soc_pmic_chtwc.c
+
+diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
+index 3eb5c93595f6..5203a86b8f6c 100644
+--- a/drivers/mfd/Kconfig
++++ b/drivers/mfd/Kconfig
+@@ -470,6 +470,22 @@ config INTEL_SOC_PMIC_BXTWC
+ thermal, charger and related power management functions
+ on these systems.
+
++config INTEL_SOC_PMIC_CHTWC
++ bool "Support for Intel Cherry Trail Whiskey Cove PMIC"
++ depends on ACPI && HAS_IOMEM && I2C=y && COMMON_CLK
++ depends on X86 || COMPILE_TEST
++ select MFD_CORE
++ select REGMAP_I2C
++ select REGMAP_IRQ
++ select I2C_DESIGNWARE_PLATFORM
++ help
++ Select this option to enable support for the Intel Cherry Trail
++ Whiskey Cove PMIC found on some Intel Cherry Trail systems.
++
++ This option is a bool as it provides an ACPI OpRegion which must be
++ available before any devices using it are probed. This option also
++ causes the designware-i2c driver to be builtin for the same reason.
++
+ config MFD_INTEL_LPSS
+ tristate
+ select COMMON_CLK
+diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
+index c16bf1ea0ea9..6f6aed8cfccc 100644
+--- a/drivers/mfd/Makefile
++++ b/drivers/mfd/Makefile
+@@ -214,6 +214,7 @@ obj-$(CONFIG_MFD_SKY81452) += sky81452.o
+ intel-soc-pmic-objs := intel_soc_pmic_core.o intel_soc_pmic_crc.o
+ obj-$(CONFIG_INTEL_SOC_PMIC) += intel-soc-pmic.o
+ obj-$(CONFIG_INTEL_SOC_PMIC_BXTWC) += intel_soc_pmic_bxtwc.o
++obj-$(CONFIG_INTEL_SOC_PMIC_CHTWC) += intel_soc_pmic_chtwc.o
+ obj-$(CONFIG_MFD_MT6397) += mt6397-core.o
+
+ obj-$(CONFIG_MFD_ALTERA_A10SR) += altera-a10sr.o
+diff --git a/drivers/mfd/intel_soc_pmic_chtwc.c b/drivers/mfd/intel_soc_pmic_chtwc.c
+new file mode 100644
+index 000000000000..b35da01d5bcf
+--- /dev/null
++++ b/drivers/mfd/intel_soc_pmic_chtwc.c
+@@ -0,0 +1,230 @@
++/*
++ * MFD core driver for Intel Cherrytrail Whiskey Cove PMIC
++ *
++ * Copyright (C) 2017 Hans de Goede <hdegoede@redhat.com>
++ *
++ * Based on various non upstream patches to support the CHT Whiskey Cove PMIC:
++ * Copyright (C) 2013-2015 Intel Corporation. All rights reserved.
++ *
++ * 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 <linux/acpi.h>
++#include <linux/delay.h>
++#include <linux/err.h>
++#include <linux/i2c.h>
++#include <linux/interrupt.h>
++#include <linux/kernel.h>
++#include <linux/mfd/core.h>
++#include <linux/mfd/intel_soc_pmic.h>
++#include <linux/regmap.h>
++
++/* PMIC device registers */
++#define REG_OFFSET_MASK GENMASK(7, 0)
++#define REG_ADDR_MASK GENMASK(15, 8)
++#define REG_ADDR_SHIFT 8
++
++#define CHT_WC_IRQLVL1 0x6e02
++#define CHT_WC_IRQLVL1_MASK 0x6e0e
++
++/* Whiskey Cove PMIC share same ACPI ID between different platforms */
++#define CHT_WC_HRV 3
++
++/* Level 1 IRQs (level 2 IRQs are handled in the child device drivers) */
++enum {
++ CHT_WC_PWRSRC_IRQ = 0,
++ CHT_WC_THRM_IRQ,
++ CHT_WC_BCU_IRQ,
++ CHT_WC_ADC_IRQ,
++ CHT_WC_EXT_CHGR_IRQ,
++ CHT_WC_GPIO_IRQ,
++ /* There is no irq 6 */
++ CHT_WC_CRIT_IRQ = 7,
++};
++
++static struct resource cht_wc_pwrsrc_resources[] = {
++ DEFINE_RES_IRQ(CHT_WC_PWRSRC_IRQ),
++};
++
++static struct resource cht_wc_ext_charger_resources[] = {
++ DEFINE_RES_IRQ(CHT_WC_EXT_CHGR_IRQ),
++};
++
++static struct mfd_cell cht_wc_dev[] = {
++ {
++ .name = "cht_wcove_pwrsrc",
++ .num_resources = ARRAY_SIZE(cht_wc_pwrsrc_resources),
++ .resources = cht_wc_pwrsrc_resources,
++ }, {
++ .name = "cht_wcove_ext_chgr",
++ .num_resources = ARRAY_SIZE(cht_wc_ext_charger_resources),
++ .resources = cht_wc_ext_charger_resources,
++ },
++ { .name = "cht_wcove_region", },
++};
++
++/*
++ * The CHT Whiskey Cove covers multiple I2C addresses, with a 1 Byte
++ * register address space per I2C address, so we use 16 bit register
++ * addresses where the high 8 bits contain the I2C client address.
++ */
++static int cht_wc_byte_reg_read(void *context, unsigned int reg,
++ unsigned int *val)
++{
++ struct i2c_client *client = context;
++ int ret, orig_addr = client->addr;
++
++ if (!(reg & REG_ADDR_MASK)) {
++ dev_err(&client->dev, "Error I2C address not specified\n");
++ return -EINVAL;
++ }
++
++ client->addr = (reg & REG_ADDR_MASK) >> REG_ADDR_SHIFT;
++ ret = i2c_smbus_read_byte_data(client, reg & REG_OFFSET_MASK);
++ client->addr = orig_addr;
++
++ if (ret < 0)
++ return ret;
++
++ *val = ret;
++ return 0;
++}
++
++static int cht_wc_byte_reg_write(void *context, unsigned int reg,
++ unsigned int val)
++{
++ struct i2c_client *client = context;
++ int ret, orig_addr = client->addr;
++
++ if (!(reg & REG_ADDR_MASK)) {
++ dev_err(&client->dev, "Error I2C address not specified\n");
++ return -EINVAL;
++ }
++
++ client->addr = (reg & REG_ADDR_MASK) >> REG_ADDR_SHIFT;
++ ret = i2c_smbus_write_byte_data(client, reg & REG_OFFSET_MASK, val);
++ client->addr = orig_addr;
++
++ return ret;
++}
++
++static const struct regmap_config cht_wc_regmap_cfg = {
++ .reg_bits = 16,
++ .val_bits = 8,
++ .reg_write = cht_wc_byte_reg_write,
++ .reg_read = cht_wc_byte_reg_read,
++};
++
++static const struct regmap_irq cht_wc_regmap_irqs[] = {
++ REGMAP_IRQ_REG(CHT_WC_PWRSRC_IRQ, 0, BIT(CHT_WC_PWRSRC_IRQ)),
++ REGMAP_IRQ_REG(CHT_WC_THRM_IRQ, 0, BIT(CHT_WC_THRM_IRQ)),
++ REGMAP_IRQ_REG(CHT_WC_BCU_IRQ, 0, BIT(CHT_WC_BCU_IRQ)),
++ REGMAP_IRQ_REG(CHT_WC_ADC_IRQ, 0, BIT(CHT_WC_ADC_IRQ)),
++ REGMAP_IRQ_REG(CHT_WC_EXT_CHGR_IRQ, 0, BIT(CHT_WC_EXT_CHGR_IRQ)),
++ REGMAP_IRQ_REG(CHT_WC_GPIO_IRQ, 0, BIT(CHT_WC_GPIO_IRQ)),
++ REGMAP_IRQ_REG(CHT_WC_CRIT_IRQ, 0, BIT(CHT_WC_CRIT_IRQ)),
++};
++
++static const struct regmap_irq_chip cht_wc_regmap_irq_chip = {
++ .name = "cht_wc_irq_chip",
++ .status_base = CHT_WC_IRQLVL1,
++ .mask_base = CHT_WC_IRQLVL1_MASK,
++ .irqs = cht_wc_regmap_irqs,
++ .num_irqs = ARRAY_SIZE(cht_wc_regmap_irqs),
++ .num_regs = 1,
++};
++
++static int cht_wc_probe(struct i2c_client *client)
++{
++ struct device *dev = &client->dev;
++ struct intel_soc_pmic *pmic;
++ acpi_status status;
++ unsigned long long hrv;
++ int ret;
++
++ status = acpi_evaluate_integer(ACPI_HANDLE(dev), "_HRV", NULL, &hrv);
++ if (ACPI_FAILURE(status)) {
++ dev_err(dev, "Failed to get PMIC hardware revision\n");
++ return -ENODEV;
++ }
++ if (hrv != CHT_WC_HRV) {
++ dev_err(dev, "Invalid PMIC hardware revision: %llu\n", hrv);
++ return -ENODEV;
++ }
++ if (client->irq < 0) {
++ dev_err(dev, "Invalid IRQ\n");
++ return -EINVAL;
++ }
++
++ pmic = devm_kzalloc(dev, sizeof(*pmic), GFP_KERNEL);
++ if (!pmic)
++ return -ENOMEM;
++
++ pmic->irq = client->irq;
++ pmic->dev = dev;
++ i2c_set_clientdata(client, pmic);
++
++ pmic->regmap = devm_regmap_init(dev, NULL, client, &cht_wc_regmap_cfg);
++ if (IS_ERR(pmic->regmap))
++ return PTR_ERR(pmic->regmap);
++
++ ret = devm_regmap_add_irq_chip(dev, pmic->regmap, pmic->irq,
++ IRQF_ONESHOT | IRQF_SHARED, 0,
++ &cht_wc_regmap_irq_chip,
++ &pmic->irq_chip_data);
++ if (ret)
++ return ret;
++
++ return devm_mfd_add_devices(dev, PLATFORM_DEVID_NONE,
++ cht_wc_dev, ARRAY_SIZE(cht_wc_dev), NULL, 0,
++ regmap_irq_get_domain(pmic->irq_chip_data));
++}
++
++static void cht_wc_shutdown(struct i2c_client *client)
++{
++ struct intel_soc_pmic *pmic = i2c_get_clientdata(client);
++
++ disable_irq(pmic->irq);
++}
++
++static int __maybe_unused cht_wc_suspend(struct device *dev)
++{
++ struct intel_soc_pmic *pmic = dev_get_drvdata(dev);
++
++ disable_irq(pmic->irq);
++
++ return 0;
++}
++
++static int __maybe_unused cht_wc_resume(struct device *dev)
++{
++ struct intel_soc_pmic *pmic = dev_get_drvdata(dev);
++
++ enable_irq(pmic->irq);
++
++ return 0;
++}
++static SIMPLE_DEV_PM_OPS(cht_wc_pm_ops, cht_wc_suspend, cht_wc_resume);
++
++static const struct i2c_device_id cht_wc_i2c_id[] = {
++ { }
++};
++
++static const struct acpi_device_id cht_wc_acpi_ids[] = {
++ { "INT34D3", },
++ { }
++};
++
++static struct i2c_driver cht_wc_driver = {
++ .driver = {
++ .name = "CHT Whiskey Cove PMIC",
++ .pm = &cht_wc_pm_ops,
++ .acpi_match_table = cht_wc_acpi_ids,
++ },
++ .probe_new = cht_wc_probe,
++ .shutdown = cht_wc_shutdown,
++ .id_table = cht_wc_i2c_id,
++};
++builtin_i2c_driver(cht_wc_driver);
+--
+2.13.0
+
diff --git a/0003-power-supply-core-Add-support-for-supplied-from-devi.patch b/0003-power-supply-core-Add-support-for-supplied-from-devi.patch
new file mode 100644
index 000000000..ab646e2e5
--- /dev/null
+++ b/0003-power-supply-core-Add-support-for-supplied-from-devi.patch
@@ -0,0 +1,57 @@
+From 69dd0606a0d8680fe0a5e9b959f6662e582e1674 Mon Sep 17 00:00:00 2001
+From: Hans de Goede <hdegoede@redhat.com>
+Date: Tue, 2 May 2017 13:43:34 +0200
+Subject: [PATCH 03/16] power: supply: core: Add support for supplied-from
+ device-property
+
+On devicetree using platforms the devicetree can provide info on which
+power-supplies supply another power-supply through phandles.
+
+This commit adds support for providing this info on non devicetree
+platforms through the platform code setting a supplied-from
+device-property on the power-supplies parent device.
+
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+---
+ drivers/power/supply/power_supply_core.c | 24 +++++++++++++++++++++++-
+ 1 file changed, 23 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/power/supply/power_supply_core.c b/drivers/power/supply/power_supply_core.c
+index 7ec7c7c202bd..0c09144193a6 100644
+--- a/drivers/power/supply/power_supply_core.c
++++ b/drivers/power/supply/power_supply_core.c
+@@ -274,8 +274,30 @@ static int power_supply_check_supplies(struct power_supply *psy)
+ return power_supply_populate_supplied_from(psy);
+ }
+ #else
+-static inline int power_supply_check_supplies(struct power_supply *psy)
++static int power_supply_check_supplies(struct power_supply *psy)
+ {
++ int nval, ret;
++
++ if (!psy->dev.parent)
++ return 0;
++
++ nval = device_property_read_string_array(psy->dev.parent,
++ "supplied-from", NULL, 0);
++ if (nval <= 0)
++ return 0;
++
++ psy->supplied_from = devm_kmalloc_array(&psy->dev, nval,
++ sizeof(char *), GFP_KERNEL);
++ if (!psy->supplied_from)
++ return -ENOMEM;
++
++ ret = device_property_read_string_array(psy->dev.parent,
++ "supplied-from", (const char **)psy->supplied_from, nval);
++ if (ret < 0)
++ return ret;
++
++ psy->num_supplies = nval;
++
+ return 0;
+ }
+ #endif
+--
+2.13.0
+
diff --git a/0004-platform-x86-intel_cht_int33fe-Set-supplied-from-pro.patch b/0004-platform-x86-intel_cht_int33fe-Set-supplied-from-pro.patch
new file mode 100644
index 000000000..342a48c54
--- /dev/null
+++ b/0004-platform-x86-intel_cht_int33fe-Set-supplied-from-pro.patch
@@ -0,0 +1,48 @@
+From 99c44df299d96db6a170ccce9b8108fc2e7f8bae Mon Sep 17 00:00:00 2001
+From: Hans de Goede <hdegoede@redhat.com>
+Date: Tue, 2 May 2017 13:40:44 +0200
+Subject: [PATCH 04/16] platform/x86: intel_cht_int33fe: Set supplied-from
+ property on max17047 dev
+
+Devices with the intel_cht_int33fe ACPI device use a max17047 fuel-gauge
+combined with a bq24272i charger, in order for the fuel-gauge driver to
+correctly display charging / discharging status it needs to know which
+charger is supplying the battery.
+
+This commit sets the supplied-from device property to the name of the
+bq24272i charger for this.
+
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+---
+ drivers/platform/x86/intel_cht_int33fe.c | 8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+diff --git a/drivers/platform/x86/intel_cht_int33fe.c b/drivers/platform/x86/intel_cht_int33fe.c
+index 6a1b2ca5b6fe..da706e2c4232 100644
+--- a/drivers/platform/x86/intel_cht_int33fe.c
++++ b/drivers/platform/x86/intel_cht_int33fe.c
+@@ -34,6 +34,13 @@ struct cht_int33fe_data {
+ struct i2c_client *pi3usb30532;
+ };
+
++static const char * const max17047_suppliers[] = { "bq24190-charger" };
++
++static const struct property_entry max17047_props[] = {
++ PROPERTY_ENTRY_STRING_ARRAY("supplied-from", max17047_suppliers),
++ { }
++};
++
+ static int cht_int33fe_probe(struct i2c_client *client)
+ {
+ struct device *dev = &client->dev;
+@@ -70,6 +77,7 @@ static int cht_int33fe_probe(struct i2c_client *client)
+
+ memset(&board_info, 0, sizeof(board_info));
+ strlcpy(board_info.type, "max17047", I2C_NAME_SIZE);
++ board_info.properties = max17047_props;
+
+ data->max17047 = i2c_acpi_new_device(dev, 1, &board_info);
+ if (!data->max17047)
+--
+2.13.0
+
diff --git a/0005-ACPI-PMIC-xpower-Add-support-for-the-GPI1-regulator-.patch b/0005-ACPI-PMIC-xpower-Add-support-for-the-GPI1-regulator-.patch
new file mode 100644
index 000000000..c6f299c29
--- /dev/null
+++ b/0005-ACPI-PMIC-xpower-Add-support-for-the-GPI1-regulator-.patch
@@ -0,0 +1,80 @@
+From cc2b0e2c164d02ab42efa736f91f53baf8d8bc36 Mon Sep 17 00:00:00 2001
+From: Hans de Goede <hdegoede@redhat.com>
+Date: Thu, 20 Apr 2017 22:41:20 +0200
+Subject: [PATCH 05/16] ACPI / PMIC: xpower: Add support for the GPI1 regulator
+ to the OpRegion handler
+
+Some Bay Trail devices use a GPI1 regulator field (address 0x4c) in
+their 0x8d power OpRegion, add support for this.
+
+This fixes AE_BAD_PARAMETER errors getting thrown on these devices and
+fixes these errors causing these devices to not suspend.
+
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+---
+Changes in v2:
+-Simplify reg == 0x92 handling (suggested by Andy Shevchenko)
+-Add special handling for reg == 0x92 to intel_xpower_pmic_get_power() too
+Changes in v3:
+-Use defines for GPI1 reg and bits, rather then hardcoded hex values
+---
+ drivers/acpi/pmic/intel_pmic_xpower.c | 21 ++++++++++++++++++++-
+ 1 file changed, 20 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/acpi/pmic/intel_pmic_xpower.c b/drivers/acpi/pmic/intel_pmic_xpower.c
+index 1a76c784cd4c..3b7d5be5b7ed 100644
+--- a/drivers/acpi/pmic/intel_pmic_xpower.c
++++ b/drivers/acpi/pmic/intel_pmic_xpower.c
+@@ -21,6 +21,11 @@
+ #include "intel_pmic.h"
+
+ #define XPOWER_GPADC_LOW 0x5b
++#define XPOWER_GPI1_CTRL 0x92
++
++#define GPI1_LDO_MASK GENMASK(2, 0)
++#define GPI1_LDO_ON (3 << 0)
++#define GPI1_LDO_OFF (4 << 0)
+
+ static struct pmic_table power_table[] = {
+ {
+@@ -118,6 +123,10 @@ static struct pmic_table power_table[] = {
+ .reg = 0x10,
+ .bit = 0x00
+ }, /* BUC6 */
++ {
++ .address = 0x4c,
++ .reg = 0x92,
++ }, /* GPI1 */
+ };
+
+ /* TMP0 - TMP5 are the same, all from GPADC */
+@@ -156,7 +165,12 @@ static int intel_xpower_pmic_get_power(struct regmap *regmap, int reg,
+ if (regmap_read(regmap, reg, &data))
+ return -EIO;
+
+- *value = (data & BIT(bit)) ? 1 : 0;
++ /* GPIO1 LDO regulator needs special handling */
++ if (reg == XPOWER_GPI1_CTRL)
++ *value = ((data & GPI1_LDO_MASK) == GPI1_LDO_ON);
++ else
++ *value = (data & BIT(bit)) ? 1 : 0;
++
+ return 0;
+ }
+
+@@ -165,6 +179,11 @@ static int intel_xpower_pmic_update_power(struct regmap *regmap, int reg,
+ {
+ int data;
+
++ /* GPIO1 LDO regulator needs special handling */
++ if (reg == XPOWER_GPI1_CTRL)
++ return regmap_update_bits(regmap, reg, GPI1_LDO_MASK,
++ on ? GPI1_LDO_ON : GPI1_LDO_OFF);
++
+ if (regmap_read(regmap, reg, &data))
+ return -EIO;
+
+--
+2.13.0
+
diff --git a/0006-Input-axp20x-pek-Add-wakeup-support.patch b/0006-Input-axp20x-pek-Add-wakeup-support.patch
new file mode 100644
index 000000000..1ec9659bd
--- /dev/null
+++ b/0006-Input-axp20x-pek-Add-wakeup-support.patch
@@ -0,0 +1,67 @@
+From fbac4c05ec1d7c2d949f50baf1e934cbfbb6a494 Mon Sep 17 00:00:00 2001
+From: Hans de Goede <hdegoede@redhat.com>
+Date: Mon, 17 Apr 2017 22:06:25 +0200
+Subject: [PATCH 06/16] Input: axp20x-pek - Add wakeup support
+
+At least on devices with the AXP288 PMIC the device is expected to
+wakeup from suspend when the power-button gets pressed, add support
+for this.
+
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+---
+ drivers/input/misc/axp20x-pek.c | 28 ++++++++++++++++++++++++++++
+ 1 file changed, 28 insertions(+)
+
+diff --git a/drivers/input/misc/axp20x-pek.c b/drivers/input/misc/axp20x-pek.c
+index 400869e61a06..5f16fceaae83 100644
+--- a/drivers/input/misc/axp20x-pek.c
++++ b/drivers/input/misc/axp20x-pek.c
+@@ -253,6 +253,9 @@ static int axp20x_pek_probe_input_device(struct axp20x_pek *axp20x_pek,
+ return error;
+ }
+
++ if (axp20x_pek->axp20x->variant == AXP288_ID)
++ enable_irq_wake(axp20x_pek->irq_dbr);
++
+ return 0;
+ }
+
+@@ -331,10 +334,35 @@ static int axp20x_pek_probe(struct platform_device *pdev)
+ return 0;
+ }
+
++static int __maybe_unused axp20x_pek_resume_noirq(struct device *dev)
++{
++ struct axp20x_pek *axp20x_pek = dev_get_drvdata(dev);
++
++ if (axp20x_pek->axp20x->variant != AXP288_ID)
++ return 0;
++
++ /*
++ * Clear interrupts from button presses during suspend, to avoid
++ * a wakeup power-button press getting reported to userspace.
++ */
++ regmap_write(axp20x_pek->axp20x->regmap,
++ AXP20X_IRQ1_STATE + AXP288_IRQ_POKN / 8,
++ BIT(AXP288_IRQ_POKN % 8));
++
++ return 0;
++}
++
++const struct dev_pm_ops axp20x_pek_pm_ops = {
++#ifdef CONFIG_PM_SLEEP
++ .resume_noirq = axp20x_pek_resume_noirq,
++#endif
++};
++
+ static struct platform_driver axp20x_pek_driver = {
+ .probe = axp20x_pek_probe,
+ .driver = {
+ .name = "axp20x-pek",
++ .pm = &axp20x_pek_pm_ops,
+ },
+ };
+ module_platform_driver(axp20x_pek_driver);
+--
+2.13.0
+
diff --git a/0007-platform-x86-silead_dmi-Add-touchscreen-info-for-GP-.patch b/0007-platform-x86-silead_dmi-Add-touchscreen-info-for-GP-.patch
new file mode 100644
index 000000000..0b7633459
--- /dev/null
+++ b/0007-platform-x86-silead_dmi-Add-touchscreen-info-for-GP-.patch
@@ -0,0 +1,56 @@
+From d95c127c48ef784214671359a41ac505ac30098a Mon Sep 17 00:00:00 2001
+From: Hans de Goede <hdegoede@redhat.com>
+Date: Sun, 7 May 2017 12:32:11 +0200
+Subject: [PATCH 07/16] platform/x86: silead_dmi: Add touchscreen info for
+ GP-electronic T701
+
+Add touchscreen info for the GP-electronic T701 tablet.
+
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+---
+ drivers/platform/x86/silead_dmi.c | 22 ++++++++++++++++++++++
+ 1 file changed, 22 insertions(+)
+
+diff --git a/drivers/platform/x86/silead_dmi.c b/drivers/platform/x86/silead_dmi.c
+index a3a57d93cf06..db3a877d2160 100644
+--- a/drivers/platform/x86/silead_dmi.c
++++ b/drivers/platform/x86/silead_dmi.c
+@@ -80,6 +80,19 @@ static const struct silead_ts_dmi_data surftab_wintron70_st70416_6_data = {
+ .properties = surftab_wintron70_st70416_6_props,
+ };
+
++static const struct property_entry gp_electronic_t701_props[] = {
++ PROPERTY_ENTRY_U32("touchscreen-size-x", 960),
++ PROPERTY_ENTRY_U32("touchscreen-size-y", 640),
++ PROPERTY_ENTRY_STRING("firmware-name",
++ "gsl1680-gp-electronic-t701.fw"),
++ { }
++};
++
++static const struct silead_ts_dmi_data gp_electronic_t701_data = {
++ .acpi_name = "MSSL1680:00",
++ .properties = gp_electronic_t701_props,
++};
++
+ static const struct dmi_system_id silead_ts_dmi_table[] = {
+ {
+ /* CUBE iwork8 Air */
+@@ -117,6 +130,15 @@ static const struct dmi_system_id silead_ts_dmi_table[] = {
+ DMI_MATCH(DMI_BIOS_VERSION, "TREK.G.WI71C.JGBMRBA04"),
+ },
+ },
++ {
++ /* GP-electronic T701 */
++ .driver_data = (void *)&gp_electronic_t701_data,
++ .matches = {
++ DMI_MATCH(DMI_SYS_VENDOR, "Insyde"),
++ DMI_MATCH(DMI_PRODUCT_NAME, "T701"),
++ DMI_MATCH(DMI_BIOS_VERSION, "BYT70A.YNCHENG.WIN.007"),
++ },
++ },
+ { },
+ };
+
+--
+2.13.0
+
diff --git a/0008-platform-x86-silead_dmi-Add-touchscreen-info-for-PoV.patch b/0008-platform-x86-silead_dmi-Add-touchscreen-info-for-PoV.patch
new file mode 100644
index 000000000..975deb8f0
--- /dev/null
+++ b/0008-platform-x86-silead_dmi-Add-touchscreen-info-for-PoV.patch
@@ -0,0 +1,59 @@
+From 55b347c61b2850d1e11e159ab02dc71f13b06481 Mon Sep 17 00:00:00 2001
+From: Hans de Goede <hdegoede@redhat.com>
+Date: Sun, 11 Jun 2017 17:42:31 +0200
+Subject: [PATCH 08/16] platform/x86: silead_dmi: Add touchscreen info for PoV
+ mobii wintab p800w
+
+Add touchscreen info for the Point of View mobii wintab p800w tablet.
+
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+---
+ drivers/platform/x86/silead_dmi.c | 25 +++++++++++++++++++++++++
+ 1 file changed, 25 insertions(+)
+
+diff --git a/drivers/platform/x86/silead_dmi.c b/drivers/platform/x86/silead_dmi.c
+index db3a877d2160..46c5e1ebfb53 100644
+--- a/drivers/platform/x86/silead_dmi.c
++++ b/drivers/platform/x86/silead_dmi.c
+@@ -93,6 +93,20 @@ static const struct silead_ts_dmi_data gp_electronic_t701_data = {
+ .properties = gp_electronic_t701_props,
+ };
+
++static const struct property_entry pov_mobii_wintab_p800w_props[] = {
++ PROPERTY_ENTRY_U32("touchscreen-size-x", 1800),
++ PROPERTY_ENTRY_U32("touchscreen-size-y", 1150),
++ PROPERTY_ENTRY_BOOL("touchscreen-swapped-x-y"),
++ PROPERTY_ENTRY_STRING("firmware-name",
++ "gsl3692-pov-mobii-wintab-p800w.fw"),
++ { }
++};
++
++static const struct silead_ts_dmi_data pov_mobii_wintab_p800w_data = {
++ .acpi_name = "MSSL1680:00",
++ .properties = pov_mobii_wintab_p800w_props,
++};
++
+ static const struct dmi_system_id silead_ts_dmi_table[] = {
+ {
+ /* CUBE iwork8 Air */
+@@ -139,6 +153,17 @@ static const struct dmi_system_id silead_ts_dmi_table[] = {
+ DMI_MATCH(DMI_BIOS_VERSION, "BYT70A.YNCHENG.WIN.007"),
+ },
+ },
++ {
++ /* Point of View mobii wintab p800w */
++ .driver_data = (void *)&pov_mobii_wintab_p800w_data,
++ .matches = {
++ DMI_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"),
++ DMI_MATCH(DMI_BOARD_NAME, "Aptio CRB"),
++ DMI_MATCH(DMI_BIOS_VERSION, "3BAIR1013"),
++ /* Above matches are too generic, add bios-date match */
++ DMI_MATCH(DMI_BIOS_DATE, "08/22/2014"),
++ },
++ },
+ { },
+ };
+
+--
+2.13.0
+
diff --git a/0009-platform-x86-silead_dmi-Add-touchscreen-info-for-Pip.patch b/0009-platform-x86-silead_dmi-Add-touchscreen-info-for-Pip.patch
new file mode 100644
index 000000000..0770395d9
--- /dev/null
+++ b/0009-platform-x86-silead_dmi-Add-touchscreen-info-for-Pip.patch
@@ -0,0 +1,57 @@
+From b239a7a0c2a1435aa5cbab3f233e0c37e82943dd Mon Sep 17 00:00:00 2001
+From: Hans de Goede <hdegoede@redhat.com>
+Date: Tue, 13 Jun 2017 18:17:07 +0200
+Subject: [PATCH 09/16] platform/x86: silead_dmi: Add touchscreen info for Pipo
+ W2S tablet
+
+Add touchscreen info for Pipo W2S tablet.
+
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+---
+ drivers/platform/x86/silead_dmi.c | 23 +++++++++++++++++++++++
+ 1 file changed, 23 insertions(+)
+
+diff --git a/drivers/platform/x86/silead_dmi.c b/drivers/platform/x86/silead_dmi.c
+index 46c5e1ebfb53..25cbea307a5e 100644
+--- a/drivers/platform/x86/silead_dmi.c
++++ b/drivers/platform/x86/silead_dmi.c
+@@ -107,6 +107,21 @@ static const struct silead_ts_dmi_data pov_mobii_wintab_p800w_data = {
+ .properties = pov_mobii_wintab_p800w_props,
+ };
+
++static const struct property_entry pipo_w2s_props[] = {
++ PROPERTY_ENTRY_U32("touchscreen-size-x", 1660),
++ PROPERTY_ENTRY_U32("touchscreen-size-y", 880),
++ PROPERTY_ENTRY_BOOL("touchscreen-inverted-x"),
++ PROPERTY_ENTRY_BOOL("touchscreen-swapped-x-y"),
++ PROPERTY_ENTRY_STRING("firmware-name",
++ "gsl1680-pipo-w2s.fw"),
++ { }
++};
++
++static const struct silead_ts_dmi_data pipo_w2s_data = {
++ .acpi_name = "MSSL1680:00",
++ .properties = pipo_w2s_props,
++};
++
+ static const struct dmi_system_id silead_ts_dmi_table[] = {
+ {
+ /* CUBE iwork8 Air */
+@@ -164,6 +179,14 @@ static const struct dmi_system_id silead_ts_dmi_table[] = {
+ DMI_MATCH(DMI_BIOS_DATE, "08/22/2014"),
+ },
+ },
++ {
++ /* Pipo W2S */
++ .driver_data = (void *)&pipo_w2s_data,
++ .matches = {
++ DMI_MATCH(DMI_SYS_VENDOR, "PIPO"),
++ DMI_MATCH(DMI_PRODUCT_NAME, "W2S"),
++ },
++ },
+ { },
+ };
+
+--
+2.13.0
+
diff --git a/0010-Input-silead-Add-support-for-capactive-home-button-f.patch b/0010-Input-silead-Add-support-for-capactive-home-button-f.patch
new file mode 100644
index 000000000..ce9be3760
--- /dev/null
+++ b/0010-Input-silead-Add-support-for-capactive-home-button-f.patch
@@ -0,0 +1,114 @@
+From 33fc16fd8aa3684e19b1d1f0a712593e2e570ab1 Mon Sep 17 00:00:00 2001
+From: Hans de Goede <hdegoede@redhat.com>
+Date: Sun, 11 Jun 2017 21:24:50 +0200
+Subject: [PATCH 10/16] Input: silead: Add support for capactive home button
+ found on some x86 tablets
+
+On some x86 tablets with a silead touchscreen the windows logo on the
+front is a capacitive home button. Touching this button results in a touch
+with bits 12-15 of the Y coordinates set, while normally only the lower 12
+are used.
+
+Detect this and report a KEY_LEFTMETA press when this happens. Note for
+now we only respond to the Y coordinate bits 12-15 containing 0x01, on some
+tablets *without* a capacative button I've noticed these bits containing
+0x04 when crossing the edges of the screen.
+
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+---
+ drivers/input/touchscreen/silead.c | 45 ++++++++++++++++++++++++++++----------
+ 1 file changed, 34 insertions(+), 11 deletions(-)
+
+diff --git a/drivers/input/touchscreen/silead.c b/drivers/input/touchscreen/silead.c
+index 0dbcf105f7db..c0ba40c09699 100644
+--- a/drivers/input/touchscreen/silead.c
++++ b/drivers/input/touchscreen/silead.c
+@@ -56,7 +56,7 @@
+ #define SILEAD_POINT_Y_MSB_OFF 0x01
+ #define SILEAD_POINT_X_OFF 0x02
+ #define SILEAD_POINT_X_MSB_OFF 0x03
+-#define SILEAD_TOUCH_ID_MASK 0xF0
++#define SILEAD_EXTRA_DATA_MASK 0xF0
+
+ #define SILEAD_CMD_SLEEP_MIN 10000
+ #define SILEAD_CMD_SLEEP_MAX 20000
+@@ -109,6 +109,8 @@ static int silead_ts_request_input_dev(struct silead_ts_data *data)
+ INPUT_MT_DIRECT | INPUT_MT_DROP_UNUSED |
+ INPUT_MT_TRACK);
+
++ input_set_capability(data->input, EV_KEY, KEY_LEFTMETA);
++
+ data->input->name = SILEAD_TS_NAME;
+ data->input->phys = "input/ts";
+ data->input->id.bustype = BUS_I2C;
+@@ -139,7 +141,8 @@ static void silead_ts_read_data(struct i2c_client *client)
+ struct input_dev *input = data->input;
+ struct device *dev = &client->dev;
+ u8 *bufp, buf[SILEAD_TS_DATA_LEN];
+- int touch_nr, error, i;
++ int touch_nr, softbutton, error, i;
++ bool softbutton_pressed = false;
+
+ error = i2c_smbus_read_i2c_block_data(client, SILEAD_REG_DATA,
+ SILEAD_TS_DATA_LEN, buf);
+@@ -148,21 +151,40 @@ static void silead_ts_read_data(struct i2c_client *client)
+ return;
+ }
+
+- touch_nr = buf[0];
+- if (touch_nr > data->max_fingers) {
++ if (buf[0] > data->max_fingers) {
+ dev_warn(dev, "More touches reported then supported %d > %d\n",
+- touch_nr, data->max_fingers);
+- touch_nr = data->max_fingers;
++ buf[0], data->max_fingers);
++ buf[0] = data->max_fingers;
+ }
+
++ touch_nr = 0;
+ bufp = buf + SILEAD_POINT_DATA_LEN;
+- for (i = 0; i < touch_nr; i++, bufp += SILEAD_POINT_DATA_LEN) {
+- /* Bits 4-7 are the touch id */
+- data->id[i] = (bufp[SILEAD_POINT_X_MSB_OFF] &
+- SILEAD_TOUCH_ID_MASK) >> 4;
+- touchscreen_set_mt_pos(&data->pos[i], &data->prop,
++ for (i = 0; i < buf[0]; i++, bufp += SILEAD_POINT_DATA_LEN) {
++ softbutton = (bufp[SILEAD_POINT_Y_MSB_OFF] &
++ SILEAD_EXTRA_DATA_MASK) >> 4;
++
++ if (softbutton) {
++ /*
++ * For now only respond to softbutton == 0x01, some
++ * tablets *without* a capacative button send 0x04
++ * when crossing the edges of the screen.
++ */
++ if (softbutton == 0x01)
++ softbutton_pressed = true;
++
++ continue;
++ }
++
++ /*
++ * Bits 4-7 are the touch id, note not all models have
++ * hardware touch ids so atm we don't use these.
++ */
++ data->id[touch_nr] = (bufp[SILEAD_POINT_X_MSB_OFF] &
++ SILEAD_EXTRA_DATA_MASK) >> 4;
++ touchscreen_set_mt_pos(&data->pos[touch_nr], &data->prop,
+ get_unaligned_le16(&bufp[SILEAD_POINT_X_OFF]) & 0xfff,
+ get_unaligned_le16(&bufp[SILEAD_POINT_Y_OFF]) & 0xfff);
++ touch_nr++;
+ }
+
+ input_mt_assign_slots(input, data->slots, data->pos, touch_nr, 0);
+@@ -178,6 +200,7 @@ static void silead_ts_read_data(struct i2c_client *client)
+ }
+
+ input_mt_sync_frame(input);
++ input_report_key(input, KEY_LEFTMETA, softbutton_pressed);
+ input_sync(input);
+ }
+
+--
+2.13.0
+
diff --git a/0011-Input-goodix-Add-support-for-capacitive-home-button.patch b/0011-Input-goodix-Add-support-for-capacitive-home-button.patch
new file mode 100644
index 000000000..162357c21
--- /dev/null
+++ b/0011-Input-goodix-Add-support-for-capacitive-home-button.patch
@@ -0,0 +1,53 @@
+From 2a99775c336303d2efc43eab4f24b34722a28faa Mon Sep 17 00:00:00 2001
+From: "Sergei A. Trusov" <sergei.a.trusov@ya.ru>
+Date: Tue, 20 Jun 2017 18:08:35 +0200
+Subject: [PATCH 11/16] Input: goodix: Add support for capacitive home button
+
+On some x86 tablets with a Goodix touchscreen, the Windows logo on the
+front is a capacitive home button. Touching this button results in a touch
+with bit 4 of the first byte set, while only the lower 4 bits (0-3) are
+used to indicate the number of touches.
+
+Report a KEY_LEFTMETA press when this happens.
+
+Note that the hardware might support more than one button, in which
+case the "id" byte of coor_data would identify the button in question.
+This is not implemented as we don't have access to hardware with
+multiple buttons.
+
+Signed-off-by: Sergei A. Trusov <sergei.a.trusov@ya.ru>
+Acked-by: Bastien Nocera <hadess@hadess.net>
+---
+ drivers/input/touchscreen/goodix.c | 9 +++++++++
+ 1 file changed, 9 insertions(+)
+
+diff --git a/drivers/input/touchscreen/goodix.c b/drivers/input/touchscreen/goodix.c
+index 240b16f3ee97..903137d9cf7d 100644
+--- a/drivers/input/touchscreen/goodix.c
++++ b/drivers/input/touchscreen/goodix.c
+@@ -267,6 +267,12 @@ static void goodix_process_events(struct goodix_ts_data *ts)
+ if (touch_num < 0)
+ return;
+
++ /*
++ * Bit 4 of the first byte reports the status of the capacitive
++ * Windows/Home button.
++ */
++ input_report_key(ts->input_dev, KEY_LEFTMETA, !!(point_data[0] & BIT(4)));
++
+ for (i = 0; i < touch_num; i++)
+ goodix_ts_report_touch(ts,
+ &point_data[1 + GOODIX_CONTACT_SIZE * i]);
+@@ -612,6 +618,9 @@ static int goodix_request_input_dev(struct goodix_ts_data *ts)
+ ts->input_dev->id.product = ts->id;
+ ts->input_dev->id.version = ts->version;
+
++ /* Capacitive Windows/Home button on some devices */
++ input_set_capability(ts->input_dev, EV_KEY, KEY_LEFTMETA);
++
+ error = input_register_device(ts->input_dev);
+ if (error) {
+ dev_err(&ts->client->dev,
+--
+2.13.0
+
diff --git a/0012-Input-gpio_keys-Do-not-report-wake-button-presses-as.patch b/0012-Input-gpio_keys-Do-not-report-wake-button-presses-as.patch
new file mode 100644
index 000000000..9b52e3908
--- /dev/null
+++ b/0012-Input-gpio_keys-Do-not-report-wake-button-presses-as.patch
@@ -0,0 +1,150 @@
+From 02b823a4d28ffb5fde5192799abd934d9de95630 Mon Sep 17 00:00:00 2001
+From: Hans de Goede <hdegoede@redhat.com>
+Date: Fri, 6 Jan 2017 20:08:11 +0100
+Subject: [PATCH 12/16] Input: gpio_keys - Do not report wake button presses as
+ evdev events
+
+If a button is a wake button, it may still be bouncing from the press
+to wakeup the device by the time the gpio interrupts get enabled again
+and / or the gpio_keys_report_state call from gpio_keys_resume may
+find the button still pressed and report this as a new press.
+
+This is undesirable, esp. since the powerbutton on tablets is typically
+a wakeup source and uses the gpio_keys driver on some tablets, leading
+to userspace immediately re-suspending the tablet after the powerbutton
+is pressed, due to it seeing a powerbutton press.
+
+This commit ignores wakeup button presses for the first 1 second after
+resume (and while resumed, as the workqueue may run before the resume
+function runs), avoiding this problem.
+
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+---
+Note: maybe we should make WAKE_DEBOUNCE part of gpio_keys_button and
+only do this when drivers / platform-data set this to a non-zero value ?
+---
+ drivers/input/keyboard/gpio_keys.c | 49 ++++++++++++++++++++++++++++++++++++--
+ 1 file changed, 47 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/input/keyboard/gpio_keys.c b/drivers/input/keyboard/gpio_keys.c
+index da3d362f21b1..e1488b534e7d 100644
+--- a/drivers/input/keyboard/gpio_keys.c
++++ b/drivers/input/keyboard/gpio_keys.c
+@@ -31,6 +31,8 @@
+ #include <linux/of_irq.h>
+ #include <linux/spinlock.h>
+
++#define WAKE_DEBOUNCE msecs_to_jiffies(1000)
++
+ struct gpio_button_data {
+ const struct gpio_keys_button *button;
+ struct input_dev *input;
+@@ -44,10 +46,14 @@ struct gpio_button_data {
+ struct delayed_work work;
+ unsigned int software_debounce; /* in msecs, for GPIO-driven buttons */
+
++ unsigned long resume_time; /* in jiffies, for wakeup buttons */
++
+ unsigned int irq;
+ spinlock_t lock;
+ bool disabled;
+ bool key_pressed;
++ bool suspended;
++ bool resume_time_valid;
+ };
+
+ struct gpio_keys_drvdata {
+@@ -356,6 +362,27 @@ static struct attribute_group gpio_keys_attr_group = {
+ .attrs = gpio_keys_attrs,
+ };
+
++static bool gpio_keys_ignore_wakeup_button_press(struct gpio_button_data *bdata)
++{
++ unsigned long flags;
++ bool ret = false;
++
++ if (!bdata->button->wakeup)
++ return ret;
++
++ spin_lock_irqsave(&bdata->lock, flags);
++
++ if (bdata->suspended)
++ ret = true; /* Our resume method did not run yet */
++ else if (bdata->resume_time_valid &&
++ time_before(jiffies, bdata->resume_time + WAKE_DEBOUNCE))
++ ret = true; /* Assume this is a wakeup press and ignore */
++
++ spin_unlock_irqrestore(&bdata->lock, flags);
++
++ return ret;
++}
++
+ static void gpio_keys_gpio_report_event(struct gpio_button_data *bdata)
+ {
+ const struct gpio_keys_button *button = bdata->button;
+@@ -370,6 +397,9 @@ static void gpio_keys_gpio_report_event(struct gpio_button_data *bdata)
+ return;
+ }
+
++ if (state && gpio_keys_ignore_wakeup_button_press(bdata))
++ return;
++
+ if (type == EV_ABS) {
+ if (state)
+ input_event(input, type, button->code, button->value);
+@@ -429,6 +459,9 @@ static irqreturn_t gpio_keys_irq_isr(int irq, void *dev_id)
+
+ BUG_ON(irq != bdata->irq);
+
++ if (gpio_keys_ignore_wakeup_button_press(bdata))
++ return IRQ_HANDLED;
++
+ spin_lock_irqsave(&bdata->lock, flags);
+
+ if (!bdata->key_pressed) {
+@@ -848,13 +881,18 @@ static int __maybe_unused gpio_keys_suspend(struct device *dev)
+ {
+ struct gpio_keys_drvdata *ddata = dev_get_drvdata(dev);
+ struct input_dev *input = ddata->input;
++ unsigned long flags;
+ int i;
+
+ if (device_may_wakeup(dev)) {
+ for (i = 0; i < ddata->pdata->nbuttons; i++) {
+ struct gpio_button_data *bdata = &ddata->data[i];
+- if (bdata->button->wakeup)
++ if (bdata->button->wakeup) {
++ spin_lock_irqsave(&bdata->lock, flags);
++ bdata->suspended = true;
++ spin_unlock_irqrestore(&bdata->lock, flags);
+ enable_irq_wake(bdata->irq);
++ }
+ }
+ } else {
+ mutex_lock(&input->mutex);
+@@ -870,14 +908,21 @@ static int __maybe_unused gpio_keys_resume(struct device *dev)
+ {
+ struct gpio_keys_drvdata *ddata = dev_get_drvdata(dev);
+ struct input_dev *input = ddata->input;
++ unsigned long flags;
+ int error = 0;
+ int i;
+
+ if (device_may_wakeup(dev)) {
+ for (i = 0; i < ddata->pdata->nbuttons; i++) {
+ struct gpio_button_data *bdata = &ddata->data[i];
+- if (bdata->button->wakeup)
++ if (bdata->button->wakeup) {
+ disable_irq_wake(bdata->irq);
++ spin_lock_irqsave(&bdata->lock, flags);
++ bdata->resume_time = jiffies;
++ bdata->resume_time_valid = true;
++ bdata->suspended = false;
++ spin_unlock_irqrestore(&bdata->lock, flags);
++ }
+ }
+ } else {
+ mutex_lock(&input->mutex);
+--
+2.13.0
+
diff --git a/0013-iio-accel-bmc150-Add-support-for-BOSC0200-ACPI-devic.patch b/0013-iio-accel-bmc150-Add-support-for-BOSC0200-ACPI-devic.patch
new file mode 100644
index 000000000..8eb41ee3f
--- /dev/null
+++ b/0013-iio-accel-bmc150-Add-support-for-BOSC0200-ACPI-devic.patch
@@ -0,0 +1,32 @@
+From bf3e9581e10a19b2ce77a45fe001116d269b4c7f Mon Sep 17 00:00:00 2001
+From: Hans de Goede <hdegoede@redhat.com>
+Date: Sun, 18 Jun 2017 12:47:38 +0200
+Subject: [PATCH 13/16] iio: accel: bmc150: Add support for BOSC0200 ACPI
+ device id
+
+Add support for the BOSC0200 ACPI device id used on some x86 tablets.
+note driver_data is not set to a specific model, driver_data is not
+used anyways (instead detection is done on the chip_id reg) and the
+2 tablets with a BOSC0200 ACPI device id I've have 2 different chips,
+one has a BMA250E, the other a BMA222E.
+
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+---
+ drivers/iio/accel/bmc150-accel-i2c.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/drivers/iio/accel/bmc150-accel-i2c.c b/drivers/iio/accel/bmc150-accel-i2c.c
+index 8ca8041267ef..f85014fbaa12 100644
+--- a/drivers/iio/accel/bmc150-accel-i2c.c
++++ b/drivers/iio/accel/bmc150-accel-i2c.c
+@@ -64,6 +64,7 @@ static const struct acpi_device_id bmc150_accel_acpi_match[] = {
+ {"BMA250E", bma250e},
+ {"BMA222E", bma222e},
+ {"BMA0280", bma280},
++ {"BOSC0200"},
+ { },
+ };
+ MODULE_DEVICE_TABLE(acpi, bmc150_accel_acpi_match);
+--
+2.13.0
+
diff --git a/0014-mmc-sdhci-acpi-Workaround-conflict-with-PCI-wifi-on-.patch b/0014-mmc-sdhci-acpi-Workaround-conflict-with-PCI-wifi-on-.patch
new file mode 100644
index 000000000..b5c717c64
--- /dev/null
+++ b/0014-mmc-sdhci-acpi-Workaround-conflict-with-PCI-wifi-on-.patch
@@ -0,0 +1,143 @@
+From 51eb7454942c68c84b82782e47637de3ba37f113 Mon Sep 17 00:00:00 2001
+From: Adrian Hunter <adrian.hunter@intel.com>
+Date: Wed, 21 Jun 2017 15:08:39 +0300
+Subject: [PATCH 14/16] mmc: sdhci-acpi: Workaround conflict with PCI wifi on
+ GPD Win handheld
+
+GPDwin uses PCI wifi which conflicts with SDIO's use of
+acpi_device_fix_up_power() on child device nodes. Specifically
+acpi_device_fix_up_power() causes the wifi module to get turned off.
+Identifying GPDwin is problematic, but since SDIO is only used for wifi,
+the presence of the PCI wifi card in the expected slot with an ACPI
+companion node, is used to indicate that acpi_device_fix_up_power() should
+be avoided.
+
+Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
+Acked-by: Hans de Goede <hdegoede@redhat.com>
+Tested-by: Hans de Goede <hdegoede@redhat.com>
+Cc: stable@vger.kernel.org
+---
+ drivers/mmc/host/sdhci-acpi.c | 70 +++++++++++++++++++++++++++++++++++++++----
+ 1 file changed, 64 insertions(+), 6 deletions(-)
+
+diff --git a/drivers/mmc/host/sdhci-acpi.c b/drivers/mmc/host/sdhci-acpi.c
+index c6a9a1bfaa22..b3fb155f50e4 100644
+--- a/drivers/mmc/host/sdhci-acpi.c
++++ b/drivers/mmc/host/sdhci-acpi.c
+@@ -45,6 +45,7 @@
+ #include <asm/cpu_device_id.h>
+ #include <asm/intel-family.h>
+ #include <asm/iosf_mbi.h>
++#include <linux/pci.h>
+ #endif
+
+ #include "sdhci.h"
+@@ -134,6 +135,16 @@ static bool sdhci_acpi_byt(void)
+ return x86_match_cpu(byt);
+ }
+
++static bool sdhci_acpi_cht(void)
++{
++ static const struct x86_cpu_id cht[] = {
++ { X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_AIRMONT },
++ {}
++ };
++
++ return x86_match_cpu(cht);
++}
++
+ #define BYT_IOSF_SCCEP 0x63
+ #define BYT_IOSF_OCP_NETCTRL0 0x1078
+ #define BYT_IOSF_OCP_TIMEOUT_BASE GENMASK(10, 8)
+@@ -178,6 +189,45 @@ static bool sdhci_acpi_byt_defer(struct device *dev)
+ return false;
+ }
+
++static bool sdhci_acpi_cht_pci_wifi(unsigned int vendor, unsigned int device,
++ unsigned int slot, unsigned int parent_slot)
++{
++ struct pci_dev *dev, *parent, *from = NULL;
++
++ while (1) {
++ dev = pci_get_device(vendor, device, from);
++ pci_dev_put(from);
++ if (!dev)
++ break;
++ parent = pci_upstream_bridge(dev);
++ if (ACPI_COMPANION(&dev->dev) && PCI_SLOT(dev->devfn) == slot &&
++ parent && PCI_SLOT(parent->devfn) == parent_slot &&
++ !pci_upstream_bridge(parent)) {
++ pci_dev_put(dev);
++ return true;
++ }
++ from = dev;
++ }
++
++ return false;
++}
++
++/*
++ * GPDwin uses PCI wifi which conflicts with SDIO's use of
++ * acpi_device_fix_up_power() on child device nodes. Identifying GPDwin is
++ * problematic, but since SDIO is only used for wifi, the presence of the PCI
++ * wifi card in the expected slot with an ACPI companion node, is used to
++ * indicate that acpi_device_fix_up_power() should be avoided.
++ */
++static inline bool sdhci_acpi_no_fixup_child_power(const char *hid,
++ const char *uid)
++{
++ return sdhci_acpi_cht() &&
++ !strcmp(hid, "80860F14") &&
++ !strcmp(uid, "2") &&
++ sdhci_acpi_cht_pci_wifi(0x14e4, 0x43ec, 0, 28);
++}
++
+ #else
+
+ static inline void sdhci_acpi_byt_setting(struct device *dev)
+@@ -189,6 +239,12 @@ static inline bool sdhci_acpi_byt_defer(struct device *dev)
+ return false;
+ }
+
++static inline bool sdhci_acpi_no_fixup_child_power(const char *hid,
++ const char *uid)
++{
++ return false;
++}
++
+ #endif
+
+ static int bxt_get_cd(struct mmc_host *mmc)
+@@ -390,11 +446,16 @@ static int sdhci_acpi_probe(struct platform_device *pdev)
+ if (acpi_bus_get_device(handle, &device))
+ return -ENODEV;
+
++ hid = acpi_device_hid(device);
++ uid = device->pnp.unique_id;
++
+ /* Power on the SDHCI controller and its children */
+ acpi_device_fix_up_power(device);
+- list_for_each_entry(child, &device->children, node)
+- if (child->status.present && child->status.enabled)
+- acpi_device_fix_up_power(child);
++ if (!sdhci_acpi_no_fixup_child_power(hid, uid)) {
++ list_for_each_entry(child, &device->children, node)
++ if (child->status.present && child->status.enabled)
++ acpi_device_fix_up_power(child);
++ }
+
+ if (acpi_bus_get_status(device) || !device->status.present)
+ return -ENODEV;
+@@ -402,9 +463,6 @@ static int sdhci_acpi_probe(struct platform_device *pdev)
+ if (sdhci_acpi_byt_defer(dev))
+ return -EPROBE_DEFER;
+
+- hid = acpi_device_hid(device);
+- uid = device->pnp.unique_id;
+-
+ iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!iomem)
+ return -ENOMEM;
+--
+2.13.0
+
diff --git a/0015-i2c-cht-wc-Add-Intel-Cherry-Trail-Whiskey-Cove-SMBUS.patch b/0015-i2c-cht-wc-Add-Intel-Cherry-Trail-Whiskey-Cove-SMBUS.patch
new file mode 100644
index 000000000..5d7497ce1
--- /dev/null
+++ b/0015-i2c-cht-wc-Add-Intel-Cherry-Trail-Whiskey-Cove-SMBUS.patch
@@ -0,0 +1,410 @@
+From bd0d7169342e47919f68e75d659968f02b62f84b Mon Sep 17 00:00:00 2001
+From: Hans de Goede <hdegoede@redhat.com>
+Date: Fri, 3 Mar 2017 23:48:50 +0100
+Subject: [PATCH 15/16] i2c-cht-wc: Add Intel Cherry Trail Whiskey Cove SMBUS
+ controller driver
+
+The Intel Cherry Trail Whiskey Cove PMIC does not contain a builtin
+battery charger, instead boards with this PMIC use an external TI
+bq24292i charger IC, which is connected to a SMBUS controller built into
+the PMIC.
+
+This commit adds an i2c-bus driver for the PMIC's builtin SMBUS
+controller. The probe function for this i2c-bus will also register an
+i2c-client for the TI bq24292i charger after the i2c-bus has been
+registered.
+
+Note that several device-properties are set on the client-device to
+tell the bq24190 power-supply driver to integrate the Whiskey Cove PMIC
+and e.g. use the PMIC's BC1.2 detection (through extcon) to determine
+the maximum input current.
+
+Cc: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+---
+Changes in v2:
+-Various style (mostly captialization and variable name) fixes
+-Use device-properties instead of platform_data for the i2c_board_info
+---
+ drivers/i2c/busses/Kconfig | 8 +
+ drivers/i2c/busses/Makefile | 1 +
+ drivers/i2c/busses/i2c-cht-wc.c | 336 ++++++++++++++++++++++++++++++++++++++++
+ 3 files changed, 345 insertions(+)
+ create mode 100644 drivers/i2c/busses/i2c-cht-wc.c
+
+diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
+index 144cbadc7c72..18c96178b177 100644
+--- a/drivers/i2c/busses/Kconfig
++++ b/drivers/i2c/busses/Kconfig
+@@ -187,6 +187,14 @@ config I2C_PIIX4
+ This driver can also be built as a module. If so, the module
+ will be called i2c-piix4.
+
++config I2C_CHT_WC
++ tristate "Intel Cherry Trail Whiskey Cove PMIC smbus controller"
++ depends on INTEL_SOC_PMIC_CHTWC
++ help
++ If you say yes to this option, support will be included for the
++ SMBus controller found in the Intel Cherry Trail Whiskey Cove PMIC
++ found on some Intel Cherry Trail systems.
++
+ config I2C_NFORCE2
+ tristate "Nvidia nForce2, nForce3 and nForce4"
+ depends on PCI
+diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile
+index 30b60855fbcd..f6443fa44f61 100644
+--- a/drivers/i2c/busses/Makefile
++++ b/drivers/i2c/busses/Makefile
+@@ -12,6 +12,7 @@ obj-$(CONFIG_I2C_ALI15X3) += i2c-ali15x3.o
+ obj-$(CONFIG_I2C_AMD756) += i2c-amd756.o
+ obj-$(CONFIG_I2C_AMD756_S4882) += i2c-amd756-s4882.o
+ obj-$(CONFIG_I2C_AMD8111) += i2c-amd8111.o
++obj-$(CONFIG_I2C_CHT_WC) += i2c-cht-wc.o
+ obj-$(CONFIG_I2C_I801) += i2c-i801.o
+ obj-$(CONFIG_I2C_ISCH) += i2c-isch.o
+ obj-$(CONFIG_I2C_ISMT) += i2c-ismt.o
+diff --git a/drivers/i2c/busses/i2c-cht-wc.c b/drivers/i2c/busses/i2c-cht-wc.c
+new file mode 100644
+index 000000000000..ccf0785bcb75
+--- /dev/null
++++ b/drivers/i2c/busses/i2c-cht-wc.c
+@@ -0,0 +1,336 @@
++/*
++ * Intel CHT Whiskey Cove PMIC I2C Master driver
++ * Copyright (C) 2017 Hans de Goede <hdegoede@redhat.com>
++ *
++ * Based on various non upstream patches to support the CHT Whiskey Cove PMIC:
++ * Copyright (C) 2011 - 2014 Intel Corporation. All rights reserved.
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License version
++ * 2 as published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ */
++
++#include <linux/completion.h>
++#include <linux/delay.h>
++#include <linux/i2c.h>
++#include <linux/interrupt.h>
++#include <linux/irq.h>
++#include <linux/irqdomain.h>
++#include <linux/mfd/intel_soc_pmic.h>
++#include <linux/module.h>
++#include <linux/platform_device.h>
++#include <linux/slab.h>
++
++#define CHT_WC_I2C_CTRL 0x5e24
++#define CHT_WC_I2C_CTRL_WR BIT(0)
++#define CHT_WC_I2C_CTRL_RD BIT(1)
++#define CHT_WC_I2C_CLIENT_ADDR 0x5e25
++#define CHT_WC_I2C_REG_OFFSET 0x5e26
++#define CHT_WC_I2C_WRDATA 0x5e27
++#define CHT_WC_I2C_RDDATA 0x5e28
++
++#define CHT_WC_EXTCHGRIRQ 0x6e0a
++#define CHT_WC_EXTCHGRIRQ_CLIENT_IRQ BIT(0)
++#define CHT_WC_EXTCHGRIRQ_WRITE_IRQ BIT(1)
++#define CHT_WC_EXTCHGRIRQ_READ_IRQ BIT(2)
++#define CHT_WC_EXTCHGRIRQ_NACK_IRQ BIT(3)
++#define CHT_WC_EXTCHGRIRQ_ADAP_IRQMASK ((u8)GENMASK(3, 1))
++#define CHT_WC_EXTCHGRIRQ_MSK 0x6e17
++
++struct cht_wc_i2c_adap {
++ struct i2c_adapter adapter;
++ wait_queue_head_t wait;
++ struct irq_chip irqchip;
++ struct mutex irqchip_lock;
++ struct regmap *regmap;
++ struct irq_domain *irq_domain;
++ struct i2c_client *client;
++ int client_irq;
++ u8 irq_mask;
++ u8 old_irq_mask;
++ bool nack;
++ bool done;
++};
++
++static irqreturn_t cht_wc_i2c_adap_thread_handler(int id, void *data)
++{
++ struct cht_wc_i2c_adap *adap = data;
++ int ret, reg;
++
++ /* Read IRQs */
++ ret = regmap_read(adap->regmap, CHT_WC_EXTCHGRIRQ, &reg);
++ if (ret) {
++ dev_err(&adap->adapter.dev, "Error reading extchgrirq reg\n");
++ return IRQ_NONE;
++ }
++
++ reg &= ~adap->irq_mask;
++
++ /*
++ * Immediately ack IRQs, so that if new IRQs arrives while we're
++ * handling the previous ones our irq will re-trigger when we're done.
++ */
++ ret = regmap_write(adap->regmap, CHT_WC_EXTCHGRIRQ, reg);
++ if (ret)
++ dev_err(&adap->adapter.dev, "Error writing extchgrirq reg\n");
++
++ /*
++ * Do NOT use handle_nested_irq here, the client irq handler will
++ * likely want to do i2c transfers and the i2c controller uses this
++ * interrupt handler as well, so running the client irq handler from
++ * this thread will cause things to lock up.
++ */
++ if (reg & CHT_WC_EXTCHGRIRQ_CLIENT_IRQ) {
++ /*
++ * generic_handle_irq expects local IRQs to be disabled
++ * as normally it is called from interrupt context.
++ */
++ local_irq_disable();
++ generic_handle_irq(adap->client_irq);
++ local_irq_enable();
++ }
++
++ if (reg & CHT_WC_EXTCHGRIRQ_ADAP_IRQMASK) {
++ adap->nack = !!(reg & CHT_WC_EXTCHGRIRQ_NACK_IRQ);
++ adap->done = true;
++ wake_up(&adap->wait);
++ }
++
++ return IRQ_HANDLED;
++}
++
++static u32 cht_wc_i2c_adap_master_func(struct i2c_adapter *adap)
++{
++ /* This i2c adapter only supports SMBUS byte transfers */
++ return I2C_FUNC_SMBUS_BYTE_DATA;
++}
++
++static int cht_wc_i2c_adap_smbus_xfer(struct i2c_adapter *_adap, u16 addr,
++ unsigned short flags, char read_write,
++ u8 command, int size,
++ union i2c_smbus_data *data)
++{
++ struct cht_wc_i2c_adap *adap = i2c_get_adapdata(_adap);
++ int ret, reg;
++
++ adap->nack = false;
++ adap->done = false;
++
++ ret = regmap_write(adap->regmap, CHT_WC_I2C_CLIENT_ADDR, addr);
++ if (ret)
++ return ret;
++
++ if (read_write == I2C_SMBUS_WRITE) {
++ ret = regmap_write(adap->regmap, CHT_WC_I2C_WRDATA, data->byte);
++ if (ret)
++ return ret;
++ }
++
++ ret = regmap_write(adap->regmap, CHT_WC_I2C_REG_OFFSET, command);
++ if (ret)
++ return ret;
++
++ ret = regmap_write(adap->regmap, CHT_WC_I2C_CTRL,
++ (read_write == I2C_SMBUS_WRITE) ?
++ CHT_WC_I2C_CTRL_WR : CHT_WC_I2C_CTRL_RD);
++ if (ret)
++ return ret;
++
++ /* 3 second timeout, during cable plug the PMIC responds quite slow */
++ ret = wait_event_timeout(adap->wait, adap->done, 3 * HZ);
++ if (ret == 0)
++ return -ETIMEDOUT;
++ if (adap->nack)
++ return -EIO;
++
++ if (read_write == I2C_SMBUS_READ) {
++ ret = regmap_read(adap->regmap, CHT_WC_I2C_RDDATA, &reg);
++ if (ret)
++ return ret;
++
++ data->byte = reg;
++ }
++
++ return 0;
++}
++
++static const struct i2c_algorithm cht_wc_i2c_adap_algo = {
++ .functionality = cht_wc_i2c_adap_master_func,
++ .smbus_xfer = cht_wc_i2c_adap_smbus_xfer,
++};
++
++/**** irqchip for the client connected to the extchgr i2c adapter ****/
++static void cht_wc_i2c_irq_lock(struct irq_data *data)
++{
++ struct cht_wc_i2c_adap *adap = irq_data_get_irq_chip_data(data);
++
++ mutex_lock(&adap->irqchip_lock);
++}
++
++static void cht_wc_i2c_irq_sync_unlock(struct irq_data *data)
++{
++ struct cht_wc_i2c_adap *adap = irq_data_get_irq_chip_data(data);
++ int ret;
++
++ if (adap->irq_mask != adap->old_irq_mask) {
++ ret = regmap_write(adap->regmap, CHT_WC_EXTCHGRIRQ_MSK,
++ adap->irq_mask);
++ if (ret == 0)
++ adap->old_irq_mask = adap->irq_mask;
++ else
++ dev_err(&adap->adapter.dev, "Error writing EXTCHGRIRQ_MSK\n");
++ }
++
++ mutex_unlock(&adap->irqchip_lock);
++}
++
++static void cht_wc_i2c_irq_enable(struct irq_data *data)
++{
++ struct cht_wc_i2c_adap *adap = irq_data_get_irq_chip_data(data);
++
++ adap->irq_mask &= ~CHT_WC_EXTCHGRIRQ_CLIENT_IRQ;
++}
++
++static void cht_wc_i2c_irq_disable(struct irq_data *data)
++{
++ struct cht_wc_i2c_adap *adap = irq_data_get_irq_chip_data(data);
++
++ adap->irq_mask |= CHT_WC_EXTCHGRIRQ_CLIENT_IRQ;
++}
++
++static const struct irq_chip cht_wc_i2c_irq_chip = {
++ .irq_bus_lock = cht_wc_i2c_irq_lock,
++ .irq_bus_sync_unlock = cht_wc_i2c_irq_sync_unlock,
++ .irq_disable = cht_wc_i2c_irq_disable,
++ .irq_enable = cht_wc_i2c_irq_enable,
++ .name = "cht_wc_ext_chrg_irq_chip",
++};
++
++static const struct property_entry bq24190_props[] = {
++ PROPERTY_ENTRY_STRING("extcon-name", "cht_wcove_pwrsrc"),
++ PROPERTY_ENTRY_BOOL("omit-battery-class"),
++ PROPERTY_ENTRY_BOOL("disable-reset"),
++ { }
++};
++
++static int cht_wc_i2c_adap_i2c_probe(struct platform_device *pdev)
++{
++ struct intel_soc_pmic *pmic = dev_get_drvdata(pdev->dev.parent);
++ struct cht_wc_i2c_adap *adap;
++ struct i2c_board_info board_info = {
++ .type = "bq24190",
++ .addr = 0x6b,
++ .properties = bq24190_props,
++ };
++ int ret, irq;
++
++ irq = platform_get_irq(pdev, 0);
++ if (irq < 0) {
++ dev_err(&pdev->dev, "Error missing irq resource\n");
++ return -EINVAL;
++ }
++
++ adap = devm_kzalloc(&pdev->dev, sizeof(*adap), GFP_KERNEL);
++ if (!adap)
++ return -ENOMEM;
++
++ init_waitqueue_head(&adap->wait);
++ mutex_init(&adap->irqchip_lock);
++ adap->irqchip = cht_wc_i2c_irq_chip;
++ adap->regmap = pmic->regmap;
++ adap->adapter.owner = THIS_MODULE;
++ adap->adapter.class = I2C_CLASS_HWMON;
++ adap->adapter.algo = &cht_wc_i2c_adap_algo;
++ strlcpy(adap->adapter.name, "PMIC I2C Adapter",
++ sizeof(adap->adapter.name));
++ adap->adapter.dev.parent = &pdev->dev;
++
++ /* Clear and activate i2c-adapter interrupts, disable client IRQ */
++ adap->old_irq_mask = adap->irq_mask = ~CHT_WC_EXTCHGRIRQ_ADAP_IRQMASK;
++ ret = regmap_write(adap->regmap, CHT_WC_EXTCHGRIRQ, ~adap->irq_mask);
++ if (ret)
++ return ret;
++
++ ret = regmap_write(adap->regmap, CHT_WC_EXTCHGRIRQ_MSK, adap->irq_mask);
++ if (ret)
++ return ret;
++
++ /* Alloc and register client IRQ */
++ adap->irq_domain = irq_domain_add_linear(pdev->dev.of_node, 1,
++ &irq_domain_simple_ops, NULL);
++ if (!adap->irq_domain)
++ return -ENOMEM;
++
++ adap->client_irq = irq_create_mapping(adap->irq_domain, 0);
++ if (!adap->client_irq) {
++ ret = -ENOMEM;
++ goto remove_irq_domain;
++ }
++
++ irq_set_chip_data(adap->client_irq, adap);
++ irq_set_chip_and_handler(adap->client_irq, &adap->irqchip,
++ handle_simple_irq);
++
++ ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,
++ cht_wc_i2c_adap_thread_handler,
++ IRQF_ONESHOT, "PMIC I2C Adapter", adap);
++ if (ret)
++ goto remove_irq_domain;
++
++ i2c_set_adapdata(&adap->adapter, adap);
++ ret = i2c_add_adapter(&adap->adapter);
++ if (ret)
++ goto remove_irq_domain;
++
++ board_info.irq = adap->client_irq;
++ adap->client = i2c_new_device(&adap->adapter, &board_info);
++ if (!adap->client) {
++ ret = -ENOMEM;
++ goto del_adapter;
++ }
++
++ platform_set_drvdata(pdev, adap);
++ return 0;
++
++del_adapter:
++ i2c_del_adapter(&adap->adapter);
++remove_irq_domain:
++ irq_domain_remove(adap->irq_domain);
++ return ret;
++}
++
++static int cht_wc_i2c_adap_i2c_remove(struct platform_device *pdev)
++{
++ struct cht_wc_i2c_adap *adap = platform_get_drvdata(pdev);
++
++ i2c_unregister_device(adap->client);
++ i2c_del_adapter(&adap->adapter);
++ irq_domain_remove(adap->irq_domain);
++
++ return 0;
++}
++
++static struct platform_device_id cht_wc_i2c_adap_id_table[] = {
++ { .name = "cht_wcove_ext_chgr" },
++ {},
++};
++MODULE_DEVICE_TABLE(platform, cht_wc_i2c_adap_id_table);
++
++struct platform_driver cht_wc_i2c_adap_driver = {
++ .probe = cht_wc_i2c_adap_i2c_probe,
++ .remove = cht_wc_i2c_adap_i2c_remove,
++ .driver = {
++ .name = "cht_wcove_ext_chgr",
++ },
++ .id_table = cht_wc_i2c_adap_id_table,
++};
++module_platform_driver(cht_wc_i2c_adap_driver);
++
++MODULE_DESCRIPTION("Intel CHT Whiskey Cove PMIC I2C Master driver");
++MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>");
++MODULE_LICENSE("GPL");
+--
+2.13.0
+
diff --git a/0016-Input-silead-Do-not-try-to-directly-access-the-GPIO-.patch b/0016-Input-silead-Do-not-try-to-directly-access-the-GPIO-.patch
new file mode 100644
index 000000000..14b4c27bf
--- /dev/null
+++ b/0016-Input-silead-Do-not-try-to-directly-access-the-GPIO-.patch
@@ -0,0 +1,54 @@
+From fd4fb1f6633b21042ff084868323e15e708fe1cd Mon Sep 17 00:00:00 2001
+From: Hans de Goede <hdegoede@redhat.com>
+Date: Sun, 1 Jan 2017 22:11:20 +0100
+Subject: [PATCH 16/16] Input: silead: Do not try to directly access the GPIO
+ when using ACPI pm
+
+On some x86 tablets we cannot directly access the GPIOs as they are
+claimed by the ACPI tables, so check it the i2c client is not being
+power-managed by ACPI before trying to get the power pin GPIO.
+
+Note this is a workaround patch to fix this until Andy' gpiolib-ACPI
+patches which make gpiolib more strict land, once those are landed this
+patch is no longer needed.
+
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+---
+ drivers/input/touchscreen/silead.c | 22 ++++++++++++++++------
+ 1 file changed, 16 insertions(+), 6 deletions(-)
+
+diff --git a/drivers/input/touchscreen/silead.c b/drivers/input/touchscreen/silead.c
+index c0ba40c09699..30fba3cbe277 100644
+--- a/drivers/input/touchscreen/silead.c
++++ b/drivers/input/touchscreen/silead.c
+@@ -517,12 +518,21 @@ static int silead_ts_probe(struct i2c_client *client,
+ if (error)
+ return error;
+
+- /* Power GPIO pin */
+- data->gpio_power = devm_gpiod_get_optional(dev, "power", GPIOD_OUT_LOW);
+- if (IS_ERR(data->gpio_power)) {
+- if (PTR_ERR(data->gpio_power) != -EPROBE_DEFER)
+- dev_err(dev, "Shutdown GPIO request failed\n");
+- return PTR_ERR(data->gpio_power);
++ /*
++ * If device power is not managed by ACPI, get the power_gpio
++ * and manage it ourselves.
++ */
++#ifdef CONFIG_ACPI
++ if (!acpi_bus_power_manageable(ACPI_HANDLE(dev)))
++#endif
++ {
++ data->gpio_power = devm_gpiod_get_optional(dev, "power",
++ GPIOD_OUT_LOW);
++ if (IS_ERR(data->gpio_power)) {
++ if (PTR_ERR(data->gpio_power) != -EPROBE_DEFER)
++ dev_err(dev, "Power GPIO request failed\n");
++ return PTR_ERR(data->gpio_power);
++ }
+ }
+
+ error = silead_ts_setup(client);
+--
+2.13.0
+
diff --git a/KEYS-Allow-unrestricted-boot-time-addition-of-keys-t.patch b/KEYS-Allow-unrestricted-boot-time-addition-of-keys-t.patch
new file mode 100644
index 000000000..1cc1e5370
--- /dev/null
+++ b/KEYS-Allow-unrestricted-boot-time-addition-of-keys-t.patch
@@ -0,0 +1,95 @@
+From fb2ac204a70da565de9ef9a9d6d69a40c2d59727 Mon Sep 17 00:00:00 2001
+From: David Howells <dhowells@redhat.com>
+Date: Fri, 5 May 2017 08:21:56 +0100
+Subject: [PATCH] KEYS: Allow unrestricted boot-time addition of keys to
+ secondary keyring
+
+Allow keys to be added to the system secondary certificates keyring during
+kernel initialisation in an unrestricted fashion. Such keys are implicitly
+trusted and don't have their trust chains checked on link.
+
+This allows keys in the UEFI database to be added in secure boot mode for
+the purposes of module signing.
+
+Signed-off-by: David Howells <dhowells@redhat.com>
+---
+ certs/internal.h | 18 ++++++++++++++++++
+ certs/system_keyring.c | 33 +++++++++++++++++++++++++++++++++
+ 2 files changed, 51 insertions(+)
+ create mode 100644 certs/internal.h
+
+diff --git a/certs/internal.h b/certs/internal.h
+new file mode 100644
+index 0000000..5dcbefb
+--- /dev/null
++++ b/certs/internal.h
+@@ -0,0 +1,18 @@
++/* Internal definitions
++ *
++ * Copyright (C) 2016 Red Hat, Inc. All Rights Reserved.
++ * Written by David Howells (dhowells@redhat.com)
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public Licence
++ * as published by the Free Software Foundation; either version
++ * 2 of the Licence, or (at your option) any later version.
++ */
++
++/*
++ * system_keyring.c
++ */
++#ifdef CONFIG_SECONDARY_TRUSTED_KEYRING
++extern void __init add_trusted_secondary_key(const char *source,
++ const void *data, size_t len);
++#endif
+diff --git a/certs/system_keyring.c b/certs/system_keyring.c
+index 6251d1b..5ac8ba6 100644
+--- a/certs/system_keyring.c
++++ b/certs/system_keyring.c
+@@ -18,6 +18,7 @@
+ #include <keys/asymmetric-type.h>
+ #include <keys/system_keyring.h>
+ #include <crypto/pkcs7.h>
++#include "internal.h"
+
+ static struct key *builtin_trusted_keys;
+ #ifdef CONFIG_SECONDARY_TRUSTED_KEYRING
+@@ -265,3 +266,35 @@ int verify_pkcs7_signature(const void *data, size_t len,
+ EXPORT_SYMBOL_GPL(verify_pkcs7_signature);
+
+ #endif /* CONFIG_SYSTEM_DATA_VERIFICATION */
++
++#ifdef CONFIG_SECONDARY_TRUSTED_KEYRING
++/**
++ * add_trusted_secondary_key - Add to secondary keyring with no validation
++ * @source: Source of key
++ * @data: The blob holding the key
++ * @len: The length of the data blob
++ *
++ * Add a key to the secondary keyring without checking its trust chain. This
++ * is available only during kernel initialisation.
++ */
++void __init add_trusted_secondary_key(const char *source,
++ const void *data, size_t len)
++{
++ key_ref_t key;
++
++ key = key_create_or_update(make_key_ref(secondary_trusted_keys, 1),
++ "asymmetric",
++ NULL, data, len,
++ (KEY_POS_ALL & ~KEY_POS_SETATTR) |
++ KEY_USR_VIEW,
++ KEY_ALLOC_NOT_IN_QUOTA |
++ KEY_ALLOC_BYPASS_RESTRICTION);
++
++ if (IS_ERR(key))
++ pr_err("Problem loading %s X.509 certificate (%ld)\n",
++ source, PTR_ERR(key));
++ else
++ pr_notice("Loaded %s cert '%s' linked to secondary sys keyring\n",
++ source, key_ref_to_ptr(key)->description);
++}
++#endif /* CONFIG_SECONDARY_TRUSTED_KEYRING */
+--
+2.9.3
+
diff --git a/RFC-audit-fix-a-race-condition-with-the-auditd-tracking-code.patch b/RFC-audit-fix-a-race-condition-with-the-auditd-tracking-code.patch
new file mode 100644
index 000000000..d79fd256f
--- /dev/null
+++ b/RFC-audit-fix-a-race-condition-with-the-auditd-tracking-code.patch
@@ -0,0 +1,156 @@
+From patchwork Thu Jun 15 15:28:58 2017
+Content-Type: text/plain; charset="utf-8"
+MIME-Version: 1.0
+Content-Transfer-Encoding: 7bit
+Subject: [RFC] audit: fix a race condition with the auditd tracking code
+From: Paul Moore <pmoore@redhat.com>
+X-Patchwork-Id: 9789009
+Message-Id: <149754053819.11365.5047864735077505545.stgit@sifl>
+To: linux-audit@redhat.com
+Cc: Dusty Mabe <dustymabe@redhat.com>
+Date: Thu, 15 Jun 2017 11:28:58 -0400
+
+From: Paul Moore <paul@paul-moore.com>
+
+Originally reported by Adam and Dusty, it appears we have a small
+race window in kauditd_thread(), as documented in the Fedora BZ:
+
+ * https://bugzilla.redhat.com/show_bug.cgi?id=1459326#c35
+
+ "This issue is partly due to the read-copy nature of RCU, and
+ partly due to how we sync the auditd_connection state across
+ kauditd_thread and the audit control channel. The kauditd_thread
+ thread is always running so it can service the record queues and
+ emit the multicast messages, if it happens to be just past the
+ "main_queue" label, but before the "if (sk == NULL || ...)"
+ if-statement which calls auditd_reset() when the new auditd
+ connection is registered it could end up resetting the auditd
+ connection, regardless of if it is valid or not. This is a rather
+ small window and the variable nature of multi-core scheduling
+ explains why this is proving rather difficult to reproduce."
+
+The fix is to have functions only call auditd_reset() when they
+believe that the kernel/auditd connection is still valid, e.g.
+non-NULL, and to have these callers pass their local copy of the
+auditd_connection pointer to auditd_reset() where it can be compared
+with the current connection state before resetting. If the caller
+has a stale state tracking pointer then the reset is ignored.
+
+We also make a small change to kauditd_thread() so that if the
+kernel/auditd connection is dead we skip the retry queue and send the
+records straight to the hold queue. This is necessary as we used to
+rely on auditd_reset() to occasionally purge the retry queue but we
+are going to be calling the reset function much less now and we want
+to make sure the retry queue doesn't grow unbounded.
+
+Reported-by: Adam Williamson <awilliam@redhat.com>
+Reported-by: Dusty Mabe <dustymabe@redhat.com>
+Signed-off-by: Paul Moore <paul@paul-moore.com>
+Reviewed-by: Richard Guy Briggs <rgb@redhat.com>
+---
+ kernel/audit.c | 36 +++++++++++++++++++++++-------------
+ 1 file changed, 23 insertions(+), 13 deletions(-)
+
+
+--
+Linux-audit mailing list
+Linux-audit@redhat.com
+https://www.redhat.com/mailman/listinfo/linux-audit
+
+diff --git a/kernel/audit.c b/kernel/audit.c
+index b2e877100242..e1e2b3abfb93 100644
+--- a/kernel/audit.c
++++ b/kernel/audit.c
+@@ -575,12 +575,16 @@ static void kauditd_retry_skb(struct sk_buff *skb)
+
+ /**
+ * auditd_reset - Disconnect the auditd connection
++ * @ac: auditd connection state
+ *
+ * Description:
+ * Break the auditd/kauditd connection and move all the queued records into the
+- * hold queue in case auditd reconnects.
++ * hold queue in case auditd reconnects. It is important to note that the @ac
++ * pointer should never be dereferenced inside this function as it may be NULL
++ * or invalid, you can only compare the memory address! If @ac is NULL then
++ * the connection will always be reset.
+ */
+-static void auditd_reset(void)
++static void auditd_reset(const struct auditd_connection *ac)
+ {
+ unsigned long flags;
+ struct sk_buff *skb;
+@@ -590,6 +594,11 @@ static void auditd_reset(void)
+ spin_lock_irqsave(&auditd_conn_lock, flags);
+ ac_old = rcu_dereference_protected(auditd_conn,
+ lockdep_is_held(&auditd_conn_lock));
++ if (ac && ac != ac_old) {
++ /* someone already registered a new auditd connection */
++ spin_unlock_irqrestore(&auditd_conn_lock, flags);
++ return;
++ }
+ rcu_assign_pointer(auditd_conn, NULL);
+ spin_unlock_irqrestore(&auditd_conn_lock, flags);
+
+@@ -649,8 +658,8 @@ static int auditd_send_unicast_skb(struct sk_buff *skb)
+ return rc;
+
+ err:
+- if (rc == -ECONNREFUSED)
+- auditd_reset();
++ if (ac && rc == -ECONNREFUSED)
++ auditd_reset(ac);
+ return rc;
+ }
+
+@@ -795,9 +804,9 @@ static int kauditd_thread(void *dummy)
+ rc = kauditd_send_queue(sk, portid,
+ &audit_hold_queue, UNICAST_RETRIES,
+ NULL, kauditd_rehold_skb);
+- if (rc < 0) {
++ if (ac && rc < 0) {
+ sk = NULL;
+- auditd_reset();
++ auditd_reset(ac);
+ goto main_queue;
+ }
+
+@@ -805,9 +814,9 @@ static int kauditd_thread(void *dummy)
+ rc = kauditd_send_queue(sk, portid,
+ &audit_retry_queue, UNICAST_RETRIES,
+ NULL, kauditd_hold_skb);
+- if (rc < 0) {
++ if (ac && rc < 0) {
+ sk = NULL;
+- auditd_reset();
++ auditd_reset(ac);
+ goto main_queue;
+ }
+
+@@ -815,12 +824,13 @@ static int kauditd_thread(void *dummy)
+ /* process the main queue - do the multicast send and attempt
+ * unicast, dump failed record sends to the retry queue; if
+ * sk == NULL due to previous failures we will just do the
+- * multicast send and move the record to the retry queue */
++ * multicast send and move the record to the hold queue */
+ rc = kauditd_send_queue(sk, portid, &audit_queue, 1,
+ kauditd_send_multicast_skb,
+- kauditd_retry_skb);
+- if (sk == NULL || rc < 0)
+- auditd_reset();
++ (sk ?
++ kauditd_retry_skb : kauditd_hold_skb));
++ if (ac && rc < 0)
++ auditd_reset(ac);
+ sk = NULL;
+
+ /* drop our netns reference, no auditd sends past this line */
+@@ -1230,7 +1240,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
+ auditd_pid, 1);
+
+ /* unregister the auditd connection */
+- auditd_reset();
++ auditd_reset(NULL);
+ }
+ }
+ if (s.mask & AUDIT_STATUS_RATE_LIMIT) {
diff --git a/arm-dts-boneblack-wireless-add-WL1835-Bluetooth-device-node.patch b/arm-dts-boneblack-wireless-add-WL1835-Bluetooth-device-node.patch
new file mode 100644
index 000000000..b4c945697
--- /dev/null
+++ b/arm-dts-boneblack-wireless-add-WL1835-Bluetooth-device-node.patch
@@ -0,0 +1,40 @@
+From patchwork Mon May 22 14:51:38 2017
+Content-Type: text/plain; charset="utf-8"
+MIME-Version: 1.0
+Content-Transfer-Encoding: 7bit
+Subject: arm: dts: boneblack-wireless: add WL1835 Bluetooth device node
+From: Ricardo Salveti <ricardo.salveti@linaro.org>
+X-Patchwork-Id: 9740719
+Message-Id: <1495464701-12046-1-git-send-email-ricardo.salveti@linaro.org>
+To: linux-omap@vger.kernel.org
+Cc: Mark Rutland <mark.rutland@arm.com>,
+ Ricardo Salveti <ricardo.salveti@linaro.org>, devicetree@vger.kernel.org,
+ Tony Lindgren <tony@atomide.com>, Russell King <linux@armlinux.org.uk>,
+ linux-kernel@vger.kernel.org, Rob Herring <robh+dt@kernel.org>,
+ =?UTF-8?q?Beno=C3=AEt=20Cousson?= <bcousson@baylibre.com>,
+ robertcnelson@gmail.com, linux-arm-kernel@lists.infradead.org
+Date: Mon, 22 May 2017 11:51:38 -0300
+
+This adds the serial slave device for the WL1835 Bluetooth interface.
+
+Signed-off-by: Ricardo Salveti <ricardo.salveti@linaro.org>
+---
+ arch/arm/boot/dts/am335x-boneblack-wireless.dts | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+diff --git a/arch/arm/boot/dts/am335x-boneblack-wireless.dts b/arch/arm/boot/dts/am335x-boneblack-wireless.dts
+index 105bd10..83f49f6 100644
+--- a/arch/arm/boot/dts/am335x-boneblack-wireless.dts
++++ b/arch/arm/boot/dts/am335x-boneblack-wireless.dts
+@@ -97,6 +97,11 @@
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart3_pins &bt_pins>;
+ status = "okay";
++
++ bluetooth {
++ compatible = "ti,wl1835-st";
++ enable-gpios = <&gpio0 28 GPIO_ACTIVE_HIGH>;
++ };
+ };
+
+ &gpio3 {
diff --git a/bcm2835-clk-audio-jitter-issues.patch b/bcm2835-clk-audio-jitter-issues.patch
new file mode 100644
index 000000000..91304d64b
--- /dev/null
+++ b/bcm2835-clk-audio-jitter-issues.patch
@@ -0,0 +1,206 @@
+From patchwork Thu Jun 1 14:14:16 2017
+Content-Type: text/plain; charset="utf-8"
+MIME-Version: 1.0
+Content-Transfer-Encoding: 7bit
+Subject: [v4,1/2] clk: bcm2835: Limit PCM clock to OSC and PLLD_PER
+From: Phil Elwell <phil@raspberrypi.org>
+X-Patchwork-Id: 9759641
+Message-Id: <8cc0ba82-d33e-127b-7b86-ac595ef416d1@raspberrypi.org>
+To: Michael Turquette <mturquette@baylibre.com>,
+ Stephen Boyd <sboyd@codeaurora.org>, Eric Anholt <eric@anholt.net>,
+ Stefan Wahren <stefan.wahren@i2se.com>,
+ Florian Fainelli <f.fainelli@gmail.com>,
+ linux-clk@vger.kernel.org, linux-rpi-kernel@lists.infradead.org,
+ linux-kernel@vger.kernel.org
+Date: Thu, 1 Jun 2017 15:14:16 +0100
+
+Restrict clock sources for the PCM peripheral to the oscillator and
+PLLD_PER because other source may have varying rates or be switched off.
+Prevent other sources from being selected by replacing their names in
+the list of potential parents with dummy entries (entry index is
+significant).
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+Reviewed-by: Eric Anholt <eric@anholt.net>
+Acked-by: Stefan Wahren <stefan.wahren@i2se.com>
+---
+ drivers/clk/bcm/clk-bcm2835.c | 27 ++++++++++++++++++++++++++-
+ 1 file changed, 26 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/clk/bcm/clk-bcm2835.c b/drivers/clk/bcm/clk-bcm2835.c
+index 0258538..49867d2 100644
+--- a/drivers/clk/bcm/clk-bcm2835.c
++++ b/drivers/clk/bcm/clk-bcm2835.c
+@@ -1516,6 +1516,31 @@ struct bcm2835_clk_desc {
+ .parents = bcm2835_clock_per_parents, \
+ __VA_ARGS__)
+
++/*
++ * Restrict clock sources for the PCM peripheral to the oscillator and
++ * PLLD_PER because other source may have varying rates or be switched
++ * off.
++ *
++ * Prevent other sources from being selected by replacing their names in
++ * the list of potential parents with dummy entries (entry index is
++ * significant).
++ */
++static const char *const bcm2835_pcm_per_parents[] = {
++ "-",
++ "xosc",
++ "-",
++ "-",
++ "-",
++ "-",
++ "plld_per",
++ "-",
++};
++
++#define REGISTER_PCM_CLK(...) REGISTER_CLK( \
++ .num_mux_parents = ARRAY_SIZE(bcm2835_pcm_per_parents), \
++ .parents = bcm2835_pcm_per_parents, \
++ __VA_ARGS__)
++
+ /* main vpu parent mux */
+ static const char *const bcm2835_clock_vpu_parents[] = {
+ "gnd",
+@@ -1993,7 +2018,7 @@ struct bcm2835_clk_desc {
+ .int_bits = 4,
+ .frac_bits = 8,
+ .tcnt_mux = 22),
+- [BCM2835_CLOCK_PCM] = REGISTER_PER_CLK(
++ [BCM2835_CLOCK_PCM] = REGISTER_PCM_CLK(
+ .name = "pcm",
+ .ctl_reg = CM_PCMCTL,
+ .div_reg = CM_PCMDIV,
+From patchwork Thu Jun 1 14:14:22 2017
+Content-Type: text/plain; charset="utf-8"
+MIME-Version: 1.0
+Content-Transfer-Encoding: 7bit
+Subject: [v4,2/2] clk: bcm2835: Minimise clock jitter for PCM clock
+From: Phil Elwell <phil@raspberrypi.org>
+X-Patchwork-Id: 9759643
+Message-Id: <9989244b-ca4d-9081-95d9-b24f51099222@raspberrypi.org>
+To: Michael Turquette <mturquette@baylibre.com>,
+ Stephen Boyd <sboyd@codeaurora.org>, Eric Anholt <eric@anholt.net>,
+ Stefan Wahren <stefan.wahren@i2se.com>,
+ Florian Fainelli <f.fainelli@gmail.com>,
+ linux-clk@vger.kernel.org, linux-rpi-kernel@lists.infradead.org,
+ linux-kernel@vger.kernel.org
+Date: Thu, 1 Jun 2017 15:14:22 +0100
+
+Fractional clock dividers generate accurate average frequencies but
+with jitter, particularly when the integer divisor is small.
+
+Introduce a new metric of clock accuracy to penalise clocks with a good
+average but worse jitter compared to clocks with an average which is no
+better but with lower jitter. The metric is the ideal rate minus the
+worse deviation from that ideal using the nearest integer divisors.
+
+Use this metric for parent selection for clocks requiring low jitter
+(currently just PCM).
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+Reviewed-by: Eric Anholt <eric@anholt.net>
+Acked-by: Stefan Wahren <stefan.wahren@i2se.com>
+---
+ drivers/clk/bcm/clk-bcm2835.c | 34 +++++++++++++++++++++++++++++-----
+ 1 file changed, 29 insertions(+), 5 deletions(-)
+
+diff --git a/drivers/clk/bcm/clk-bcm2835.c b/drivers/clk/bcm/clk-bcm2835.c
+index 49867d2..0bc56a0 100644
+--- a/drivers/clk/bcm/clk-bcm2835.c
++++ b/drivers/clk/bcm/clk-bcm2835.c
+@@ -530,6 +530,7 @@ struct bcm2835_clock_data {
+
+ bool is_vpu_clock;
+ bool is_mash_clock;
++ bool low_jitter;
+
+ u32 tcnt_mux;
+ };
+@@ -1124,7 +1125,8 @@ static unsigned long bcm2835_clock_choose_div_and_prate(struct clk_hw *hw,
+ int parent_idx,
+ unsigned long rate,
+ u32 *div,
+- unsigned long *prate)
++ unsigned long *prate,
++ unsigned long *avgrate)
+ {
+ struct bcm2835_clock *clock = bcm2835_clock_from_hw(hw);
+ struct bcm2835_cprman *cprman = clock->cprman;
+@@ -1139,8 +1141,25 @@ static unsigned long bcm2835_clock_choose_div_and_prate(struct clk_hw *hw,
+ *prate = clk_hw_get_rate(parent);
+ *div = bcm2835_clock_choose_div(hw, rate, *prate, true);
+
+- return bcm2835_clock_rate_from_divisor(clock, *prate,
+- *div);
++ *avgrate = bcm2835_clock_rate_from_divisor(clock, *prate, *div);
++
++ if (data->low_jitter && (*div & CM_DIV_FRAC_MASK)) {
++ unsigned long high, low;
++ u32 int_div = *div & ~CM_DIV_FRAC_MASK;
++
++ high = bcm2835_clock_rate_from_divisor(clock, *prate,
++ int_div);
++ int_div += CM_DIV_FRAC_MASK + 1;
++ low = bcm2835_clock_rate_from_divisor(clock, *prate,
++ int_div);
++
++ /*
++ * Return a value which is the maximum deviation
++ * below the ideal rate, for use as a metric.
++ */
++ return *avgrate - max(*avgrate - low, high - *avgrate);
++ }
++ return *avgrate;
+ }
+
+ if (data->frac_bits)
+@@ -1167,6 +1186,7 @@ static unsigned long bcm2835_clock_choose_div_and_prate(struct clk_hw *hw,
+
+ *div = curdiv << CM_DIV_FRAC_BITS;
+ *prate = curdiv * best_rate;
++ *avgrate = best_rate;
+
+ return best_rate;
+ }
+@@ -1178,6 +1198,7 @@ static int bcm2835_clock_determine_rate(struct clk_hw *hw,
+ bool current_parent_is_pllc;
+ unsigned long rate, best_rate = 0;
+ unsigned long prate, best_prate = 0;
++ unsigned long avgrate, best_avgrate = 0;
+ size_t i;
+ u32 div;
+
+@@ -1202,11 +1223,13 @@ static int bcm2835_clock_determine_rate(struct clk_hw *hw,
+ continue;
+
+ rate = bcm2835_clock_choose_div_and_prate(hw, i, req->rate,
+- &div, &prate);
++ &div, &prate,
++ &avgrate);
+ if (rate > best_rate && rate <= req->rate) {
+ best_parent = parent;
+ best_prate = prate;
+ best_rate = rate;
++ best_avgrate = avgrate;
+ }
+ }
+
+@@ -1216,7 +1239,7 @@ static int bcm2835_clock_determine_rate(struct clk_hw *hw,
+ req->best_parent_hw = best_parent;
+ req->best_parent_rate = best_prate;
+
+- req->rate = best_rate;
++ req->rate = best_avgrate;
+
+ return 0;
+ }
+@@ -2025,6 +2048,7 @@ struct bcm2835_clk_desc {
+ .int_bits = 12,
+ .frac_bits = 12,
+ .is_mash_clock = true,
++ .low_jitter = true,
+ .tcnt_mux = 23),
+ [BCM2835_CLOCK_PWM] = REGISTER_PER_CLK(
+ .name = "pwm",
diff --git a/bcm2835-fix-potential-null-pointer-dereferences.patch b/bcm2835-fix-potential-null-pointer-dereferences.patch
new file mode 100644
index 000000000..862e77fe8
--- /dev/null
+++ b/bcm2835-fix-potential-null-pointer-dereferences.patch
@@ -0,0 +1,70 @@
+From patchwork Thu May 25 17:04:55 2017
+Content-Type: text/plain; charset="utf-8"
+MIME-Version: 1.0
+Content-Transfer-Encoding: 7bit
+Subject: [v2] mmc: bcm2835: fix potential null pointer dereferences
+From: "Gustavo A. R. Silva" <garsilva@embeddedor.com>
+X-Patchwork-Id: 9748761
+Message-Id: <20170525170455.GA6904@embeddedgus>
+To: Stefan Wahren <stefan.wahren@i2se.com>,
+ Ulf Hansson <ulf.hansson@linaro.org>,
+ Florian Fainelli <f.fainelli@gmail.com>,
+ Ray Jui <rjui@broadcom.com>, Scott Branden <sbranden@broadcom.com>,
+ bcm-kernel-feedback-list@broadcom.com, Eric Anholt <eric@anholt.net>
+Cc: "Gustavo A. R. Silva" <garsilva@embeddedor.com>,
+ linux-mmc@vger.kernel.org, linux-rpi-kernel@lists.infradead.org,
+ linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org
+Date: Thu, 25 May 2017 12:04:55 -0500
+
+Null check at line 1165: if (mrq->cmd), implies that mrq->cmd might
+be NULL.
+Add null checks before dereferencing pointer mrq->cmd in order to avoid
+any potential NULL pointer dereference.
+
+Addresses-Coverity-ID: 1408740
+Tested-by: Stefan Wahren <stefan.wahren@i2se.com>
+Signed-off-by: Gustavo A. R. Silva <garsilva@embeddedor.com>
+---
+Changes in v2:
+ Change subject to make it clear the patch is bcm2835 related.
+
+ drivers/mmc/host/bcm2835.c | 12 +++++++++---
+ 1 file changed, 9 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/mmc/host/bcm2835.c b/drivers/mmc/host/bcm2835.c
+index 1f343a4..abba9a2 100644
+--- a/drivers/mmc/host/bcm2835.c
++++ b/drivers/mmc/host/bcm2835.c
+@@ -1172,7 +1172,10 @@ static void bcm2835_request(struct mmc_host *mmc, struct mmc_request *mrq)
+ if (mrq->data && !is_power_of_2(mrq->data->blksz)) {
+ dev_err(dev, "unsupported block size (%d bytes)\n",
+ mrq->data->blksz);
+- mrq->cmd->error = -EINVAL;
++
++ if (mrq->cmd)
++ mrq->cmd->error = -EINVAL;
++
+ mmc_request_done(mmc, mrq);
+ return;
+ }
+@@ -1194,7 +1197,10 @@ static void bcm2835_request(struct mmc_host *mmc, struct mmc_request *mrq)
+ readl(host->ioaddr + SDCMD) & SDCMD_CMD_MASK,
+ edm);
+ bcm2835_dumpregs(host);
+- mrq->cmd->error = -EILSEQ;
++
++ if (mrq->cmd)
++ mrq->cmd->error = -EILSEQ;
++
+ bcm2835_finish_request(host);
+ mutex_unlock(&host->mutex);
+ return;
+@@ -1207,7 +1213,7 @@ static void bcm2835_request(struct mmc_host *mmc, struct mmc_request *mrq)
+ if (!host->use_busy)
+ bcm2835_finish_command(host);
+ }
+- } else if (bcm2835_send_command(host, mrq->cmd)) {
++ } else if (mrq->cmd && bcm2835_send_command(host, mrq->cmd)) {
+ if (host->data && host->dma_desc) {
+ /* DMA transfer starts now, PIO starts after irq */
+ bcm2835_start_dma(host);
diff --git a/bcm283x-vc4-fix-vblank.patch b/bcm283x-vc4-fix-vblank.patch
new file mode 100644
index 000000000..ce4f8b16f
--- /dev/null
+++ b/bcm283x-vc4-fix-vblank.patch
@@ -0,0 +1,123 @@
+From d40a5938a10a3ba73bce6395729fefd8b8bb1c07 Mon Sep 17 00:00:00 2001
+From: Peter Robinson <pbrobinson@gmail.com>
+Date: Thu, 29 Jun 2017 10:05:05 +0100
+Subject: [PATCH] drm/vc4: Fix VBLANK handling in crtc->enable() path
+
+When we are enabling a CRTC, drm_crtc_vblank_get() is called before
+drm_crtc_vblank_on(), which is not supposed to happen (hence the
+WARN_ON() in the code). To solve the problem, we delay the 'update
+display list' operation after the CRTC is actually enabled.
+
+Signed-off-by: Boris Brezillon <boris.brezillon@free-electrons.com>
+---
+ drivers/gpu/drm/vc4/vc4_crtc.c | 66 +++++++++++++++++++++++++++---------------
+ 1 file changed, 43 insertions(+), 23 deletions(-)
+
+diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
+index d86c8cce3182..316bd6210d69 100644
+--- a/drivers/gpu/drm/vc4/vc4_crtc.c
++++ b/drivers/gpu/drm/vc4/vc4_crtc.c
+@@ -530,6 +530,34 @@ static void vc4_crtc_disable(struct drm_crtc *crtc)
+ SCALER_DISPSTATX_EMPTY);
+ }
+
++static void vc4_crtc_update_dlist(struct drm_crtc *crtc)
++{
++ struct drm_device *dev = crtc->dev;
++ struct vc4_dev *vc4 = to_vc4_dev(dev);
++ struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
++ struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(crtc->state);
++
++ if (crtc->state->event) {
++ unsigned long flags;
++
++ crtc->state->event->pipe = drm_crtc_index(crtc);
++
++ WARN_ON(drm_crtc_vblank_get(crtc) != 0);
++
++ spin_lock_irqsave(&dev->event_lock, flags);
++ vc4_crtc->event = crtc->state->event;
++ crtc->state->event = NULL;
++
++ HVS_WRITE(SCALER_DISPLISTX(vc4_crtc->channel),
++ vc4_state->mm.start);
++
++ spin_unlock_irqrestore(&dev->event_lock, flags);
++ } else {
++ HVS_WRITE(SCALER_DISPLISTX(vc4_crtc->channel),
++ vc4_state->mm.start);
++ }
++}
++
+ static void vc4_crtc_enable(struct drm_crtc *crtc)
+ {
+ struct drm_device *dev = crtc->dev;
+@@ -540,6 +568,12 @@ static void vc4_crtc_enable(struct drm_crtc *crtc)
+
+ require_hvs_enabled(dev);
+
++ /* Enable vblank irq handling before crtc is started otherwise
++ * drm_crtc_get_vblank() fails in vc4_crtc_update_dlist().
++ */
++ drm_crtc_vblank_on(crtc);
++ vc4_crtc_update_dlist(crtc);
++
+ /* Turn on the scaler, which will wait for vstart to start
+ * compositing.
+ */
+@@ -551,9 +585,6 @@ static void vc4_crtc_enable(struct drm_crtc *crtc)
+ /* Turn on the pixel valve, which will emit the vstart signal. */
+ CRTC_WRITE(PV_V_CONTROL,
+ CRTC_READ(PV_V_CONTROL) | PV_VCONTROL_VIDEN);
+-
+- /* Enable vblank irq handling after crtc is started. */
+- drm_crtc_vblank_on(crtc);
+ }
+
+ static bool vc4_crtc_mode_fixup(struct drm_crtc *crtc,
+@@ -608,7 +639,6 @@ static void vc4_crtc_atomic_flush(struct drm_crtc *crtc,
+ {
+ struct drm_device *dev = crtc->dev;
+ struct vc4_dev *vc4 = to_vc4_dev(dev);
+- struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
+ struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(crtc->state);
+ struct drm_plane *plane;
+ bool debug_dump_regs = false;
+@@ -630,25 +660,15 @@ static void vc4_crtc_atomic_flush(struct drm_crtc *crtc,
+
+ WARN_ON_ONCE(dlist_next - dlist_start != vc4_state->mm.size);
+
+- if (crtc->state->event) {
+- unsigned long flags;
+-
+- crtc->state->event->pipe = drm_crtc_index(crtc);
+-
+- WARN_ON(drm_crtc_vblank_get(crtc) != 0);
+-
+- spin_lock_irqsave(&dev->event_lock, flags);
+- vc4_crtc->event = crtc->state->event;
+- crtc->state->event = NULL;
+-
+- HVS_WRITE(SCALER_DISPLISTX(vc4_crtc->channel),
+- vc4_state->mm.start);
+-
+- spin_unlock_irqrestore(&dev->event_lock, flags);
+- } else {
+- HVS_WRITE(SCALER_DISPLISTX(vc4_crtc->channel),
+- vc4_state->mm.start);
+- }
++ /* Only update DISPLIST if the CRTC was already running and is not
++ * being disabled.
++ * vc4_crtc_enable() takes care of updating the dlist just after
++ * re-enabling VBLANK interrupts and before enabling the engine.
++ * If the CRTC is being disabled, there's no point in updating this
++ * information.
++ */
++ if (crtc->state->active && old_state->active)
++ vc4_crtc_update_dlist(crtc);
+
+ if (debug_dump_regs) {
+ DRM_INFO("CRTC %d HVS after:\n", drm_crtc_index(crtc));
+--
+2.13.0
+
diff --git a/qcom-msm89xx-fixes.patch b/qcom-msm89xx-fixes.patch
new file mode 100644
index 000000000..fc2f16dc3
--- /dev/null
+++ b/qcom-msm89xx-fixes.patch
@@ -0,0 +1,285 @@
+From 83b8b93188114e1a39b3475d9429a2ee8977a398 Mon Sep 17 00:00:00 2001
+From: Bjorn Andersson <bjorn.andersson@linaro.org>
+Date: Wed, 28 Jun 2017 14:53:23 -0700
+Subject: [PATCH 1/6] rpmsg: Make modalias work for DeviceTree based devices
+
+When rpmsg devices are expected to be matched based on their compatible
+the modalias should reflect this, so that module autoloading has a
+chance to match and load the appropriate module.
+
+Tested-by: Rob Clark <robdclark@gmail.com>
+Reported-by: Rob Clark <robdclark@gmail.com>
+Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
+---
+ drivers/rpmsg/rpmsg_core.c | 10 ++++++++++
+ 1 file changed, 10 insertions(+)
+
+diff --git a/drivers/rpmsg/rpmsg_core.c b/drivers/rpmsg/rpmsg_core.c
+index 600f5f9f7431..62580ad1b1f1 100644
+--- a/drivers/rpmsg/rpmsg_core.c
++++ b/drivers/rpmsg/rpmsg_core.c
+@@ -342,6 +342,11 @@ static ssize_t modalias_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+ {
+ struct rpmsg_device *rpdev = to_rpmsg_device(dev);
++ ssize_t len;
++
++ len = of_device_modalias(dev, buf, PAGE_SIZE);
++ if (len != -ENODEV)
++ return len;
+
+ return sprintf(buf, RPMSG_DEVICE_MODALIAS_FMT "\n", rpdev->id.name);
+ }
+@@ -384,6 +389,11 @@ static int rpmsg_dev_match(struct device *dev, struct device_driver *drv)
+ static int rpmsg_uevent(struct device *dev, struct kobj_uevent_env *env)
+ {
+ struct rpmsg_device *rpdev = to_rpmsg_device(dev);
++ int ret;
++
++ ret = of_device_uevent_modalias(dev, env);
++ if (ret != -ENODEV)
++ return ret;
+
+ return add_uevent_var(env, "MODALIAS=" RPMSG_DEVICE_MODALIAS_FMT,
+ rpdev->id.name);
+--
+2.13.0
+
+From ccdf75f90484a87ddb29649304156a503bf5a829 Mon Sep 17 00:00:00 2001
+From: Bjorn Andersson <bjorn.andersson@linaro.org>
+Date: Wed, 28 Jun 2017 16:44:58 -0700
+Subject: [PATCH 2/6] spmi: Include OF based modalias in device uevent
+
+Include the OF-based modalias in the uevent sent when registering SPMI
+devices, so that user space has a chance to autoload the kernel module
+for the device.
+
+Reported-by: Rob Clark <robdclark@gmail.com>
+Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
+Tested-by: Rob Clark <robdclark@gmail.com>
+Reviewed-by: Stephen Boyd <sboyd@codeaurora.org>
+---
+ drivers/spmi/spmi.c | 12 ++++++++++++
+ 1 file changed, 12 insertions(+)
+
+diff --git a/drivers/spmi/spmi.c b/drivers/spmi/spmi.c
+index 2b9b0941d9eb..6d23226e5f69 100644
+--- a/drivers/spmi/spmi.c
++++ b/drivers/spmi/spmi.c
+@@ -365,11 +365,23 @@ static int spmi_drv_remove(struct device *dev)
+ return 0;
+ }
+
++static int spmi_drv_uevent(struct device *dev, struct kobj_uevent_env *env)
++{
++ int ret;
++
++ ret = of_device_uevent_modalias(dev, env);
++ if (ret != -ENODEV)
++ return ret;
++
++ return 0;
++}
++
+ static struct bus_type spmi_bus_type = {
+ .name = "spmi",
+ .match = spmi_device_match,
+ .probe = spmi_drv_probe,
+ .remove = spmi_drv_remove,
++ .uevent = spmi_drv_uevent,
+ };
+
+ /**
+--
+2.13.0
+
+From 283d0e00a18b294ec56f1fb904896a546704faaf Mon Sep 17 00:00:00 2001
+From: Rob Clark <robdclark@gmail.com>
+Date: Fri, 30 Jun 2017 11:47:21 -0400
+Subject: [PATCH 3/6] soc: qcom: smsm: fix of_node refcnting problem
+
+of_find_node_with_property() drops the reference to the 'from' node,
+which eventually (after enough -EPROBE_DEFERs) drops the last reference
+to the node causing all sorts of fun problems, and this nice splat.
+
+ BUG: sleeping function called from invalid context at ../kernel/locking/mutex.c:747
+ in_atomic(): 1, irqs_disabled(): 128, pid: 33, name: kworker/0:1
+ 4 locks held by kworker/0:1/33:
+ #0: ("events"){.+.+.+}, at: [<ffff0000080fa91c>] process_one_work+0x1a4/0x728
+ #1: (deferred_probe_work){+.+.+.}, at: [<ffff0000080fa91c>] process_one_work+0x1a4/0x728
+ #2: (&dev->mutex){......}, at: [<ffff000008676078>] __device_attach+0x30/0x168
+ #3: (devtree_lock){......}, at: [<ffff000008828fd0>] of_find_node_with_property+0x30/0xe0
+ irq event stamp: 18976
+ hardirqs last enabled at (18975): [<ffff00000815794c>] __down_trylock_console_sem+0x74/0xb8
+ hardirqs last disabled at (18976): [<ffff0000089e26d4>] _raw_spin_lock_irqsave+0x2c/0x78
+ softirqs last enabled at (16880): [<ffff0000080e0f00>] __do_softirq+0x580/0x640
+ softirqs last disabled at (16871): [<ffff0000080e13a4>] irq_exit+0xe4/0x138
+ CPU: 0 PID: 33 Comm: kworker/0:1 Tainted: G E 4.12.0-rc5+ #1455
+ Hardware name: qualcomm dragonboard410c/dragonboard410c, BIOS 2017.07-rc1-00234-g22fa70a-dirty 06/26/2017
+ Workqueue: events deferred_probe_work_func
+ Call trace:
+ [<ffff000008089ee0>] dump_backtrace+0x0/0x230
+ [<ffff00000808a134>] show_stack+0x24/0x30
+ [<ffff0000084e1944>] dump_stack+0xac/0xe8
+ [<ffff00000810d7e0>] ___might_sleep+0x150/0x230
+ [<ffff00000810d918>] __might_sleep+0x58/0x90
+ [<ffff0000089dde18>] __mutex_lock+0x50/0x870
+ [<ffff0000089de674>] mutex_lock_nested+0x3c/0x50
+ [<ffff000008388ae0>] kernfs_remove+0x30/0x50
+ [<ffff00000838b720>] sysfs_remove_dir+0x58/0x70
+ [<ffff0000084e393c>] kobject_del+0x1c/0x58
+ [<ffff0000084e374c>] kobject_put+0xb4/0x208
+ [<ffff00000882c364>] of_node_put+0x24/0x30
+ [<ffff000008829018>] of_find_node_with_property+0x78/0xe0
+ [<ffff000000aff5f4>] qcom_smsm_probe+0x194/0x720 [smsm]
+ [<ffff0000086793b4>] platform_drv_probe+0x74/0x110
+ [<ffff0000086765bc>] driver_probe_device+0x2b4/0x420
+ [<ffff000008676920>] __device_attach_driver+0xd0/0x150
+ [<ffff000008673e78>] bus_for_each_drv+0x68/0xa8
+ [<ffff00000867611c>] __device_attach+0xd4/0x168
+ [<ffff000008676a1c>] device_initial_probe+0x24/0x30
+ [<ffff000008675380>] bus_probe_device+0xa0/0xa8
+ [<ffff000008675948>] deferred_probe_work_func+0xb8/0xf8
+ [<ffff0000080fa9d4>] process_one_work+0x25c/0x728
+ [<ffff0000080faef4>] worker_thread+0x54/0x3d8
+ [<ffff0000081031d8>] kthread+0x110/0x140
+ [<ffff000008082d90>] ret_from_fork+0x10/0x40
+ OF: ERROR: Bad of_node_put() on /smsm
+ CPU: 0 PID: 33 Comm: kworker/0:1 Tainted: G W E 4.12.0-rc5+ #1455
+ Hardware name: qualcomm dragonboard410c/dragonboard410c, BIOS 2017.07-rc1-00234-g22fa70a-dirty 06/26/2017
+ Workqueue: events deferred_probe_work_func
+
+Signed-off-by: Rob Clark <robdclark@gmail.com>
+---
+ drivers/soc/qcom/smsm.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/soc/qcom/smsm.c b/drivers/soc/qcom/smsm.c
+index d0337b2a71c8..a64ecd597a22 100644
+--- a/drivers/soc/qcom/smsm.c
++++ b/drivers/soc/qcom/smsm.c
+@@ -495,7 +495,8 @@ static int qcom_smsm_probe(struct platform_device *pdev)
+ if (!smsm->hosts)
+ return -ENOMEM;
+
+- local_node = of_find_node_with_property(pdev->dev.of_node, "#qcom,smem-state-cells");
++ local_node = of_find_node_with_property(of_node_get(pdev->dev.of_node),
++ "#qcom,smem-state-cells");
+ if (!local_node) {
+ dev_err(&pdev->dev, "no state entry\n");
+ return -EINVAL;
+--
+2.13.0
+
+From 40cb129048e5d2456da8d9d6468f292da3071b91 Mon Sep 17 00:00:00 2001
+From: Rob Clark <robdclark@gmail.com>
+Date: Fri, 30 Jun 2017 16:40:23 -0400
+Subject: [PATCH 4/6] thermal: qcom: tsens: fix crash due to incorrect __init
+
+init_common() is called from probe, which can happen after the __init
+section is already unloaded in the case of -EPROBE_DEFER. Causing a
+later probe to attempt to branch to hyperspace.
+
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Rob Clark <robdclark@gmail.com>
+Acked-by: Bjorn Andersson <bjorn.andersson@linaro.org>
+---
+ drivers/thermal/qcom/tsens-common.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/thermal/qcom/tsens-common.c b/drivers/thermal/qcom/tsens-common.c
+index b1449ad67fc0..22ad37c9808c 100644
+--- a/drivers/thermal/qcom/tsens-common.c
++++ b/drivers/thermal/qcom/tsens-common.c
+@@ -123,7 +123,7 @@ static const struct regmap_config tsens_config = {
+ .reg_stride = 4,
+ };
+
+-int __init init_common(struct tsens_device *tmdev)
++int init_common(struct tsens_device *tmdev)
+ {
+ void __iomem *base;
+
+--
+2.13.0
+
+From ae9b4fa55748cc9ce3c8ac039e46feab7257eff9 Mon Sep 17 00:00:00 2001
+From: Rob Clark <robdclark@gmail.com>
+Date: Sun, 2 Jul 2017 09:23:36 -0400
+Subject: [PATCH 5/6] soc: qcom: wcnss_ctrl: add missing MODULE_DEVICE_TABLE()
+
+This fixes a problem of wifi module not loading on db410c.
+
+Signed-off-by: Rob Clark <robdclark@gmail.com>
+Reviewed-by: Bjorn Andersson <bjorn.andersson@linaro.org>
+---
+ drivers/soc/qcom/wcnss_ctrl.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/drivers/soc/qcom/wcnss_ctrl.c b/drivers/soc/qcom/wcnss_ctrl.c
+index b9069184df19..d008e5b82db4 100644
+--- a/drivers/soc/qcom/wcnss_ctrl.c
++++ b/drivers/soc/qcom/wcnss_ctrl.c
+@@ -347,6 +347,7 @@ static const struct of_device_id wcnss_ctrl_of_match[] = {
+ { .compatible = "qcom,wcnss", },
+ {}
+ };
++MODULE_DEVICE_TABLE(of, wcnss_ctrl_of_match);
+
+ static struct rpmsg_driver wcnss_ctrl_driver = {
+ .probe = wcnss_ctrl_probe,
+--
+2.13.0
+
+From 173c1207986956ea4c00601a67c952751a1985e6 Mon Sep 17 00:00:00 2001
+From: Peter Robinson <pbrobinson@gmail.com>
+Date: Mon, 3 Jul 2017 10:10:21 +0100
+Subject: [PATCH 6/6] wcn36xx: check dma_mapping_error()
+
+Fixes splat:
+
+ wcn36xx a204000.wcnss:smd-edge:wcnss:wifi: DMA-API: device driver failed to check map error[device address=0x00000000b45ba000] [size=3872 bytes] [mapped as single]
+ ------------[ cut here ]------------
+ WARNING: CPU: 0 PID: 0 at ../lib/dma-debug.c:1167 check_unmap+0x474/0x8d0
+ Modules linked in: bnep(E) arc4(E) wcn36xx(E) mac80211(E) btqcomsmd(E) btqca(E) bluetooth(E) cfg80211(E) ecdh_generic(E) rfkill(E) vfat(E) fat(E) wcnss_ctrl qcom_wcnss_pil(E) mdt_loader(E) qcom_common(E) remoteproc(E) crc32_ce(E) virtio_ring(E) snd_soc_lpass_apq8016(E) snd_soc_lpass_cpu(E) virtio(E) snd_soc_lpass_platform(E) leds_gpio(E) snd_soc_hdmi_codec(E) snd_soc_apq8016_sbc(E) snd_soc_msm8916_digital(E) snd_soc_core(E) qcom_spmi_temp_alarm(E) ac97_bus(E) snd_pcm_dmaengine(E) snd_seq(E) snd_seq_device(E) snd_pcm(E) spi_qup(E) nvmem_qfprom(E) snd_timer(E) snd(E) soundcore(E) msm_rng(E) qcom_tsens(E) nvmem_core(E) uas(E) usb_storage(E) dm9601(E) cdc_ether(E) usbnet(E) mii(E) mmc_block(E) sdhci_msm(E) sdhci_pltfm(E) qcom_spmi_vadc(E) qcom_vadc_common(PE) clk_smd_rpm(E) industrialio(E)
+ qcom_smd_regulator(E) pinctrl_spmi_mpp(E) pinctrl_spmi_gpio(E) rtc_pm8xxx(E) adv7511(E) smd_rpm(E) qcom_spmi_pmic(E) regmap_spmi(E) phy_msm_usb(E) usb3503(E) extcon_usb_gpio(E) ci_hdrc_msm(E) ci_hdrc(E) qcom_hwspinlock(E) udc_core(E) extcon_core(E) ehci_msm(E) i2c_qup(E) sdhci(E) msm(E) mmc_core(E) drm_kms_helper(E) syscopyarea(E) sysfillrect(E) sysimgblt(E) fb_sys_fops(E) spmi_pmic_arb(E) drm(E) spmi(E) qcom_smd(E) rpmsg_core smsm(E) gpio_keys(E) smp2p(E) smem(E) hwspinlock_core(E) sunrpc(E) scsi_transport_iscsi(E)
+ CPU: 0 PID: 0 Comm: swapper/0 Tainted: P E 4.12.0-rc7+ #1476
+ Hardware name: qualcomm dragonboard410c/dragonboard410c, BIOS 2017.07-rc1-00234-g22fa70a-dirty 06/26/2017
+ task: ffff000009049780 task.stack: ffff000009030000
+ PC is at check_unmap+0x474/0x8d0
+ LR is at check_unmap+0x474/0x8d0
+ ...
+ Mapped at:
+ dma_entry_alloc+0x68/0xa8
+ debug_dma_map_page+0x94/0x148
+ wcn36xx_dxe_fill_skb.isra.1+0xbc/0xf8 [wcn36xx]
+ wcn36xx_dxe_init+0x244/0x398 [wcn36xx]
+ wcn36xx_start+0xf4/0x298 [wcn36xx]
+
+v2: pbrobinson: add kfree_skb(skb);
+
+Signed-off-by: Rob Clark <robdclark@gmail.com>
+Signed-off-by: Peter Robinson <pbrobinson@gmail.com>
+---
+ drivers/net/wireless/ath/wcn36xx/dxe.c | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+diff --git a/drivers/net/wireless/ath/wcn36xx/dxe.c b/drivers/net/wireless/ath/wcn36xx/dxe.c
+index 87dfdaf9044c..d5c810a8cc52 100644
+--- a/drivers/net/wireless/ath/wcn36xx/dxe.c
++++ b/drivers/net/wireless/ath/wcn36xx/dxe.c
+@@ -289,6 +289,11 @@ static int wcn36xx_dxe_fill_skb(struct device *dev, struct wcn36xx_dxe_ctl *ctl)
+ skb_tail_pointer(skb),
+ WCN36XX_PKT_SIZE,
+ DMA_FROM_DEVICE);
++ if (dma_mapping_error(dev, dxe->dst_addr_l)) {
++ dev_err(dev, "unable to map skb\n");
++ kfree_skb(skb);
++ return -ENOMEM;
++ }
+ ctl->skb = skb;
+
+ return 0;
+--
+2.13.0
+