--- /dev/null
+From 8c01275e0cdf1959aa25c322fd5870c097733195 Mon Sep 17 00:00:00 2001
+From: Chen Yu <yu.c.chen@intel.com>
+Date: Sun, 25 Oct 2015 01:02:46 +0800
+Subject: ACPI / PM: Fix incorrect wakeup IRQ setting during suspend-to-idle
+
+From: Chen Yu <yu.c.chen@intel.com>
+
+commit 8c01275e0cdf1959aa25c322fd5870c097733195 upstream.
+
+For an ACPI compatible system, the SCI (ACPI System Control
+Interrupt) is used to wake the system up from suspend-to-idle.
+Once the CPU is woken up by the SCI, the interrupt handler will
+first check if the current IRQ has been configured for system
+wakeup, so irq_pm_check_wakeup() is invoked to validate the IRQ
+number. However, during suspend-to-idle, enable_irq_wake() is
+called for acpi_gbl_FADT.sci_interrupt, although the IRQ number
+that the SCI handler has been installed for should be passed to
+it instead. Thus, if acpi_gbl_FADT.sci_interrupt happens to be
+different from that number, ACPI interrupts will not be able to
+wake up the system from sleep.
+
+Fix this problem by passing the IRQ number returned by
+acpi_gsi_to_irq() to enable_irq_wake() instead of
+acpi_gbl_FADT.sci_interrupt.
+
+Acked-by: Lv Zheng <lv.zheng@intel.com>
+Signed-off-by: Chen Yu <yu.c.chen@intel.com>
+Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/acpi/sleep.c | 6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+--- a/drivers/acpi/sleep.c
++++ b/drivers/acpi/sleep.c
+@@ -632,14 +632,16 @@ static int acpi_freeze_prepare(void)
+ acpi_enable_wakeup_devices(ACPI_STATE_S0);
+ acpi_enable_all_wakeup_gpes();
+ acpi_os_wait_events_complete();
+- enable_irq_wake(acpi_gbl_FADT.sci_interrupt);
++ if (acpi_sci_irq_valid())
++ enable_irq_wake(acpi_sci_irq);
+ return 0;
+ }
+
+ static void acpi_freeze_restore(void)
+ {
+ acpi_disable_wakeup_devices(ACPI_STATE_S0);
+- disable_irq_wake(acpi_gbl_FADT.sci_interrupt);
++ if (acpi_sci_irq_valid())
++ disable_irq_wake(acpi_sci_irq);
+ acpi_enable_all_runtime_gpes();
+ }
+
--- /dev/null
+From 49e4b84333f338d4f183f28f1f3c1131b9fb2b5a Mon Sep 17 00:00:00 2001
+From: Chen Yu <yu.c.chen@intel.com>
+Date: Sun, 25 Oct 2015 01:02:19 +0800
+Subject: ACPI: Use correct IRQ when uninstalling ACPI interrupt handler
+
+From: Chen Yu <yu.c.chen@intel.com>
+
+commit 49e4b84333f338d4f183f28f1f3c1131b9fb2b5a upstream.
+
+Currently when the system is trying to uninstall the ACPI interrupt
+handler, it uses acpi_gbl_FADT.sci_interrupt as the IRQ number.
+However, the IRQ number that the ACPI interrupt handled is installed
+for comes from acpi_gsi_to_irq() and that is the number that should
+be used for the handler removal.
+
+Fix this problem by using the mapped IRQ returned from acpi_gsi_to_irq()
+as appropriate.
+
+Acked-by: Lv Zheng <lv.zheng@intel.com>
+Signed-off-by: Chen Yu <yu.c.chen@intel.com>
+Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/acpi/osl.c | 9 ++++++---
+ include/linux/acpi.h | 6 ++++++
+ 2 files changed, 12 insertions(+), 3 deletions(-)
+
+--- a/drivers/acpi/osl.c
++++ b/drivers/acpi/osl.c
+@@ -81,6 +81,7 @@ static struct workqueue_struct *kacpid_w
+ static struct workqueue_struct *kacpi_notify_wq;
+ static struct workqueue_struct *kacpi_hotplug_wq;
+ static bool acpi_os_initialized;
++unsigned int acpi_sci_irq = INVALID_ACPI_IRQ;
+
+ /*
+ * This list of permanent mappings is for memory that may be accessed from
+@@ -856,17 +857,19 @@ acpi_os_install_interrupt_handler(u32 gs
+ acpi_irq_handler = NULL;
+ return AE_NOT_ACQUIRED;
+ }
++ acpi_sci_irq = irq;
+
+ return AE_OK;
+ }
+
+-acpi_status acpi_os_remove_interrupt_handler(u32 irq, acpi_osd_handler handler)
++acpi_status acpi_os_remove_interrupt_handler(u32 gsi, acpi_osd_handler handler)
+ {
+- if (irq != acpi_gbl_FADT.sci_interrupt)
++ if (gsi != acpi_gbl_FADT.sci_interrupt || !acpi_sci_irq_valid())
+ return AE_BAD_PARAMETER;
+
+- free_irq(irq, acpi_irq);
++ free_irq(acpi_sci_irq, acpi_irq);
+ acpi_irq_handler = NULL;
++ acpi_sci_irq = INVALID_ACPI_IRQ;
+
+ return AE_OK;
+ }
+--- a/include/linux/acpi.h
++++ b/include/linux/acpi.h
+@@ -193,6 +193,12 @@ int acpi_ioapic_registered(acpi_handle h
+ void acpi_irq_stats_init(void);
+ extern u32 acpi_irq_handled;
+ extern u32 acpi_irq_not_handled;
++extern unsigned int acpi_sci_irq;
++#define INVALID_ACPI_IRQ ((unsigned)-1)
++static inline bool acpi_sci_irq_valid(void)
++{
++ return acpi_sci_irq != INVALID_ACPI_IRQ;
++}
+
+ extern int sbf_port;
+ extern unsigned long acpi_realmode_flags;
--- /dev/null
+From efb1cf7d28b8aeacec53e9ba8f3f2809c5cb9686 Mon Sep 17 00:00:00 2001
+From: Chen Yu <yu.c.chen@intel.com>
+Date: Sun, 25 Oct 2015 01:02:36 +0800
+Subject: ACPI: Using correct irq when waiting for events
+
+From: Chen Yu <yu.c.chen@intel.com>
+
+commit efb1cf7d28b8aeacec53e9ba8f3f2809c5cb9686 upstream.
+
+When the system is waiting for GPE/fixed event handler to finish,
+it uses acpi_gbl_FADT.sci_interrupt directly as the IRQ number.
+However, the remapped IRQ returned by acpi_gsi_to_irq() should be
+passed to synchronize_hardirq() instead of it.
+
+Acked-by: Lv Zheng <lv.zheng@intel.com>
+Signed-off-by: Chen Yu <yu.c.chen@intel.com>
+Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/acpi/osl.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/drivers/acpi/osl.c
++++ b/drivers/acpi/osl.c
+@@ -1183,8 +1183,8 @@ void acpi_os_wait_events_complete(void)
+ * Make sure the GPE handler or the fixed event handler is not used
+ * on another CPU after removal.
+ */
+- if (acpi_irq_handler)
+- synchronize_hardirq(acpi_gbl_FADT.sci_interrupt);
++ if (acpi_sci_irq_valid())
++ synchronize_hardirq(acpi_sci_irq);
+ flush_workqueue(kacpid_wq);
+ flush_workqueue(kacpi_notify_wq);
+ }
--- /dev/null
+From ben@decadent.org.uk Thu Dec 17 14:12:57 2015
+From: Ben Hutchings <ben@decadent.org.uk>
+Date: Tue, 15 Dec 2015 15:31:49 +0000
+Subject: Revert "vrf: fix double free and memory corruption on register_netdevice failure"
+To: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Cc: David Ahern <dsa@cumulusnetworks.com>, linux-kernel@vger.kernel.org, stable@vger.kernel.org, Nikolay Aleksandrov <nikolay@cumulusnetworks.com>, "David S. Miller" <davem@davemloft.net>
+Message-ID: <20151215153149.GO28542@decadent.org.uk>
+
+From: Ben Hutchings <ben@decadent.org.uk>
+
+This reverts commit b3abad339f8e268bb261e5844ab68b18a7797c29, which
+was an attempt to backport commit 7f109f7cc37108cba7243bc832988525b0d85909
+upstream. The backport introduced a deadlock and other bugs.
+
+Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
+Acked-by: David S. Miller <davem@davemloft.net>
+Acked-by: David Ahern <dsa@cumulusnetworks.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/net/vrf.c | 15 +++++++++++++--
+ 1 file changed, 13 insertions(+), 2 deletions(-)
+
+--- a/drivers/net/vrf.c
++++ b/drivers/net/vrf.c
+@@ -581,6 +581,7 @@ static int vrf_newlink(struct net *src_n
+ {
+ struct net_vrf *vrf = netdev_priv(dev);
+ struct net_vrf_dev *vrf_ptr;
++ int err;
+
+ if (!data || !data[IFLA_VRF_TABLE])
+ return -EINVAL;
+@@ -589,16 +590,26 @@ static int vrf_newlink(struct net *src_n
+
+ dev->priv_flags |= IFF_VRF_MASTER;
+
++ err = -ENOMEM;
+ vrf_ptr = kmalloc(sizeof(*dev->vrf_ptr), GFP_KERNEL);
+ if (!vrf_ptr)
+- return -ENOMEM;
++ goto out_fail;
+
+ vrf_ptr->ifindex = dev->ifindex;
+ vrf_ptr->tb_id = vrf->tb_id;
+
++ err = register_netdevice(dev);
++ if (err < 0)
++ goto out_fail;
++
+ rcu_assign_pointer(dev->vrf_ptr, vrf_ptr);
+
+- return register_netdev(dev);
++ return 0;
++
++out_fail:
++ kfree(vrf_ptr);
++ free_netdev(dev);
++ return err;
+ }
+
+ static size_t vrf_nl_getsize(const struct net_device *dev)
--- /dev/null
+From ben@decadent.org.uk Thu Dec 17 14:16:22 2015
+From: Ben Hutchings <ben@decadent.org.uk>
+Date: Tue, 15 Dec 2015 21:21:57 +0000
+Subject: tipc: Fix kfree_skb() of uninitialised pointer
+To: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Cc: stable@vger.kernel.org, ying.xue@windriver.com, "David S. Miller" <davem@davemloft.net>
+Message-ID: <20151215212156.GQ28542@decadent.org.uk>
+Content-Disposition: inline
+
+From: Ben Hutchings <ben@decadent.org.uk>
+
+Commit 7098356baca7 ("tipc: fix error handling of expanding buffer
+headroom") added a "goto tx_error". This is fine upstream, but
+when backported to 4.3 it results in attempting to free the clone
+before it has been allocated. In this early error case, no
+cleanup is needed.
+
+Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/tipc/udp_media.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/net/tipc/udp_media.c
++++ b/net/tipc/udp_media.c
+@@ -162,7 +162,7 @@ static int tipc_udp_send_msg(struct net
+ if (skb_headroom(skb) < UDP_MIN_HEADROOM) {
+ err = pskb_expand_head(skb, UDP_MIN_HEADROOM, 0, GFP_ATOMIC);
+ if (err)
+- goto tx_error;
++ return err;
+ }
+
+ clone = skb_clone(skb, GFP_ATOMIC);
--- /dev/null
+From d2f20619942fe4618160a7fa3dbdcbac335cff59 Mon Sep 17 00:00:00 2001
+From: Azael Avalos <coproscefalo@gmail.com>
+Date: Wed, 4 Nov 2015 09:28:26 -0700
+Subject: toshiba_acpi: Initialize hotkey_event_type variable
+
+From: Azael Avalos <coproscefalo@gmail.com>
+
+commit d2f20619942fe4618160a7fa3dbdcbac335cff59 upstream.
+
+Commit 53147b6cabee5e8d1997b5682fcc0c3b72ddf9c2 ("toshiba_acpi: Fix
+hotkeys registration on some toshiba models") fixed an issue on some
+laptops regarding hotkeys registration, however, if failed to address
+the initialization of the hotkey_event_type variable, and thus, it can
+lead to potential unwanted effects as the variable is being checked.
+
+This patch initializes such variable to avoid such unwanted effects.
+
+Signed-off-by: Azael Avalos <coproscefalo@gmail.com>
+Signed-off-by: Darren Hart <dvhart@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/platform/x86/toshiba_acpi.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/drivers/platform/x86/toshiba_acpi.c
++++ b/drivers/platform/x86/toshiba_acpi.c
+@@ -2676,6 +2676,7 @@ static int toshiba_acpi_add(struct acpi_
+ ret = toshiba_function_keys_get(dev, &special_functions);
+ dev->kbd_function_keys_supported = !ret;
+
++ dev->hotkey_event_type = 0;
+ if (toshiba_acpi_setup_keyboard(dev))
+ pr_info("Unable to activate hotkeys\n");
+
--- /dev/null
+From 399235dc6e95400a1322a9999e92073bc572f0c8 Mon Sep 17 00:00:00 2001
+From: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
+Date: Tue, 29 Sep 2015 00:32:19 +0300
+Subject: tpm, tpm_tis: fix tpm_tis ACPI detection issue with TPM 2.0
+
+From: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
+
+commit 399235dc6e95400a1322a9999e92073bc572f0c8 upstream.
+
+Both for FIFO and CRB interface TCG has decided to use the same HID
+MSFT0101. They can be differentiated by looking at the start method from
+TPM2 ACPI table. This patches makes necessary fixes to tpm_tis and
+tpm_crb modules in order to correctly detect, which module should be
+used.
+
+For MSFT0101 we must use struct acpi_driver because struct pnp_driver
+has a 7 character limitation.
+
+It turned out that the root cause in b371616b8 was not correct for
+https://bugzilla.kernel.org/show_bug.cgi?id=98181.
+
+v2:
+
+* One fixup was missing from v1: is_tpm2_fifo -> is_fifo
+
+v3:
+
+* Use pnp_driver for existing HIDs and acpi_driver only for MSFT0101 in
+ order ensure backwards compatibility.
+
+v4:
+
+* Check for FIFO before doing *anything* in crb_acpi_add().
+* There was return immediately after acpi_bus_unregister_driver() in
+ cleanup_tis(). This caused pnp_unregister_driver() not to be called.
+
+Reported-by: Michael Saunders <mick.saunders@gmail.com>
+Reported-by: Michael Marley <michael@michaelmarley.com>
+Reported-by: Jethro Beekman <kernel@jbeekman.nl>
+Reported-by: Matthew Garrett <mjg59@srcf.ucam.org>
+Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
+Tested-by: Michael Marley <michael@michaelmarley.com>
+Tested-by: Mimi Zohar <zohar@linux.vnet.ibm.com> (on TPM 1.2)
+Reviewed-by: Peter Huewe <peterhuewe@gmx.de>
+Signed-off-by: Peter Huewe <peterhuewe@gmx.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/char/tpm/tpm.h | 7 +
+ drivers/char/tpm/tpm_crb.c | 32 ++-----
+ drivers/char/tpm/tpm_tis.c | 192 ++++++++++++++++++++++++++++++++++++++-------
+ 3 files changed, 181 insertions(+), 50 deletions(-)
+
+--- a/drivers/char/tpm/tpm.h
++++ b/drivers/char/tpm/tpm.h
+@@ -115,6 +115,13 @@ enum tpm2_startup_types {
+ TPM2_SU_STATE = 0x0001,
+ };
+
++enum tpm2_start_method {
++ TPM2_START_ACPI = 2,
++ TPM2_START_FIFO = 6,
++ TPM2_START_CRB = 7,
++ TPM2_START_CRB_WITH_ACPI = 8,
++};
++
+ struct tpm_chip;
+
+ struct tpm_vendor_specific {
+--- a/drivers/char/tpm/tpm_crb.c
++++ b/drivers/char/tpm/tpm_crb.c
+@@ -34,12 +34,6 @@ enum crb_defaults {
+ CRB_ACPI_START_INDEX = 1,
+ };
+
+-enum crb_start_method {
+- CRB_SM_ACPI_START = 2,
+- CRB_SM_CRB = 7,
+- CRB_SM_CRB_WITH_ACPI_START = 8,
+-};
+-
+ struct acpi_tpm2 {
+ struct acpi_table_header hdr;
+ u16 platform_class;
+@@ -220,12 +214,6 @@ static int crb_acpi_add(struct acpi_devi
+ u64 pa;
+ int rc;
+
+- chip = tpmm_chip_alloc(dev, &tpm_crb);
+- if (IS_ERR(chip))
+- return PTR_ERR(chip);
+-
+- chip->flags = TPM_CHIP_FLAG_TPM2;
+-
+ status = acpi_get_table(ACPI_SIG_TPM2, 1,
+ (struct acpi_table_header **) &buf);
+ if (ACPI_FAILURE(status)) {
+@@ -233,13 +221,15 @@ static int crb_acpi_add(struct acpi_devi
+ return -ENODEV;
+ }
+
+- /* At least some versions of AMI BIOS have a bug that TPM2 table has
+- * zero address for the control area and therefore we must fail.
+- */
+- if (!buf->control_area_pa) {
+- dev_err(dev, "TPM2 ACPI table has a zero address for the control area\n");
+- return -EINVAL;
+- }
++ /* Should the FIFO driver handle this? */
++ if (buf->start_method == TPM2_START_FIFO)
++ return -ENODEV;
++
++ chip = tpmm_chip_alloc(dev, &tpm_crb);
++ if (IS_ERR(chip))
++ return PTR_ERR(chip);
++
++ chip->flags = TPM_CHIP_FLAG_TPM2;
+
+ if (buf->hdr.length < sizeof(struct acpi_tpm2)) {
+ dev_err(dev, "TPM2 ACPI table has wrong size");
+@@ -259,11 +249,11 @@ static int crb_acpi_add(struct acpi_devi
+ * report only ACPI start but in practice seems to require both
+ * ACPI start and CRB start.
+ */
+- if (sm == CRB_SM_CRB || sm == CRB_SM_CRB_WITH_ACPI_START ||
++ if (sm == TPM2_START_CRB || sm == TPM2_START_FIFO ||
+ !strcmp(acpi_device_hid(device), "MSFT0101"))
+ priv->flags |= CRB_FL_CRB_START;
+
+- if (sm == CRB_SM_ACPI_START || sm == CRB_SM_CRB_WITH_ACPI_START)
++ if (sm == TPM2_START_ACPI || sm == TPM2_START_CRB_WITH_ACPI)
+ priv->flags |= CRB_FL_ACPI_START;
+
+ priv->cca = (struct crb_control_area __iomem *)
+--- a/drivers/char/tpm/tpm_tis.c
++++ b/drivers/char/tpm/tpm_tis.c
+@@ -1,6 +1,6 @@
+ /*
+ * Copyright (C) 2005, 2006 IBM Corporation
+- * Copyright (C) 2014 Intel Corporation
++ * Copyright (C) 2014, 2015 Intel Corporation
+ *
+ * Authors:
+ * Leendert van Doorn <leendert@watson.ibm.com>
+@@ -28,6 +28,7 @@
+ #include <linux/wait.h>
+ #include <linux/acpi.h>
+ #include <linux/freezer.h>
++#include <acpi/actbl2.h>
+ #include "tpm.h"
+
+ enum tis_access {
+@@ -65,6 +66,17 @@ enum tis_defaults {
+ TIS_LONG_TIMEOUT = 2000, /* 2 sec */
+ };
+
++struct tpm_info {
++ unsigned long start;
++ unsigned long len;
++ unsigned int irq;
++};
++
++static struct tpm_info tis_default_info = {
++ .start = TIS_MEM_BASE,
++ .len = TIS_MEM_LEN,
++ .irq = 0,
++};
+
+ /* Some timeout values are needed before it is known whether the chip is
+ * TPM 1.0 or TPM 2.0.
+@@ -91,26 +103,54 @@ struct priv_data {
+ };
+
+ #if defined(CONFIG_PNP) && defined(CONFIG_ACPI)
+-static int is_itpm(struct pnp_dev *dev)
++static int has_hid(struct acpi_device *dev, const char *hid)
+ {
+- struct acpi_device *acpi = pnp_acpi_device(dev);
+ struct acpi_hardware_id *id;
+
+- if (!acpi)
+- return 0;
+-
+- list_for_each_entry(id, &acpi->pnp.ids, list) {
+- if (!strcmp("INTC0102", id->id))
++ list_for_each_entry(id, &dev->pnp.ids, list)
++ if (!strcmp(hid, id->id))
+ return 1;
+- }
+
+ return 0;
+ }
++
++static inline int is_itpm(struct acpi_device *dev)
++{
++ return has_hid(dev, "INTC0102");
++}
++
++static inline int is_fifo(struct acpi_device *dev)
++{
++ struct acpi_table_tpm2 *tbl;
++ acpi_status st;
++
++ /* TPM 1.2 FIFO */
++ if (!has_hid(dev, "MSFT0101"))
++ return 1;
++
++ st = acpi_get_table(ACPI_SIG_TPM2, 1,
++ (struct acpi_table_header **) &tbl);
++ if (ACPI_FAILURE(st)) {
++ dev_err(&dev->dev, "failed to get TPM2 ACPI table\n");
++ return 0;
++ }
++
++ if (le32_to_cpu(tbl->start_method) != TPM2_START_FIFO)
++ return 0;
++
++ /* TPM 2.0 FIFO */
++ return 1;
++}
+ #else
+-static inline int is_itpm(struct pnp_dev *dev)
++static inline int is_itpm(struct acpi_device *dev)
+ {
+ return 0;
+ }
++
++static inline int is_fifo(struct acpi_device *dev)
++{
++ return 1;
++}
+ #endif
+
+ /* Before we attempt to access the TPM we must see that the valid bit is set.
+@@ -600,9 +640,8 @@ static void tpm_tis_remove(struct tpm_ch
+ release_locality(chip, chip->vendor.locality, 1);
+ }
+
+-static int tpm_tis_init(struct device *dev, acpi_handle acpi_dev_handle,
+- resource_size_t start, resource_size_t len,
+- unsigned int irq)
++static int tpm_tis_init(struct device *dev, struct tpm_info *tpm_info,
++ acpi_handle acpi_dev_handle)
+ {
+ u32 vendor, intfcaps, intmask;
+ int rc, i, irq_s, irq_e, probe;
+@@ -622,7 +661,7 @@ static int tpm_tis_init(struct device *d
+ chip->acpi_dev_handle = acpi_dev_handle;
+ #endif
+
+- chip->vendor.iobase = devm_ioremap(dev, start, len);
++ chip->vendor.iobase = devm_ioremap(dev, tpm_info->start, tpm_info->len);
+ if (!chip->vendor.iobase)
+ return -EIO;
+
+@@ -707,7 +746,7 @@ static int tpm_tis_init(struct device *d
+ chip->vendor.iobase +
+ TPM_INT_ENABLE(chip->vendor.locality));
+ if (interrupts)
+- chip->vendor.irq = irq;
++ chip->vendor.irq = tpm_info->irq;
+ if (interrupts && !chip->vendor.irq) {
+ irq_s =
+ ioread8(chip->vendor.iobase +
+@@ -890,27 +929,27 @@ static SIMPLE_DEV_PM_OPS(tpm_tis_pm, tpm
+ static int tpm_tis_pnp_init(struct pnp_dev *pnp_dev,
+ const struct pnp_device_id *pnp_id)
+ {
+- resource_size_t start, len;
+- unsigned int irq = 0;
++ struct tpm_info tpm_info = tis_default_info;
+ acpi_handle acpi_dev_handle = NULL;
+
+- start = pnp_mem_start(pnp_dev, 0);
+- len = pnp_mem_len(pnp_dev, 0);
++ tpm_info.start = pnp_mem_start(pnp_dev, 0);
++ tpm_info.len = pnp_mem_len(pnp_dev, 0);
+
+ if (pnp_irq_valid(pnp_dev, 0))
+- irq = pnp_irq(pnp_dev, 0);
++ tpm_info.irq = pnp_irq(pnp_dev, 0);
+ else
+ interrupts = false;
+
+- if (is_itpm(pnp_dev))
+- itpm = true;
+-
+ #ifdef CONFIG_ACPI
+- if (pnp_acpi_device(pnp_dev))
++ if (pnp_acpi_device(pnp_dev)) {
++ if (is_itpm(pnp_acpi_device(pnp_dev)))
++ itpm = true;
++
+ acpi_dev_handle = pnp_acpi_device(pnp_dev)->handle;
++ }
+ #endif
+
+- return tpm_tis_init(&pnp_dev->dev, acpi_dev_handle, start, len, irq);
++ return tpm_tis_init(&pnp_dev->dev, &tpm_info, acpi_dev_handle);
+ }
+
+ static struct pnp_device_id tpm_pnp_tbl[] = {
+@@ -930,6 +969,7 @@ MODULE_DEVICE_TABLE(pnp, tpm_pnp_tbl);
+ static void tpm_tis_pnp_remove(struct pnp_dev *dev)
+ {
+ struct tpm_chip *chip = pnp_get_drvdata(dev);
++
+ tpm_chip_unregister(chip);
+ tpm_tis_remove(chip);
+ }
+@@ -950,6 +990,79 @@ module_param_string(hid, tpm_pnp_tbl[TIS
+ MODULE_PARM_DESC(hid, "Set additional specific HID for this driver to probe");
+ #endif
+
++#ifdef CONFIG_ACPI
++static int tpm_check_resource(struct acpi_resource *ares, void *data)
++{
++ struct tpm_info *tpm_info = (struct tpm_info *) data;
++ struct resource res;
++
++ if (acpi_dev_resource_interrupt(ares, 0, &res)) {
++ tpm_info->irq = res.start;
++ } else if (acpi_dev_resource_memory(ares, &res)) {
++ tpm_info->start = res.start;
++ tpm_info->len = resource_size(&res);
++ }
++
++ return 1;
++}
++
++static int tpm_tis_acpi_init(struct acpi_device *acpi_dev)
++{
++ struct list_head resources;
++ struct tpm_info tpm_info = tis_default_info;
++ int ret;
++
++ if (!is_fifo(acpi_dev))
++ return -ENODEV;
++
++ INIT_LIST_HEAD(&resources);
++ ret = acpi_dev_get_resources(acpi_dev, &resources, tpm_check_resource,
++ &tpm_info);
++ if (ret < 0)
++ return ret;
++
++ acpi_dev_free_resource_list(&resources);
++
++ if (!tpm_info.irq)
++ interrupts = false;
++
++ if (is_itpm(acpi_dev))
++ itpm = true;
++
++ return tpm_tis_init(&acpi_dev->dev, &tpm_info, acpi_dev->handle);
++}
++
++static int tpm_tis_acpi_remove(struct acpi_device *dev)
++{
++ struct tpm_chip *chip = dev_get_drvdata(&dev->dev);
++
++ tpm_chip_unregister(chip);
++ tpm_tis_remove(chip);
++
++ return 0;
++}
++
++static struct acpi_device_id tpm_acpi_tbl[] = {
++ {"MSFT0101", 0}, /* TPM 2.0 */
++ /* Add new here */
++ {"", 0}, /* User Specified */
++ {"", 0} /* Terminator */
++};
++MODULE_DEVICE_TABLE(acpi, tpm_acpi_tbl);
++
++static struct acpi_driver tis_acpi_driver = {
++ .name = "tpm_tis",
++ .ids = tpm_acpi_tbl,
++ .ops = {
++ .add = tpm_tis_acpi_init,
++ .remove = tpm_tis_acpi_remove,
++ },
++ .drv = {
++ .pm = &tpm_tis_pm,
++ },
++};
++#endif
++
+ static struct platform_driver tis_drv = {
+ .driver = {
+ .name = "tpm_tis",
+@@ -966,9 +1079,25 @@ static int __init init_tis(void)
+ {
+ int rc;
+ #ifdef CONFIG_PNP
+- if (!force)
+- return pnp_register_driver(&tis_pnp_driver);
++ if (!force) {
++ rc = pnp_register_driver(&tis_pnp_driver);
++ if (rc)
++ return rc;
++ }
++#endif
++#ifdef CONFIG_ACPI
++ if (!force) {
++ rc = acpi_bus_register_driver(&tis_acpi_driver);
++ if (rc) {
++#ifdef CONFIG_PNP
++ pnp_unregister_driver(&tis_pnp_driver);
+ #endif
++ return rc;
++ }
++ }
++#endif
++ if (!force)
++ return 0;
+
+ rc = platform_driver_register(&tis_drv);
+ if (rc < 0)
+@@ -978,7 +1107,7 @@ static int __init init_tis(void)
+ rc = PTR_ERR(pdev);
+ goto err_dev;
+ }
+- rc = tpm_tis_init(&pdev->dev, NULL, TIS_MEM_BASE, TIS_MEM_LEN, 0);
++ rc = tpm_tis_init(&pdev->dev, &tis_default_info, NULL);
+ if (rc)
+ goto err_init;
+ return 0;
+@@ -992,9 +1121,14 @@ err_dev:
+ static void __exit cleanup_tis(void)
+ {
+ struct tpm_chip *chip;
+-#ifdef CONFIG_PNP
++#if defined(CONFIG_PNP) || defined(CONFIG_ACPI)
+ if (!force) {
++#ifdef CONFIG_ACPI
++ acpi_bus_unregister_driver(&tis_acpi_driver);
++#endif
++#ifdef CONFIG_PNP
+ pnp_unregister_driver(&tis_pnp_driver);
++#endif
+ return;
+ }
+ #endif
--- /dev/null
+From ben@decadent.org.uk Thu Dec 17 14:14:13 2015
+From: Ben Hutchings <ben@decadent.org.uk>
+Date: Tue, 15 Dec 2015 15:32:20 +0000
+Subject: vrf: fix double free and memory corruption on register_netdevice failure
+To: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Cc: David Ahern <dsa@cumulusnetworks.com>, linux-kernel@vger.kernel.org, stable@vger.kernel.org, Nikolay Aleksandrov <nikolay@cumulusnetworks.com>, "David S. Miller" <davem@davemloft.net>
+Message-ID: <20151215153220.GP28542@decadent.org.uk>
+Content-Disposition: inline
+
+From: Ben Hutchings <ben@decadent.org.uk>
+
+commit 7f109f7cc37108cba7243bc832988525b0d85909 upstream.
+
+When vrf's ->newlink is called, if register_netdevice() fails then it
+does free_netdev(), but that's also done by rtnl_newlink() so a second
+free happens and memory gets corrupted, to reproduce execute the
+following line a couple of times (1 - 5 usually is enough):
+$ for i in `seq 1 5`; do ip link add vrf: type vrf table 1; done;
+This works because we fail in register_netdevice() because of the wrong
+name "vrf:".
+
+And here's a trace of one crash:
+[ 28.792157] ------------[ cut here ]------------
+[ 28.792407] kernel BUG at fs/namei.c:246!
+[ 28.792608] invalid opcode: 0000 [#1] SMP
+[ 28.793240] Modules linked in: vrf nfsd auth_rpcgss oid_registry nfs_acl nfs lockd grace sunrpc crct10dif_pclmul crc32_pclmul crc32c_intel qxl drm_kms_helper ttm drm aesni_intel aes_x86_64 psmouse glue_helper lrw evdev gf128mul i2c_piix4 ablk_helper cryptd ppdev parport_pc parport serio_raw pcspkr virtio_balloon virtio_console i2c_core acpi_cpufreq button 9pnet_virtio 9p 9pnet fscache ipv6 autofs4 ext4 crc16 mbcache jbd2 virtio_blk virtio_net sg sr_mod cdrom ata_generic ehci_pci uhci_hcd ehci_hcd e1000 usbcore usb_common ata_piix libata virtio_pci virtio_ring virtio scsi_mod floppy
+[ 28.796016] CPU: 0 PID: 1148 Comm: ld-linux-x86-64 Not tainted
+4.4.0-rc1+ #24
+[ 28.796016] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.8.1-20150318_183358- 04/01/2014
+[ 28.796016] task: ffff8800352561c0 ti: ffff88003592c000 task.ti: ffff88003592c000
+[ 28.796016] RIP: 0010:[<ffffffff812187b3>] [<ffffffff812187b3>] putname+0x43/0x60
+[ 28.796016] RSP: 0018:ffff88003592fe88 EFLAGS: 00010246
+[ 28.796016] RAX: 0000000000000000 RBX: ffff8800352561c0 RCX: 0000000000000001
+[ 28.796016] RDX: 0000000000000000 RSI: 0000000000000000 RDI: ffff88003784f000
+[ 28.796016] RBP: ffff88003592ff08 R08: 0000000000000001 R09: 0000000000000000
+[ 28.796016] R10: 0000000000000000 R11: 0000000000000001 R12: 0000000000000000
+[ 28.796016] R13: 000000000000047c R14: ffff88003784f000 R15: ffff8800358c4a00
+[ 28.796016] FS: 0000000000000000(0000) GS:ffff88003fc00000(0000) knlGS:0000000000000000
+[ 28.796016] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
+[ 28.796016] CR2: 00007ffd583bc2d9 CR3: 0000000035a99000 CR4: 00000000000406f0
+[ 28.796016] Stack:
+[ 28.796016] ffffffff8121045d ffffffff812102d3 ffff8800352561c0 ffff880035a91660
+[ 28.796016] ffff8800008a9880 0000000000000000 ffffffff81a49940 00ffffff81218684
+[ 28.796016] ffff8800352561c0 000000000000047c 0000000000000000 ffff880035b36d80
+[ 28.796016] Call Trace:
+[ 28.796016] [<ffffffff8121045d>] ? do_execveat_common.isra.34+0x74d/0x930
+[ 28.796016] [<ffffffff812102d3>] ? do_execveat_common.isra.34+0x5c3/0x930
+[ 28.796016] [<ffffffff8121066c>] do_execve+0x2c/0x30
+[ 28.796016] [<ffffffff810939a0>] call_usermodehelper_exec_async+0xf0/0x140
+[ 28.796016] [<ffffffff810938b0>] ? umh_complete+0x40/0x40
+[ 28.796016] [<ffffffff815cb1af>] ret_from_fork+0x3f/0x70
+[ 28.796016] Code: 48 8d 47 1c 48 89 e5 53 48 8b 37 48 89 fb 48 39 c6 74 1a 48 8b 3d 7e e9 8f 00 e8 49 fa fc ff 48 89 df e8 f1 01 fd ff 5b 5d f3 c3 <0f> 0b 48 89 fe 48 8b 3d 61 e9 8f 00 e8 2c fa fc ff 5b 5d eb e9
+[ 28.796016] RIP [<ffffffff812187b3>] putname+0x43/0x60
+[ 28.796016] RSP <ffff88003592fe88>
+
+Fixes: 193125dbd8eb ("net: Introduce VRF device driver")
+Signed-off-by: Nikolay Aleksandrov <nikolay@cumulusnetworks.com>
+Acked-by: David Ahern <dsa@cumulusnetworks.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+[bwh: For 4.3, retain the kfree() on failure]
+Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
+Acked-by: David S. Miller <davem@davemloft.net>
+Acked-by: David Ahern <dsa@cumulusnetworks.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/net/vrf.c | 1 -
+ 1 file changed, 1 deletion(-)
+
+--- a/drivers/net/vrf.c
++++ b/drivers/net/vrf.c
+@@ -608,7 +608,6 @@ static int vrf_newlink(struct net *src_n
+
+ out_fail:
+ kfree(vrf_ptr);
+- free_netdev(dev);
+ return err;
+ }
+