--- /dev/null
+From 3cd99136d06b2375b3ea058c348883a0061af547 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 14 Oct 2019 13:32:53 +0100
+Subject: arm64: capabilities: Handle sign of the feature bit
+
+From: Suzuki K Poulose <suzuki.poulose@arm.com>
+
+commit ff96f7bc7bf6393eef8ff2bde1279715ce13343a usptream
+
+Use the appropriate accessor for the feature bit by keeping
+track of the sign of the feature.
+
+This is a pre-requisite for the commit 28c5dcb22f90 upstream,
+which fixes the arm64_ftr_value() for signed feature fields.
+
+Cc: stable@vger.kernel.org # v4.4
+Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
+Acked-by: Will Deacon <will.deacon@arm.com>
+Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/arm64/include/asm/cpufeature.h | 7 +++---
+ arch/arm64/kernel/cpufeature.c | 33 +++++++++++++++++------------
+ 2 files changed, 23 insertions(+), 17 deletions(-)
+
+diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
+index 0a66f8241f185..690961a749da1 100644
+--- a/arch/arm64/include/asm/cpufeature.h
++++ b/arch/arm64/include/asm/cpufeature.h
+@@ -88,9 +88,10 @@ struct arm64_cpu_capabilities {
+
+ struct { /* Feature register checking */
+ u32 sys_reg;
+- int field_pos;
+- int min_field_value;
+- int hwcap_type;
++ u8 field_pos;
++ u8 min_field_value;
++ u8 hwcap_type;
++ bool sign;
+ unsigned long hwcap;
+ };
+ };
+diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
+index 062484d344509..3949991e544bf 100644
+--- a/arch/arm64/kernel/cpufeature.c
++++ b/arch/arm64/kernel/cpufeature.c
+@@ -636,6 +636,7 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
+ .matches = has_useable_gicv3_cpuif,
+ .sys_reg = SYS_ID_AA64PFR0_EL1,
+ .field_pos = ID_AA64PFR0_GIC_SHIFT,
++ .sign = FTR_UNSIGNED,
+ .min_field_value = 1,
+ },
+ #ifdef CONFIG_ARM64_PAN
+@@ -645,6 +646,7 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
+ .matches = has_cpuid_feature,
+ .sys_reg = SYS_ID_AA64MMFR1_EL1,
+ .field_pos = ID_AA64MMFR1_PAN_SHIFT,
++ .sign = FTR_UNSIGNED,
+ .min_field_value = 1,
+ .enable = cpu_enable_pan,
+ },
+@@ -656,6 +658,7 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
+ .matches = has_cpuid_feature,
+ .sys_reg = SYS_ID_AA64ISAR0_EL1,
+ .field_pos = ID_AA64ISAR0_ATOMICS_SHIFT,
++ .sign = FTR_UNSIGNED,
+ .min_field_value = 2,
+ },
+ #endif /* CONFIG_AS_LSE && CONFIG_ARM64_LSE_ATOMICS */
+@@ -665,37 +668,39 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
+ .matches = has_cpuid_feature,
+ .sys_reg = SYS_ID_AA64PFR0_EL1,
+ .field_pos = ID_AA64PFR0_EL0_SHIFT,
++ .sign = FTR_UNSIGNED,
+ .min_field_value = ID_AA64PFR0_EL0_32BIT_64BIT,
+ },
+ {},
+ };
+
+-#define HWCAP_CAP(reg, field, min_value, type, cap) \
++#define HWCAP_CAP(reg, field, s, min_value, type, cap) \
+ { \
+ .desc = #cap, \
+ .matches = has_cpuid_feature, \
+ .sys_reg = reg, \
+ .field_pos = field, \
++ .sign = s, \
+ .min_field_value = min_value, \
+ .hwcap_type = type, \
+ .hwcap = cap, \
+ }
+
+ static const struct arm64_cpu_capabilities arm64_hwcaps[] = {
+- HWCAP_CAP(SYS_ID_AA64ISAR0_EL1, ID_AA64ISAR0_AES_SHIFT, 2, CAP_HWCAP, HWCAP_PMULL),
+- HWCAP_CAP(SYS_ID_AA64ISAR0_EL1, ID_AA64ISAR0_AES_SHIFT, 1, CAP_HWCAP, HWCAP_AES),
+- HWCAP_CAP(SYS_ID_AA64ISAR0_EL1, ID_AA64ISAR0_SHA1_SHIFT, 1, CAP_HWCAP, HWCAP_SHA1),
+- HWCAP_CAP(SYS_ID_AA64ISAR0_EL1, ID_AA64ISAR0_SHA2_SHIFT, 1, CAP_HWCAP, HWCAP_SHA2),
+- HWCAP_CAP(SYS_ID_AA64ISAR0_EL1, ID_AA64ISAR0_CRC32_SHIFT, 1, CAP_HWCAP, HWCAP_CRC32),
+- HWCAP_CAP(SYS_ID_AA64ISAR0_EL1, ID_AA64ISAR0_ATOMICS_SHIFT, 2, CAP_HWCAP, HWCAP_ATOMICS),
+- HWCAP_CAP(SYS_ID_AA64PFR0_EL1, ID_AA64PFR0_FP_SHIFT, 0, CAP_HWCAP, HWCAP_FP),
+- HWCAP_CAP(SYS_ID_AA64PFR0_EL1, ID_AA64PFR0_ASIMD_SHIFT, 0, CAP_HWCAP, HWCAP_ASIMD),
++ HWCAP_CAP(SYS_ID_AA64ISAR0_EL1, ID_AA64ISAR0_AES_SHIFT, FTR_UNSIGNED, 2, CAP_HWCAP, HWCAP_PMULL),
++ HWCAP_CAP(SYS_ID_AA64ISAR0_EL1, ID_AA64ISAR0_AES_SHIFT, FTR_UNSIGNED, 1, CAP_HWCAP, HWCAP_AES),
++ HWCAP_CAP(SYS_ID_AA64ISAR0_EL1, ID_AA64ISAR0_SHA1_SHIFT, FTR_UNSIGNED, 1, CAP_HWCAP, HWCAP_SHA1),
++ HWCAP_CAP(SYS_ID_AA64ISAR0_EL1, ID_AA64ISAR0_SHA2_SHIFT, FTR_UNSIGNED, 1, CAP_HWCAP, HWCAP_SHA2),
++ HWCAP_CAP(SYS_ID_AA64ISAR0_EL1, ID_AA64ISAR0_CRC32_SHIFT, FTR_UNSIGNED, 1, CAP_HWCAP, HWCAP_CRC32),
++ HWCAP_CAP(SYS_ID_AA64ISAR0_EL1, ID_AA64ISAR0_ATOMICS_SHIFT, FTR_UNSIGNED, 2, CAP_HWCAP, HWCAP_ATOMICS),
++ HWCAP_CAP(SYS_ID_AA64PFR0_EL1, ID_AA64PFR0_FP_SHIFT, FTR_SIGNED, 0, CAP_HWCAP, HWCAP_FP),
++ HWCAP_CAP(SYS_ID_AA64PFR0_EL1, ID_AA64PFR0_ASIMD_SHIFT, FTR_SIGNED, 0, CAP_HWCAP, HWCAP_ASIMD),
+ #ifdef CONFIG_COMPAT
+- HWCAP_CAP(SYS_ID_ISAR5_EL1, ID_ISAR5_AES_SHIFT, 2, CAP_COMPAT_HWCAP2, COMPAT_HWCAP2_PMULL),
+- HWCAP_CAP(SYS_ID_ISAR5_EL1, ID_ISAR5_AES_SHIFT, 1, CAP_COMPAT_HWCAP2, COMPAT_HWCAP2_AES),
+- HWCAP_CAP(SYS_ID_ISAR5_EL1, ID_ISAR5_SHA1_SHIFT, 1, CAP_COMPAT_HWCAP2, COMPAT_HWCAP2_SHA1),
+- HWCAP_CAP(SYS_ID_ISAR5_EL1, ID_ISAR5_SHA2_SHIFT, 1, CAP_COMPAT_HWCAP2, COMPAT_HWCAP2_SHA2),
+- HWCAP_CAP(SYS_ID_ISAR5_EL1, ID_ISAR5_CRC32_SHIFT, 1, CAP_COMPAT_HWCAP2, COMPAT_HWCAP2_CRC32),
++ HWCAP_CAP(SYS_ID_ISAR5_EL1, ID_ISAR5_AES_SHIFT, FTR_UNSIGNED, 2, CAP_COMPAT_HWCAP2, COMPAT_HWCAP2_PMULL),
++ HWCAP_CAP(SYS_ID_ISAR5_EL1, ID_ISAR5_AES_SHIFT, FTR_UNSIGNED, 1, CAP_COMPAT_HWCAP2, COMPAT_HWCAP2_AES),
++ HWCAP_CAP(SYS_ID_ISAR5_EL1, ID_ISAR5_SHA1_SHIFT, FTR_UNSIGNED, 1, CAP_COMPAT_HWCAP2, COMPAT_HWCAP2_SHA1),
++ HWCAP_CAP(SYS_ID_ISAR5_EL1, ID_ISAR5_SHA2_SHIFT, FTR_UNSIGNED, 1, CAP_COMPAT_HWCAP2, COMPAT_HWCAP2_SHA2),
++ HWCAP_CAP(SYS_ID_ISAR5_EL1, ID_ISAR5_CRC32_SHIFT, FTR_UNSIGNED, 1, CAP_COMPAT_HWCAP2, COMPAT_HWCAP2_CRC32),
+ #endif
+ {},
+ };
+--
+2.20.1
+
--- /dev/null
+From d40dd95a120e5127af8f4aa2bf47ab3e81265cea Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 14 Oct 2019 13:32:54 +0100
+Subject: arm64: Rename cpuid_feature field extract routines
+
+From: Suzuki K Poulose <suzuki.poulose@arm.com>
+
+commit 28c5dcb22f90113dea101b0421bc6971bccb7a74 upstream
+
+Now that we have a clear understanding of the sign of a feature,
+rename the routines to reflect the sign, so that it is not misused.
+The cpuid_feature_extract_field() now accepts a 'sign' parameter.
+
+This makes sure that the arm64_ftr_value() extracts the feature
+field properly for signed fields.
+
+Cc: stable@vger.kernel.org # v4.4
+Signed-off-by: Suzuki K. Poulose <suzuki.poulose@arm.com>
+Acked-by: Will Deacon <will.deacon@arm.com>
+Acked-by: Marc Zyngier <marc.zyngier@arm.com>
+Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/arm64/include/asm/cpufeature.h | 22 ++++++++++++++--------
+ arch/arm64/kernel/cpufeature.c | 2 +-
+ arch/arm64/kernel/debug-monitors.c | 2 +-
+ arch/arm64/kvm/sys_regs.c | 2 +-
+ arch/arm64/mm/context.c | 3 ++-
+ 5 files changed, 19 insertions(+), 12 deletions(-)
+
+diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
+index 690961a749da1..518eaa63e633e 100644
+--- a/arch/arm64/include/asm/cpufeature.h
++++ b/arch/arm64/include/asm/cpufeature.h
+@@ -121,15 +121,15 @@ static inline void cpus_set_cap(unsigned int num)
+ }
+
+ static inline int __attribute_const__
+-cpuid_feature_extract_field_width(u64 features, int field, int width)
++cpuid_feature_extract_signed_field_width(u64 features, int field, int width)
+ {
+ return (s64)(features << (64 - width - field)) >> (64 - width);
+ }
+
+ static inline int __attribute_const__
+-cpuid_feature_extract_field(u64 features, int field)
++cpuid_feature_extract_signed_field(u64 features, int field)
+ {
+- return cpuid_feature_extract_field_width(features, field, 4);
++ return cpuid_feature_extract_signed_field_width(features, field, 4);
+ }
+
+ static inline unsigned int __attribute_const__
+@@ -149,17 +149,23 @@ static inline u64 arm64_ftr_mask(struct arm64_ftr_bits *ftrp)
+ return (u64)GENMASK(ftrp->shift + ftrp->width - 1, ftrp->shift);
+ }
+
++static inline int __attribute_const__
++cpuid_feature_extract_field(u64 features, int field, bool sign)
++{
++ return (sign) ?
++ cpuid_feature_extract_signed_field(features, field) :
++ cpuid_feature_extract_unsigned_field(features, field);
++}
++
+ static inline s64 arm64_ftr_value(struct arm64_ftr_bits *ftrp, u64 val)
+ {
+- return ftrp->sign ?
+- cpuid_feature_extract_field_width(val, ftrp->shift, ftrp->width) :
+- cpuid_feature_extract_unsigned_field_width(val, ftrp->shift, ftrp->width);
++ return (s64)cpuid_feature_extract_field(val, ftrp->shift, ftrp->sign);
+ }
+
+ static inline bool id_aa64mmfr0_mixed_endian_el0(u64 mmfr0)
+ {
+- return cpuid_feature_extract_field(mmfr0, ID_AA64MMFR0_BIGENDEL_SHIFT) == 0x1 ||
+- cpuid_feature_extract_field(mmfr0, ID_AA64MMFR0_BIGENDEL0_SHIFT) == 0x1;
++ return cpuid_feature_extract_unsigned_field(mmfr0, ID_AA64MMFR0_BIGENDEL_SHIFT) == 0x1 ||
++ cpuid_feature_extract_unsigned_field(mmfr0, ID_AA64MMFR0_BIGENDEL0_SHIFT) == 0x1;
+ }
+
+ void __init setup_cpu_features(void);
+diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
+index 3949991e544bf..a0118a07a4a5f 100644
+--- a/arch/arm64/kernel/cpufeature.c
++++ b/arch/arm64/kernel/cpufeature.c
+@@ -600,7 +600,7 @@ u64 read_system_reg(u32 id)
+ static bool
+ feature_matches(u64 reg, const struct arm64_cpu_capabilities *entry)
+ {
+- int val = cpuid_feature_extract_field(reg, entry->field_pos);
++ int val = cpuid_feature_extract_field(reg, entry->field_pos, entry->sign);
+
+ return val >= entry->min_field_value;
+ }
+diff --git a/arch/arm64/kernel/debug-monitors.c b/arch/arm64/kernel/debug-monitors.c
+index c8875b64be909..8e7675e5ce4a5 100644
+--- a/arch/arm64/kernel/debug-monitors.c
++++ b/arch/arm64/kernel/debug-monitors.c
+@@ -34,7 +34,7 @@
+ /* Determine debug architecture. */
+ u8 debug_monitors_arch(void)
+ {
+- return cpuid_feature_extract_field(read_system_reg(SYS_ID_AA64DFR0_EL1),
++ return cpuid_feature_extract_unsigned_field(read_system_reg(SYS_ID_AA64DFR0_EL1),
+ ID_AA64DFR0_DEBUGVER_SHIFT);
+ }
+
+diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c
+index c2489f62c4fb1..0a587e7b9b6eb 100644
+--- a/arch/arm64/kvm/sys_regs.c
++++ b/arch/arm64/kvm/sys_regs.c
+@@ -687,7 +687,7 @@ static bool trap_dbgidr(struct kvm_vcpu *vcpu,
+ } else {
+ u64 dfr = read_system_reg(SYS_ID_AA64DFR0_EL1);
+ u64 pfr = read_system_reg(SYS_ID_AA64PFR0_EL1);
+- u32 el3 = !!cpuid_feature_extract_field(pfr, ID_AA64PFR0_EL3_SHIFT);
++ u32 el3 = !!cpuid_feature_extract_unsigned_field(pfr, ID_AA64PFR0_EL3_SHIFT);
+
+ p->regval = ((((dfr >> ID_AA64DFR0_WRPS_SHIFT) & 0xf) << 28) |
+ (((dfr >> ID_AA64DFR0_BRPS_SHIFT) & 0xf) << 24) |
+diff --git a/arch/arm64/mm/context.c b/arch/arm64/mm/context.c
+index e87f53ff5f583..5c8759cd66f15 100644
+--- a/arch/arm64/mm/context.c
++++ b/arch/arm64/mm/context.c
+@@ -187,7 +187,8 @@ void check_and_switch_context(struct mm_struct *mm, unsigned int cpu)
+
+ static int asids_init(void)
+ {
+- int fld = cpuid_feature_extract_field(read_cpuid(ID_AA64MMFR0_EL1), 4);
++ int fld = cpuid_feature_extract_unsigned_field(read_cpuid(ID_AA64MMFR0_EL1),
++ ID_AA64MMFR0_ASID_SHIFT);
+
+ switch (fld) {
+ default:
+--
+2.20.1
+
--- /dev/null
+From 66612b92c09bf9ba59366473f8a76cacb173de26 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 2 Dec 2015 14:46:08 +0000
+Subject: cifs: Check uniqueid for SMB2+ and return -ESTALE if necessary
+
+From: Ross Lagerwall <ross.lagerwall@citrix.com>
+
+[ Upstream commit a108471b5730b52017e73b58c9f486319d2ac308 ]
+
+Commit 7196ac113a4f ("Fix to check Unique id and FileType when client
+refer file directly.") checks whether the uniqueid of an inode has
+changed when getting the inode info, but only when using the UNIX
+extensions. Add a similar check for SMB2+, since this can be done
+without an extra network roundtrip.
+
+Signed-off-by: Ross Lagerwall <ross.lagerwall@citrix.com>
+Signed-off-by: Steve French <smfrench@gmail.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/cifs/inode.c | 24 ++++++++++++++++++++++--
+ 1 file changed, 22 insertions(+), 2 deletions(-)
+
+diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
+index 0f210cb5038a4..3d3c66fcb5ee6 100644
+--- a/fs/cifs/inode.c
++++ b/fs/cifs/inode.c
+@@ -829,8 +829,21 @@ cifs_get_inode_info(struct inode **inode, const char *full_path,
+ }
+ } else
+ fattr.cf_uniqueid = iunique(sb, ROOT_I);
+- } else
+- fattr.cf_uniqueid = CIFS_I(*inode)->uniqueid;
++ } else {
++ if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) &&
++ validinum == false && server->ops->get_srv_inum) {
++ /*
++ * Pass a NULL tcon to ensure we don't make a round
++ * trip to the server. This only works for SMB2+.
++ */
++ tmprc = server->ops->get_srv_inum(xid,
++ NULL, cifs_sb, full_path,
++ &fattr.cf_uniqueid, data);
++ if (tmprc)
++ fattr.cf_uniqueid = CIFS_I(*inode)->uniqueid;
++ } else
++ fattr.cf_uniqueid = CIFS_I(*inode)->uniqueid;
++ }
+
+ /* query for SFU type info if supported and needed */
+ if (fattr.cf_cifsattrs & ATTR_SYSTEM &&
+@@ -871,6 +884,13 @@ cifs_get_inode_info(struct inode **inode, const char *full_path,
+ } else {
+ /* we already have inode, update it */
+
++ /* if uniqueid is different, return error */
++ if (unlikely(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM &&
++ CIFS_I(*inode)->uniqueid != fattr.cf_uniqueid)) {
++ rc = -ESTALE;
++ goto cgii_exit;
++ }
++
+ /* if filetype is different, return error */
+ if (unlikely(((*inode)->i_mode & S_IFMT) !=
+ (fattr.cf_mode & S_IFMT))) {
+--
+2.20.1
+
--- /dev/null
+From 067ec71b5f3e6b20fc1854ec54746146fa6557d9 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 30 Sep 2019 10:06:19 -0700
+Subject: CIFS: Force revalidate inode when dentry is stale
+
+From: Pavel Shilovsky <piastryyy@gmail.com>
+
+[ Upstream commit c82e5ac7fe3570a269c0929bf7899f62048e7dbc ]
+
+Currently the client indicates that a dentry is stale when inode
+numbers or type types between a local inode and a remote file
+don't match. If this is the case attributes is not being copied
+from remote to local, so, it is already known that the local copy
+has stale metadata. That's why the inode needs to be marked for
+revalidation in order to tell the VFS to lookup the dentry again
+before openning a file. This prevents unexpected stale errors
+to be returned to the user space when openning a file.
+
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Pavel Shilovsky <pshilov@microsoft.com>
+Signed-off-by: Steve French <stfrench@microsoft.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/cifs/inode.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
+index 3d3c66fcb5ee6..0a219545940d9 100644
+--- a/fs/cifs/inode.c
++++ b/fs/cifs/inode.c
+@@ -405,6 +405,7 @@ int cifs_get_inode_info_unix(struct inode **pinode,
+ /* if uniqueid is different, return error */
+ if (unlikely(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM &&
+ CIFS_I(*pinode)->uniqueid != fattr.cf_uniqueid)) {
++ CIFS_I(*pinode)->time = 0; /* force reval */
+ rc = -ESTALE;
+ goto cgiiu_exit;
+ }
+@@ -412,6 +413,7 @@ int cifs_get_inode_info_unix(struct inode **pinode,
+ /* if filetype is different, return error */
+ if (unlikely(((*pinode)->i_mode & S_IFMT) !=
+ (fattr.cf_mode & S_IFMT))) {
++ CIFS_I(*pinode)->time = 0; /* force reval */
+ rc = -ESTALE;
+ goto cgiiu_exit;
+ }
+@@ -887,6 +889,7 @@ cifs_get_inode_info(struct inode **inode, const char *full_path,
+ /* if uniqueid is different, return error */
+ if (unlikely(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM &&
+ CIFS_I(*inode)->uniqueid != fattr.cf_uniqueid)) {
++ CIFS_I(*inode)->time = 0; /* force reval */
+ rc = -ESTALE;
+ goto cgii_exit;
+ }
+@@ -894,6 +897,7 @@ cifs_get_inode_info(struct inode **inode, const char *full_path,
+ /* if filetype is different, return error */
+ if (unlikely(((*inode)->i_mode & S_IFMT) !=
+ (fattr.cf_mode & S_IFMT))) {
++ CIFS_I(*inode)->time = 0; /* force reval */
+ rc = -ESTALE;
+ goto cgii_exit;
+ }
+--
+2.20.1
+
cifs-gracefully-handle-queryinfo-errors-during-open.patch
cifs-force-reval-dentry-if-lookup_reval-flag-is-set.patch
kernel-sysctl.c-do-not-override-max_threads-provided-by-userspace.patch
+arm64-capabilities-handle-sign-of-the-feature-bit.patch
+arm64-rename-cpuid_feature-field-extract-routines.patch
+staging-fbtft-fix-memory-leak-in-fbtft_framebuffer_a.patch
+cifs-check-uniqueid-for-smb2-and-return-estale-if-ne.patch
+cifs-force-revalidate-inode-when-dentry-is-stale.patch
--- /dev/null
+From 7c8878e6aeddec61635d4d3dd7697442b505fcc4 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 29 Sep 2019 22:09:45 -0500
+Subject: Staging: fbtft: fix memory leak in fbtft_framebuffer_alloc
+
+From: Navid Emamdoost <navid.emamdoost@gmail.com>
+
+[ Upstream commit 5bdea6060618cfcf1459dca137e89aee038ac8b9 ]
+
+In fbtft_framebuffer_alloc the error handling path should take care of
+releasing frame buffer after it is allocated via framebuffer_alloc, too.
+Therefore, in two failure cases the goto destination is changed to
+address this issue.
+
+Fixes: c296d5f9957c ("staging: fbtft: core support")
+Signed-off-by: Navid Emamdoost <navid.emamdoost@gmail.com>
+Reviewed-by: Dan Carpenter <dan.carpenter@gmail.com>
+Cc: stable <stable@vger.kernel.org>
+Link: https://lore.kernel.org/r/20190930030949.28615-1-navid.emamdoost@gmail.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/staging/fbtft/fbtft-core.c | 7 +++++--
+ 1 file changed, 5 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/staging/fbtft/fbtft-core.c b/drivers/staging/fbtft/fbtft-core.c
+index 18c2b6daf5885..15937e0ef4d96 100644
+--- a/drivers/staging/fbtft/fbtft-core.c
++++ b/drivers/staging/fbtft/fbtft-core.c
+@@ -813,7 +813,7 @@ struct fb_info *fbtft_framebuffer_alloc(struct fbtft_display *display,
+ if (par->gamma.curves && gamma) {
+ if (fbtft_gamma_parse_str(par,
+ par->gamma.curves, gamma, strlen(gamma)))
+- goto alloc_fail;
++ goto release_framebuf;
+ }
+
+ /* Transmit buffer */
+@@ -836,7 +836,7 @@ struct fb_info *fbtft_framebuffer_alloc(struct fbtft_display *display,
+ txbuf = devm_kzalloc(par->info->device, txbuflen, GFP_KERNEL);
+ }
+ if (!txbuf)
+- goto alloc_fail;
++ goto release_framebuf;
+ par->txbuf.buf = txbuf;
+ par->txbuf.len = txbuflen;
+ }
+@@ -872,6 +872,9 @@ struct fb_info *fbtft_framebuffer_alloc(struct fbtft_display *display,
+
+ return info;
+
++release_framebuf:
++ framebuffer_release(info);
++
+ alloc_fail:
+ vfree(vmem);
+
+--
+2.20.1
+