From: Greg Kroah-Hartman Date: Thu, 6 Dec 2018 11:31:53 +0000 (+0100) Subject: 4.14-stable patches X-Git-Tag: v4.19.8~13 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=9188e9c13ff6dd398f062a6a40997bb23be44fd2;p=thirdparty%2Fkernel%2Fstable-queue.git 4.14-stable patches added patches: arc-add-support-of-nfsv3-acl.patch arc-change-defconfig-defaults-to-arcv2.patch btrfs-always-try-all-copies-when-reading-extent-buffers.patch btrfs-tree-checker-don-t-check-max-block-group-size-as-current-max-chunk-size-limit-is-unreliable.patch drm-msm-fix-of-child-node-lookup.patch input-cros_ec_keyb-fix-button-switch-capability-reports.patch input-elan_i2c-add-acpi-id-for-lenovo-ideapad-330-15arr.patch input-elan_i2c-add-elan0620-to-the-acpi-table.patch input-elan_i2c-add-support-for-elan0621-touchpad.patch input-matrix_keypad-check-for-errors-from-of_get_named_gpio.patch input-synaptics-add-pnp-id-for-thinkpad-p50-to-smbus.patch input-xpad-quirk-all-pdp-xbox-one-gamepads.patch kgdboc-fix-warning-with-module-build.patch mm-cleancache-fix-corruption-on-missed-inode-invalidation.patch mm-hide-incomplete-nr_indirectly_reclaimable-in-proc-zoneinfo.patch reset-make-device_reset_optional-really-optional.patch reset-remove-remaining-warn_on-in-linux-reset.h.patch svm-add-mutex_lock-to-protect-apic_access_page_done-on-amd-systems.patch thermal-drivers-hisi-encapsulate-register-writes-into-helpers.patch thermal-drivers-hisi-fix-configuration-register-setting.patch thermal-drivers-hisi-remove-costly-sensor-inspection.patch thermal-drivers-hisi-remove-pointless-lock.patch thermal-drivers-hisi-remove-the-multiple-sensors-support.patch udf-allow-mounting-volumes-with-incorrect-identification-strings.patch --- diff --git a/queue-4.14/arc-add-support-of-nfsv3-acl.patch b/queue-4.14/arc-add-support-of-nfsv3-acl.patch new file mode 100644 index 00000000000..4767c6a3b84 --- /dev/null +++ b/queue-4.14/arc-add-support-of-nfsv3-acl.patch @@ -0,0 +1,133 @@ +From 6b04114f6fae5e84d33404c2970b1949c032546e Mon Sep 17 00:00:00 2001 +From: Alexey Brodkin +Date: Tue, 20 Nov 2018 13:30:19 +0300 +Subject: arc: [devboards] Add support of NFSv3 ACL + +From: Alexey Brodkin + +commit 6b04114f6fae5e84d33404c2970b1949c032546e upstream. + +By default NFSv3 doesn't support ACL (Access Control Lists) +which might be quite convenient to have so that +mounted NFS behaves exactly as any other local file-system. + +In particular missing support of ACL makes umask useless. +This among other thigs fixes Glibc's "nptl/tst-umask1". + +Signed-off-by: Alexey Brodkin +Cc: Cupertino Miranda +Cc: stable@vger.kernel.org #4.14+ +Signed-off-by: Vineet Gupta +Signed-off-by: Greg Kroah-Hartman + +--- + arch/arc/configs/axs101_defconfig | 1 + + arch/arc/configs/axs103_defconfig | 1 + + arch/arc/configs/axs103_smp_defconfig | 1 + + arch/arc/configs/hsdk_defconfig | 1 + + arch/arc/configs/nps_defconfig | 1 + + arch/arc/configs/nsimosci_defconfig | 1 + + arch/arc/configs/nsimosci_hs_defconfig | 1 + + arch/arc/configs/nsimosci_hs_smp_defconfig | 1 + + arch/arc/configs/vdk_hs38_defconfig | 1 + + arch/arc/configs/vdk_hs38_smp_defconfig | 1 + + 10 files changed, 10 insertions(+) + +--- a/arch/arc/configs/axs101_defconfig ++++ b/arch/arc/configs/axs101_defconfig +@@ -99,6 +99,7 @@ CONFIG_VFAT_FS=y + CONFIG_NTFS_FS=y + CONFIG_TMPFS=y + CONFIG_NFS_FS=y ++CONFIG_NFS_V3_ACL=y + CONFIG_NLS_CODEPAGE_437=y + CONFIG_NLS_ISO8859_1=y + # CONFIG_ENABLE_WARN_DEPRECATED is not set +--- a/arch/arc/configs/axs103_defconfig ++++ b/arch/arc/configs/axs103_defconfig +@@ -97,6 +97,7 @@ CONFIG_VFAT_FS=y + CONFIG_NTFS_FS=y + CONFIG_TMPFS=y + CONFIG_NFS_FS=y ++CONFIG_NFS_V3_ACL=y + CONFIG_NLS_CODEPAGE_437=y + CONFIG_NLS_ISO8859_1=y + # CONFIG_ENABLE_WARN_DEPRECATED is not set +--- a/arch/arc/configs/axs103_smp_defconfig ++++ b/arch/arc/configs/axs103_smp_defconfig +@@ -100,6 +100,7 @@ CONFIG_VFAT_FS=y + CONFIG_NTFS_FS=y + CONFIG_TMPFS=y + CONFIG_NFS_FS=y ++CONFIG_NFS_V3_ACL=y + CONFIG_NLS_CODEPAGE_437=y + CONFIG_NLS_ISO8859_1=y + # CONFIG_ENABLE_WARN_DEPRECATED is not set +--- a/arch/arc/configs/hsdk_defconfig ++++ b/arch/arc/configs/hsdk_defconfig +@@ -66,6 +66,7 @@ CONFIG_EXT3_FS=y + CONFIG_VFAT_FS=y + CONFIG_TMPFS=y + CONFIG_NFS_FS=y ++CONFIG_NFS_V3_ACL=y + CONFIG_NLS_CODEPAGE_437=y + CONFIG_NLS_ISO8859_1=y + # CONFIG_ENABLE_WARN_DEPRECATED is not set +--- a/arch/arc/configs/nps_defconfig ++++ b/arch/arc/configs/nps_defconfig +@@ -75,6 +75,7 @@ CONFIG_PROC_KCORE=y + CONFIG_TMPFS=y + # CONFIG_MISC_FILESYSTEMS is not set + CONFIG_NFS_FS=y ++CONFIG_NFS_V3_ACL=y + CONFIG_ROOT_NFS=y + CONFIG_DEBUG_INFO=y + # CONFIG_ENABLE_WARN_DEPRECATED is not set +--- a/arch/arc/configs/nsimosci_defconfig ++++ b/arch/arc/configs/nsimosci_defconfig +@@ -70,5 +70,6 @@ CONFIG_EXT2_FS_XATTR=y + CONFIG_TMPFS=y + # CONFIG_MISC_FILESYSTEMS is not set + CONFIG_NFS_FS=y ++CONFIG_NFS_V3_ACL=y + # CONFIG_ENABLE_WARN_DEPRECATED is not set + # CONFIG_ENABLE_MUST_CHECK is not set +--- a/arch/arc/configs/nsimosci_hs_defconfig ++++ b/arch/arc/configs/nsimosci_hs_defconfig +@@ -68,5 +68,6 @@ CONFIG_EXT2_FS_XATTR=y + CONFIG_TMPFS=y + # CONFIG_MISC_FILESYSTEMS is not set + CONFIG_NFS_FS=y ++CONFIG_NFS_V3_ACL=y + # CONFIG_ENABLE_WARN_DEPRECATED is not set + # CONFIG_ENABLE_MUST_CHECK is not set +--- a/arch/arc/configs/nsimosci_hs_smp_defconfig ++++ b/arch/arc/configs/nsimosci_hs_smp_defconfig +@@ -79,6 +79,7 @@ CONFIG_EXT2_FS_XATTR=y + CONFIG_TMPFS=y + # CONFIG_MISC_FILESYSTEMS is not set + CONFIG_NFS_FS=y ++CONFIG_NFS_V3_ACL=y + # CONFIG_ENABLE_WARN_DEPRECATED is not set + # CONFIG_ENABLE_MUST_CHECK is not set + CONFIG_FTRACE=y +--- a/arch/arc/configs/vdk_hs38_defconfig ++++ b/arch/arc/configs/vdk_hs38_defconfig +@@ -88,6 +88,7 @@ CONFIG_NTFS_FS=y + CONFIG_TMPFS=y + CONFIG_JFFS2_FS=y + CONFIG_NFS_FS=y ++CONFIG_NFS_V3_ACL=y + CONFIG_NLS_CODEPAGE_437=y + CONFIG_NLS_ISO8859_1=y + # CONFIG_ENABLE_WARN_DEPRECATED is not set +--- a/arch/arc/configs/vdk_hs38_smp_defconfig ++++ b/arch/arc/configs/vdk_hs38_smp_defconfig +@@ -92,6 +92,7 @@ CONFIG_NTFS_FS=y + CONFIG_TMPFS=y + CONFIG_JFFS2_FS=y + CONFIG_NFS_FS=y ++CONFIG_NFS_V3_ACL=y + CONFIG_NLS_CODEPAGE_437=y + CONFIG_NLS_ISO8859_1=y + # CONFIG_ENABLE_WARN_DEPRECATED is not set diff --git a/queue-4.14/arc-change-defconfig-defaults-to-arcv2.patch b/queue-4.14/arc-change-defconfig-defaults-to-arcv2.patch new file mode 100644 index 00000000000..6d4b8abcef2 --- /dev/null +++ b/queue-4.14/arc-change-defconfig-defaults-to-arcv2.patch @@ -0,0 +1,109 @@ +From b7cc40c32a8bfa6f2581a71747f6a7d491fe43ba Mon Sep 17 00:00:00 2001 +From: Kevin Hilman +Date: Fri, 30 Nov 2018 15:51:56 +0300 +Subject: ARC: change defconfig defaults to ARCv2 + +From: Kevin Hilman + +commit b7cc40c32a8bfa6f2581a71747f6a7d491fe43ba upstream. + +Change the default defconfig (used with 'make defconfig') to the ARCv2 +nsim_hs_defconfig, and also switch the default Kconfig ISA selection to +ARCv2. + +This allows several default defconfigs (e.g. make defconfig, make +allnoconfig, make tinyconfig) to all work with ARCv2 by default. + +Note since we change default architecture from ARCompact to ARCv2 +it's required to explicitly mention architecture type in ARCompact +defconfigs otherwise ARCv2 will be implied and binaries will be +generated for ARCv2. + +Cc: # 4.4.x +Signed-off-by: Kevin Hilman +Signed-off-by: Alexey Brodkin +Signed-off-by: Vineet Gupta +Signed-off-by: Greg Kroah-Hartman + +--- + arch/arc/Kconfig | 2 +- + arch/arc/Makefile | 2 +- + arch/arc/configs/axs101_defconfig | 1 + + arch/arc/configs/nps_defconfig | 1 + + arch/arc/configs/nsim_700_defconfig | 1 + + arch/arc/configs/nsimosci_defconfig | 1 + + arch/arc/configs/tb10x_defconfig | 1 + + 7 files changed, 7 insertions(+), 2 deletions(-) + +--- a/arch/arc/Kconfig ++++ b/arch/arc/Kconfig +@@ -109,7 +109,7 @@ endmenu + + choice + prompt "ARC Instruction Set" +- default ISA_ARCOMPACT ++ default ISA_ARCV2 + + config ISA_ARCOMPACT + bool "ARCompact ISA" +--- a/arch/arc/Makefile ++++ b/arch/arc/Makefile +@@ -6,7 +6,7 @@ + # published by the Free Software Foundation. + # + +-KBUILD_DEFCONFIG := nsim_700_defconfig ++KBUILD_DEFCONFIG := nsim_hs_defconfig + + cflags-y += -fno-common -pipe -fno-builtin -mmedium-calls -D__linux__ + cflags-$(CONFIG_ISA_ARCOMPACT) += -mA7 +--- a/arch/arc/configs/axs101_defconfig ++++ b/arch/arc/configs/axs101_defconfig +@@ -15,6 +15,7 @@ CONFIG_PERF_EVENTS=y + # CONFIG_VM_EVENT_COUNTERS is not set + # CONFIG_SLUB_DEBUG is not set + # CONFIG_COMPAT_BRK is not set ++CONFIG_ISA_ARCOMPACT=y + CONFIG_MODULES=y + CONFIG_MODULE_FORCE_LOAD=y + CONFIG_MODULE_UNLOAD=y +--- a/arch/arc/configs/nps_defconfig ++++ b/arch/arc/configs/nps_defconfig +@@ -15,6 +15,7 @@ CONFIG_SYSCTL_SYSCALL=y + CONFIG_EMBEDDED=y + CONFIG_PERF_EVENTS=y + # CONFIG_COMPAT_BRK is not set ++CONFIG_ISA_ARCOMPACT=y + CONFIG_KPROBES=y + CONFIG_MODULES=y + CONFIG_MODULE_FORCE_LOAD=y +--- a/arch/arc/configs/nsim_700_defconfig ++++ b/arch/arc/configs/nsim_700_defconfig +@@ -16,6 +16,7 @@ CONFIG_EMBEDDED=y + CONFIG_PERF_EVENTS=y + # CONFIG_SLUB_DEBUG is not set + # CONFIG_COMPAT_BRK is not set ++CONFIG_ISA_ARCOMPACT=y + CONFIG_KPROBES=y + CONFIG_MODULES=y + # CONFIG_LBDAF is not set +--- a/arch/arc/configs/nsimosci_defconfig ++++ b/arch/arc/configs/nsimosci_defconfig +@@ -16,6 +16,7 @@ CONFIG_EMBEDDED=y + CONFIG_PERF_EVENTS=y + # CONFIG_SLUB_DEBUG is not set + # CONFIG_COMPAT_BRK is not set ++CONFIG_ISA_ARCOMPACT=y + CONFIG_KPROBES=y + CONFIG_MODULES=y + # CONFIG_LBDAF is not set +--- a/arch/arc/configs/tb10x_defconfig ++++ b/arch/arc/configs/tb10x_defconfig +@@ -19,6 +19,7 @@ CONFIG_KALLSYMS_ALL=y + # CONFIG_AIO is not set + CONFIG_EMBEDDED=y + # CONFIG_COMPAT_BRK is not set ++CONFIG_ISA_ARCOMPACT=y + CONFIG_SLAB=y + CONFIG_MODULES=y + CONFIG_MODULE_FORCE_LOAD=y diff --git a/queue-4.14/btrfs-always-try-all-copies-when-reading-extent-buffers.patch b/queue-4.14/btrfs-always-try-all-copies-when-reading-extent-buffers.patch new file mode 100644 index 00000000000..4b04ed22730 --- /dev/null +++ b/queue-4.14/btrfs-always-try-all-copies-when-reading-extent-buffers.patch @@ -0,0 +1,78 @@ +From f8397d69daef06d358430d3054662fb597e37c00 Mon Sep 17 00:00:00 2001 +From: Nikolay Borisov +Date: Tue, 6 Nov 2018 16:40:20 +0200 +Subject: btrfs: Always try all copies when reading extent buffers + +From: Nikolay Borisov + +commit f8397d69daef06d358430d3054662fb597e37c00 upstream. + +When a metadata read is served the endio routine btree_readpage_end_io_hook +is called which eventually runs the tree-checker. If tree-checker fails +to validate the read eb then it sets EXTENT_BUFFER_CORRUPT flag. This +leads to btree_read_extent_buffer_pages wrongly assuming that all +available copies of this extent buffer are wrong and failing prematurely. +Fix this modify btree_read_extent_buffer_pages to read all copies of +the data. + +This failure was exhibitted in xfstests btrfs/124 which would +spuriously fail its balance operations. The reason was that when balance +was run following re-introduction of the missing raid1 disk +__btrfs_map_block would map the read request to stripe 0, which +corresponded to devid 2 (the disk which is being removed in the test): + + item 2 key (FIRST_CHUNK_TREE CHUNK_ITEM 3553624064) itemoff 15975 itemsize 112 + length 1073741824 owner 2 stripe_len 65536 type DATA|RAID1 + io_align 65536 io_width 65536 sector_size 4096 + num_stripes 2 sub_stripes 1 + stripe 0 devid 2 offset 2156920832 + dev_uuid 8466c350-ed0c-4c3b-b17d-6379b445d5c8 + stripe 1 devid 1 offset 3553624064 + dev_uuid 1265d8db-5596-477e-af03-df08eb38d2ca + +This caused read requests for a checksum item that to be routed to the +stale disk which triggered the aforementioned logic involving +EXTENT_BUFFER_CORRUPT flag. This then triggered cascading failures of +the balance operation. + +Fixes: a826d6dcb32d ("Btrfs: check items for correctness as we search") +CC: stable@vger.kernel.org # 4.4+ +Suggested-by: Qu Wenruo +Reviewed-by: Qu Wenruo +Signed-off-by: Nikolay Borisov +Signed-off-by: David Sterba +Signed-off-by: Greg Kroah-Hartman + + +--- + fs/btrfs/disk-io.c | 10 +--------- + 1 file changed, 1 insertion(+), 9 deletions(-) + +--- a/fs/btrfs/disk-io.c ++++ b/fs/btrfs/disk-io.c +@@ -451,9 +451,9 @@ static int btree_read_extent_buffer_page + int mirror_num = 0; + int failed_mirror = 0; + +- clear_bit(EXTENT_BUFFER_CORRUPT, &eb->bflags); + io_tree = &BTRFS_I(fs_info->btree_inode)->io_tree; + while (1) { ++ clear_bit(EXTENT_BUFFER_CORRUPT, &eb->bflags); + ret = read_extent_buffer_pages(io_tree, eb, WAIT_COMPLETE, + btree_get_extent, mirror_num); + if (!ret) { +@@ -464,14 +464,6 @@ static int btree_read_extent_buffer_page + ret = -EIO; + } + +- /* +- * This buffer's crc is fine, but its contents are corrupted, so +- * there is no reason to read the other copies, they won't be +- * any less wrong. +- */ +- if (test_bit(EXTENT_BUFFER_CORRUPT, &eb->bflags)) +- break; +- + num_copies = btrfs_num_copies(fs_info, + eb->start, eb->len); + if (num_copies == 1) diff --git a/queue-4.14/btrfs-tree-checker-don-t-check-max-block-group-size-as-current-max-chunk-size-limit-is-unreliable.patch b/queue-4.14/btrfs-tree-checker-don-t-check-max-block-group-size-as-current-max-chunk-size-limit-is-unreliable.patch new file mode 100644 index 00000000000..f86d4292e90 --- /dev/null +++ b/queue-4.14/btrfs-tree-checker-don-t-check-max-block-group-size-as-current-max-chunk-size-limit-is-unreliable.patch @@ -0,0 +1,74 @@ +From 10950929e994c5ecee149ff0873388d3c98f12b5 Mon Sep 17 00:00:00 2001 +From: Qu Wenruo +Date: Fri, 23 Nov 2018 09:06:36 +0800 +Subject: btrfs: tree-checker: Don't check max block group size as current max chunk size limit is unreliable + +From: Qu Wenruo + +commit 10950929e994c5ecee149ff0873388d3c98f12b5 upstream. + +[BUG] +A completely valid btrfs will refuse to mount, with error message like: + BTRFS critical (device sdb2): corrupt leaf: root=2 block=239681536 slot=172 \ + bg_start=12018974720 bg_len=10888413184, invalid block group size, \ + have 10888413184 expect (0, 10737418240] + +This has been reported several times as the 4.19 kernel is now being +used. The filesystem refuses to mount, but is otherwise ok and booting +4.18 is a workaround. + +Btrfs check returns no error, and all kernels used on this fs is later +than 2011, which should all have the 10G size limit commit. + +[CAUSE] +For a 12 devices btrfs, we could allocate a chunk larger than 10G due to +stripe stripe bump up. + +__btrfs_alloc_chunk() +|- max_stripe_size = 1G +|- max_chunk_size = 10G +|- data_stripe = 11 +|- if (1G * 11 > 10G) { + stripe_size = 976128930; + stripe_size = round_up(976128930, SZ_16M) = 989855744 + +However the final stripe_size (989855744) * 11 = 10888413184, which is +still larger than 10G. + +[FIX] +For the comprehensive check, we need to do the full check at chunk read +time, and rely on bg <-> chunk mapping to do the check. + +We could just skip the length check for now. + +Fixes: fce466eab7ac ("btrfs: tree-checker: Verify block_group_item") +Cc: stable@vger.kernel.org # v4.19+ +Reported-by: Wang Yugui +Signed-off-by: Qu Wenruo +Reviewed-by: David Sterba +Signed-off-by: David Sterba +Signed-off-by: Greg Kroah-Hartman + +--- + fs/btrfs/tree-checker.c | 8 +++----- + 1 file changed, 3 insertions(+), 5 deletions(-) + +--- a/fs/btrfs/tree-checker.c ++++ b/fs/btrfs/tree-checker.c +@@ -348,13 +348,11 @@ static int check_block_group_item(struct + + /* + * Here we don't really care about alignment since extent allocator can +- * handle it. We care more about the size, as if one block group is +- * larger than maximum size, it's must be some obvious corruption. ++ * handle it. We care more about the size. + */ +- if (key->offset > BTRFS_MAX_DATA_CHUNK_SIZE || key->offset == 0) { ++ if (key->offset == 0) { + block_group_err(fs_info, leaf, slot, +- "invalid block group size, have %llu expect (0, %llu]", +- key->offset, BTRFS_MAX_DATA_CHUNK_SIZE); ++ "invalid block group size 0"); + return -EUCLEAN; + } + diff --git a/queue-4.14/drm-msm-fix-of-child-node-lookup.patch b/queue-4.14/drm-msm-fix-of-child-node-lookup.patch new file mode 100644 index 00000000000..8a815aa3380 --- /dev/null +++ b/queue-4.14/drm-msm-fix-of-child-node-lookup.patch @@ -0,0 +1,56 @@ +From f9a7082327e26f54067a49cac2316d31e0cc8ba7 Mon Sep 17 00:00:00 2001 +From: Johan Hovold +Date: Mon, 27 Aug 2018 10:21:47 +0200 +Subject: drm/msm: fix OF child-node lookup + +From: Johan Hovold + +commit f9a7082327e26f54067a49cac2316d31e0cc8ba7 upstream. + +Use the new of_get_compatible_child() helper to lookup the legacy +pwrlevels child node instead of using of_find_compatible_node(), which +searches the entire tree from a given start node and thus can return an +unrelated (i.e. non-child) node. + +This also addresses a potential use-after-free (e.g. after probe +deferral) as the tree-wide helper drops a reference to its first +argument (i.e. the probed device's node). + +While at it, also fix the related child-node reference leak. + +Fixes: e2af8b6b0ca1 ("drm/msm: gpu: Use OPP tables if we can") +Cc: stable # 4.12 +Cc: Jordan Crouse +Cc: Rob Clark +Cc: David Airlie +Signed-off-by: Johan Hovold +Signed-off-by: Rob Herring +[ johan: backport to 4.14 ] +Signed-off-by: Johan Hovold +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/msm/adreno/adreno_device.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +--- a/drivers/gpu/drm/msm/adreno/adreno_device.c ++++ b/drivers/gpu/drm/msm/adreno/adreno_device.c +@@ -223,8 +223,7 @@ static int adreno_get_legacy_pwrlevels(s + struct device_node *child, *node; + int ret; + +- node = of_find_compatible_node(dev->of_node, NULL, +- "qcom,gpu-pwrlevels"); ++ node = of_get_compatible_child(dev->of_node, "qcom,gpu-pwrlevels"); + if (!node) { + dev_err(dev, "Could not find the GPU powerlevels\n"); + return -ENXIO; +@@ -245,6 +244,8 @@ static int adreno_get_legacy_pwrlevels(s + dev_pm_opp_add(dev, val, 0); + } + ++ of_node_put(node); ++ + return 0; + } + diff --git a/queue-4.14/input-cros_ec_keyb-fix-button-switch-capability-reports.patch b/queue-4.14/input-cros_ec_keyb-fix-button-switch-capability-reports.patch new file mode 100644 index 00000000000..3e1f8761e20 --- /dev/null +++ b/queue-4.14/input-cros_ec_keyb-fix-button-switch-capability-reports.patch @@ -0,0 +1,53 @@ +From ac5722c1643a2fb75224c79b578214956d34f989 Mon Sep 17 00:00:00 2001 +From: Brian Norris +Date: Mon, 12 Nov 2018 11:23:39 -0800 +Subject: Input: cros_ec_keyb - fix button/switch capability reports + +From: Brian Norris + +commit ac5722c1643a2fb75224c79b578214956d34f989 upstream. + +The cros_ec_keyb_bs array lists buttons and switches together, expecting +that its users will match the appropriate type and bit fields. But +cros_ec_keyb_register_bs() only checks the 'bit' field, which causes +misreported input capabilities in some cases. For example, tablets +(e.g., Scarlet -- a.k.a. Acer Chromebook Tab 10) were reporting a SW_LID +capability, because EC_MKBP_POWER_BUTTON and EC_MKBP_LID_OPEN happen to +share the same bit. + +(This has comedic effect on a tablet, in which a power-management daemon +then thinks this "lid" is closed, and so puts the system to sleep as +soon as it boots!) + +To fix this, check both the 'ev_type' and 'bit' fields before reporting +the capability. + +Tested with a lid (Kevin / Samsung Chromebook Plus) and without a lid +(Scarlet / Acer Chromebook Tab 10). + +This error got introduced when porting the feature from the downstream +Chromium OS kernel to be upstreamed. + +Fixes: cdd7950e7aa4 ("input: cros_ec_keyb: Add non-matrix buttons and switches") +Cc: +Signed-off-by: Brian Norris +Reviewed-by: Heiko Stuebner +Signed-off-by: Dmitry Torokhov +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/input/keyboard/cros_ec_keyb.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/drivers/input/keyboard/cros_ec_keyb.c ++++ b/drivers/input/keyboard/cros_ec_keyb.c +@@ -506,7 +506,8 @@ static int cros_ec_keyb_register_bs(stru + for (i = 0; i < ARRAY_SIZE(cros_ec_keyb_bs); i++) { + const struct cros_ec_bs_map *map = &cros_ec_keyb_bs[i]; + +- if (buttons & BIT(map->bit)) ++ if ((map->ev_type == EV_KEY && (buttons & BIT(map->bit))) || ++ (map->ev_type == EV_SW && (switches & BIT(map->bit)))) + input_set_capability(idev, map->ev_type, map->code); + } + diff --git a/queue-4.14/input-elan_i2c-add-acpi-id-for-lenovo-ideapad-330-15arr.patch b/queue-4.14/input-elan_i2c-add-acpi-id-for-lenovo-ideapad-330-15arr.patch new file mode 100644 index 00000000000..b230e49ab16 --- /dev/null +++ b/queue-4.14/input-elan_i2c-add-acpi-id-for-lenovo-ideapad-330-15arr.patch @@ -0,0 +1,31 @@ +From ad33429cd02565c28404bb16ae7a4c2bdfda6626 Mon Sep 17 00:00:00 2001 +From: Noah Westervelt +Date: Thu, 29 Nov 2018 10:10:35 -0800 +Subject: Input: elan_i2c - add ACPI ID for Lenovo IdeaPad 330-15ARR + +From: Noah Westervelt + +commit ad33429cd02565c28404bb16ae7a4c2bdfda6626 upstream. + +Add ELAN061E to the ACPI table to support Elan touchpad found in Lenovo +IdeaPad 330-15ARR. + +Signed-off-by: Noah Westervelt +Cc: stable@vger.kernel.org +Signed-off-by: Dmitry Torokhov +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/input/mouse/elan_i2c_core.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/input/mouse/elan_i2c_core.c ++++ b/drivers/input/mouse/elan_i2c_core.c +@@ -1264,6 +1264,7 @@ static const struct acpi_device_id elan_ + { "ELAN0618", 0 }, + { "ELAN061C", 0 }, + { "ELAN061D", 0 }, ++ { "ELAN061E", 0 }, + { "ELAN0620", 0 }, + { "ELAN0622", 0 }, + { "ELAN1000", 0 }, diff --git a/queue-4.14/input-elan_i2c-add-elan0620-to-the-acpi-table.patch b/queue-4.14/input-elan_i2c-add-elan0620-to-the-acpi-table.patch new file mode 100644 index 00000000000..cd1c099e7db --- /dev/null +++ b/queue-4.14/input-elan_i2c-add-elan0620-to-the-acpi-table.patch @@ -0,0 +1,31 @@ +From 3ed64da3b790be7c63601e8ca6341b7dff74a660 Mon Sep 17 00:00:00 2001 +From: Patrick Gaskin +Date: Mon, 12 Nov 2018 11:12:24 -0800 +Subject: Input: elan_i2c - add ELAN0620 to the ACPI table + +From: Patrick Gaskin + +commit 3ed64da3b790be7c63601e8ca6341b7dff74a660 upstream. + +Add ELAN0620 to the ACPI table to support the elan touchpad in +the Lenovo IdeaPad 130-15IKB. + +Signed-off-by: Patrick Gaskin +Cc: stable@vger.kernel.org +Signed-off-by: Dmitry Torokhov +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/input/mouse/elan_i2c_core.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/input/mouse/elan_i2c_core.c ++++ b/drivers/input/mouse/elan_i2c_core.c +@@ -1264,6 +1264,7 @@ static const struct acpi_device_id elan_ + { "ELAN0618", 0 }, + { "ELAN061C", 0 }, + { "ELAN061D", 0 }, ++ { "ELAN0620", 0 }, + { "ELAN0622", 0 }, + { "ELAN1000", 0 }, + { } diff --git a/queue-4.14/input-elan_i2c-add-support-for-elan0621-touchpad.patch b/queue-4.14/input-elan_i2c-add-support-for-elan0621-touchpad.patch new file mode 100644 index 00000000000..167e2d3ac08 --- /dev/null +++ b/queue-4.14/input-elan_i2c-add-support-for-elan0621-touchpad.patch @@ -0,0 +1,31 @@ +From bf87ade0dd7f8cf19dac4d3161d5e86abe0c062b Mon Sep 17 00:00:00 2001 +From: Adam Wong +Date: Thu, 29 Nov 2018 10:04:35 -0800 +Subject: Input: elan_i2c - add support for ELAN0621 touchpad + +From: Adam Wong + +commit bf87ade0dd7f8cf19dac4d3161d5e86abe0c062b upstream. + +Added the ability to detect the ELAN0621 touchpad found in some Lenovo +laptops. + +Signed-off-by: Adam Wong +Cc: stable@vger.kernel.org +Signed-off-by: Dmitry Torokhov +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/input/mouse/elan_i2c_core.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/input/mouse/elan_i2c_core.c ++++ b/drivers/input/mouse/elan_i2c_core.c +@@ -1266,6 +1266,7 @@ static const struct acpi_device_id elan_ + { "ELAN061D", 0 }, + { "ELAN061E", 0 }, + { "ELAN0620", 0 }, ++ { "ELAN0621", 0 }, + { "ELAN0622", 0 }, + { "ELAN1000", 0 }, + { } diff --git a/queue-4.14/input-matrix_keypad-check-for-errors-from-of_get_named_gpio.patch b/queue-4.14/input-matrix_keypad-check-for-errors-from-of_get_named_gpio.patch new file mode 100644 index 00000000000..968f8a2fd76 --- /dev/null +++ b/queue-4.14/input-matrix_keypad-check-for-errors-from-of_get_named_gpio.patch @@ -0,0 +1,91 @@ +From d55bda1b3e7c5a87f10da54fdda866a9a9cef30b Mon Sep 17 00:00:00 2001 +From: Christian Hoff +Date: Mon, 12 Nov 2018 11:11:29 -0800 +Subject: Input: matrix_keypad - check for errors from of_get_named_gpio() + +From: Christian Hoff + +commit d55bda1b3e7c5a87f10da54fdda866a9a9cef30b upstream. + +"of_get_named_gpio()" returns a negative error value if it fails +and drivers should check for this. This missing check was now +added to the matrix_keypad driver. + +In my case "of_get_named_gpio()" returned -EPROBE_DEFER because +the referenced GPIOs belong to an I/O expander, which was not yet +probed at the point in time when the matrix_keypad driver was +loading. Because the driver did not check for errors from the +"of_get_named_gpio()" routine, it was assuming that "-EPROBE_DEFER" +is actually a GPIO number and continued as usual, which led to further +errors like this later on: + +WARNING: CPU: 3 PID: 167 at drivers/gpio/gpiolib.c:114 +gpio_to_desc+0xc8/0xd0 +invalid GPIO -517 + +Note that the "GPIO number" -517 in the error message above is +actually "-EPROBE_DEFER". + +As part of the patch a misleading error message "no platform data defined" +was also removed. This does not lead to information loss because the other +error paths in matrix_keypad_parse_dt() already print an error. + +Signed-off-by: Christian Hoff +Suggested-by: Sebastian Reichel +Reviewed-by: Sebastian Reichel +Cc: stable@vger.kernel.org +Signed-off-by: Dmitry Torokhov +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/input/keyboard/matrix_keypad.c | 23 ++++++++++++++--------- + 1 file changed, 14 insertions(+), 9 deletions(-) + +--- a/drivers/input/keyboard/matrix_keypad.c ++++ b/drivers/input/keyboard/matrix_keypad.c +@@ -407,7 +407,7 @@ matrix_keypad_parse_dt(struct device *de + struct matrix_keypad_platform_data *pdata; + struct device_node *np = dev->of_node; + unsigned int *gpios; +- int i, nrow, ncol; ++ int ret, i, nrow, ncol; + + if (!np) { + dev_err(dev, "device lacks DT data\n"); +@@ -452,12 +452,19 @@ matrix_keypad_parse_dt(struct device *de + return ERR_PTR(-ENOMEM); + } + +- for (i = 0; i < pdata->num_row_gpios; i++) +- gpios[i] = of_get_named_gpio(np, "row-gpios", i); ++ for (i = 0; i < nrow; i++) { ++ ret = of_get_named_gpio(np, "row-gpios", i); ++ if (ret < 0) ++ return ERR_PTR(ret); ++ gpios[i] = ret; ++ } + +- for (i = 0; i < pdata->num_col_gpios; i++) +- gpios[pdata->num_row_gpios + i] = +- of_get_named_gpio(np, "col-gpios", i); ++ for (i = 0; i < ncol; i++) { ++ ret = of_get_named_gpio(np, "col-gpios", i); ++ if (ret < 0) ++ return ERR_PTR(ret); ++ gpios[nrow + i] = ret; ++ } + + pdata->row_gpios = gpios; + pdata->col_gpios = &gpios[pdata->num_row_gpios]; +@@ -484,10 +491,8 @@ static int matrix_keypad_probe(struct pl + pdata = dev_get_platdata(&pdev->dev); + if (!pdata) { + pdata = matrix_keypad_parse_dt(&pdev->dev); +- if (IS_ERR(pdata)) { +- dev_err(&pdev->dev, "no platform data defined\n"); ++ if (IS_ERR(pdata)) + return PTR_ERR(pdata); +- } + } else if (!pdata->keymap_data) { + dev_err(&pdev->dev, "no keymap data defined\n"); + return -EINVAL; diff --git a/queue-4.14/input-synaptics-add-pnp-id-for-thinkpad-p50-to-smbus.patch b/queue-4.14/input-synaptics-add-pnp-id-for-thinkpad-p50-to-smbus.patch new file mode 100644 index 00000000000..4d62e7b79f8 --- /dev/null +++ b/queue-4.14/input-synaptics-add-pnp-id-for-thinkpad-p50-to-smbus.patch @@ -0,0 +1,33 @@ +From 9df39bedbf292680655c6a947c77d6562c693d4a Mon Sep 17 00:00:00 2001 +From: Lyude Paul +Date: Sat, 24 Nov 2018 23:28:10 -0800 +Subject: Input: synaptics - add PNP ID for ThinkPad P50 to SMBus + +From: Lyude Paul + +commit 9df39bedbf292680655c6a947c77d6562c693d4a upstream. + +Noticed the other day the trackpoint felt different on my P50, then +realized it was because rmi4 wasn't loading for this machine +automatically. Suspend/resume, hibernate, and everything else seem to +work perfectly fine on here. + +Signed-off-by: Lyude Paul +Cc: stable@vger.kernel.org +Signed-off-by: Dmitry Torokhov +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/input/mouse/synaptics.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/input/mouse/synaptics.c ++++ b/drivers/input/mouse/synaptics.c +@@ -170,6 +170,7 @@ static const char * const smbus_pnp_ids[ + "LEN0048", /* X1 Carbon 3 */ + "LEN0046", /* X250 */ + "LEN004a", /* W541 */ ++ "LEN005b", /* P50 */ + "LEN0071", /* T480 */ + "LEN0072", /* X1 Carbon Gen 5 (2017) - Elan/ALPS trackpoint */ + "LEN0073", /* X1 Carbon G5 (Elantech) */ diff --git a/queue-4.14/input-xpad-quirk-all-pdp-xbox-one-gamepads.patch b/queue-4.14/input-xpad-quirk-all-pdp-xbox-one-gamepads.patch new file mode 100644 index 00000000000..d4b1b10a663 --- /dev/null +++ b/queue-4.14/input-xpad-quirk-all-pdp-xbox-one-gamepads.patch @@ -0,0 +1,70 @@ +From a6754fae1e66e9a40fed406290d7ca3f2b4d227c Mon Sep 17 00:00:00 2001 +From: Cameron Gutman +Date: Thu, 29 Nov 2018 10:09:33 -0800 +Subject: Input: xpad - quirk all PDP Xbox One gamepads + +From: Cameron Gutman + +commit a6754fae1e66e9a40fed406290d7ca3f2b4d227c upstream. + +Since we continue to find tons of new variants [0,1,2,3,4,5,6] that +need the PDP quirk, let's just quirk all devices from PDP. + +[0]: https://github.com/paroj/xpad/pull/104 +[1]: https://github.com/paroj/xpad/pull/105 +[2]: https://github.com/paroj/xpad/pull/108 +[3]: https://github.com/paroj/xpad/pull/109 +[4]: https://github.com/paroj/xpad/pull/112 +[5]: https://github.com/paroj/xpad/pull/115 +[6]: https://github.com/paroj/xpad/pull/116 + +Fixes: e5c9c6a885fa ("Input: xpad - add support for PDP Xbox One controllers") +Cc: stable@vger.kernel.org +Signed-off-by: Cameron Gutman +Signed-off-by: Dmitry Torokhov +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/input/joystick/xpad.c | 16 ++++++---------- + 1 file changed, 6 insertions(+), 10 deletions(-) + +--- a/drivers/input/joystick/xpad.c ++++ b/drivers/input/joystick/xpad.c +@@ -483,18 +483,18 @@ static const u8 xboxone_hori_init[] = { + }; + + /* +- * This packet is required for some of the PDP pads to start ++ * This packet is required for most (all?) of the PDP pads to start + * sending input reports. These pads include: (0x0e6f:0x02ab), +- * (0x0e6f:0x02a4). ++ * (0x0e6f:0x02a4), (0x0e6f:0x02a6). + */ + static const u8 xboxone_pdp_init1[] = { + 0x0a, 0x20, 0x00, 0x03, 0x00, 0x01, 0x14 + }; + + /* +- * This packet is required for some of the PDP pads to start ++ * This packet is required for most (all?) of the PDP pads to start + * sending input reports. These pads include: (0x0e6f:0x02ab), +- * (0x0e6f:0x02a4). ++ * (0x0e6f:0x02a4), (0x0e6f:0x02a6). + */ + static const u8 xboxone_pdp_init2[] = { + 0x06, 0x20, 0x00, 0x02, 0x01, 0x00 +@@ -530,12 +530,8 @@ static const struct xboxone_init_packet + XBOXONE_INIT_PKT(0x0e6f, 0x0165, xboxone_hori_init), + XBOXONE_INIT_PKT(0x0f0d, 0x0067, xboxone_hori_init), + XBOXONE_INIT_PKT(0x0000, 0x0000, xboxone_fw2015_init), +- XBOXONE_INIT_PKT(0x0e6f, 0x02ab, xboxone_pdp_init1), +- XBOXONE_INIT_PKT(0x0e6f, 0x02ab, xboxone_pdp_init2), +- XBOXONE_INIT_PKT(0x0e6f, 0x02a4, xboxone_pdp_init1), +- XBOXONE_INIT_PKT(0x0e6f, 0x02a4, xboxone_pdp_init2), +- XBOXONE_INIT_PKT(0x0e6f, 0x02a6, xboxone_pdp_init1), +- XBOXONE_INIT_PKT(0x0e6f, 0x02a6, xboxone_pdp_init2), ++ XBOXONE_INIT_PKT(0x0e6f, 0x0000, xboxone_pdp_init1), ++ XBOXONE_INIT_PKT(0x0e6f, 0x0000, xboxone_pdp_init2), + XBOXONE_INIT_PKT(0x24c6, 0x541a, xboxone_rumblebegin_init), + XBOXONE_INIT_PKT(0x24c6, 0x542a, xboxone_rumblebegin_init), + XBOXONE_INIT_PKT(0x24c6, 0x543a, xboxone_rumblebegin_init), diff --git a/queue-4.14/kgdboc-fix-warning-with-module-build.patch b/queue-4.14/kgdboc-fix-warning-with-module-build.patch new file mode 100644 index 00000000000..79568851348 --- /dev/null +++ b/queue-4.14/kgdboc-fix-warning-with-module-build.patch @@ -0,0 +1,81 @@ +From 1cd25cbb2fedbc777f3a8c3cb1ba69b645aeaa64 Mon Sep 17 00:00:00 2001 +From: Laura Abbott +Date: Wed, 19 Sep 2018 18:59:01 -0700 +Subject: kgdboc: Fix warning with module build + +From: Laura Abbott + +commit 1cd25cbb2fedbc777f3a8c3cb1ba69b645aeaa64 upstream. + +After 2dd453168643 ("kgdboc: Fix restrict error"), kgdboc_option_setup is +now only used when built in, resulting in a warning when compiled as a +module: + +drivers/tty/serial/kgdboc.c:134:12: warning: 'kgdboc_option_setup' defined but not used [-Wunused-function] + static int kgdboc_option_setup(char *opt) + ^~~~~~~~~~~~~~~~~~~ + +Move the function under the appropriate ifdef for builtin only. + +Fixes: 2dd453168643 ("kgdboc: Fix restrict error") +Reported-by: Stephen Rothwell +Signed-off-by: Laura Abbott +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/tty/serial/kgdboc.c | 37 +++++++++++++++++++------------------ + 1 file changed, 19 insertions(+), 18 deletions(-) + +--- a/drivers/tty/serial/kgdboc.c ++++ b/drivers/tty/serial/kgdboc.c +@@ -131,24 +131,6 @@ static void kgdboc_unregister_kbd(void) + #define kgdboc_restore_input() + #endif /* ! CONFIG_KDB_KEYBOARD */ + +-static int kgdboc_option_setup(char *opt) +-{ +- if (!opt) { +- pr_err("kgdboc: config string not provided\n"); +- return -EINVAL; +- } +- +- if (strlen(opt) >= MAX_CONFIG_LEN) { +- printk(KERN_ERR "kgdboc: config string too long\n"); +- return -ENOSPC; +- } +- strcpy(config, opt); +- +- return 0; +-} +- +-__setup("kgdboc=", kgdboc_option_setup); +- + static void cleanup_kgdboc(void) + { + if (kgdb_unregister_nmi_console()) +@@ -316,6 +298,25 @@ static struct kgdb_io kgdboc_io_ops = { + }; + + #ifdef CONFIG_KGDB_SERIAL_CONSOLE ++static int kgdboc_option_setup(char *opt) ++{ ++ if (!opt) { ++ pr_err("config string not provided\n"); ++ return -EINVAL; ++ } ++ ++ if (strlen(opt) >= MAX_CONFIG_LEN) { ++ pr_err("config string too long\n"); ++ return -ENOSPC; ++ } ++ strcpy(config, opt); ++ ++ return 0; ++} ++ ++__setup("kgdboc=", kgdboc_option_setup); ++ ++ + /* This is only available if kgdboc is a built in for early debugging */ + static int __init kgdboc_early_init(char *opt) + { diff --git a/queue-4.14/mm-cleancache-fix-corruption-on-missed-inode-invalidation.patch b/queue-4.14/mm-cleancache-fix-corruption-on-missed-inode-invalidation.patch new file mode 100644 index 00000000000..bef19dceaca --- /dev/null +++ b/queue-4.14/mm-cleancache-fix-corruption-on-missed-inode-invalidation.patch @@ -0,0 +1,74 @@ +From 6ff38bd40230af35e446239396e5fc8ebd6a5248 Mon Sep 17 00:00:00 2001 +From: Pavel Tikhomirov +Date: Fri, 30 Nov 2018 14:09:00 -0800 +Subject: mm: cleancache: fix corruption on missed inode invalidation + +From: Pavel Tikhomirov + +commit 6ff38bd40230af35e446239396e5fc8ebd6a5248 upstream. + +If all pages are deleted from the mapping by memory reclaim and also +moved to the cleancache: + +__delete_from_page_cache + (no shadow case) + unaccount_page_cache_page + cleancache_put_page + page_cache_delete + mapping->nrpages -= nr + (nrpages becomes 0) + +We don't clean the cleancache for an inode after final file truncation +(removal). + +truncate_inode_pages_final + check (nrpages || nrexceptional) is false + no truncate_inode_pages + no cleancache_invalidate_inode(mapping) + +These way when reading the new file created with same inode we may get +these trash leftover pages from cleancache and see wrong data instead of +the contents of the new file. + +Fix it by always doing truncate_inode_pages which is already ready for +nrpages == 0 && nrexceptional == 0 case and just invalidates inode. + +[akpm@linux-foundation.org: add comment, per Jan] +Link: http://lkml.kernel.org/r/20181112095734.17979-1-ptikhomirov@virtuozzo.com +Fixes: commit 91b0abe36a7b ("mm + fs: store shadow entries in page cache") +Signed-off-by: Pavel Tikhomirov +Reviewed-by: Vasily Averin +Reviewed-by: Andrey Ryabinin +Reviewed-by: Jan Kara +Cc: Johannes Weiner +Cc: Mel Gorman +Cc: Matthew Wilcox +Cc: Andi Kleen +Cc: +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +Signed-off-by: Vasily Averin +Signed-off-by: Greg Kroah-Hartman + +--- + mm/truncate.c | 8 ++++++-- + 1 file changed, 6 insertions(+), 2 deletions(-) + +--- a/mm/truncate.c ++++ b/mm/truncate.c +@@ -471,9 +471,13 @@ void truncate_inode_pages_final(struct a + */ + spin_lock_irq(&mapping->tree_lock); + spin_unlock_irq(&mapping->tree_lock); +- +- truncate_inode_pages(mapping, 0); + } ++ ++ /* ++ * Cleancache needs notification even if there are no pages or shadow ++ * entries. ++ */ ++ truncate_inode_pages(mapping, 0); + } + EXPORT_SYMBOL(truncate_inode_pages_final); + diff --git a/queue-4.14/mm-hide-incomplete-nr_indirectly_reclaimable-in-proc-zoneinfo.patch b/queue-4.14/mm-hide-incomplete-nr_indirectly_reclaimable-in-proc-zoneinfo.patch new file mode 100644 index 00000000000..a224345e9c6 --- /dev/null +++ b/queue-4.14/mm-hide-incomplete-nr_indirectly_reclaimable-in-proc-zoneinfo.patch @@ -0,0 +1,71 @@ +From guro@fb.com Thu Dec 6 12:12:35 2018 +From: Roman Gushchin +Date: Tue, 30 Oct 2018 17:48:25 +0000 +Subject: mm: hide incomplete nr_indirectly_reclaimable in /proc/zoneinfo +To: "stable@vger.kernel.org" +Cc: Yongqin Liu , "linux-mm@kvack.org" , "linux-kernel@vger.kernel.org" , Kernel Team , "Roman Gushchin" , Vlastimil Babka , Andrew Morton +Message-ID: <20181030174649.16778-1-guro@fb.com> + +From: Roman Gushchin + +[fixed differently upstream, this is a work-around to resolve it for 4.14.y] + +Yongqin reported that /proc/zoneinfo format is broken in 4.14 +due to commit 7aaf77272358 ("mm: don't show nr_indirectly_reclaimable +in /proc/vmstat") + +Node 0, zone DMA + per-node stats + nr_inactive_anon 403 + nr_active_anon 89123 + nr_inactive_file 128887 + nr_active_file 47377 + nr_unevictable 2053 + nr_slab_reclaimable 7510 + nr_slab_unreclaimable 10775 + nr_isolated_anon 0 + nr_isolated_file 0 + <...> + nr_vmscan_write 0 + nr_vmscan_immediate_reclaim 0 + nr_dirtied 6022 + nr_written 5985 + 74240 + ^^^^^^^^^^ + pages free 131656 + +The problem is caused by the nr_indirectly_reclaimable counter, +which is hidden from the /proc/vmstat, but not from the +/proc/zoneinfo. Let's fix this inconsistency and hide the +counter from /proc/zoneinfo exactly as from /proc/vmstat. + +BTW, in 4.19+ the counter has been renamed and exported by +the commit b29940c1abd7 ("mm: rename and change semantics of +nr_indirectly_reclaimable_bytes"), so there is no such a problem +anymore. + +Cc: # 4.14.x-4.18.x +Fixes: 7aaf77272358 ("mm: don't show nr_indirectly_reclaimable in /proc/vmstat") +Reported-by: Yongqin Liu +Signed-off-by: Roman Gushchin +Cc: Vlastimil Babka +Cc: Andrew Morton +Signed-off-by: Greg Kroah-Hartman + +--- + mm/vmstat.c | 4 ++++ + 1 file changed, 4 insertions(+) + +--- a/mm/vmstat.c ++++ b/mm/vmstat.c +@@ -1500,6 +1500,10 @@ static void zoneinfo_show_print(struct s + if (is_zone_first_populated(pgdat, zone)) { + seq_printf(m, "\n per-node stats"); + for (i = 0; i < NR_VM_NODE_STAT_ITEMS; i++) { ++ /* Skip hidden vmstat items. */ ++ if (*vmstat_text[i + NR_VM_ZONE_STAT_ITEMS + ++ NR_VM_NUMA_STAT_ITEMS] == '\0') ++ continue; + seq_printf(m, "\n %-12s %lu", + vmstat_text[i + NR_VM_ZONE_STAT_ITEMS + + NR_VM_NUMA_STAT_ITEMS], diff --git a/queue-4.14/reset-make-device_reset_optional-really-optional.patch b/queue-4.14/reset-make-device_reset_optional-really-optional.patch new file mode 100644 index 00000000000..121984f8a4e --- /dev/null +++ b/queue-4.14/reset-make-device_reset_optional-really-optional.patch @@ -0,0 +1,117 @@ +From 1554bbd4ad401b7f0f916c0891874111c10befe5 Mon Sep 17 00:00:00 2001 +From: Masahiro Yamada +Date: Sun, 29 Oct 2017 01:50:06 +0900 +Subject: reset: make device_reset_optional() really optional + +From: Masahiro Yamada + +commit 1554bbd4ad401b7f0f916c0891874111c10befe5 upstream. + +Commit bb475230b8e5 ("reset: make optional functions really optional") +converted *_get_optional* functions, but device_reset_optional() was +left behind. Convert it in the same way. + +Signed-off-by: Masahiro Yamada +Signed-off-by: Philipp Zabel +Cc: Dinh Nguyen +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/reset/core.c | 9 +++++---- + include/linux/reset.h | 28 +++++++++++++--------------- + 2 files changed, 18 insertions(+), 19 deletions(-) + +--- a/drivers/reset/core.c ++++ b/drivers/reset/core.c +@@ -566,17 +566,18 @@ EXPORT_SYMBOL_GPL(__devm_reset_control_g + * device_reset - find reset controller associated with the device + * and perform reset + * @dev: device to be reset by the controller ++ * @optional: whether it is optional to reset the device + * +- * Convenience wrapper for reset_control_get() and reset_control_reset(). ++ * Convenience wrapper for __reset_control_get() and reset_control_reset(). + * This is useful for the common case of devices with single, dedicated reset + * lines. + */ +-int device_reset(struct device *dev) ++int __device_reset(struct device *dev, bool optional) + { + struct reset_control *rstc; + int ret; + +- rstc = reset_control_get(dev, NULL); ++ rstc = __reset_control_get(dev, NULL, 0, 0, optional); + if (IS_ERR(rstc)) + return PTR_ERR(rstc); + +@@ -586,7 +587,7 @@ int device_reset(struct device *dev) + + return ret; + } +-EXPORT_SYMBOL_GPL(device_reset); ++EXPORT_SYMBOL_GPL(__device_reset); + + /** + * APIs to manage an array of reset controls. +--- a/include/linux/reset.h ++++ b/include/linux/reset.h +@@ -20,22 +20,16 @@ struct reset_control *__reset_control_ge + int index, bool shared, + bool optional); + void reset_control_put(struct reset_control *rstc); ++int __device_reset(struct device *dev, bool optional); + struct reset_control *__devm_reset_control_get(struct device *dev, + const char *id, int index, bool shared, + bool optional); + +-int __must_check device_reset(struct device *dev); +- + struct reset_control *devm_reset_control_array_get(struct device *dev, + bool shared, bool optional); + struct reset_control *of_reset_control_array_get(struct device_node *np, + bool shared, bool optional); + +-static inline int device_reset_optional(struct device *dev) +-{ +- return device_reset(dev); +-} +- + #else + + static inline int reset_control_reset(struct reset_control *rstc) +@@ -62,15 +56,9 @@ static inline void reset_control_put(str + { + } + +-static inline int __must_check device_reset(struct device *dev) +-{ +- WARN_ON(1); +- return -ENOTSUPP; +-} +- +-static inline int device_reset_optional(struct device *dev) ++static inline int __device_reset(struct device *dev, bool optional) + { +- return -ENOTSUPP; ++ return optional ? 0 : -ENOTSUPP; + } + + static inline struct reset_control *__of_reset_control_get( +@@ -109,6 +97,16 @@ of_reset_control_array_get(struct device + + #endif /* CONFIG_RESET_CONTROLLER */ + ++static inline int __must_check device_reset(struct device *dev) ++{ ++ return __device_reset(dev, false); ++} ++ ++static inline int device_reset_optional(struct device *dev) ++{ ++ return __device_reset(dev, true); ++} ++ + /** + * reset_control_get_exclusive - Lookup and obtain an exclusive reference + * to a reset controller. diff --git a/queue-4.14/reset-remove-remaining-warn_on-in-linux-reset.h.patch b/queue-4.14/reset-remove-remaining-warn_on-in-linux-reset.h.patch new file mode 100644 index 00000000000..196f7766808 --- /dev/null +++ b/queue-4.14/reset-remove-remaining-warn_on-in-linux-reset.h.patch @@ -0,0 +1,47 @@ +From bb6c7768385b200063a14d6615cc1246c3d00760 Mon Sep 17 00:00:00 2001 +From: Masahiro Yamada +Date: Sun, 29 Oct 2017 01:50:07 +0900 +Subject: reset: remove remaining WARN_ON() in + +From: Masahiro Yamada + +commit bb6c7768385b200063a14d6615cc1246c3d00760 upstream. + +Commit bb475230b8e5 ("reset: make optional functions really optional") +gave a new meaning to _get_optional variants. + +The differentiation by WARN_ON() is not needed any more. We already +have inconsistency about this; (devm_)reset_control_get_exclusive() +has WARN_ON() check, but of_reset_control_get_exclusive() does not. + +Signed-off-by: Masahiro Yamada +Signed-off-by: Philipp Zabel +Cc: Dinh Nguyen +Signed-off-by: Greg Kroah-Hartman + +--- + include/linux/reset.h | 6 ------ + 1 file changed, 6 deletions(-) + +--- a/include/linux/reset.h ++++ b/include/linux/reset.h +@@ -125,9 +125,6 @@ static inline int device_reset_optional( + static inline struct reset_control * + __must_check reset_control_get_exclusive(struct device *dev, const char *id) + { +-#ifndef CONFIG_RESET_CONTROLLER +- WARN_ON(1); +-#endif + return __reset_control_get(dev, id, 0, false, false); + } + +@@ -273,9 +270,6 @@ static inline struct reset_control * + __must_check devm_reset_control_get_exclusive(struct device *dev, + const char *id) + { +-#ifndef CONFIG_RESET_CONTROLLER +- WARN_ON(1); +-#endif + return __devm_reset_control_get(dev, id, 0, false, false); + } + diff --git a/queue-4.14/series b/queue-4.14/series index 8ade3d4ed04..ab0b914b7c8 100644 --- a/queue-4.14/series +++ b/queue-4.14/series @@ -27,3 +27,27 @@ scsi-scsi_devinfo-cleanly-zero-pad-devinfo-strings.patch userfaultfd-shmem-hugetlbfs-only-allow-to-register-vm_maywrite-vmas.patch alsa-trident-suppress-gcc-string-warning.patch kgdboc-fix-restrict-error.patch +kgdboc-fix-warning-with-module-build.patch +svm-add-mutex_lock-to-protect-apic_access_page_done-on-amd-systems.patch +drm-msm-fix-of-child-node-lookup.patch +input-xpad-quirk-all-pdp-xbox-one-gamepads.patch +input-synaptics-add-pnp-id-for-thinkpad-p50-to-smbus.patch +input-matrix_keypad-check-for-errors-from-of_get_named_gpio.patch +input-cros_ec_keyb-fix-button-switch-capability-reports.patch +input-elan_i2c-add-elan0620-to-the-acpi-table.patch +input-elan_i2c-add-acpi-id-for-lenovo-ideapad-330-15arr.patch +input-elan_i2c-add-support-for-elan0621-touchpad.patch +btrfs-tree-checker-don-t-check-max-block-group-size-as-current-max-chunk-size-limit-is-unreliable.patch +btrfs-always-try-all-copies-when-reading-extent-buffers.patch +arc-change-defconfig-defaults-to-arcv2.patch +arc-add-support-of-nfsv3-acl.patch +udf-allow-mounting-volumes-with-incorrect-identification-strings.patch +reset-make-device_reset_optional-really-optional.patch +reset-remove-remaining-warn_on-in-linux-reset.h.patch +mm-cleancache-fix-corruption-on-missed-inode-invalidation.patch +thermal-drivers-hisi-remove-the-multiple-sensors-support.patch +thermal-drivers-hisi-remove-pointless-lock.patch +thermal-drivers-hisi-encapsulate-register-writes-into-helpers.patch +thermal-drivers-hisi-fix-configuration-register-setting.patch +thermal-drivers-hisi-remove-costly-sensor-inspection.patch +mm-hide-incomplete-nr_indirectly_reclaimable-in-proc-zoneinfo.patch diff --git a/queue-4.14/svm-add-mutex_lock-to-protect-apic_access_page_done-on-amd-systems.patch b/queue-4.14/svm-add-mutex_lock-to-protect-apic_access_page_done-on-amd-systems.patch new file mode 100644 index 00000000000..3f998afb376 --- /dev/null +++ b/queue-4.14/svm-add-mutex_lock-to-protect-apic_access_page_done-on-amd-systems.patch @@ -0,0 +1,63 @@ +From 30510387a5e45bfcf8190e03ec7aa15b295828e2 Mon Sep 17 00:00:00 2001 +From: Wei Wang +Date: Mon, 12 Nov 2018 12:23:14 +0000 +Subject: svm: Add mutex_lock to protect apic_access_page_done on AMD systems + +From: Wei Wang + +commit 30510387a5e45bfcf8190e03ec7aa15b295828e2 upstream. + +There is a race condition when accessing kvm->arch.apic_access_page_done. +Due to it, x86_set_memory_region will fail when creating the second vcpu +for a svm guest. + +Add a mutex_lock to serialize the accesses to apic_access_page_done. +This lock is also used by vmx for the same purpose. + +Signed-off-by: Wei Wang +Signed-off-by: Amadeusz Juskowiak +Signed-off-by: Julian Stecklina +Signed-off-by: Suravee Suthikulpanit +Reviewed-by: Joerg Roedel +Cc: stable@vger.kernel.org +Signed-off-by: Paolo Bonzini +Signed-off-by: Greg Kroah-Hartman + +--- + arch/x86/kvm/svm.c | 19 +++++++++++-------- + 1 file changed, 11 insertions(+), 8 deletions(-) + +--- a/arch/x86/kvm/svm.c ++++ b/arch/x86/kvm/svm.c +@@ -1399,20 +1399,23 @@ static u64 *avic_get_physical_id_entry(s + static int avic_init_access_page(struct kvm_vcpu *vcpu) + { + struct kvm *kvm = vcpu->kvm; +- int ret; ++ int ret = 0; + ++ mutex_lock(&kvm->slots_lock); + if (kvm->arch.apic_access_page_done) +- return 0; ++ goto out; + +- ret = x86_set_memory_region(kvm, +- APIC_ACCESS_PAGE_PRIVATE_MEMSLOT, +- APIC_DEFAULT_PHYS_BASE, +- PAGE_SIZE); ++ ret = __x86_set_memory_region(kvm, ++ APIC_ACCESS_PAGE_PRIVATE_MEMSLOT, ++ APIC_DEFAULT_PHYS_BASE, ++ PAGE_SIZE); + if (ret) +- return ret; ++ goto out; + + kvm->arch.apic_access_page_done = true; +- return 0; ++out: ++ mutex_unlock(&kvm->slots_lock); ++ return ret; + } + + static int avic_init_backing_page(struct kvm_vcpu *vcpu) diff --git a/queue-4.14/thermal-drivers-hisi-encapsulate-register-writes-into-helpers.patch b/queue-4.14/thermal-drivers-hisi-encapsulate-register-writes-into-helpers.patch new file mode 100644 index 00000000000..2056a9b4a6e --- /dev/null +++ b/queue-4.14/thermal-drivers-hisi-encapsulate-register-writes-into-helpers.patch @@ -0,0 +1,169 @@ +From 1e11b014271ceccb5ea04ae58f4829ac8209a86d Mon Sep 17 00:00:00 2001 +From: Daniel Lezcano +Date: Thu, 19 Oct 2017 19:05:49 +0200 +Subject: thermal/drivers/hisi: Encapsulate register writes into helpers + +From: Daniel Lezcano + +commit 1e11b014271ceccb5ea04ae58f4829ac8209a86d upstream. + +Hopefully, the function name can help to clarify the semantic of the operations +when writing in the register. + +Signed-off-by: Daniel Lezcano +Signed-off-by: Eduardo Valentin +Signed-off-by: Rafael David Tinoco +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/thermal/hisi_thermal.c | 92 +++++++++++++++++++++++++++++++---------- + 1 file changed, 70 insertions(+), 22 deletions(-) + +--- a/drivers/thermal/hisi_thermal.c ++++ b/drivers/thermal/hisi_thermal.c +@@ -26,6 +26,7 @@ + + #include "thermal_core.h" + ++#define TEMP0_LAG (0x0) + #define TEMP0_TH (0x4) + #define TEMP0_RST_TH (0x8) + #define TEMP0_CFG (0xC) +@@ -96,6 +97,56 @@ static inline long hisi_thermal_round_te + hisi_thermal_temp_to_step(temp)); + } + ++static inline void hisi_thermal_set_lag(void __iomem *addr, int value) ++{ ++ writel(value, addr + TEMP0_LAG); ++} ++ ++static inline void hisi_thermal_alarm_clear(void __iomem *addr, int value) ++{ ++ writel(value, addr + TEMP0_INT_CLR); ++} ++ ++static inline void hisi_thermal_alarm_enable(void __iomem *addr, int value) ++{ ++ writel(value, addr + TEMP0_INT_EN); ++} ++ ++static inline void hisi_thermal_alarm_set(void __iomem *addr, int temp) ++{ ++ writel(hisi_thermal_temp_to_step(temp) | 0x0FFFFFF00, addr + TEMP0_TH); ++} ++ ++static inline void hisi_thermal_reset_set(void __iomem *addr, int temp) ++{ ++ writel(hisi_thermal_temp_to_step(temp), addr + TEMP0_RST_TH); ++} ++ ++static inline void hisi_thermal_reset_enable(void __iomem *addr, int value) ++{ ++ writel(value, addr + TEMP0_RST_MSK); ++} ++ ++static inline void hisi_thermal_enable(void __iomem *addr, int value) ++{ ++ writel(value, addr + TEMP0_EN); ++} ++ ++static inline void hisi_thermal_sensor_select(void __iomem *addr, int sensor) ++{ ++ writel((sensor << 12), addr + TEMP0_CFG); ++} ++ ++static inline int hisi_thermal_get_temperature(void __iomem *addr) ++{ ++ return hisi_thermal_step_to_temp(readl(addr + TEMP0_VALUE)); ++} ++ ++static inline void hisi_thermal_hdak_set(void __iomem *addr, int value) ++{ ++ writel(value, addr + TEMP0_CFG); ++} ++ + static long hisi_thermal_get_sensor_temp(struct hisi_thermal_data *data, + struct hisi_thermal_sensor *sensor) + { +@@ -104,22 +155,21 @@ static long hisi_thermal_get_sensor_temp + mutex_lock(&data->thermal_lock); + + /* disable interrupt */ +- writel(0x0, data->regs + TEMP0_INT_EN); +- writel(0x1, data->regs + TEMP0_INT_CLR); ++ hisi_thermal_alarm_enable(data->regs, 0); ++ hisi_thermal_alarm_clear(data->regs, 1); + + /* disable module firstly */ +- writel(0x0, data->regs + TEMP0_EN); ++ hisi_thermal_enable(data->regs, 0); + + /* select sensor id */ +- writel((sensor->id << 12), data->regs + TEMP0_CFG); ++ hisi_thermal_sensor_select(data->regs, sensor->id); + + /* enable module */ +- writel(0x1, data->regs + TEMP0_EN); ++ hisi_thermal_enable(data->regs, 1); + + usleep_range(3000, 5000); + +- val = readl(data->regs + TEMP0_VALUE); +- val = hisi_thermal_step_to_temp(val); ++ val = hisi_thermal_get_temperature(data->regs); + + mutex_unlock(&data->thermal_lock); + +@@ -136,28 +186,26 @@ static void hisi_thermal_enable_bind_irq + sensor = &data->sensors; + + /* setting the hdak time */ +- writel(0x0, data->regs + TEMP0_CFG); ++ hisi_thermal_hdak_set(data->regs, 0); + + /* disable module firstly */ +- writel(0x0, data->regs + TEMP0_RST_MSK); +- writel(0x0, data->regs + TEMP0_EN); ++ hisi_thermal_reset_enable(data->regs, 0); ++ hisi_thermal_enable(data->regs, 0); + + /* select sensor id */ +- writel((sensor->id << 12), data->regs + TEMP0_CFG); ++ hisi_thermal_sensor_select(data->regs, sensor->id); + + /* enable for interrupt */ +- writel(hisi_thermal_temp_to_step(sensor->thres_temp) | 0x0FFFFFF00, +- data->regs + TEMP0_TH); ++ hisi_thermal_alarm_set(data->regs, sensor->thres_temp); + +- writel(hisi_thermal_temp_to_step(HISI_TEMP_RESET), +- data->regs + TEMP0_RST_TH); ++ hisi_thermal_reset_set(data->regs, HISI_TEMP_RESET); + + /* enable module */ +- writel(0x1, data->regs + TEMP0_RST_MSK); +- writel(0x1, data->regs + TEMP0_EN); ++ hisi_thermal_reset_enable(data->regs, 1); ++ hisi_thermal_enable(data->regs, 1); + +- writel(0x0, data->regs + TEMP0_INT_CLR); +- writel(0x1, data->regs + TEMP0_INT_EN); ++ hisi_thermal_alarm_clear(data->regs, 0); ++ hisi_thermal_alarm_enable(data->regs, 1); + + usleep_range(3000, 5000); + +@@ -169,9 +217,9 @@ static void hisi_thermal_disable_sensor( + mutex_lock(&data->thermal_lock); + + /* disable sensor module */ +- writel(0x0, data->regs + TEMP0_INT_EN); +- writel(0x0, data->regs + TEMP0_RST_MSK); +- writel(0x0, data->regs + TEMP0_EN); ++ hisi_thermal_enable(data->regs, 0); ++ hisi_thermal_alarm_enable(data->regs, 0); ++ hisi_thermal_reset_enable(data->regs, 0); + + mutex_unlock(&data->thermal_lock); + } diff --git a/queue-4.14/thermal-drivers-hisi-fix-configuration-register-setting.patch b/queue-4.14/thermal-drivers-hisi-fix-configuration-register-setting.patch new file mode 100644 index 00000000000..e11105b52f9 --- /dev/null +++ b/queue-4.14/thermal-drivers-hisi-fix-configuration-register-setting.patch @@ -0,0 +1,84 @@ +From b424315a287c70eeb5f920f84c92492bd2f5658e Mon Sep 17 00:00:00 2001 +From: Daniel Lezcano +Date: Thu, 19 Oct 2017 19:05:50 +0200 +Subject: thermal/drivers/hisi: Fix configuration register setting + +From: Daniel Lezcano + +commit b424315a287c70eeb5f920f84c92492bd2f5658e upstream. + +The TEMP0_CFG configuration register contains different field to set up the +temperature controller. However in the code, nothing prevents a setup to +overwrite the previous one: eg. writing the hdak value overwrites the sensor +selection, the sensor selection overwrites the hdak value. + +In order to prevent such thing, use a regmap-like mechanism by reading the +value before, set the corresponding bits and write the result. + +Signed-off-by: Daniel Lezcano +Signed-off-by: Eduardo Valentin +Signed-off-by: Rafael David Tinoco +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/thermal/hisi_thermal.c | 34 +++++++++++++++++++++++++++++----- + 1 file changed, 29 insertions(+), 5 deletions(-) + +--- a/drivers/thermal/hisi_thermal.c ++++ b/drivers/thermal/hisi_thermal.c +@@ -30,6 +30,8 @@ + #define TEMP0_TH (0x4) + #define TEMP0_RST_TH (0x8) + #define TEMP0_CFG (0xC) ++#define TEMP0_CFG_SS_MSK (0xF000) ++#define TEMP0_CFG_HDAK_MSK (0x30) + #define TEMP0_EN (0x10) + #define TEMP0_INT_EN (0x14) + #define TEMP0_INT_CLR (0x18) +@@ -132,19 +134,41 @@ static inline void hisi_thermal_enable(v + writel(value, addr + TEMP0_EN); + } + +-static inline void hisi_thermal_sensor_select(void __iomem *addr, int sensor) ++static inline int hisi_thermal_get_temperature(void __iomem *addr) + { +- writel((sensor << 12), addr + TEMP0_CFG); ++ return hisi_thermal_step_to_temp(readl(addr + TEMP0_VALUE)); + } + +-static inline int hisi_thermal_get_temperature(void __iomem *addr) ++/* ++ * Temperature configuration register - Sensor selection ++ * ++ * Bits [19:12] ++ * ++ * 0x0: local sensor (default) ++ * 0x1: remote sensor 1 (ACPU cluster 1) ++ * 0x2: remote sensor 2 (ACPU cluster 0) ++ * 0x3: remote sensor 3 (G3D) ++ */ ++static inline void hisi_thermal_sensor_select(void __iomem *addr, int sensor) + { +- return hisi_thermal_step_to_temp(readl(addr + TEMP0_VALUE)); ++ writel((readl(addr + TEMP0_CFG) & ~TEMP0_CFG_SS_MSK) | ++ (sensor << 12), addr + TEMP0_CFG); + } + ++/* ++ * Temperature configuration register - Hdak conversion polling interval ++ * ++ * Bits [5:4] ++ * ++ * 0x0 : 0.768 ms ++ * 0x1 : 6.144 ms ++ * 0x2 : 49.152 ms ++ * 0x3 : 393.216 ms ++ */ + static inline void hisi_thermal_hdak_set(void __iomem *addr, int value) + { +- writel(value, addr + TEMP0_CFG); ++ writel((readl(addr + TEMP0_CFG) & ~TEMP0_CFG_HDAK_MSK) | ++ (value << 4), addr + TEMP0_CFG); + } + + static long hisi_thermal_get_sensor_temp(struct hisi_thermal_data *data, diff --git a/queue-4.14/thermal-drivers-hisi-remove-costly-sensor-inspection.patch b/queue-4.14/thermal-drivers-hisi-remove-costly-sensor-inspection.patch new file mode 100644 index 00000000000..ae9e22695f2 --- /dev/null +++ b/queue-4.14/thermal-drivers-hisi-remove-costly-sensor-inspection.patch @@ -0,0 +1,346 @@ +From 10d7e9a9181f4637640f388d334c6740c1b5d0e8 Mon Sep 17 00:00:00 2001 +From: Daniel Lezcano +Date: Thu, 19 Oct 2017 19:05:51 +0200 +Subject: thermal/drivers/hisi: Remove costly sensor inspection + +From: Daniel Lezcano + +commit 10d7e9a9181f4637640f388d334c6740c1b5d0e8 upstream. + +The sensor is all setup, bind, resetted, acked, etc... every single second. + +That was the way to workaround a problem with the interrupt bouncing again and +again. + +With the following changes, we fix all in one: + + - Do the setup, one time, at probe time + + - Add the IRQF_ONESHOT, ack the interrupt in the threaded handler + + - Remove the interrupt handler + + - Set the correct value for the LAG register + + - Remove all the irq_enabled stuff in the code as the interruption + handling is fixed + + - Remove the 3ms delay + + - Reorder the initialization routine to be in the right order + +It ends up to a nicer code and more efficient, the 3-5ms delay is removed from +the get_temp() path. + +Signed-off-by: Daniel Lezcano +Reviewed-by: Leo Yan +Tested-by: Leo Yan +Signed-off-by: Eduardo Valentin +Signed-off-by: Rafael David Tinoco +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/thermal/hisi_thermal.c | 205 ++++++++++++++++++----------------------- + 1 file changed, 94 insertions(+), 111 deletions(-) + +--- a/drivers/thermal/hisi_thermal.c ++++ b/drivers/thermal/hisi_thermal.c +@@ -41,6 +41,7 @@ + #define HISI_TEMP_BASE (-60000) + #define HISI_TEMP_RESET (100000) + #define HISI_TEMP_STEP (784) ++#define HISI_TEMP_LAG (3500) + + #define HISI_MAX_SENSORS 4 + #define HISI_DEFAULT_SENSOR 2 +@@ -60,8 +61,6 @@ struct hisi_thermal_data { + struct clk *clk; + struct hisi_thermal_sensor sensors; + int irq; +- bool irq_enabled; +- + void __iomem *regs; + }; + +@@ -99,9 +98,40 @@ static inline long hisi_thermal_round_te + hisi_thermal_temp_to_step(temp)); + } + ++/* ++ * The lag register contains 5 bits encoding the temperature in steps. ++ * ++ * Each time the temperature crosses the threshold boundary, an ++ * interrupt is raised. It could be when the temperature is going ++ * above the threshold or below. However, if the temperature is ++ * fluctuating around this value due to the load, we can receive ++ * several interrupts which may not desired. ++ * ++ * We can setup a temperature representing the delta between the ++ * threshold and the current temperature when the temperature is ++ * decreasing. ++ * ++ * For instance: the lag register is 5°C, the threshold is 65°C, when ++ * the temperature reaches 65°C an interrupt is raised and when the ++ * temperature decrease to 65°C - 5°C another interrupt is raised. ++ * ++ * A very short lag can lead to an interrupt storm, a long lag ++ * increase the latency to react to the temperature changes. In our ++ * case, that is not really a problem as we are polling the ++ * temperature. ++ * ++ * [0:4] : lag register ++ * ++ * The temperature is coded in steps, cf. HISI_TEMP_STEP. ++ * ++ * Min : 0x00 : 0.0 °C ++ * Max : 0x1F : 24.3 °C ++ * ++ * The 'value' parameter is in milliCelsius. ++ */ + static inline void hisi_thermal_set_lag(void __iomem *addr, int value) + { +- writel(value, addr + TEMP0_LAG); ++ writel((value / HISI_TEMP_STEP) & 0x1F, addr + TEMP0_LAG); + } + + static inline void hisi_thermal_alarm_clear(void __iomem *addr, int value) +@@ -171,71 +201,6 @@ static inline void hisi_thermal_hdak_set + (value << 4), addr + TEMP0_CFG); + } + +-static long hisi_thermal_get_sensor_temp(struct hisi_thermal_data *data, +- struct hisi_thermal_sensor *sensor) +-{ +- long val; +- +- mutex_lock(&data->thermal_lock); +- +- /* disable interrupt */ +- hisi_thermal_alarm_enable(data->regs, 0); +- hisi_thermal_alarm_clear(data->regs, 1); +- +- /* disable module firstly */ +- hisi_thermal_enable(data->regs, 0); +- +- /* select sensor id */ +- hisi_thermal_sensor_select(data->regs, sensor->id); +- +- /* enable module */ +- hisi_thermal_enable(data->regs, 1); +- +- usleep_range(3000, 5000); +- +- val = hisi_thermal_get_temperature(data->regs); +- +- mutex_unlock(&data->thermal_lock); +- +- return val; +-} +- +-static void hisi_thermal_enable_bind_irq_sensor +- (struct hisi_thermal_data *data) +-{ +- struct hisi_thermal_sensor *sensor; +- +- mutex_lock(&data->thermal_lock); +- +- sensor = &data->sensors; +- +- /* setting the hdak time */ +- hisi_thermal_hdak_set(data->regs, 0); +- +- /* disable module firstly */ +- hisi_thermal_reset_enable(data->regs, 0); +- hisi_thermal_enable(data->regs, 0); +- +- /* select sensor id */ +- hisi_thermal_sensor_select(data->regs, sensor->id); +- +- /* enable for interrupt */ +- hisi_thermal_alarm_set(data->regs, sensor->thres_temp); +- +- hisi_thermal_reset_set(data->regs, HISI_TEMP_RESET); +- +- /* enable module */ +- hisi_thermal_reset_enable(data->regs, 1); +- hisi_thermal_enable(data->regs, 1); +- +- hisi_thermal_alarm_clear(data->regs, 0); +- hisi_thermal_alarm_enable(data->regs, 1); +- +- usleep_range(3000, 5000); +- +- mutex_unlock(&data->thermal_lock); +-} +- + static void hisi_thermal_disable_sensor(struct hisi_thermal_data *data) + { + mutex_lock(&data->thermal_lock); +@@ -253,25 +218,10 @@ static int hisi_thermal_get_temp(void *_ + struct hisi_thermal_sensor *sensor = _sensor; + struct hisi_thermal_data *data = sensor->thermal; + +- *temp = hisi_thermal_get_sensor_temp(data, sensor); ++ *temp = hisi_thermal_get_temperature(data->regs); + +- dev_dbg(&data->pdev->dev, "id=%d, irq=%d, temp=%d, thres=%d\n", +- sensor->id, data->irq_enabled, *temp, sensor->thres_temp); +- /* +- * Bind irq to sensor for two cases: +- * Reenable alarm IRQ if temperature below threshold; +- * if irq has been enabled, always set it; +- */ +- if (data->irq_enabled) { +- hisi_thermal_enable_bind_irq_sensor(data); +- return 0; +- } +- +- if (*temp < sensor->thres_temp) { +- data->irq_enabled = true; +- hisi_thermal_enable_bind_irq_sensor(data); +- enable_irq(data->irq); +- } ++ dev_dbg(&data->pdev->dev, "id=%d, temp=%d, thres=%d\n", ++ sensor->id, *temp, sensor->thres_temp); + + return 0; + } +@@ -280,26 +230,27 @@ static const struct thermal_zone_of_devi + .get_temp = hisi_thermal_get_temp, + }; + +-static irqreturn_t hisi_thermal_alarm_irq(int irq, void *dev) +-{ +- struct hisi_thermal_data *data = dev; +- +- disable_irq_nosync(irq); +- data->irq_enabled = false; +- +- return IRQ_WAKE_THREAD; +-} +- + static irqreturn_t hisi_thermal_alarm_irq_thread(int irq, void *dev) + { + struct hisi_thermal_data *data = dev; + struct hisi_thermal_sensor *sensor = &data->sensors; ++ int temp; + +- dev_crit(&data->pdev->dev, "THERMAL ALARM: T > %d\n", +- sensor->thres_temp); ++ hisi_thermal_alarm_clear(data->regs, 1); + +- thermal_zone_device_update(data->sensors.tzd, +- THERMAL_EVENT_UNSPECIFIED); ++ temp = hisi_thermal_get_temperature(data->regs); ++ ++ if (temp >= sensor->thres_temp) { ++ dev_crit(&data->pdev->dev, "THERMAL ALARM: %d > %d\n", ++ temp, sensor->thres_temp); ++ ++ thermal_zone_device_update(data->sensors.tzd, ++ THERMAL_EVENT_UNSPECIFIED); ++ ++ } else if (temp < sensor->thres_temp) { ++ dev_crit(&data->pdev->dev, "THERMAL ALARM stopped: %d < %d\n", ++ temp, sensor->thres_temp); ++ } + + return IRQ_HANDLED; + } +@@ -352,6 +303,40 @@ static void hisi_thermal_toggle_sensor(s + on ? THERMAL_DEVICE_ENABLED : THERMAL_DEVICE_DISABLED); + } + ++static int hisi_thermal_setup(struct hisi_thermal_data *data) ++{ ++ struct hisi_thermal_sensor *sensor; ++ ++ sensor = &data->sensors; ++ ++ /* disable module firstly */ ++ hisi_thermal_reset_enable(data->regs, 0); ++ hisi_thermal_enable(data->regs, 0); ++ ++ /* select sensor id */ ++ hisi_thermal_sensor_select(data->regs, sensor->id); ++ ++ /* setting the hdak time */ ++ hisi_thermal_hdak_set(data->regs, 0); ++ ++ /* setting lag value between current temp and the threshold */ ++ hisi_thermal_set_lag(data->regs, HISI_TEMP_LAG); ++ ++ /* enable for interrupt */ ++ hisi_thermal_alarm_set(data->regs, sensor->thres_temp); ++ ++ hisi_thermal_reset_set(data->regs, HISI_TEMP_RESET); ++ ++ /* enable module */ ++ hisi_thermal_reset_enable(data->regs, 1); ++ hisi_thermal_enable(data->regs, 1); ++ ++ hisi_thermal_alarm_clear(data->regs, 0); ++ hisi_thermal_alarm_enable(data->regs, 1); ++ ++ return 0; ++} ++ + static int hisi_thermal_probe(struct platform_device *pdev) + { + struct hisi_thermal_data *data; +@@ -394,9 +379,6 @@ static int hisi_thermal_probe(struct pla + return ret; + } + +- hisi_thermal_enable_bind_irq_sensor(data); +- data->irq_enabled = true; +- + ret = hisi_thermal_register_sensor(pdev, data, + &data->sensors, + HISI_DEFAULT_SENSOR); +@@ -406,10 +388,15 @@ static int hisi_thermal_probe(struct pla + return ret; + } + +- ret = devm_request_threaded_irq(&pdev->dev, data->irq, +- hisi_thermal_alarm_irq, ++ ret = hisi_thermal_setup(data); ++ if (ret) { ++ dev_err(&pdev->dev, "Failed to setup the sensor: %d\n", ret); ++ return ret; ++ } ++ ++ ret = devm_request_threaded_irq(&pdev->dev, data->irq, NULL, + hisi_thermal_alarm_irq_thread, +- 0, "hisi_thermal", data); ++ IRQF_ONESHOT, "hisi_thermal", data); + if (ret < 0) { + dev_err(&pdev->dev, "failed to request alarm irq: %d\n", ret); + return ret; +@@ -417,8 +404,6 @@ static int hisi_thermal_probe(struct pla + + hisi_thermal_toggle_sensor(&data->sensors, true); + +- enable_irq(data->irq); +- + return 0; + } + +@@ -440,7 +425,6 @@ static int hisi_thermal_suspend(struct d + struct hisi_thermal_data *data = dev_get_drvdata(dev); + + hisi_thermal_disable_sensor(data); +- data->irq_enabled = false; + + clk_disable_unprepare(data->clk); + +@@ -456,8 +440,7 @@ static int hisi_thermal_resume(struct de + if (ret) + return ret; + +- data->irq_enabled = true; +- hisi_thermal_enable_bind_irq_sensor(data); ++ hisi_thermal_setup(data); + + return 0; + } diff --git a/queue-4.14/thermal-drivers-hisi-remove-pointless-lock.patch b/queue-4.14/thermal-drivers-hisi-remove-pointless-lock.patch new file mode 100644 index 00000000000..a4f66d0b2cd --- /dev/null +++ b/queue-4.14/thermal-drivers-hisi-remove-pointless-lock.patch @@ -0,0 +1,42 @@ +From 2d4fa7b4c6f8080ced2e8237c9f46fb1fc110d64 Mon Sep 17 00:00:00 2001 +From: Daniel Lezcano +Date: Thu, 19 Oct 2017 19:05:48 +0200 +Subject: thermal/drivers/hisi: Remove pointless lock + +From: Daniel Lezcano + +commit 2d4fa7b4c6f8080ced2e8237c9f46fb1fc110d64 upstream. + +The threaded interrupt inspect the sensors structure to look in the temp +threshold field, but this field is read-only in all the code, except in the +probe function before the threaded interrupt is set. In other words there +is not race window in the threaded interrupt when reading the field value. + +Signed-off-by: Daniel Lezcano +Reviewed-by: Leo Yan +Signed-off-by: Eduardo Valentin +Signed-off-by: Rafael David Tinoco +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/thermal/hisi_thermal.c | 6 +----- + 1 file changed, 1 insertion(+), 5 deletions(-) + +--- a/drivers/thermal/hisi_thermal.c ++++ b/drivers/thermal/hisi_thermal.c +@@ -221,14 +221,10 @@ static irqreturn_t hisi_thermal_alarm_ir + static irqreturn_t hisi_thermal_alarm_irq_thread(int irq, void *dev) + { + struct hisi_thermal_data *data = dev; +- struct hisi_thermal_sensor *sensor; +- +- mutex_lock(&data->thermal_lock); +- sensor = &data->sensors; ++ struct hisi_thermal_sensor *sensor = &data->sensors; + + dev_crit(&data->pdev->dev, "THERMAL ALARM: T > %d\n", + sensor->thres_temp); +- mutex_unlock(&data->thermal_lock); + + thermal_zone_device_update(data->sensors.tzd, + THERMAL_EVENT_UNSPECIFIED); diff --git a/queue-4.14/thermal-drivers-hisi-remove-the-multiple-sensors-support.patch b/queue-4.14/thermal-drivers-hisi-remove-the-multiple-sensors-support.patch new file mode 100644 index 00000000000..4f6cbdaa2e0 --- /dev/null +++ b/queue-4.14/thermal-drivers-hisi-remove-the-multiple-sensors-support.patch @@ -0,0 +1,185 @@ +From ff4ec2997df8fe7cc40513dbe5f86d9f88fb6be7 Mon Sep 17 00:00:00 2001 +From: Daniel Lezcano +Date: Thu, 19 Oct 2017 19:05:44 +0200 +Subject: thermal/drivers/hisi: Remove the multiple sensors support + +From: Daniel Lezcano + +commit ff4ec2997df8fe7cc40513dbe5f86d9f88fb6be7 upstream. + +By essence, the tsensor does not really support multiple sensor at the same +time. It allows to set a sensor and use it to get the temperature, another +sensor could be switched but with a delay of 3-5ms. It is difficult to read +simultaneously several sensors without a big delay. + +Today, just one sensor is used, it is not necessary to deal with multiple +sensors in the code. Remove them and if it is needed in the future add them +on top of a code which will be clean up in the meantime. + +Signed-off-by: Daniel Lezcano +Reviewed-by: Leo Yan +Acked-by: Wangtao (Kevin, Kirin) +Signed-off-by: Eduardo Valentin +Signed-off-by: Rafael David Tinoco +Signed-off-by: Greg Kroah-Hartman +--- + drivers/thermal/hisi_thermal.c | 75 ++++++++++------------------------------- + 1 file changed, 19 insertions(+), 56 deletions(-) + +--- a/drivers/thermal/hisi_thermal.c ++++ b/drivers/thermal/hisi_thermal.c +@@ -40,6 +40,7 @@ + #define HISI_TEMP_STEP (784) + + #define HISI_MAX_SENSORS 4 ++#define HISI_DEFAULT_SENSOR 2 + + struct hisi_thermal_sensor { + struct hisi_thermal_data *thermal; +@@ -54,9 +55,8 @@ struct hisi_thermal_data { + struct mutex thermal_lock; /* protects register data */ + struct platform_device *pdev; + struct clk *clk; +- struct hisi_thermal_sensor sensors[HISI_MAX_SENSORS]; +- +- int irq, irq_bind_sensor; ++ struct hisi_thermal_sensor sensors; ++ int irq; + bool irq_enabled; + + void __iomem *regs; +@@ -133,7 +133,7 @@ static void hisi_thermal_enable_bind_irq + + mutex_lock(&data->thermal_lock); + +- sensor = &data->sensors[data->irq_bind_sensor]; ++ sensor = &data->sensors; + + /* setting the hdak time */ + writel(0x0, data->regs + TEMP0_CFG); +@@ -181,31 +181,8 @@ static int hisi_thermal_get_temp(void *_ + struct hisi_thermal_sensor *sensor = _sensor; + struct hisi_thermal_data *data = sensor->thermal; + +- int sensor_id = -1, i; +- long max_temp = 0; +- + *temp = hisi_thermal_get_sensor_temp(data, sensor); + +- sensor->sensor_temp = *temp; +- +- for (i = 0; i < HISI_MAX_SENSORS; i++) { +- if (!data->sensors[i].tzd) +- continue; +- +- if (data->sensors[i].sensor_temp >= max_temp) { +- max_temp = data->sensors[i].sensor_temp; +- sensor_id = i; +- } +- } +- +- /* If no sensor has been enabled, then skip to enable irq */ +- if (sensor_id == -1) +- return 0; +- +- mutex_lock(&data->thermal_lock); +- data->irq_bind_sensor = sensor_id; +- mutex_unlock(&data->thermal_lock); +- + dev_dbg(&data->pdev->dev, "id=%d, irq=%d, temp=%d, thres=%d\n", + sensor->id, data->irq_enabled, *temp, sensor->thres_temp); + /* +@@ -218,7 +195,7 @@ static int hisi_thermal_get_temp(void *_ + return 0; + } + +- if (max_temp < sensor->thres_temp) { ++ if (*temp < sensor->thres_temp) { + data->irq_enabled = true; + hisi_thermal_enable_bind_irq_sensor(data); + enable_irq(data->irq); +@@ -245,22 +222,16 @@ static irqreturn_t hisi_thermal_alarm_ir + { + struct hisi_thermal_data *data = dev; + struct hisi_thermal_sensor *sensor; +- int i; + + mutex_lock(&data->thermal_lock); +- sensor = &data->sensors[data->irq_bind_sensor]; ++ sensor = &data->sensors; + + dev_crit(&data->pdev->dev, "THERMAL ALARM: T > %d\n", + sensor->thres_temp); + mutex_unlock(&data->thermal_lock); + +- for (i = 0; i < HISI_MAX_SENSORS; i++) { +- if (!data->sensors[i].tzd) +- continue; +- +- thermal_zone_device_update(data->sensors[i].tzd, +- THERMAL_EVENT_UNSPECIFIED); +- } ++ thermal_zone_device_update(data->sensors.tzd, ++ THERMAL_EVENT_UNSPECIFIED); + + return IRQ_HANDLED; + } +@@ -317,7 +288,6 @@ static int hisi_thermal_probe(struct pla + { + struct hisi_thermal_data *data; + struct resource *res; +- int i; + int ret; + + data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); +@@ -359,14 +329,13 @@ static int hisi_thermal_probe(struct pla + hisi_thermal_enable_bind_irq_sensor(data); + data->irq_enabled = true; + +- for (i = 0; i < HISI_MAX_SENSORS; ++i) { +- ret = hisi_thermal_register_sensor(pdev, data, +- &data->sensors[i], i); +- if (ret) +- dev_err(&pdev->dev, +- "failed to register thermal sensor: %d\n", ret); +- else +- hisi_thermal_toggle_sensor(&data->sensors[i], true); ++ ret = hisi_thermal_register_sensor(pdev, data, ++ &data->sensors, ++ HISI_DEFAULT_SENSOR); ++ if (ret) { ++ dev_err(&pdev->dev, "failed to register thermal sensor: %d\n", ++ ret); ++ return ret; + } + + ret = devm_request_threaded_irq(&pdev->dev, data->irq, +@@ -378,6 +347,8 @@ static int hisi_thermal_probe(struct pla + return ret; + } + ++ hisi_thermal_toggle_sensor(&data->sensors, true); ++ + enable_irq(data->irq); + + return 0; +@@ -386,17 +357,9 @@ static int hisi_thermal_probe(struct pla + static int hisi_thermal_remove(struct platform_device *pdev) + { + struct hisi_thermal_data *data = platform_get_drvdata(pdev); +- int i; +- +- for (i = 0; i < HISI_MAX_SENSORS; i++) { +- struct hisi_thermal_sensor *sensor = &data->sensors[i]; +- +- if (!sensor->tzd) +- continue; +- +- hisi_thermal_toggle_sensor(sensor, false); +- } ++ struct hisi_thermal_sensor *sensor = &data->sensors; + ++ hisi_thermal_toggle_sensor(sensor, false); + hisi_thermal_disable_sensor(data); + clk_disable_unprepare(data->clk); + diff --git a/queue-4.14/udf-allow-mounting-volumes-with-incorrect-identification-strings.patch b/queue-4.14/udf-allow-mounting-volumes-with-incorrect-identification-strings.patch new file mode 100644 index 00000000000..c0b44173858 --- /dev/null +++ b/queue-4.14/udf-allow-mounting-volumes-with-incorrect-identification-strings.patch @@ -0,0 +1,94 @@ +From b54e41f5efcb4316b2f30b30c2535cc194270373 Mon Sep 17 00:00:00 2001 +From: Jan Kara +Date: Fri, 16 Nov 2018 13:43:17 +0100 +Subject: udf: Allow mounting volumes with incorrect identification strings + +From: Jan Kara + +commit b54e41f5efcb4316b2f30b30c2535cc194270373 upstream. + +Commit c26f6c615788 ("udf: Fix conversion of 'dstring' fields to UTF8") +started to be more strict when checking whether converted strings are +properly formatted. Sudip reports that there are DVDs where the volume +identification string is actually too long - UDF reports: + +[ 632.309320] UDF-fs: incorrect dstring lengths (32/32) + +during mount and fails the mount. This is mostly harmless failure as we +don't need volume identification (and even less volume set +identification) for anything. So just truncate the volume identification +string if it is too long and replace it with 'Invalid' if we just cannot +convert it for other reasons. This keeps slightly incorrect media still +mountable. + +CC: stable@vger.kernel.org +Fixes: c26f6c615788 ("udf: Fix conversion of 'dstring' fields to UTF8") +Reported-and-tested-by: Sudip Mukherjee +Signed-off-by: Jan Kara +Signed-off-by: Sudip Mukherjee +Signed-off-by: Greg Kroah-Hartman + +--- + fs/udf/super.c | 16 ++++++++++------ + fs/udf/unicode.c | 14 +++++++++++--- + 2 files changed, 21 insertions(+), 9 deletions(-) + +--- a/fs/udf/super.c ++++ b/fs/udf/super.c +@@ -922,16 +922,20 @@ static int udf_load_pvoldesc(struct supe + } + + ret = udf_dstrCS0toUTF8(outstr, 31, pvoldesc->volIdent, 32); +- if (ret < 0) +- goto out_bh; +- +- strncpy(UDF_SB(sb)->s_volume_ident, outstr, ret); ++ if (ret < 0) { ++ strcpy(UDF_SB(sb)->s_volume_ident, "InvalidName"); ++ pr_warn("incorrect volume identification, setting to " ++ "'InvalidName'\n"); ++ } else { ++ strncpy(UDF_SB(sb)->s_volume_ident, outstr, ret); ++ } + udf_debug("volIdent[] = '%s'\n", UDF_SB(sb)->s_volume_ident); + + ret = udf_dstrCS0toUTF8(outstr, 127, pvoldesc->volSetIdent, 128); +- if (ret < 0) ++ if (ret < 0) { ++ ret = 0; + goto out_bh; +- ++ } + outstr[ret] = 0; + udf_debug("volSetIdent[] = '%s'\n", outstr); + +--- a/fs/udf/unicode.c ++++ b/fs/udf/unicode.c +@@ -341,6 +341,11 @@ try_again: + return u_len; + } + ++/* ++ * Convert CS0 dstring to output charset. Warning: This function may truncate ++ * input string if it is too long as it is used for informational strings only ++ * and it is better to truncate the string than to refuse mounting a media. ++ */ + int udf_dstrCS0toUTF8(uint8_t *utf_o, int o_len, + const uint8_t *ocu_i, int i_len) + { +@@ -349,9 +354,12 @@ int udf_dstrCS0toUTF8(uint8_t *utf_o, in + if (i_len > 0) { + s_len = ocu_i[i_len - 1]; + if (s_len >= i_len) { +- pr_err("incorrect dstring lengths (%d/%d)\n", +- s_len, i_len); +- return -EINVAL; ++ pr_warn("incorrect dstring lengths (%d/%d)," ++ " truncating\n", s_len, i_len); ++ s_len = i_len - 1; ++ /* 2-byte encoding? Need to round properly... */ ++ if (ocu_i[0] == 16) ++ s_len -= (s_len - 1) & 2; + } + } +