From faad2b874feaca00465997ec56bbd67ad26c3d15 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Wed, 10 May 2017 11:21:25 +0200 Subject: [PATCH 001/396] ANDROID: rfkill: fix unused function warning As reported by kernelci, we get a harmless warning in this driver when CONFIG_PM is disabled: net/rfkill/core.c:810:12: warning: 'rfkill_resume' defined but not used [-Wunused-function] net/rfkill/core.c:800:12: warning: 'rfkill_suspend' defined but not used [-Wunused-function] This marks the functions as __maybe_unused to remove the #ifdef, and uses a conditional reference to the pm operations instead, which will work in any combination. The patch is needed for both android-common-4.9 and 4.4. Link: https://kernelci.org/build/id/59117c2f59b5147b06b12d54/logs/ Fixes: de6f7210e931 ("ANDROID: rfkill: Introduce CONFIG_RFKILL_PM and use instead of CONFIG_PM to power down") Cc: Nick Pelly Signed-off-by: Arnd Bergmann Signed-off-by: Greg Kroah-Hartman --- net/rfkill/core.c | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/net/rfkill/core.c b/net/rfkill/core.c index 9b4260dab2a4..a9a7128f039e 100644 --- a/net/rfkill/core.c +++ b/net/rfkill/core.c @@ -796,8 +796,7 @@ void rfkill_resume_polling(struct rfkill *rfkill) } EXPORT_SYMBOL(rfkill_resume_polling); -#ifdef CONFIG_RFKILL_PM -static int rfkill_suspend(struct device *dev) +static __maybe_unused int rfkill_suspend(struct device *dev) { struct rfkill *rfkill = to_rfkill(dev); @@ -807,7 +806,7 @@ static int rfkill_suspend(struct device *dev) return 0; } -static int rfkill_resume(struct device *dev) +static __maybe_unused int rfkill_resume(struct device *dev) { struct rfkill *rfkill = to_rfkill(dev); bool cur; @@ -827,19 +826,13 @@ static int rfkill_resume(struct device *dev) } static SIMPLE_DEV_PM_OPS(rfkill_pm_ops, rfkill_suspend, rfkill_resume); -#define RFKILL_PM_OPS (&rfkill_pm_ops) -#else -#define RFKILL_PM_OPS NULL -#endif static struct class rfkill_class = { .name = "rfkill", .dev_release = rfkill_release, .dev_groups = rfkill_dev_groups, .dev_uevent = rfkill_dev_uevent, -#ifdef CONFIG_RFKILL_PM - .pm = RFKILL_PM_OPS, -#endif + .pm = IS_ENABLED(CONFIG_RFKILL_PM) ? &rfkill_pm_ops : NULL, }; bool rfkill_blocked(struct rfkill *rfkill) From 3482704132fc32d1c80d1db727b46cba64e832bd Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Wed, 10 May 2017 11:21:27 +0200 Subject: [PATCH 002/396] ANDROID: memory_state_time: fix undefined behavior with missing DT properties kernelci reports warnings about unintialized variable usage: drivers/misc/memory_state_time.c:351:12: warning: 'lenf' is used uninitialized in this function [-Wuninitialized] drivers/misc/memory_state_time.c:321:14: warning: 'lenb' is used uninitialized in this function [-Wuninitialized] In both cases we try to continue without a DT property but use the length that has not been assigned at this point. This rearranges the code in the two functions to bail out earlier in case of an error. The patch is needed for both android-common-4.9, 4.4 and 3.18. Link: https://kernelci.org/build/id/591177f459b5147648b12d54/logs/ Fixes: ad3c02f8b3a5 ("ANDROID: Implement memory_state_time, used by qcom,cpubw") Cc: James Carr Signed-off-by: Arnd Bergmann Signed-off-by: Greg Kroah-Hartman --- drivers/misc/memory_state_time.c | 78 ++++++++++++++++++-------------- 1 file changed, 43 insertions(+), 35 deletions(-) diff --git a/drivers/misc/memory_state_time.c b/drivers/misc/memory_state_time.c index 34c797a06a31..ba94dcf09169 100644 --- a/drivers/misc/memory_state_time.c +++ b/drivers/misc/memory_state_time.c @@ -296,27 +296,31 @@ static int get_bw_buckets(struct device *dev) struct device_node *node = dev->of_node; of_property_read_u32(node, NUM_SOURCES, &num_sources); - if (of_find_property(node, BW_TBL, &lenb)) { - bandwidths = devm_kzalloc(dev, - sizeof(*bandwidths) * num_sources, GFP_KERNEL); - if (!bandwidths) - return -ENOMEM; - lenb /= sizeof(*bw_buckets); - bw_buckets = devm_kzalloc(dev, lenb * sizeof(*bw_buckets), - GFP_KERNEL); - if (!bw_buckets) { - devm_kfree(dev, bandwidths); - return -ENOMEM; - } - ret = of_property_read_u32_array(node, BW_TBL, bw_buckets, - lenb); - if (ret < 0) { - devm_kfree(dev, bandwidths); - devm_kfree(dev, bw_buckets); - pr_err("Unable to read bandwidth table from device tree.\n"); - return ret; - } + if (!of_find_property(node, BW_TBL, &lenb)) { + pr_err("Missing %s property\n", BW_TBL); + return -ENODATA; } + + bandwidths = devm_kzalloc(dev, + sizeof(*bandwidths) * num_sources, GFP_KERNEL); + if (!bandwidths) + return -ENOMEM; + lenb /= sizeof(*bw_buckets); + bw_buckets = devm_kzalloc(dev, lenb * sizeof(*bw_buckets), + GFP_KERNEL); + if (!bw_buckets) { + devm_kfree(dev, bandwidths); + return -ENOMEM; + } + ret = of_property_read_u32_array(node, BW_TBL, bw_buckets, + lenb); + if (ret < 0) { + devm_kfree(dev, bandwidths); + devm_kfree(dev, bw_buckets); + pr_err("Unable to read bandwidth table from device tree.\n"); + return ret; + } + curr_bw = 0; num_buckets = lenb; return 0; @@ -332,22 +336,26 @@ static int freq_buckets_init(struct device *dev) int ret, lenf; struct device_node *node = dev->of_node; - if (of_find_property(node, FREQ_TBL, &lenf)) { - lenf /= sizeof(*freq_buckets); - freq_buckets = devm_kzalloc(dev, lenf * sizeof(*freq_buckets), - GFP_KERNEL); - if (!freq_buckets) - return -ENOMEM; - pr_debug("freqs found len %d\n", lenf); - ret = of_property_read_u32_array(node, FREQ_TBL, freq_buckets, - lenf); - if (ret < 0) { - devm_kfree(dev, freq_buckets); - pr_err("Unable to read frequency table from device tree.\n"); - return ret; - } - pr_debug("ret freq %d\n", ret); + if (!of_find_property(node, FREQ_TBL, &lenf)) { + pr_err("Missing %s property\n", FREQ_TBL); + return -ENODATA; } + + lenf /= sizeof(*freq_buckets); + freq_buckets = devm_kzalloc(dev, lenf * sizeof(*freq_buckets), + GFP_KERNEL); + if (!freq_buckets) + return -ENOMEM; + pr_debug("freqs found len %d\n", lenf); + ret = of_property_read_u32_array(node, FREQ_TBL, freq_buckets, + lenf); + if (ret < 0) { + devm_kfree(dev, freq_buckets); + pr_err("Unable to read frequency table from device tree.\n"); + return ret; + } + pr_debug("ret freq %d\n", ret); + num_freqs = lenf; curr_freq = freq_buckets[LOWEST_FREQ]; From 99c809676f6c895a5a97bf37d7c412bc9919710d Mon Sep 17 00:00:00 2001 From: Steve Muckle Date: Fri, 12 May 2017 10:17:05 -0700 Subject: [PATCH 003/396] ANDROID: android-base.cfg: remove spurious CONFIG_MODULES line CONFIG_MODULES must be enabled as part of the android base kernel configuration. There is already a line specifying the option be enabled, but there was a pre-existing line requiring it be disabled. Remove it. Bug: 38224475 Change-Id: I608de5ae68f3a03d5da4e5800bbf37cc71dff8b8 Signed-off-by: Steve Muckle --- kernel/configs/android-base.config | 1 - 1 file changed, 1 deletion(-) diff --git a/kernel/configs/android-base.config b/kernel/configs/android-base.config index 23686fc15d45..b7b997fd58c9 100644 --- a/kernel/configs/android-base.config +++ b/kernel/configs/android-base.config @@ -3,7 +3,6 @@ # CONFIG_DEVMEM is not set # CONFIG_FHANDLE is not set # CONFIG_INET_LRO is not set -# CONFIG_MODULES is not set # CONFIG_OABI_COMPAT is not set # CONFIG_SYSVIPC is not set # CONFIG_USELIB is not set From f5ca890f138d010e26a56e622316d4065add67f0 Mon Sep 17 00:00:00 2001 From: Cong Wang Date: Wed, 22 Feb 2017 15:40:53 -0800 Subject: [PATCH 004/396] 9p: fix a potential acl leak commit b5c66bab72a6a65edb15beb60b90d3cb84c5763b upstream. posix_acl_update_mode() could possibly clear 'acl', if so we leak the memory pointed by 'acl'. Save this pointer before calling posix_acl_update_mode() and release the memory if 'acl' really gets cleared. Link: http://lkml.kernel.org/r/1486678332-2430-1-git-send-email-xiyou.wangcong@gmail.com Signed-off-by: Cong Wang Reported-by: Mark Salyzyn Reviewed-by: Jan Kara Reviewed-by: Greg Kurz Cc: Eric Van Hensbergen Cc: Ron Minnich Cc: Latchesar Ionkov Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- fs/9p/acl.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/fs/9p/acl.c b/fs/9p/acl.c index b3c2cc79c20d..082d227fa56b 100644 --- a/fs/9p/acl.c +++ b/fs/9p/acl.c @@ -277,6 +277,7 @@ static int v9fs_xattr_set_acl(const struct xattr_handler *handler, case ACL_TYPE_ACCESS: if (acl) { struct iattr iattr; + struct posix_acl *old_acl = acl; retval = posix_acl_update_mode(inode, &iattr.ia_mode, &acl); if (retval) @@ -287,6 +288,7 @@ static int v9fs_xattr_set_acl(const struct xattr_handler *handler, * by the mode bits. So don't * update ACL. */ + posix_acl_release(old_acl); value = NULL; size = 0; } From 898c6bbfc88de33ceabcee6545bda3bbe12d3e5c Mon Sep 17 00:00:00 2001 From: Vincent Abriou Date: Thu, 23 Mar 2017 15:44:52 +0100 Subject: [PATCH 005/396] drm/sti: fix GDP size to support up to UHD resolution commit 2f410f88c0a1c7e19762918d2614f506a7b63a82 upstream. On stih407-410 chip family the GDP layers are able to support up to UHD resolution (3840 x 2160). Signed-off-by: Vincent Abriou Acked-by: Lee Jones Tested-by: Lee Jones Link: http://patchwork.freedesktop.org/patch/msgid/1490280292-30466-1-git-send-email-vincent.abriou@st.com Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/sti/sti_gdp.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/sti/sti_gdp.c b/drivers/gpu/drm/sti/sti_gdp.c index 81df3097b545..7fd496f99385 100644 --- a/drivers/gpu/drm/sti/sti_gdp.c +++ b/drivers/gpu/drm/sti/sti_gdp.c @@ -66,7 +66,9 @@ static struct gdp_format_to_str { #define GAM_GDP_ALPHARANGE_255 BIT(5) #define GAM_GDP_AGC_FULL_RANGE 0x00808080 #define GAM_GDP_PPT_IGNORE (BIT(1) | BIT(0)) -#define GAM_GDP_SIZE_MAX 0x7FF + +#define GAM_GDP_SIZE_MAX_WIDTH 3840 +#define GAM_GDP_SIZE_MAX_HEIGHT 2160 #define GDP_NODE_NB_BANK 2 #define GDP_NODE_PER_FIELD 2 @@ -633,8 +635,8 @@ static int sti_gdp_atomic_check(struct drm_plane *drm_plane, /* src_x are in 16.16 format */ src_x = state->src_x >> 16; src_y = state->src_y >> 16; - src_w = clamp_val(state->src_w >> 16, 0, GAM_GDP_SIZE_MAX); - src_h = clamp_val(state->src_h >> 16, 0, GAM_GDP_SIZE_MAX); + src_w = clamp_val(state->src_w >> 16, 0, GAM_GDP_SIZE_MAX_WIDTH); + src_h = clamp_val(state->src_h >> 16, 0, GAM_GDP_SIZE_MAX_HEIGHT); format = sti_gdp_fourcc2format(fb->pixel_format); if (format == -1) { @@ -732,8 +734,8 @@ static void sti_gdp_atomic_update(struct drm_plane *drm_plane, /* src_x are in 16.16 format */ src_x = state->src_x >> 16; src_y = state->src_y >> 16; - src_w = clamp_val(state->src_w >> 16, 0, GAM_GDP_SIZE_MAX); - src_h = clamp_val(state->src_h >> 16, 0, GAM_GDP_SIZE_MAX); + src_w = clamp_val(state->src_w >> 16, 0, GAM_GDP_SIZE_MAX_WIDTH); + src_h = clamp_val(state->src_h >> 16, 0, GAM_GDP_SIZE_MAX_HEIGHT); list = sti_gdp_get_free_nodes(gdp); top_field = list->top_field; From a941f261c8f16faa22d3fcd16842f6d8c2723eac Mon Sep 17 00:00:00 2001 From: Guenter Roeck Date: Wed, 8 Feb 2017 14:05:56 -0800 Subject: [PATCH 006/396] hwmon: (it87) Fix pwm4 detection for IT8620 and IT8628 commit d66777caa57ffade6061782f3a4d4056f0b0c1ac upstream. pwm4 is enabled if bit 2 of GPIO control register 4 is disabled, not when it is enabled. Since the check is for the skip condition, it is reversed. This applies to both IT8620 and IT8628. Fixes: 36c4d98a7883d ("hwmon: (it87) Add support for all pwm channels ...") Signed-off-by: Guenter Roeck Signed-off-by: Greg Kroah-Hartman --- drivers/hwmon/it87.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/hwmon/it87.c b/drivers/hwmon/it87.c index b99c1df48156..81853ee85f6a 100644 --- a/drivers/hwmon/it87.c +++ b/drivers/hwmon/it87.c @@ -2600,7 +2600,7 @@ static int __init it87_find(int sioaddr, unsigned short *address, /* Check for pwm4 */ reg = superio_inb(sioaddr, IT87_SIO_GPIO4_REG); - if (!(reg & BIT(2))) + if (reg & BIT(2)) sio_data->skip_pwm |= BIT(3); /* Check for pwm2, fan2 */ From 326f9b0a39d3a27221dafc46e9862c7a1aa8fb19 Mon Sep 17 00:00:00 2001 From: Jarkko Sakkinen Date: Wed, 25 Jan 2017 23:00:22 +0200 Subject: [PATCH 007/396] tpm: fix RC value check in tpm2_seal_trusted commit 7d761119a914ec0ac05ec2a5378d1f86e680967d upstream. The error code handling is broken as any error code that has the same bits set as TPM_RC_HASH passes. Implemented tpm2_rc_value() helper to parse the error value from FMT0 and FMT1 error codes so that these types of mistakes are prevented in the future. Fixes: 5ca4c20cfd37 ("keys, trusted: select hash algorithm for TPM2 chips") Signed-off-by: Jarkko Sakkinen Reviewed-by: Jason Gunthorpe Signed-off-by: Greg Kroah-Hartman --- drivers/char/tpm/tpm.h | 5 +++++ drivers/char/tpm/tpm2-cmd.c | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h index 4d183c97f6a6..aa4299cf7e5a 100644 --- a/drivers/char/tpm/tpm.h +++ b/drivers/char/tpm/tpm.h @@ -518,6 +518,11 @@ static inline void tpm_add_ppi(struct tpm_chip *chip) } #endif +static inline inline u32 tpm2_rc_value(u32 rc) +{ + return (rc & BIT(7)) ? rc & 0xff : rc; +} + int tpm2_pcr_read(struct tpm_chip *chip, int pcr_idx, u8 *res_buf); int tpm2_pcr_extend(struct tpm_chip *chip, int pcr_idx, const u8 *hash); int tpm2_get_random(struct tpm_chip *chip, u8 *out, size_t max); diff --git a/drivers/char/tpm/tpm2-cmd.c b/drivers/char/tpm/tpm2-cmd.c index 7df55d58c939..17896d654033 100644 --- a/drivers/char/tpm/tpm2-cmd.c +++ b/drivers/char/tpm/tpm2-cmd.c @@ -529,7 +529,7 @@ out: tpm_buf_destroy(&buf); if (rc > 0) { - if ((rc & TPM2_RC_HASH) == TPM2_RC_HASH) + if (tpm2_rc_value(rc) == TPM2_RC_HASH) rc = -EINVAL; else rc = -EPERM; From 819e3601d3c5e483d8c42839a2acfbfb2eafe784 Mon Sep 17 00:00:00 2001 From: "Winkler, Tomas" Date: Wed, 23 Nov 2016 12:04:13 +0200 Subject: [PATCH 008/396] tmp: use pdev for parent device in tpm_chip_alloc commit 2998b02b2fb58f36ccbc318b00513174e9947d8e upstream. The tpm stack uses pdev name convention for the parent device. Fix that also in tpm_chip_alloc(). Fixes: 3897cd9c8d1d ("tpm: Split out the devm stuff from tpmm_chip_alloc")' Signed-off-by: Tomas Winkler Reviewed-by: Jarkko Sakkinen Tested-by: Jarkko Sakkinen Signed-off-by: Jarkko Sakkinen Signed-off-by: Greg Kroah-Hartman --- drivers/char/tpm/tpm-chip.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/char/tpm/tpm-chip.c b/drivers/char/tpm/tpm-chip.c index e5950131bd90..a017ccd8cc3b 100644 --- a/drivers/char/tpm/tpm-chip.c +++ b/drivers/char/tpm/tpm-chip.c @@ -140,7 +140,7 @@ static void tpm_dev_release(struct device *dev) * Allocates a new struct tpm_chip instance and assigns a free * device number for it. Must be paired with put_device(&chip->dev). */ -struct tpm_chip *tpm_chip_alloc(struct device *dev, +struct tpm_chip *tpm_chip_alloc(struct device *pdev, const struct tpm_class_ops *ops) { struct tpm_chip *chip; @@ -159,7 +159,7 @@ struct tpm_chip *tpm_chip_alloc(struct device *dev, rc = idr_alloc(&dev_nums_idr, NULL, 0, TPM_NUM_DEVICES, GFP_KERNEL); mutex_unlock(&idr_lock); if (rc < 0) { - dev_err(dev, "No available tpm device numbers\n"); + dev_err(pdev, "No available tpm device numbers\n"); kfree(chip); return ERR_PTR(rc); } @@ -169,7 +169,7 @@ struct tpm_chip *tpm_chip_alloc(struct device *dev, chip->dev.class = tpm_class; chip->dev.release = tpm_dev_release; - chip->dev.parent = dev; + chip->dev.parent = pdev; chip->dev.groups = chip->groups; if (chip->dev_num == 0) @@ -181,7 +181,7 @@ struct tpm_chip *tpm_chip_alloc(struct device *dev, if (rc) goto out; - if (!dev) + if (!pdev) chip->flags |= TPM_CHIP_FLAG_VIRTUAL; cdev_init(&chip->cdev, &tpm_fops); From ccef31d22e802f98bd161aa7e54f2ad98bc5ba17 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Horia=20Geant=C4=83?= Date: Fri, 10 Feb 2017 14:07:23 +0200 Subject: [PATCH 009/396] crypto: caam - fix error path for ctx_dma mapping failure MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 87ec02e7409d787348c244039aa3536a812dfa8b upstream. In case ctx_dma dma mapping fails, ahash_unmap_ctx() tries to dma unmap an invalid address: map_seq_out_ptr_ctx() / ctx_map_to_sec4_sg() -> goto unmap_ctx -> -> ahash_unmap_ctx() -> dma unmap ctx_dma There is also possible to reach ahash_unmap_ctx() with ctx_dma uninitialzed or to try to unmap the same address twice. Fix these by setting ctx_dma = 0 where needed: -initialize ctx_dma in ahash_init() -clear ctx_dma in case of mapping error (instead of holding the error code returned by the dma map function) -clear ctx_dma after each unmapping Fixes: 32686d34f8fb6 ("crypto: caam - ensure that we clean up after an error") Signed-off-by: Horia Geantă Signed-off-by: Herbert Xu Signed-off-by: Greg Kroah-Hartman --- drivers/crypto/caam/caamhash.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/crypto/caam/caamhash.c b/drivers/crypto/caam/caamhash.c index 660dc206969f..2474f1494955 100644 --- a/drivers/crypto/caam/caamhash.c +++ b/drivers/crypto/caam/caamhash.c @@ -154,6 +154,7 @@ static inline int map_seq_out_ptr_ctx(u32 *desc, struct device *jrdev, ctx_len, DMA_FROM_DEVICE); if (dma_mapping_error(jrdev, state->ctx_dma)) { dev_err(jrdev, "unable to map ctx\n"); + state->ctx_dma = 0; return -ENOMEM; } @@ -214,6 +215,7 @@ static inline int ctx_map_to_sec4_sg(u32 *desc, struct device *jrdev, state->ctx_dma = dma_map_single(jrdev, state->caam_ctx, ctx_len, flag); if (dma_mapping_error(jrdev, state->ctx_dma)) { dev_err(jrdev, "unable to map ctx\n"); + state->ctx_dma = 0; return -ENOMEM; } @@ -620,8 +622,10 @@ static inline void ahash_unmap_ctx(struct device *dev, struct caam_hash_ctx *ctx = crypto_ahash_ctx(ahash); struct caam_hash_state *state = ahash_request_ctx(req); - if (state->ctx_dma) + if (state->ctx_dma) { dma_unmap_single(dev, state->ctx_dma, ctx->ctx_len, flag); + state->ctx_dma = 0; + } ahash_unmap(dev, edesc, req, dst_len); } @@ -1605,6 +1609,7 @@ static int ahash_init(struct ahash_request *req) state->finup = ahash_finup_first; state->final = ahash_final_no_ctx; + state->ctx_dma = 0; state->current_buf = 0; state->buf_dma = 0; state->buflen_0 = 0; From 4f39fcce99d7acd5712347a0bde57352a5abc8a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Giedrius=20Statkevi=C4=8Dius?= Date: Sat, 25 Mar 2017 18:00:49 +0200 Subject: [PATCH 010/396] power: supply: lp8788: prevent out of bounds array access MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit bdd9968d35f7fcdb76089347d1529bf079534214 upstream. val might become 7 in which case stime[7] (array of length 7) would be accessed during the scnprintf call later and that will cause issues. Obviously, string concatenation is not intended here so just a comma needs to be added to fix the issue. Fixes: 98a276649358 ("power_supply: Add new lp8788 charger driver") Signed-off-by: Giedrius Statkevičius Acked-by: Milo Kim Signed-off-by: Sebastian Reichel Signed-off-by: Greg Kroah-Hartman --- drivers/power/supply/lp8788-charger.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/power/supply/lp8788-charger.c b/drivers/power/supply/lp8788-charger.c index 7321b727d484..cd614fe69d14 100644 --- a/drivers/power/supply/lp8788-charger.c +++ b/drivers/power/supply/lp8788-charger.c @@ -654,7 +654,7 @@ static ssize_t lp8788_show_eoc_time(struct device *dev, { struct lp8788_charger *pchg = dev_get_drvdata(dev); char *stime[] = { "400ms", "5min", "10min", "15min", - "20min", "25min", "30min" "No timeout" }; + "20min", "25min", "30min", "No timeout" }; u8 val; lp8788_read_byte(pchg->lp, LP8788_CHG_EOC, &val); From a19718bd0b199c0431579d4cc9cf2b4e894d1831 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Tue, 11 Apr 2017 00:29:44 +0100 Subject: [PATCH 011/396] cpupower: Fix turbo frequency reporting for pre-Sandy Bridge cores commit 4cca0457686e4ee1677d69469e4ddfd94d389a80 upstream. The switch that conditionally sets CPUPOWER_CAP_HAS_TURBO_RATIO and CPUPOWER_CAP_IS_SNB flags is missing a break, so all cores get both flags set and an assumed base clock of 100 MHz for turbo values. Reported-by: GSR Tested-by: GSR References: https://bugs.debian.org/859978 Fixes: 8fb2e440b223 (cpupower: Show Intel turbo ratio support via ...) Signed-off-by: Ben Hutchings Signed-off-by: Rafael J. Wysocki Signed-off-by: Greg Kroah-Hartman --- tools/power/cpupower/utils/helpers/cpuid.c | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/power/cpupower/utils/helpers/cpuid.c b/tools/power/cpupower/utils/helpers/cpuid.c index 93b0aa74ca03..39c2c7d067bb 100644 --- a/tools/power/cpupower/utils/helpers/cpuid.c +++ b/tools/power/cpupower/utils/helpers/cpuid.c @@ -156,6 +156,7 @@ out: */ case 0x2C: /* Westmere EP - Gulftown */ cpu_info->caps |= CPUPOWER_CAP_HAS_TURBO_RATIO; + break; case 0x2A: /* SNB */ case 0x2D: /* SNB Xeon */ case 0x3A: /* IVB */ From 754a2bcfd8b10e70784169b08fca70255d4e5838 Mon Sep 17 00:00:00 2001 From: "Aneesh Kumar K.V" Date: Thu, 8 Dec 2016 09:12:13 +0530 Subject: [PATCH 012/396] powerpc/mm: Fixup wrong LPCR_VRMASD value commit 4ab2537c4204b976e4ca350bbdc193b4649cad28 upstream. In commit a4b349540a26af ("powerpc/mm: Cleanup LPCR defines") we updated LPCR_VRMASD wrongly as below. -#define LPCR_VRMASD (0x1ful << (63-16)) +#define LPCR_VRMASD_SH 47 +#define LPCR_VRMASD (ASM_CONST(1) << LPCR_VRMASD_SH) We initialize the VRMA bits in LPCR to 0x00 in kvm. Hence using a different mask value as above while updating lpcr should not have any impact. This patch updates it to the correct value. Fixes: a4b349540a26 ("powerpc/mm: Cleanup LPCR defines") Reported-by: Ram Pai Signed-off-by: Aneesh Kumar K.V Signed-off-by: Jia He Acked-by: Paul Mackerras Signed-off-by: Michael Ellerman Signed-off-by: Greg Kroah-Hartman --- arch/powerpc/include/asm/reg.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/powerpc/include/asm/reg.h b/arch/powerpc/include/asm/reg.h index 13f5fad21066..e7d9eca53af3 100644 --- a/arch/powerpc/include/asm/reg.h +++ b/arch/powerpc/include/asm/reg.h @@ -337,7 +337,7 @@ #define LPCR_DPFD_SH 52 #define LPCR_DPFD (ASM_CONST(7) << LPCR_DPFD_SH) #define LPCR_VRMASD_SH 47 -#define LPCR_VRMASD (ASM_CONST(1) << LPCR_VRMASD_SH) +#define LPCR_VRMASD (ASM_CONST(0x1f) << LPCR_VRMASD_SH) #define LPCR_VRMA_L ASM_CONST(0x0008000000000000) #define LPCR_VRMA_LP0 ASM_CONST(0x0001000000000000) #define LPCR_VRMA_LP1 ASM_CONST(0x0000800000000000) From 50e027728915ead0551e09ed238e33d2b2784344 Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Tue, 7 Feb 2017 21:01:01 +1100 Subject: [PATCH 013/396] powerpc/powernv: Fix opal_exit tracepoint opcode commit a7e0fb6c2029a780444d09560f739e020d54fe4d upstream. Currently the opal_exit tracepoint usually shows the opcode as 0: -0 [047] d.h. 635.654292: opal_entry: opcode=63 -0 [047] d.h. 635.654296: opal_exit: opcode=0 retval=0 kopald-1209 [019] d... 636.420943: opal_entry: opcode=10 kopald-1209 [019] d... 636.420959: opal_exit: opcode=0 retval=0 This is because we incorrectly load the opcode into r0 before calling __trace_opal_exit(), whereas it expects the opcode in r3 (first function parameter). In fact we are leaving the retval in r3, so opcode and retval will always show the same value. Instead load the opcode into r3, resulting in: -0 [040] d.h. 636.618625: opal_entry: opcode=63 -0 [040] d.h. 636.618627: opal_exit: opcode=63 retval=0 Fixes: c49f63530bb6 ("powernv: Add OPAL tracepoints") Signed-off-by: Michael Ellerman Signed-off-by: Greg Kroah-Hartman --- arch/powerpc/platforms/powernv/opal-wrappers.S | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/powerpc/platforms/powernv/opal-wrappers.S b/arch/powerpc/platforms/powernv/opal-wrappers.S index 44d2d842cee7..483d8c05d11a 100644 --- a/arch/powerpc/platforms/powernv/opal-wrappers.S +++ b/arch/powerpc/platforms/powernv/opal-wrappers.S @@ -146,7 +146,7 @@ opal_tracepoint_entry: opal_tracepoint_return: std r3,STK_REG(R31)(r1) mr r4,r3 - ld r0,STK_REG(R23)(r1) + ld r3,STK_REG(R23)(r1) bl __trace_opal_exit ld r3,STK_REG(R31)(r1) addi r1,r1,STACKFRAMESIZE From b47a6b40655b56bd4e578cb079013b666c9626fd Mon Sep 17 00:00:00 2001 From: Anton Blanchard Date: Fri, 10 Feb 2017 12:16:59 +1100 Subject: [PATCH 014/396] powerpc/ftrace: Fix confusing help text for DISABLE_MPROFILE_KERNEL commit 496e9cb5b2aa2ba303d2bbd08518f9be2219ab4b upstream. The final paragraph of the help text is reversed. We want to enable this option by default, and disable it if the toolchain has a working -mprofile-kernel. Fixes: 8c50b72a3b4f ("powerpc/ftrace: Add Kconfig & Make glue for mprofile-kernel") Signed-off-by: Anton Blanchard Signed-off-by: Michael Ellerman Signed-off-by: Greg Kroah-Hartman --- arch/powerpc/Kconfig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index 65fba4c34cd7..8f01f21e78f1 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig @@ -388,8 +388,8 @@ config DISABLE_MPROFILE_KERNEL be disabled also. If you have a toolchain which supports mprofile-kernel, then you can - enable this. Otherwise leave it disabled. If you're not sure, say - "N". + disable this. Otherwise leave it enabled. If you're not sure, say + "Y". config MPROFILE_KERNEL depends on PPC64 && CPU_LITTLE_ENDIAN From 1641bb14e8be44579b5854f7b89e145d95a291ab Mon Sep 17 00:00:00 2001 From: Andrew Donnellan Date: Tue, 6 Dec 2016 17:27:59 +1100 Subject: [PATCH 015/396] powerpc: Correctly disable latent entropy GCC plugin on prom_init.o commit eac6f8b0c7adb003776dbad9d037ee2fc64f9d62 upstream. Commit 38addce8b600 ("gcc-plugins: Add latent_entropy plugin") excludes certain powerpc early boot code from the latent entropy plugin by adding appropriate CFLAGS. It looks like this was supposed to cover prom_init.o, but ended up saying init.o (which doesn't exist) instead. Fix the typo. Fixes: 38addce8b600 ("gcc-plugins: Add latent_entropy plugin") Signed-off-by: Andrew Donnellan Signed-off-by: Michael Ellerman Signed-off-by: Greg Kroah-Hartman --- arch/powerpc/kernel/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile index 1925341dbb9c..adb52d101133 100644 --- a/arch/powerpc/kernel/Makefile +++ b/arch/powerpc/kernel/Makefile @@ -15,7 +15,7 @@ CFLAGS_btext.o += -fPIC endif CFLAGS_cputable.o += $(DISABLE_LATENT_ENTROPY_PLUGIN) -CFLAGS_init.o += $(DISABLE_LATENT_ENTROPY_PLUGIN) +CFLAGS_prom_init.o += $(DISABLE_LATENT_ENTROPY_PLUGIN) CFLAGS_btext.o += $(DISABLE_LATENT_ENTROPY_PLUGIN) CFLAGS_prom.o += $(DISABLE_LATENT_ENTROPY_PLUGIN) From 89e8bd3add69debe228842e73b1df9925b44eb6e Mon Sep 17 00:00:00 2001 From: Alexander Shishkin Date: Fri, 27 Jan 2017 17:16:43 +0200 Subject: [PATCH 016/396] perf/x86/intel/pt: Add format strings for PTWRITE and power event tracing commit 5443624bedd0d23e112d5f2a919435182875bce9 upstream. Commit: 8ee83b2ab3 ("perf/x86/intel/pt: Add support for PTWRITE and power event tracing") forgot to add format strings to the PT driver. So one could enable these features by setting corresponding bits in the event config, but not by their mnemonic names. This patch adds the format strings. Signed-off-by: Alexander Shishkin Signed-off-by: Peter Zijlstra (Intel) Cc: Arnaldo Carvalho de Melo Cc: Arnaldo Carvalho de Melo Cc: Borislav Petkov Cc: Jiri Olsa Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Stephane Eranian Cc: Thomas Gleixner Cc: Vince Weaver Cc: vince@deater.net Fixes: 8ee83b2ab3 ("perf/x86/intel/pt: Add support for PTWRITE...") Link: http://lkml.kernel.org/r/20170127151644.8585-2-alexander.shishkin@linux.intel.com Signed-off-by: Ingo Molnar Signed-off-by: Greg Kroah-Hartman --- arch/x86/events/intel/pt.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/arch/x86/events/intel/pt.c b/arch/x86/events/intel/pt.c index c5047b8f777b..df60b58691e7 100644 --- a/arch/x86/events/intel/pt.c +++ b/arch/x86/events/intel/pt.c @@ -106,18 +106,24 @@ static struct attribute_group pt_cap_group = { }; PMU_FORMAT_ATTR(cyc, "config:1" ); +PMU_FORMAT_ATTR(pwr_evt, "config:4" ); +PMU_FORMAT_ATTR(fup_on_ptw, "config:5" ); PMU_FORMAT_ATTR(mtc, "config:9" ); PMU_FORMAT_ATTR(tsc, "config:10" ); PMU_FORMAT_ATTR(noretcomp, "config:11" ); +PMU_FORMAT_ATTR(ptw, "config:12" ); PMU_FORMAT_ATTR(mtc_period, "config:14-17" ); PMU_FORMAT_ATTR(cyc_thresh, "config:19-22" ); PMU_FORMAT_ATTR(psb_period, "config:24-27" ); static struct attribute *pt_formats_attr[] = { &format_attr_cyc.attr, + &format_attr_pwr_evt.attr, + &format_attr_fup_on_ptw.attr, &format_attr_mtc.attr, &format_attr_tsc.attr, &format_attr_noretcomp.attr, + &format_attr_ptw.attr, &format_attr_mtc_period.attr, &format_attr_cyc_thresh.attr, &format_attr_psb_period.attr, From d8d6aedd54ce583b31aceef491adb2419f2b4ac6 Mon Sep 17 00:00:00 2001 From: Liam Breck Date: Wed, 18 Jan 2017 09:26:48 -0800 Subject: [PATCH 017/396] power: supply: bq24190_charger: Fix irq trigger to IRQF_TRIGGER_FALLING commit 767eee362fd72bb2ca44cc80419ca4b38c6d8369 upstream. The interrupt signal is TRIGGER_FALLING. This is is specified in the data sheet PIN FUNCTIONS: "The INT pin sends active low, 256us pulse to host to report charger device status and fault." Also the direction can be seen in the data sheet Figure 37 "BQ24190 with D+/D- Detection and USB On-The-Go (OTG)" which shows a 10k pull-up resistor installed for the sample configurations. Fixes: d7bf353fd0aa3 ("bq24190_charger: Add support for TI BQ24190 Battery Charger") Signed-off-by: Liam Breck Acked-by: Mark Greer Acked-by: Tony Lindgren Signed-off-by: Sebastian Reichel Signed-off-by: Greg Kroah-Hartman --- drivers/power/supply/bq24190_charger.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/power/supply/bq24190_charger.c b/drivers/power/supply/bq24190_charger.c index e9584330aeed..21a149f8046e 100644 --- a/drivers/power/supply/bq24190_charger.c +++ b/drivers/power/supply/bq24190_charger.c @@ -1394,7 +1394,7 @@ static int bq24190_probe(struct i2c_client *client, ret = devm_request_threaded_irq(dev, bdi->irq, NULL, bq24190_irq_handler_thread, - IRQF_TRIGGER_RISING | IRQF_ONESHOT, + IRQF_TRIGGER_FALLING | IRQF_ONESHOT, "bq24190-charger", bdi); if (ret < 0) { dev_err(dev, "Can't set up irq handler\n"); From 20e448f2251c0a78421889267b3709758c544ff2 Mon Sep 17 00:00:00 2001 From: Liam Breck Date: Wed, 18 Jan 2017 09:26:49 -0800 Subject: [PATCH 018/396] power: supply: bq24190_charger: Call set_mode_host() on pm_resume() commit e05ad7e0741ce0505e1df157c62b22b95172bb97 upstream. pm_resume() does a register_reset() which clears charger host mode. Fix by calling set_mode_host() after the reset. Fixes: d7bf353fd0aa3 ("bq24190_charger: Add support for TI BQ24190 Battery Charger") Signed-off-by: Liam Breck Acked-by: Mark Greer Acked-by: Tony Lindgren Signed-off-by: Sebastian Reichel Signed-off-by: Greg Kroah-Hartman --- drivers/power/supply/bq24190_charger.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/power/supply/bq24190_charger.c b/drivers/power/supply/bq24190_charger.c index 21a149f8046e..31090cef5a7f 100644 --- a/drivers/power/supply/bq24190_charger.c +++ b/drivers/power/supply/bq24190_charger.c @@ -1494,6 +1494,7 @@ static int bq24190_pm_resume(struct device *dev) pm_runtime_get_sync(bdi->dev); bq24190_register_reset(bdi); + bq24190_set_mode_host(bdi); pm_runtime_put_sync(bdi->dev); /* Things may have changed while suspended so alert upper layer */ From 63e1acc84d28d73107e72482e33dcca152bb5ea4 Mon Sep 17 00:00:00 2001 From: Liam Breck Date: Wed, 18 Jan 2017 09:26:50 -0800 Subject: [PATCH 019/396] power: supply: bq24190_charger: Install irq_handler_thread() at end of probe() commit d62acc5ef0621463446091ebd7a345e06e9ab80c upstream. The device specific data is not fully initialized on request_threaded_irq(). This may cause a crash when the IRQ handler tries to reference them. Fix the issue by installing IRQ handler at the end of the probe. Fixes: d7bf353fd0aa3 ("bq24190_charger: Add support for TI BQ24190 Battery Charger") Signed-off-by: Liam Breck Acked-by: Mark Greer Acked-by: Tony Lindgren Signed-off-by: Sebastian Reichel Signed-off-by: Greg Kroah-Hartman --- drivers/power/supply/bq24190_charger.c | 31 +++++++++++++------------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/drivers/power/supply/bq24190_charger.c b/drivers/power/supply/bq24190_charger.c index 31090cef5a7f..d0afafd7b1cb 100644 --- a/drivers/power/supply/bq24190_charger.c +++ b/drivers/power/supply/bq24190_charger.c @@ -1392,22 +1392,13 @@ static int bq24190_probe(struct i2c_client *client, return -EINVAL; } - ret = devm_request_threaded_irq(dev, bdi->irq, NULL, - bq24190_irq_handler_thread, - IRQF_TRIGGER_FALLING | IRQF_ONESHOT, - "bq24190-charger", bdi); - if (ret < 0) { - dev_err(dev, "Can't set up irq handler\n"); - goto out1; - } - pm_runtime_enable(dev); pm_runtime_resume(dev); ret = bq24190_hw_init(bdi); if (ret < 0) { dev_err(dev, "Hardware init failed\n"); - goto out2; + goto out1; } charger_cfg.drv_data = bdi; @@ -1418,7 +1409,7 @@ static int bq24190_probe(struct i2c_client *client, if (IS_ERR(bdi->charger)) { dev_err(dev, "Can't register charger\n"); ret = PTR_ERR(bdi->charger); - goto out2; + goto out1; } battery_cfg.drv_data = bdi; @@ -1427,24 +1418,34 @@ static int bq24190_probe(struct i2c_client *client, if (IS_ERR(bdi->battery)) { dev_err(dev, "Can't register battery\n"); ret = PTR_ERR(bdi->battery); - goto out3; + goto out2; } ret = bq24190_sysfs_create_group(bdi); if (ret) { dev_err(dev, "Can't create sysfs entries\n"); + goto out3; + } + + ret = devm_request_threaded_irq(dev, bdi->irq, NULL, + bq24190_irq_handler_thread, + IRQF_TRIGGER_FALLING | IRQF_ONESHOT, + "bq24190-charger", bdi); + if (ret < 0) { + dev_err(dev, "Can't set up irq handler\n"); goto out4; } return 0; out4: - power_supply_unregister(bdi->battery); + bq24190_sysfs_remove_group(bdi); out3: - power_supply_unregister(bdi->charger); + power_supply_unregister(bdi->battery); out2: - pm_runtime_disable(dev); + power_supply_unregister(bdi->charger); out1: + pm_runtime_disable(dev); if (bdi->gpio_int) gpio_free(bdi->gpio_int); From 4b7dac0a23b7c416b30962362268e8e55da9eaff Mon Sep 17 00:00:00 2001 From: Liam Breck Date: Wed, 18 Jan 2017 09:26:52 -0800 Subject: [PATCH 020/396] power: supply: bq24190_charger: Call power_supply_changed() for relevant component commit 2d9fee6a42ea170e4378b3363a7ad385d0e67281 upstream. We wrongly get uevents for bq24190-charger and bq24190-battery on every register change. Fix by checking the association with charger and battery before emitting uevent(s). Fixes: d7bf353fd0aa3 ("bq24190_charger: Add support for TI BQ24190 Battery Charger") Signed-off-by: Liam Breck Acked-by: Mark Greer Acked-by: Tony Lindgren Signed-off-by: Sebastian Reichel Signed-off-by: Greg Kroah-Hartman --- drivers/power/supply/bq24190_charger.c | 50 ++++++++++++++------------ 1 file changed, 27 insertions(+), 23 deletions(-) diff --git a/drivers/power/supply/bq24190_charger.c b/drivers/power/supply/bq24190_charger.c index d0afafd7b1cb..94d282286bfd 100644 --- a/drivers/power/supply/bq24190_charger.c +++ b/drivers/power/supply/bq24190_charger.c @@ -159,7 +159,6 @@ struct bq24190_dev_info { unsigned int gpio_int; unsigned int irq; struct mutex f_reg_lock; - bool first_time; bool charger_health_valid; bool battery_health_valid; bool battery_status_valid; @@ -1197,7 +1196,10 @@ static const struct power_supply_desc bq24190_battery_desc = { static irqreturn_t bq24190_irq_handler_thread(int irq, void *data) { struct bq24190_dev_info *bdi = data; - bool alert_userspace = false; + const u8 battery_mask_ss = BQ24190_REG_SS_CHRG_STAT_MASK; + const u8 battery_mask_f = BQ24190_REG_F_BAT_FAULT_MASK + | BQ24190_REG_F_NTC_FAULT_MASK; + bool alert_charger = false, alert_battery = false; u8 ss_reg = 0, f_reg = 0; int ret; @@ -1225,8 +1227,12 @@ static irqreturn_t bq24190_irq_handler_thread(int irq, void *data) ret); } + if ((bdi->ss_reg & battery_mask_ss) != (ss_reg & battery_mask_ss)) + alert_battery = true; + if ((bdi->ss_reg & ~battery_mask_ss) != (ss_reg & ~battery_mask_ss)) + alert_charger = true; + bdi->ss_reg = ss_reg; - alert_userspace = true; } mutex_lock(&bdi->f_reg_lock); @@ -1239,33 +1245,23 @@ static irqreturn_t bq24190_irq_handler_thread(int irq, void *data) } if (f_reg != bdi->f_reg) { + if ((bdi->f_reg & battery_mask_f) != (f_reg & battery_mask_f)) + alert_battery = true; + if ((bdi->f_reg & ~battery_mask_f) != (f_reg & ~battery_mask_f)) + alert_charger = true; + bdi->f_reg = f_reg; bdi->charger_health_valid = true; bdi->battery_health_valid = true; bdi->battery_status_valid = true; - - alert_userspace = true; } mutex_unlock(&bdi->f_reg_lock); - /* - * Sometimes bq24190 gives a steady trickle of interrupts even - * though the watchdog timer is turned off and neither the STATUS - * nor FAULT registers have changed. Weed out these sprurious - * interrupts so userspace isn't alerted for no reason. - * In addition, the chip always generates an interrupt after - * register reset so we should ignore that one (the very first - * interrupt received). - */ - if (alert_userspace) { - if (!bdi->first_time) { - power_supply_changed(bdi->charger); - power_supply_changed(bdi->battery); - } else { - bdi->first_time = false; - } - } + if (alert_charger) + power_supply_changed(bdi->charger); + if (alert_battery) + power_supply_changed(bdi->battery); out: pm_runtime_put_sync(bdi->dev); @@ -1300,6 +1296,10 @@ static int bq24190_hw_init(struct bq24190_dev_info *bdi) goto out; ret = bq24190_set_mode_host(bdi); + if (ret < 0) + goto out; + + ret = bq24190_read(bdi, BQ24190_REG_SS, &bdi->ss_reg); out: pm_runtime_put_sync(bdi->dev); return ret; @@ -1375,7 +1375,8 @@ static int bq24190_probe(struct i2c_client *client, bdi->model = id->driver_data; strncpy(bdi->model_name, id->name, I2C_NAME_SIZE); mutex_init(&bdi->f_reg_lock); - bdi->first_time = true; + bdi->f_reg = 0; + bdi->ss_reg = BQ24190_REG_SS_VBUS_STAT_MASK; /* impossible state */ bdi->charger_health_valid = false; bdi->battery_health_valid = false; bdi->battery_status_valid = false; @@ -1489,6 +1490,8 @@ static int bq24190_pm_resume(struct device *dev) struct i2c_client *client = to_i2c_client(dev); struct bq24190_dev_info *bdi = i2c_get_clientdata(client); + bdi->f_reg = 0; + bdi->ss_reg = BQ24190_REG_SS_VBUS_STAT_MASK; /* impossible state */ bdi->charger_health_valid = false; bdi->battery_health_valid = false; bdi->battery_status_valid = false; @@ -1496,6 +1499,7 @@ static int bq24190_pm_resume(struct device *dev) pm_runtime_get_sync(bdi->dev); bq24190_register_reset(bdi); bq24190_set_mode_host(bdi); + bq24190_read(bdi, BQ24190_REG_SS, &bdi->ss_reg); pm_runtime_put_sync(bdi->dev); /* Things may have changed while suspended so alert upper layer */ From 7f2b4ad9c07af5291ff4b18548160b2816cda849 Mon Sep 17 00:00:00 2001 From: Liam Breck Date: Wed, 18 Jan 2017 09:26:53 -0800 Subject: [PATCH 021/396] power: supply: bq24190_charger: Don't read fault register outside irq_handle_thread() commit 68abfb8015832ddf728b911769659468efaf8bd9 upstream. Caching the fault register after a single I2C read may not keep an accurate value. Fix by doing two reads in irq_handle_thread() and using the cached value elsewhere. If a safety timer fault later clears itself, we apparently don't get an interrupt (INT), however other interrupts would refresh the register cache. From the data sheet: "When a fault occurs, the charger device sends out INT and keeps the fault state in REG09 until the host reads the fault register. Before the host reads REG09 and all the faults are cleared, the charger device would not send any INT upon new faults. In order to read the current fault status, the host has to read REG09 two times consecutively. The 1st reads fault register status from the last read [1] and the 2nd reads the current fault register status." [1] presumably a typo; should be "last fault" Fixes: d7bf353fd0aa3 ("bq24190_charger: Add support for TI BQ24190 Battery Charger") Signed-off-by: Liam Breck Acked-by: Mark Greer Acked-by: Tony Lindgren Signed-off-by: Sebastian Reichel Signed-off-by: Greg Kroah-Hartman --- drivers/power/supply/bq24190_charger.c | 94 ++++++++------------------ 1 file changed, 27 insertions(+), 67 deletions(-) diff --git a/drivers/power/supply/bq24190_charger.c b/drivers/power/supply/bq24190_charger.c index 94d282286bfd..5659b831720f 100644 --- a/drivers/power/supply/bq24190_charger.c +++ b/drivers/power/supply/bq24190_charger.c @@ -144,10 +144,7 @@ * so the first read after a fault returns the latched value and subsequent * reads return the current value. In order to return the fault status * to the user, have the interrupt handler save the reg's value and retrieve - * it in the appropriate health/status routine. Each routine has its own - * flag indicating whether it should use the value stored by the last run - * of the interrupt handler or do an actual reg read. That way each routine - * can report back whatever fault may have occured. + * it in the appropriate health/status routine. */ struct bq24190_dev_info { struct i2c_client *client; @@ -159,9 +156,6 @@ struct bq24190_dev_info { unsigned int gpio_int; unsigned int irq; struct mutex f_reg_lock; - bool charger_health_valid; - bool battery_health_valid; - bool battery_status_valid; u8 f_reg; u8 ss_reg; u8 watchdog; @@ -635,21 +629,11 @@ static int bq24190_charger_get_health(struct bq24190_dev_info *bdi, union power_supply_propval *val) { u8 v; - int health, ret; + int health; mutex_lock(&bdi->f_reg_lock); - - if (bdi->charger_health_valid) { - v = bdi->f_reg; - bdi->charger_health_valid = false; - mutex_unlock(&bdi->f_reg_lock); - } else { - mutex_unlock(&bdi->f_reg_lock); - - ret = bq24190_read(bdi, BQ24190_REG_F, &v); - if (ret < 0) - return ret; - } + v = bdi->f_reg; + mutex_unlock(&bdi->f_reg_lock); if (v & BQ24190_REG_F_BOOST_FAULT_MASK) { /* @@ -936,18 +920,8 @@ static int bq24190_battery_get_status(struct bq24190_dev_info *bdi, int status, ret; mutex_lock(&bdi->f_reg_lock); - - if (bdi->battery_status_valid) { - chrg_fault = bdi->f_reg; - bdi->battery_status_valid = false; - mutex_unlock(&bdi->f_reg_lock); - } else { - mutex_unlock(&bdi->f_reg_lock); - - ret = bq24190_read(bdi, BQ24190_REG_F, &chrg_fault); - if (ret < 0) - return ret; - } + chrg_fault = bdi->f_reg; + mutex_unlock(&bdi->f_reg_lock); chrg_fault &= BQ24190_REG_F_CHRG_FAULT_MASK; chrg_fault >>= BQ24190_REG_F_CHRG_FAULT_SHIFT; @@ -995,21 +969,11 @@ static int bq24190_battery_get_health(struct bq24190_dev_info *bdi, union power_supply_propval *val) { u8 v; - int health, ret; + int health; mutex_lock(&bdi->f_reg_lock); - - if (bdi->battery_health_valid) { - v = bdi->f_reg; - bdi->battery_health_valid = false; - mutex_unlock(&bdi->f_reg_lock); - } else { - mutex_unlock(&bdi->f_reg_lock); - - ret = bq24190_read(bdi, BQ24190_REG_F, &v); - if (ret < 0) - return ret; - } + v = bdi->f_reg; + mutex_unlock(&bdi->f_reg_lock); if (v & BQ24190_REG_F_BAT_FAULT_MASK) { health = POWER_SUPPLY_HEALTH_OVERVOLTAGE; @@ -1201,7 +1165,7 @@ static irqreturn_t bq24190_irq_handler_thread(int irq, void *data) | BQ24190_REG_F_NTC_FAULT_MASK; bool alert_charger = false, alert_battery = false; u8 ss_reg = 0, f_reg = 0; - int ret; + int i, ret; pm_runtime_get_sync(bdi->dev); @@ -1231,33 +1195,35 @@ static irqreturn_t bq24190_irq_handler_thread(int irq, void *data) alert_battery = true; if ((bdi->ss_reg & ~battery_mask_ss) != (ss_reg & ~battery_mask_ss)) alert_charger = true; - bdi->ss_reg = ss_reg; } - mutex_lock(&bdi->f_reg_lock); - - ret = bq24190_read(bdi, BQ24190_REG_F, &f_reg); - if (ret < 0) { - mutex_unlock(&bdi->f_reg_lock); - dev_err(bdi->dev, "Can't read F reg: %d\n", ret); - goto out; - } + i = 0; + do { + ret = bq24190_read(bdi, BQ24190_REG_F, &f_reg); + if (ret < 0) { + dev_err(bdi->dev, "Can't read F reg: %d\n", ret); + goto out; + } + } while (f_reg && ++i < 2); if (f_reg != bdi->f_reg) { + dev_info(bdi->dev, + "Fault: boost %d, charge %d, battery %d, ntc %d\n", + !!(f_reg & BQ24190_REG_F_BOOST_FAULT_MASK), + !!(f_reg & BQ24190_REG_F_CHRG_FAULT_MASK), + !!(f_reg & BQ24190_REG_F_BAT_FAULT_MASK), + !!(f_reg & BQ24190_REG_F_NTC_FAULT_MASK)); + + mutex_lock(&bdi->f_reg_lock); if ((bdi->f_reg & battery_mask_f) != (f_reg & battery_mask_f)) alert_battery = true; if ((bdi->f_reg & ~battery_mask_f) != (f_reg & ~battery_mask_f)) alert_charger = true; - bdi->f_reg = f_reg; - bdi->charger_health_valid = true; - bdi->battery_health_valid = true; - bdi->battery_status_valid = true; + mutex_unlock(&bdi->f_reg_lock); } - mutex_unlock(&bdi->f_reg_lock); - if (alert_charger) power_supply_changed(bdi->charger); if (alert_battery) @@ -1377,9 +1343,6 @@ static int bq24190_probe(struct i2c_client *client, mutex_init(&bdi->f_reg_lock); bdi->f_reg = 0; bdi->ss_reg = BQ24190_REG_SS_VBUS_STAT_MASK; /* impossible state */ - bdi->charger_health_valid = false; - bdi->battery_health_valid = false; - bdi->battery_status_valid = false; i2c_set_clientdata(client, bdi); @@ -1492,9 +1455,6 @@ static int bq24190_pm_resume(struct device *dev) bdi->f_reg = 0; bdi->ss_reg = BQ24190_REG_SS_VBUS_STAT_MASK; /* impossible state */ - bdi->charger_health_valid = false; - bdi->battery_health_valid = false; - bdi->battery_status_valid = false; pm_runtime_get_sync(bdi->dev); bq24190_register_reset(bdi); From e7b34f4a74f607e6ad67763ef47c26b762b8dd34 Mon Sep 17 00:00:00 2001 From: Liam Breck Date: Wed, 18 Jan 2017 09:26:54 -0800 Subject: [PATCH 022/396] power: supply: bq24190_charger: Handle fault before status on interrupt commit ba52e75718784fda1b683ee0bfded72a0b83b047 upstream. Reading both fault and status registers and logging any fault should take priority over handling status register update. Fix by moving the status handling to later in interrupt routine. Fixes: d7bf353fd0aa3 ("bq24190_charger: Add support for TI BQ24190 Battery Charger") Signed-off-by: Liam Breck Acked-by: Mark Greer Acked-by: Tony Lindgren Signed-off-by: Sebastian Reichel Signed-off-by: Greg Kroah-Hartman --- drivers/power/supply/bq24190_charger.c | 46 +++++++++++++------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/drivers/power/supply/bq24190_charger.c b/drivers/power/supply/bq24190_charger.c index 5659b831720f..50171fd3cc6d 100644 --- a/drivers/power/supply/bq24190_charger.c +++ b/drivers/power/supply/bq24190_charger.c @@ -1175,29 +1175,6 @@ static irqreturn_t bq24190_irq_handler_thread(int irq, void *data) goto out; } - if (ss_reg != bdi->ss_reg) { - /* - * The device is in host mode so when PG_STAT goes from 1->0 - * (i.e., power removed) HIZ needs to be disabled. - */ - if ((bdi->ss_reg & BQ24190_REG_SS_PG_STAT_MASK) && - !(ss_reg & BQ24190_REG_SS_PG_STAT_MASK)) { - ret = bq24190_write_mask(bdi, BQ24190_REG_ISC, - BQ24190_REG_ISC_EN_HIZ_MASK, - BQ24190_REG_ISC_EN_HIZ_SHIFT, - 0); - if (ret < 0) - dev_err(bdi->dev, "Can't access ISC reg: %d\n", - ret); - } - - if ((bdi->ss_reg & battery_mask_ss) != (ss_reg & battery_mask_ss)) - alert_battery = true; - if ((bdi->ss_reg & ~battery_mask_ss) != (ss_reg & ~battery_mask_ss)) - alert_charger = true; - bdi->ss_reg = ss_reg; - } - i = 0; do { ret = bq24190_read(bdi, BQ24190_REG_F, &f_reg); @@ -1224,6 +1201,29 @@ static irqreturn_t bq24190_irq_handler_thread(int irq, void *data) mutex_unlock(&bdi->f_reg_lock); } + if (ss_reg != bdi->ss_reg) { + /* + * The device is in host mode so when PG_STAT goes from 1->0 + * (i.e., power removed) HIZ needs to be disabled. + */ + if ((bdi->ss_reg & BQ24190_REG_SS_PG_STAT_MASK) && + !(ss_reg & BQ24190_REG_SS_PG_STAT_MASK)) { + ret = bq24190_write_mask(bdi, BQ24190_REG_ISC, + BQ24190_REG_ISC_EN_HIZ_MASK, + BQ24190_REG_ISC_EN_HIZ_SHIFT, + 0); + if (ret < 0) + dev_err(bdi->dev, "Can't access ISC reg: %d\n", + ret); + } + + if ((bdi->ss_reg & battery_mask_ss) != (ss_reg & battery_mask_ss)) + alert_battery = true; + if ((bdi->ss_reg & ~battery_mask_ss) != (ss_reg & ~battery_mask_ss)) + alert_charger = true; + bdi->ss_reg = ss_reg; + } + if (alert_charger) power_supply_changed(bdi->charger); if (alert_battery) From e33fb57428a11d5285b959ed263a15264cf6585b Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Wed, 25 Jan 2017 14:19:30 +0100 Subject: [PATCH 023/396] arm64: dts: r8a7795: Mark EthernetAVB device node disabled commit 0d1390ff283f6c38595288e7f74da6829896b8b7 upstream. Device nodes representing I/O devices should be marked disabled in the SoC-specific DTS, and overridden by board-specific DTSes where needed. Fixes: a92843c8a6f8c039 ("arm64: dts: r8a7795: add EthernetAVB device node") Signed-off-by: Geert Uytterhoeven Signed-off-by: Simon Horman Signed-off-by: Greg Kroah-Hartman --- arch/arm64/boot/dts/renesas/r8a7795.dtsi | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/boot/dts/renesas/r8a7795.dtsi b/arch/arm64/boot/dts/renesas/r8a7795.dtsi index 8c15040f2540..9536f2013bf4 100644 --- a/arch/arm64/boot/dts/renesas/r8a7795.dtsi +++ b/arch/arm64/boot/dts/renesas/r8a7795.dtsi @@ -553,6 +553,7 @@ phy-mode = "rgmii-id"; #address-cells = <1>; #size-cells = <0>; + status = "disabled"; }; can0: can@e6c30000 { From aadb7e073e813a447ba6c5f5636702f07e8805dd Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Wed, 9 Nov 2016 17:13:57 -0800 Subject: [PATCH 024/396] arm: dts: qcom: Fix ipq board clock rates commit 06dbf468a2c42bf6c327a8eaf11ecb3ea96196f9 upstream. The ipq board has these rates as 25MHz, and not 19.2 and 27. I copy/pasted from other boards that have those rates but forgot to fix the rates here. Fixes: 30fc4212d541 ("arm: dts: qcom: Add more board clocks") Signed-off-by: Stephen Boyd Signed-off-by: Andy Gross Signed-off-by: Greg Kroah-Hartman --- arch/arm/boot/dts/qcom-ipq8064.dtsi | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/boot/dts/qcom-ipq8064.dtsi b/arch/arm/boot/dts/qcom-ipq8064.dtsi index 2e375576ffd0..76f4e8921d58 100644 --- a/arch/arm/boot/dts/qcom-ipq8064.dtsi +++ b/arch/arm/boot/dts/qcom-ipq8064.dtsi @@ -65,13 +65,13 @@ cxo_board { compatible = "fixed-clock"; #clock-cells = <0>; - clock-frequency = <19200000>; + clock-frequency = <25000000>; }; pxo_board { compatible = "fixed-clock"; #clock-cells = <0>; - clock-frequency = <27000000>; + clock-frequency = <25000000>; }; sleep_clk: sleep_clk { From f46fdb8a2611b4ffe9dda5b712ac02add90e930f Mon Sep 17 00:00:00 2001 From: Catalin Marinas Date: Fri, 27 Jan 2017 10:54:12 +0000 Subject: [PATCH 025/396] arm64: Improve detection of user/non-user mappings in set_pte(_at) commit ec663d967b2276448a416406ca59ff247c0c80c5 upstream. Commit cab15ce604e5 ("arm64: Introduce execute-only page access permissions") allowed a valid user PTE to have the PTE_USER bit clear. As a consequence, the pte_valid_not_user() macro in set_pte() was replaced with pte_valid_global() under the assumption that only user pages have the nG bit set. EFI mappings, however, also have the nG bit set and set_pte() wrongly ignores issuing the DSB+ISB. This patch reinstates the pte_valid_not_user() macro and adds the PTE_UXN bit check since all kernel mappings have this bit set. For clarity, pte_exec() is renamed to pte_user_exec() as it only checks for the absence of PTE_UXN. Consequently, the user executable check in set_pte_at() drops the pte_ng() test since pte_user_exec() is sufficient. Fixes: cab15ce604e5 ("arm64: Introduce execute-only page access permissions") Signed-off-by: Catalin Marinas Signed-off-by: Will Deacon Signed-off-by: Greg Kroah-Hartman --- arch/arm64/include/asm/pgtable.h | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/arch/arm64/include/asm/pgtable.h b/arch/arm64/include/asm/pgtable.h index ffbb9a520563..61e214015b38 100644 --- a/arch/arm64/include/asm/pgtable.h +++ b/arch/arm64/include/asm/pgtable.h @@ -71,9 +71,8 @@ extern unsigned long empty_zero_page[PAGE_SIZE / sizeof(unsigned long)]; #define pte_young(pte) (!!(pte_val(pte) & PTE_AF)) #define pte_special(pte) (!!(pte_val(pte) & PTE_SPECIAL)) #define pte_write(pte) (!!(pte_val(pte) & PTE_WRITE)) -#define pte_exec(pte) (!(pte_val(pte) & PTE_UXN)) +#define pte_user_exec(pte) (!(pte_val(pte) & PTE_UXN)) #define pte_cont(pte) (!!(pte_val(pte) & PTE_CONT)) -#define pte_ng(pte) (!!(pte_val(pte) & PTE_NG)) #ifdef CONFIG_ARM64_HW_AFDBM #define pte_hw_dirty(pte) (pte_write(pte) && !(pte_val(pte) & PTE_RDONLY)) @@ -84,8 +83,12 @@ extern unsigned long empty_zero_page[PAGE_SIZE / sizeof(unsigned long)]; #define pte_dirty(pte) (pte_sw_dirty(pte) || pte_hw_dirty(pte)) #define pte_valid(pte) (!!(pte_val(pte) & PTE_VALID)) -#define pte_valid_global(pte) \ - ((pte_val(pte) & (PTE_VALID | PTE_NG)) == PTE_VALID) +/* + * Execute-only user mappings do not have the PTE_USER bit set. All valid + * kernel mappings have the PTE_UXN bit set. + */ +#define pte_valid_not_user(pte) \ + ((pte_val(pte) & (PTE_VALID | PTE_USER | PTE_UXN)) == (PTE_VALID | PTE_UXN)) #define pte_valid_young(pte) \ ((pte_val(pte) & (PTE_VALID | PTE_AF)) == (PTE_VALID | PTE_AF)) @@ -178,7 +181,7 @@ static inline void set_pte(pte_t *ptep, pte_t pte) * Only if the new pte is valid and kernel, otherwise TLB maintenance * or update_mmu_cache() have the necessary barriers. */ - if (pte_valid_global(pte)) { + if (pte_valid_not_user(pte)) { dsb(ishst); isb(); } @@ -212,7 +215,7 @@ static inline void set_pte_at(struct mm_struct *mm, unsigned long addr, pte_val(pte) &= ~PTE_RDONLY; else pte_val(pte) |= PTE_RDONLY; - if (pte_ng(pte) && pte_exec(pte) && !pte_special(pte)) + if (pte_user_exec(pte) && !pte_special(pte)) __sync_icache_dcache(pte, addr); } From 329607b4864d5b55bb3add768787360ad6f9ebfe Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Wed, 25 Jan 2017 23:22:36 +0100 Subject: [PATCH 026/396] leds: ktd2692: avoid harmless maybe-uninitialized warning commit cbe99c538d1776009e8710755bb6e726f7fffa9b upstream. gcc gets confused about the control flow in ktd2692_parse_dt(), causing it to warn about what seems like a potential bug: drivers/leds/leds-ktd2692.c: In function 'ktd2692_probe': drivers/leds/leds-ktd2692.c:244:15: error: '*((void *)&led_cfg+8)' may be used uninitialized in this function [-Werror=maybe-uninitialized] drivers/leds/leds-ktd2692.c:225:7: error: 'led_cfg.flash_max_microamp' may be used uninitialized in this function [-Werror=maybe-uninitialized] drivers/leds/leds-ktd2692.c:232:3: error: 'led_cfg.movie_max_microamp' may be used uninitialized in this function [-Werror=maybe-uninitialized] The code is fine, and slightly reworking it in an equivalent way lets gcc figure that out too, which gets rid of the warning. Fixes: 77e7915b15bb ("leds: ktd2692: Add missing of_node_put") Signed-off-by: Arnd Bergmann Acked-by: Pavel Machek Signed-off-by: Jacek Anaszewski Signed-off-by: Greg Kroah-Hartman --- drivers/leds/leds-ktd2692.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/leds/leds-ktd2692.c b/drivers/leds/leds-ktd2692.c index bf23ba191ad0..45296aaca9da 100644 --- a/drivers/leds/leds-ktd2692.c +++ b/drivers/leds/leds-ktd2692.c @@ -270,15 +270,15 @@ static int ktd2692_parse_dt(struct ktd2692_context *led, struct device *dev, return -ENXIO; led->ctrl_gpio = devm_gpiod_get(dev, "ctrl", GPIOD_ASIS); - if (IS_ERR(led->ctrl_gpio)) { - ret = PTR_ERR(led->ctrl_gpio); + ret = PTR_ERR_OR_ZERO(led->ctrl_gpio); + if (ret) { dev_err(dev, "cannot get ctrl-gpios %d\n", ret); return ret; } led->aux_gpio = devm_gpiod_get(dev, "aux", GPIOD_ASIS); - if (IS_ERR(led->aux_gpio)) { - ret = PTR_ERR(led->aux_gpio); + ret = PTR_ERR_OR_ZERO(led->aux_gpio); + if (ret) { dev_err(dev, "cannot get aux-gpios %d\n", ret); return ret; } From f4bff2c44dc9e366e93734741021bf19d0f5604f Mon Sep 17 00:00:00 2001 From: Jon Mason Date: Wed, 1 Mar 2017 18:02:28 -0500 Subject: [PATCH 027/396] ARM: dts: NSP: GPIO reboot open-source commit acfa28b3649ec07775efaac0c00de2db39d71634 upstream. The libgpio code pre-sets the GPIO values for the gpio-reset in the device tree. This results in the device being reset during bringup. To prevent this pre-setting, use the "open-source" flag in the device tree. Signed-off-by: Jon Mason Fixes: b1aaf88 ("ARM: dts: NSP: Add GPIO reboot method to bcm958625hr DTS file") Fixes: 10baed1 ("ARM: dts: NSP: Add GPIO reboot method to bcm958625xmc DTS file") Fixes: 088e3148 ("ARM: dts: NSP: Add new DT file for bcm958522er") Fixes: e3227c1 ("ARM: dts: NSP: Add new DT file for bcm958525er") Fixes: 2f8bc00 ("ARM: dts: NSP: Add new DT file for bcm958622hr") Fixes: d454c37 ("ARM: dts: NSP: Add new DT file for bcm958623hr") Fixes: f27eacf ("ARM: dts: NSP: Add new DT file for bcm988312hr") Signed-off-by: Florian Fainelli Signed-off-by: Greg Kroah-Hartman --- arch/arm/boot/dts/bcm958522er.dts | 1 + arch/arm/boot/dts/bcm958525er.dts | 1 + arch/arm/boot/dts/bcm958525xmc.dts | 1 + arch/arm/boot/dts/bcm958622hr.dts | 1 + arch/arm/boot/dts/bcm958623hr.dts | 1 + arch/arm/boot/dts/bcm958625hr.dts | 1 + arch/arm/boot/dts/bcm988312hr.dts | 1 + 7 files changed, 7 insertions(+) diff --git a/arch/arm/boot/dts/bcm958522er.dts b/arch/arm/boot/dts/bcm958522er.dts index a21b0fd21f4e..417f65738402 100644 --- a/arch/arm/boot/dts/bcm958522er.dts +++ b/arch/arm/boot/dts/bcm958522er.dts @@ -55,6 +55,7 @@ gpio-restart { compatible = "gpio-restart"; gpios = <&gpioa 15 GPIO_ACTIVE_LOW>; + open-source; priority = <200>; }; }; diff --git a/arch/arm/boot/dts/bcm958525er.dts b/arch/arm/boot/dts/bcm958525er.dts index be7f2f8ecf39..5279b769fdfc 100644 --- a/arch/arm/boot/dts/bcm958525er.dts +++ b/arch/arm/boot/dts/bcm958525er.dts @@ -55,6 +55,7 @@ gpio-restart { compatible = "gpio-restart"; gpios = <&gpioa 15 GPIO_ACTIVE_LOW>; + open-source; priority = <200>; }; }; diff --git a/arch/arm/boot/dts/bcm958525xmc.dts b/arch/arm/boot/dts/bcm958525xmc.dts index 959cde911c3c..872882bd01bc 100644 --- a/arch/arm/boot/dts/bcm958525xmc.dts +++ b/arch/arm/boot/dts/bcm958525xmc.dts @@ -55,6 +55,7 @@ gpio-restart { compatible = "gpio-restart"; gpios = <&gpioa 31 GPIO_ACTIVE_LOW>; + open-source; priority = <200>; }; }; diff --git a/arch/arm/boot/dts/bcm958622hr.dts b/arch/arm/boot/dts/bcm958622hr.dts index ad2aa87dd15a..a340e1d93a58 100644 --- a/arch/arm/boot/dts/bcm958622hr.dts +++ b/arch/arm/boot/dts/bcm958622hr.dts @@ -55,6 +55,7 @@ gpio-restart { compatible = "gpio-restart"; gpios = <&gpioa 15 GPIO_ACTIVE_LOW>; + open-source; priority = <200>; }; }; diff --git a/arch/arm/boot/dts/bcm958623hr.dts b/arch/arm/boot/dts/bcm958623hr.dts index 4ceb8fef8041..226b652ccdc8 100644 --- a/arch/arm/boot/dts/bcm958623hr.dts +++ b/arch/arm/boot/dts/bcm958623hr.dts @@ -55,6 +55,7 @@ gpio-restart { compatible = "gpio-restart"; gpios = <&gpioa 15 GPIO_ACTIVE_LOW>; + open-source; priority = <200>; }; }; diff --git a/arch/arm/boot/dts/bcm958625hr.dts b/arch/arm/boot/dts/bcm958625hr.dts index 442002597063..a1658d0721b8 100644 --- a/arch/arm/boot/dts/bcm958625hr.dts +++ b/arch/arm/boot/dts/bcm958625hr.dts @@ -55,6 +55,7 @@ gpio-restart { compatible = "gpio-restart"; gpios = <&gpioa 15 GPIO_ACTIVE_LOW>; + open-source; priority = <200>; }; }; diff --git a/arch/arm/boot/dts/bcm988312hr.dts b/arch/arm/boot/dts/bcm988312hr.dts index 104afe98a43b..ed05e33d56de 100644 --- a/arch/arm/boot/dts/bcm988312hr.dts +++ b/arch/arm/boot/dts/bcm988312hr.dts @@ -55,6 +55,7 @@ gpio-restart { compatible = "gpio-restart"; gpios = <&gpioa 15 GPIO_ACTIVE_LOW>; + open-source; priority = <200>; }; }; From ebae7681697dada6ca0afce8cbad57f2e96a451a Mon Sep 17 00:00:00 2001 From: Matthijs van Duin Date: Thu, 16 Feb 2017 01:05:04 +0100 Subject: [PATCH 028/396] ARM: OMAP5 / DRA7: Fix HYP mode boot for thumb2 build commit 448c077eeb02240c430db2a2c3bf5285a4c65d66 upstream. 'adr' yields a data-pointer, not a function-pointer. Fixes: 999f934de195 ("ARM: omap5/dra7xx: Enable booting secondary CPU in HYP mode") Signed-off-by: Matthijs van Duin Signed-off-by: Tony Lindgren Signed-off-by: Greg Kroah-Hartman --- arch/arm/mach-omap2/omap-headsmp.S | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/arm/mach-omap2/omap-headsmp.S b/arch/arm/mach-omap2/omap-headsmp.S index fe36ce2734d4..4c6f14cf92a8 100644 --- a/arch/arm/mach-omap2/omap-headsmp.S +++ b/arch/arm/mach-omap2/omap-headsmp.S @@ -17,6 +17,7 @@ #include #include +#include #include "omap44xx.h" @@ -66,7 +67,7 @@ wait_2: ldr r2, =AUX_CORE_BOOT0_PA @ read from AuxCoreBoot0 cmp r0, r4 bne wait_2 ldr r12, =API_HYP_ENTRY - adr r0, hyp_boot + badr r0, hyp_boot smc #0 hyp_boot: b omap_secondary_startup From 1d61da618969a2f51503003075683a72f75f2142 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Sat, 18 Mar 2017 21:53:20 -0700 Subject: [PATCH 029/396] ARM: dts: sun7i: lamobo-r1: Fix CPU port RGMII settings commit 0cdefd5b5485ee6eb3512a75739d09a4090176ed upstream. The CPU port of the BCM53125 is configured with RGMII (no delays) but this should actually be RGMII with transmit delay (rgmii-txid) because STMMAC takes care of inserting the transmitter delay. This fixes occasional packet loss encountered. Fixes: d7b9eaff5f0c ("ARM: dts: sun7i: Add BCM53125 switch nodes to the lamobo-r1 board") Reported-by: Hartmut Knaack Signed-off-by: Florian Fainelli Signed-off-by: Maxime Ripard Signed-off-by: Greg Kroah-Hartman --- arch/arm/boot/dts/sun7i-a20-lamobo-r1.dts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/sun7i-a20-lamobo-r1.dts b/arch/arm/boot/dts/sun7i-a20-lamobo-r1.dts index 73c05dab0a69..e00539ae1b8a 100644 --- a/arch/arm/boot/dts/sun7i-a20-lamobo-r1.dts +++ b/arch/arm/boot/dts/sun7i-a20-lamobo-r1.dts @@ -167,7 +167,7 @@ reg = <8>; label = "cpu"; ethernet = <&gmac>; - phy-mode = "rgmii"; + phy-mode = "rgmii-txid"; fixed-link { speed = <1000>; full-duplex; From 525fda9221a8f78d214e42a6e18d1fd13d73dc11 Mon Sep 17 00:00:00 2001 From: Brian Norris Date: Mon, 9 Jan 2017 15:33:50 -0800 Subject: [PATCH 030/396] mwifiex: debugfs: Fix (sometimes) off-by-1 SSID print commit 6183468a23fc6b6903f8597982017ad2c7fdefcf upstream. Similar to commit fcd2042e8d36 ("mwifiex: printk() overflow with 32-byte SSIDs"), we failed to account for the existence of 32-char SSIDs in our debugfs code. Unlike in that case though, we zeroed out the containing struct first, and I'm pretty sure we're guaranteed to have some padding after the 'ssid.ssid' and 'ssid.ssid_len' fields (the struct is 33 bytes long). So, this is the difference between: # cat /sys/kernel/debug/mwifiex/mlan0/info ... essid="0123456789abcdef0123456789abcdef " ... and the correct output: # cat /sys/kernel/debug/mwifiex/mlan0/info ... essid="0123456789abcdef0123456789abcdef" ... Fixes: 5e6e3a92b9a4 ("wireless: mwifiex: initial commit for Marvell mwifiex driver") Signed-off-by: Brian Norris Signed-off-by: Kalle Valo Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/marvell/mwifiex/debugfs.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/marvell/mwifiex/debugfs.c b/drivers/net/wireless/marvell/mwifiex/debugfs.c index b9284b533294..ae2b69db5994 100644 --- a/drivers/net/wireless/marvell/mwifiex/debugfs.c +++ b/drivers/net/wireless/marvell/mwifiex/debugfs.c @@ -114,7 +114,8 @@ mwifiex_info_read(struct file *file, char __user *ubuf, if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA) { p += sprintf(p, "multicast_count=\"%d\"\n", netdev_mc_count(netdev)); - p += sprintf(p, "essid=\"%s\"\n", info.ssid.ssid); + p += sprintf(p, "essid=\"%.*s\"\n", info.ssid.ssid_len, + info.ssid.ssid); p += sprintf(p, "bssid=\"%pM\"\n", info.bssid); p += sprintf(p, "channel=\"%d\"\n", (int) info.bss_chan); p += sprintf(p, "country_code = \"%s\"\n", info.country_code); From dcdeaa74334299fd98c29703aa82deec3ae6b37a Mon Sep 17 00:00:00 2001 From: Xinming Hu Date: Wed, 11 Jan 2017 21:41:24 +0530 Subject: [PATCH 031/396] mwifiex: remove redundant dma padding in AMSDU commit 5f0a221f59ad6b72202ef9c6e232086de8c336f2 upstream. We already ensure 64 bytes alignment and add padding if required during skb_aggr allocation. Alignment and padding in mwifiex_11n_form_amsdu_txpd() is redundant. We may end up accessing more data than allocated size with this. This patch fixes following issue by removing redundant padding. [ 370.241338] skbuff: skb_over_panic: text:ffffffffc046946a len:3550 put:72 head:ffff880000110000 data:ffff8800001100e4 tail:0xec2 end:0xec0 dev: [ 370.241374] ------------[ cut here ]------------ [ 370.241382] kernel BUG at net/core/skbuff.c:104! 370.244032] Call Trace: [ 370.244041] [] skb_put+0x44/0x45 [ 370.244055] [] mwifiex_11n_aggregate_pkt+0x1e9/0xa50 [mwifiex] [ 370.244067] [] mwifiex_wmm_process_tx+0x44a/0x6b7 [mwifiex] [ 370.244074] [] ? 0xffffffffc0411eb8 [ 370.244084] [] mwifiex_main_process+0x476/0x5a5 [mwifiex] [ 370.244098] [] mwifiex_main_process+0x5a3/0x5a5 [mwifiex] [ 370.244113] [] process_one_work+0x1a4/0x309 [ 370.244123] [] worker_thread+0x20c/0x2ee [ 370.244130] [] ? rescuer_thread+0x383/0x383 [ 370.244136] [] ? rescuer_thread+0x383/0x383 [ 370.244143] [] kthread+0x11c/0x124 [ 370.244150] [] ? kthread_parkme+0x24/0x24 [ 370.244157] [] ret_from_fork+0x3f/0x70 [ 370.244168] [] ? kthread_parkme+0x24/0x24 Fixes: 84b313b35f8158d ("mwifiex: make tx packet 64 byte DMA aligned") Signed-off-by: Xinming Hu Signed-off-by: Amitkumar Karwar Signed-off-by: Kalle Valo Signed-off-by: Greg Kroah-Hartman --- .../net/wireless/marvell/mwifiex/11n_aggr.c | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/drivers/net/wireless/marvell/mwifiex/11n_aggr.c b/drivers/net/wireless/marvell/mwifiex/11n_aggr.c index c47d6366875d..a75013ac84d7 100644 --- a/drivers/net/wireless/marvell/mwifiex/11n_aggr.c +++ b/drivers/net/wireless/marvell/mwifiex/11n_aggr.c @@ -101,13 +101,6 @@ mwifiex_11n_form_amsdu_txpd(struct mwifiex_private *priv, { struct txpd *local_tx_pd; struct mwifiex_txinfo *tx_info = MWIFIEX_SKB_TXCB(skb); - unsigned int pad; - int headroom = (priv->adapter->iface_type == - MWIFIEX_USB) ? 0 : INTF_HEADER_LEN; - - pad = ((void *)skb->data - sizeof(*local_tx_pd) - - headroom - NULL) & (MWIFIEX_DMA_ALIGN_SZ - 1); - skb_push(skb, pad); skb_push(skb, sizeof(*local_tx_pd)); @@ -121,12 +114,10 @@ mwifiex_11n_form_amsdu_txpd(struct mwifiex_private *priv, local_tx_pd->bss_num = priv->bss_num; local_tx_pd->bss_type = priv->bss_type; /* Always zero as the data is followed by struct txpd */ - local_tx_pd->tx_pkt_offset = cpu_to_le16(sizeof(struct txpd) + - pad); + local_tx_pd->tx_pkt_offset = cpu_to_le16(sizeof(struct txpd)); local_tx_pd->tx_pkt_type = cpu_to_le16(PKT_TYPE_AMSDU); local_tx_pd->tx_pkt_length = cpu_to_le16(skb->len - - sizeof(*local_tx_pd) - - pad); + sizeof(*local_tx_pd)); if (tx_info->flags & MWIFIEX_BUF_FLAG_TDLS_PKT) local_tx_pd->flags |= MWIFIEX_TXPD_FLAGS_TDLS_PACKET; @@ -190,7 +181,11 @@ mwifiex_11n_aggregate_pkt(struct mwifiex_private *priv, ra_list_flags); return -1; } - skb_reserve(skb_aggr, MWIFIEX_MIN_DATA_HEADER_LEN); + + /* skb_aggr->data already 64 byte align, just reserve bus interface + * header and txpd. + */ + skb_reserve(skb_aggr, headroom + sizeof(struct txpd)); tx_info_aggr = MWIFIEX_SKB_TXCB(skb_aggr); memset(tx_info_aggr, 0, sizeof(*tx_info_aggr)); From 9291cabe094b2504c4d14c4ed0b77c4edfb538e7 Mon Sep 17 00:00:00 2001 From: Ganapathi Bhat Date: Fri, 3 Feb 2017 18:30:22 +0530 Subject: [PATCH 032/396] mwifiex: Avoid skipping WEP key deletion for AP commit a5b60de6972decc6b50a39abb376077c3c3621c8 upstream. This patch fixes the issue specific to AP. AP is started with WEP security and external station is connected to it. Data path works in this case. Now if AP is restarted with WPA/WPA2 security, station is able to connect but ping fails. Driver skips the deletion of WEP keys if interface type is AP. Removing that redundant check resolves the issue. Fixes: e57f1734d87a ("mwifiex: add key material v2 support") Signed-off-by: Ganapathi Bhat Signed-off-by: Amitkumar Karwar Signed-off-by: Kalle Valo Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/marvell/mwifiex/sta_ioctl.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/net/wireless/marvell/mwifiex/sta_ioctl.c b/drivers/net/wireless/marvell/mwifiex/sta_ioctl.c index 644f3a248741..1532ac9cee0b 100644 --- a/drivers/net/wireless/marvell/mwifiex/sta_ioctl.c +++ b/drivers/net/wireless/marvell/mwifiex/sta_ioctl.c @@ -1159,8 +1159,6 @@ int mwifiex_set_encode(struct mwifiex_private *priv, struct key_params *kp, encrypt_key.is_rx_seq_valid = true; } } else { - if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_UAP) - return 0; encrypt_key.key_disable = true; if (mac_addr) memcpy(encrypt_key.mac_addr, mac_addr, ETH_ALEN); From d0a8075ffe0572819e19aac9110e1913cef754d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=BCrg=20Billeter?= Date: Mon, 10 Oct 2016 18:30:00 +0200 Subject: [PATCH 033/396] iwlwifi: fix MODULE_FIRMWARE for 6030 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit d8320d75b59ecdc1b8e60ac793d3a54d84333a18 upstream. IWL6000G2B_UCODE_API_MAX is not defined. ucode_api_max of IWL_DEVICE_6030 uses IWL6000G2_UCODE_API_MAX. Use this also for MODULE_FIRMWARE. Fixes: 9d9b21d1b616 ("iwlwifi: remove IWL_*_UCODE_API_OK") Signed-off-by: Jürg Billeter Signed-off-by: Luca Coelho Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/intel/iwlwifi/iwl-6000.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-6000.c b/drivers/net/wireless/intel/iwlwifi/iwl-6000.c index 0b9f6a7bc834..39335b7b0c16 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-6000.c @@ -371,4 +371,4 @@ const struct iwl_cfg iwl6000_3agn_cfg = { MODULE_FIRMWARE(IWL6000_MODULE_FIRMWARE(IWL6000_UCODE_API_MAX)); MODULE_FIRMWARE(IWL6050_MODULE_FIRMWARE(IWL6050_UCODE_API_MAX)); MODULE_FIRMWARE(IWL6005_MODULE_FIRMWARE(IWL6000G2_UCODE_API_MAX)); -MODULE_FIRMWARE(IWL6030_MODULE_FIRMWARE(IWL6000G2B_UCODE_API_MAX)); +MODULE_FIRMWARE(IWL6030_MODULE_FIRMWARE(IWL6000G2_UCODE_API_MAX)); From 45dad03aca5596cc8c1ba71b7644b5859377b823 Mon Sep 17 00:00:00 2001 From: Luca Coelho Date: Fri, 7 Oct 2016 15:16:26 +0300 Subject: [PATCH 034/396] iwlwifi: mvm: don't restart HW if suspend fails with unified image commit bac453ab3745eaa64137ea6e77e009b45954f0ae upstream. For unified images, we shouldn't restart the HW if suspend fails. The only reason for restarting the HW with non-unified images is to go back to the D0 image. Fixes: 23ae61282b88 ("iwlwifi: mvm: Do not switch to D3 image on suspend") Signed-off-by: Luca Coelho Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/intel/iwlwifi/mvm/d3.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/d3.c b/drivers/net/wireless/intel/iwlwifi/mvm/d3.c index b88e2048ae0b..207d8ae1e116 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/d3.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/d3.c @@ -1262,12 +1262,15 @@ static int __iwl_mvm_suspend(struct ieee80211_hw *hw, iwl_trans_d3_suspend(mvm->trans, test, !unified_image); out: if (ret < 0) { - iwl_mvm_ref(mvm, IWL_MVM_REF_UCODE_DOWN); - if (mvm->restart_fw > 0) { - mvm->restart_fw--; - ieee80211_restart_hw(mvm->hw); - } iwl_mvm_free_nd(mvm); + + if (!unified_image) { + iwl_mvm_ref(mvm, IWL_MVM_REF_UCODE_DOWN); + if (mvm->restart_fw > 0) { + mvm->restart_fw--; + ieee80211_restart_hw(mvm->hw); + } + } } out_noreset: mutex_unlock(&mvm->mutex); From 948634492b4069a208934a64781b85cfa70e198b Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 2 Dec 2016 09:57:40 +0100 Subject: [PATCH 035/396] iwlwifi: mvm: overwrite skb info later commit bd05a5bd6b11d7fd26a668de83c5cb996de05f8f upstream. We don't really need clear the skb's status area nor store the dev_cmd into it until we really commit to the frame by handing it to the transport - defer those operations until just before we do that. This doesn't entirely fix the bug with frames not getting sent out after having been deferred due to DQA, because it doesn't restore the info->driver_data[0] place that was already set to zero (or another value) by the A-MSDU logic. Fixes: 24afba7690e4 ("iwlwifi: mvm: support bss dynamic alloc/dealloc of queues") Signed-off-by: Johannes Berg Signed-off-by: Luca Coelho Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/intel/iwlwifi/mvm/tx.c | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c index 66957ac12ca4..95b2ec1517e5 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c @@ -459,7 +459,6 @@ iwl_mvm_set_tx_params(struct iwl_mvm *mvm, struct sk_buff *skb, struct ieee80211_sta *sta, u8 sta_id) { struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; - struct ieee80211_tx_info *skb_info = IEEE80211_SKB_CB(skb); struct iwl_device_cmd *dev_cmd; struct iwl_tx_cmd *tx_cmd; @@ -479,12 +478,18 @@ iwl_mvm_set_tx_params(struct iwl_mvm *mvm, struct sk_buff *skb, iwl_mvm_set_tx_cmd_rate(mvm, tx_cmd, info, sta, hdr->frame_control); + return dev_cmd; +} + +static void iwl_mvm_skb_prepare_status(struct sk_buff *skb, + struct iwl_device_cmd *cmd) +{ + struct ieee80211_tx_info *skb_info = IEEE80211_SKB_CB(skb); + memset(&skb_info->status, 0, sizeof(skb_info->status)); memset(skb_info->driver_data, 0, sizeof(skb_info->driver_data)); - skb_info->driver_data[1] = dev_cmd; - - return dev_cmd; + skb_info->driver_data[1] = cmd; } static int iwl_mvm_get_ctrl_vif_queue(struct iwl_mvm *mvm, @@ -598,6 +603,9 @@ int iwl_mvm_tx_skb_non_sta(struct iwl_mvm *mvm, struct sk_buff *skb) if (!dev_cmd) return -1; + /* From now on, we cannot access info->control */ + iwl_mvm_skb_prepare_status(skb, dev_cmd); + tx_cmd = (struct iwl_tx_cmd *)dev_cmd->payload; /* Copy MAC header from skb into command buffer */ @@ -908,7 +916,6 @@ static int iwl_mvm_tx_mpdu(struct iwl_mvm *mvm, struct sk_buff *skb, goto drop; tx_cmd = (struct iwl_tx_cmd *)dev_cmd->payload; - /* From now on, we cannot access info->control */ /* * we handle that entirely ourselves -- for uAPSD the firmware @@ -1015,6 +1022,9 @@ static int iwl_mvm_tx_mpdu(struct iwl_mvm *mvm, struct sk_buff *skb, IWL_DEBUG_TX(mvm, "TX to [%d|%d] Q:%d - seq: 0x%x\n", mvmsta->sta_id, tid, txq_id, IEEE80211_SEQ_TO_SN(seq_number)); + /* From now on, we cannot access info->control */ + iwl_mvm_skb_prepare_status(skb, dev_cmd); + if (iwl_trans_tx(mvm->trans, skb, dev_cmd, txq_id)) goto drop_unlock_sta; From 9c8655c0a86099a45669f5ed38120584a9e13b11 Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Sat, 7 Jan 2017 20:11:47 +0200 Subject: [PATCH 036/396] iwlwifi: pcie: don't increment / decrement a bool commit 04fa3e680b4dd2fdd11d0152fb9b6067e7aac140 upstream. David reported that the code I added uses the decrement and increment operator on a boolean variable. Fix that. Fixes: 0cd58eaab148 ("iwlwifi: pcie: allow the op_mode to block the tx queues") Reported-by: David Binderman Signed-off-by: Emmanuel Grumbach Signed-off-by: Luca Coelho Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/intel/iwlwifi/pcie/internal.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/internal.h b/drivers/net/wireless/intel/iwlwifi/pcie/internal.h index cac6d99012b3..e3cede979751 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/internal.h +++ b/drivers/net/wireless/intel/iwlwifi/pcie/internal.h @@ -279,7 +279,7 @@ struct iwl_txq { bool frozen; u8 active; bool ampdu; - bool block; + int block; unsigned long wd_timeout; struct sk_buff_head overflow_q; From 562c868d94a87af8595541c5b9f2f8944e9bf850 Mon Sep 17 00:00:00 2001 From: Kirtika Ruchandani Date: Tue, 8 Nov 2016 21:50:48 -0800 Subject: [PATCH 037/396] iwlwifi: pcie: trans: Remove unused 'shift_param' MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 3ce4a03852d6dd3fd28c2fb2ee9f89bb9ccf9a9b upstream. shift_param is defined and set in iwl_pcie_load_cpu_sections but not used. Fix this to avoid -Wunused-but-set-variable warning. The code using it turned into dead code with commit dcab8ecd5617 ("iwlwifi: mvm: support ucode load for family_8000 B0 only") which added a separate function iwl_pcie_load_given_ucode_8000 (then 8000b) for IWL_DEVICE_FAMILY_8000. Commit 76f8c0e17edc ("iwlwifi: pcie: remove dead code") removed the dead code but left shift_param as is. iwlwifi/pcie/trans.c: In function ‘iwl_pcie_load_cpu_sections’: iwlwifi/pcie/trans.c:871:6: warning: variable ‘shift_param’ set but not used [-Wunused-but-set-variable] Fixes: dcab8ecd5617 ("iwlwifi: mvm: support ucode load for family_8000 B0 only") Fixes: 76f8c0e17edc ("iwlwifi: pcie: remove dead code") Signed-off-by: Kirtika Ruchandani Cc: Sara Sharon Cc: Luca Coelho Cc: Liad Kaufman Cc: Emmanuel Grumbach [removed some unnecessary braces] Signed-off-by: Luca Coelho Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/intel/iwlwifi/pcie/trans.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c index ae95533e587d..9ba45b089a5d 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c @@ -868,17 +868,13 @@ static int iwl_pcie_load_cpu_sections(struct iwl_trans *trans, int cpu, int *first_ucode_section) { - int shift_param; int i, ret = 0; u32 last_read_idx = 0; - if (cpu == 1) { - shift_param = 0; + if (cpu == 1) *first_ucode_section = 0; - } else { - shift_param = 16; + else (*first_ucode_section)++; - } for (i = *first_ucode_section; i < IWL_UCODE_SECTION_MAX; i++) { last_read_idx = i; From 20a9de99a0da9021e9d00db635bab47eeb3ca978 Mon Sep 17 00:00:00 2001 From: Sara Sharon Date: Wed, 7 Dec 2016 12:22:11 +0200 Subject: [PATCH 038/396] iwlwifi: pcie: fix the set of DMA memory mask commit 2c6262b754f3c3338cb40b23880a3ac1f4693b25 upstream. Our 9000 device supports 64 bit DMA address for RX only, and not for TX. Setting DMA mask to 64 for the whole device is erroneous - we can do it only for a000 devices where device is capable of both RX & TX DMA with 64 bit address space. Fixes: 96a6497bc3ed ("iwlwifi: pcie: add 9000 series multi queue rx DMA support") Signed-off-by: Sara Sharon Signed-off-by: Luca Coelho Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/intel/iwlwifi/pcie/trans.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c index 9ba45b089a5d..10ef44e8ecd5 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c @@ -2929,16 +2929,12 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev, PCIE_LINK_STATE_CLKPM); } - if (cfg->mq_rx_supported) - addr_size = 64; - else - addr_size = 36; - if (cfg->use_tfh) { + addr_size = 64; trans_pcie->max_tbs = IWL_TFH_NUM_TBS; trans_pcie->tfd_size = sizeof(struct iwl_tfh_tfd); - } else { + addr_size = 36; trans_pcie->max_tbs = IWL_NUM_OF_TBS; trans_pcie->tfd_size = sizeof(struct iwl_tfd); } From a6fe39262c518c105f7003dca5eb5ae45b72713e Mon Sep 17 00:00:00 2001 From: Sara Sharon Date: Tue, 3 Jan 2017 21:03:35 +0200 Subject: [PATCH 039/396] iwlwifi: mvm: fix reorder timer re-arming commit 5351f9ab254c30d41659924265f1ecd7b4758d9e upstream. When NSSN is behind the reorder buffer due to timeout the reorder timer isn't getting re-armed until NSSN catches up. Fix it. Fixes: 0690405fef29 ("iwlwifi: mvm: add reorder timeout per frame") Signed-off-by: Sara Sharon Signed-off-by: Luca Coelho Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c b/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c index 6c802cee900c..a481eb41f693 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c @@ -409,7 +409,7 @@ static void iwl_mvm_release_frames(struct iwl_mvm *mvm, /* ignore nssn smaller than head sn - this can happen due to timeout */ if (iwl_mvm_is_sn_less(nssn, ssn, reorder_buf->buf_size)) - return; + goto set_timer; while (iwl_mvm_is_sn_less(ssn, nssn, reorder_buf->buf_size)) { int index = ssn % reorder_buf->buf_size; @@ -432,6 +432,7 @@ static void iwl_mvm_release_frames(struct iwl_mvm *mvm, } reorder_buf->head_sn = nssn; +set_timer: if (reorder_buf->num_stored && !reorder_buf->removed) { u16 index = reorder_buf->head_sn % reorder_buf->buf_size; From 04dd401a5145da42a040a622bac2eb9a96c01308 Mon Sep 17 00:00:00 2001 From: Beni Lev Date: Thu, 17 Nov 2016 14:03:17 +0200 Subject: [PATCH 040/396] iwlwifi: mvm: Use aux queue for offchannel frames in dqa commit 6574dc943fc32a2fce69fab14891abca7eecb67c upstream. Since offchannel activity doesn't always require a BSS, e.g. ANQP sessions, offchannel frames should not use the BSS queue, because it might not be initialized. Use the auxilary queue instead Fixes: e3118ad74d7e ("iwlwifi: mvm: support tdls in dqa mode") Signed-off-by: Beni Lev Signed-off-by: Luca Coelho Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/intel/iwlwifi/mvm/tx.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c index 95b2ec1517e5..e129661e4d99 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c @@ -568,9 +568,10 @@ int iwl_mvm_tx_skb_non_sta(struct iwl_mvm *mvm, struct sk_buff *skb) * (this is not possible for unicast packets as a TLDS discovery * response are sent without a station entry); otherwise use the * AUX station. - * In DQA mode, if vif is of type STATION and frames are not multicast, - * they should be sent from the BSS queue. For example, TDLS setup - * frames should be sent on this queue, as they go through the AP. + * In DQA mode, if vif is of type STATION and frames are not multicast + * or offchannel, they should be sent from the BSS queue. + * For example, TDLS setup frames should be sent on this queue, + * as they go through the AP. */ sta_id = mvm->aux_sta.sta_id; if (info.control.vif) { @@ -592,7 +593,8 @@ int iwl_mvm_tx_skb_non_sta(struct iwl_mvm *mvm, struct sk_buff *skb) if (ap_sta_id != IWL_MVM_STATION_COUNT) sta_id = ap_sta_id; } else if (iwl_mvm_is_dqa_supported(mvm) && - info.control.vif->type == NL80211_IFTYPE_STATION) { + info.control.vif->type == NL80211_IFTYPE_STATION && + queue != mvm->aux_queue) { queue = IWL_MVM_DQA_BSS_CLIENT_QUEUE; } } From 48aa5ec292f3eba8f22a5b4d3a8eee123e7680dc Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 2 Dec 2016 10:04:49 +0100 Subject: [PATCH 041/396] iwlwifi: mvm/pcie: adjust A-MSDU tx_cmd length in PCIe commit 05e5a7e58d3f8f597ebe6f78aaa13a2656b78239 upstream. Instead of setting the tx_cmd length in the mvm code, which is complicated by the fact that DQA may want to temporarily store the SKB on the side, adjust the length in the PCIe code which also knows about this since it's responsible for duplicating all those headers that are account for in this code. As the PCIe code already relies on the tx_cmd->len field, this doesn't really introduce any new dependencies. To make this possible we need to move the memcpy() of the TX command until after it was updated. This does even simplify the code though, since the PCIe code already does a lot of manipulations to build A-MSDUs correctly and changing the length becomes a simple operation to see how much was added/removed, rather than predicting it. Fixes: 24afba7690e4 ("iwlwifi: mvm: support bss dynamic alloc/dealloc of queues") Signed-off-by: Johannes Berg Signed-off-by: Luca Coelho Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/intel/iwlwifi/mvm/tx.c | 38 ++------------------ drivers/net/wireless/intel/iwlwifi/pcie/tx.c | 23 +++++++++--- 2 files changed, 22 insertions(+), 39 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c index e129661e4d99..1d116c06cd1c 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c @@ -202,7 +202,6 @@ void iwl_mvm_set_tx_cmd(struct iwl_mvm *mvm, struct sk_buff *skb, struct iwl_tx_cmd *tx_cmd, struct ieee80211_tx_info *info, u8 sta_id) { - struct ieee80211_tx_info *skb_info = IEEE80211_SKB_CB(skb); struct ieee80211_hdr *hdr = (void *)skb->data; __le16 fc = hdr->frame_control; u32 tx_flags = le32_to_cpu(tx_cmd->tx_flags); @@ -284,9 +283,8 @@ void iwl_mvm_set_tx_cmd(struct iwl_mvm *mvm, struct sk_buff *skb, tx_flags |= TX_CMD_FLG_WRITE_TX_POWER; tx_cmd->tx_flags = cpu_to_le32(tx_flags); - /* Total # bytes to be transmitted */ - tx_cmd->len = cpu_to_le16((u16)skb->len + - (uintptr_t)skb_info->driver_data[0]); + /* Total # bytes to be transmitted - PCIe code will adjust for A-MSDU */ + tx_cmd->len = cpu_to_le16((u16)skb->len); tx_cmd->life_time = cpu_to_le32(TX_CMD_LIFE_TIME_INFINITE); tx_cmd->sta_id = sta_id; @@ -555,9 +553,6 @@ int iwl_mvm_tx_skb_non_sta(struct iwl_mvm *mvm, struct sk_buff *skb) info.hw_queue != info.control.vif->cab_queue))) return -1; - /* This holds the amsdu headers length */ - skb_info->driver_data[0] = (void *)(uintptr_t)0; - queue = info.hw_queue; /* @@ -644,7 +639,7 @@ static int iwl_mvm_tx_tso(struct iwl_mvm *mvm, struct sk_buff *skb, unsigned int num_subframes, tcp_payload_len, subf_len, max_amsdu_len; bool ipv4 = (skb->protocol == htons(ETH_P_IP)); u16 ip_base_id = ipv4 ? ntohs(ip_hdr(skb)->id) : 0; - u16 amsdu_add, snap_ip_tcp, pad, i = 0; + u16 snap_ip_tcp, pad, i = 0; unsigned int dbg_max_amsdu_len; netdev_features_t netdev_features = NETIF_F_CSUM_MASK | NETIF_F_SG; u8 *qc, tid, txf; @@ -746,21 +741,6 @@ static int iwl_mvm_tx_tso(struct iwl_mvm *mvm, struct sk_buff *skb, /* This skb fits in one single A-MSDU */ if (num_subframes * mss >= tcp_payload_len) { - struct ieee80211_tx_info *skb_info = IEEE80211_SKB_CB(skb); - - /* - * Compute the length of all the data added for the A-MSDU. - * This will be used to compute the length to write in the TX - * command. We have: SNAP + IP + TCP for n -1 subframes and - * ETH header for n subframes. Note that the original skb - * already had one set of SNAP / IP / TCP headers. - */ - num_subframes = DIV_ROUND_UP(tcp_payload_len, mss); - amsdu_add = num_subframes * sizeof(struct ethhdr) + - (num_subframes - 1) * (snap_ip_tcp + pad); - /* This holds the amsdu headers length */ - skb_info->driver_data[0] = (void *)(uintptr_t)amsdu_add; - __skb_queue_tail(mpdus_skb, skb); return 0; } @@ -799,14 +779,6 @@ segment: ip_hdr(tmp)->id = htons(ip_base_id + i * num_subframes); if (tcp_payload_len > mss) { - struct ieee80211_tx_info *skb_info = - IEEE80211_SKB_CB(tmp); - - num_subframes = DIV_ROUND_UP(tcp_payload_len, mss); - amsdu_add = num_subframes * sizeof(struct ethhdr) + - (num_subframes - 1) * (snap_ip_tcp + pad); - skb_info->driver_data[0] = - (void *)(uintptr_t)amsdu_add; skb_shinfo(tmp)->gso_size = mss; } else { qc = ieee80211_get_qos_ctl((void *)tmp->data); @@ -1052,7 +1024,6 @@ int iwl_mvm_tx_skb(struct iwl_mvm *mvm, struct sk_buff *skb, struct ieee80211_sta *sta) { struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta); - struct ieee80211_tx_info *skb_info = IEEE80211_SKB_CB(skb); struct ieee80211_tx_info info; struct sk_buff_head mpdus_skbs; unsigned int payload_len; @@ -1066,9 +1037,6 @@ int iwl_mvm_tx_skb(struct iwl_mvm *mvm, struct sk_buff *skb, memcpy(&info, skb->cb, sizeof(info)); - /* This holds the amsdu headers length */ - skb_info->driver_data[0] = (void *)(uintptr_t)0; - if (!skb_is_gso(skb)) return iwl_mvm_tx_mpdu(mvm, skb, &info, sta); diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/tx.c b/drivers/net/wireless/intel/iwlwifi/pcie/tx.c index 5f840f16f40b..e1bfc9522cbe 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/tx.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/tx.c @@ -2096,6 +2096,7 @@ static int iwl_fill_data_tbs_amsdu(struct iwl_trans *trans, struct sk_buff *skb, struct iwl_cmd_meta *out_meta, struct iwl_device_cmd *dev_cmd, u16 tb1_len) { + struct iwl_tx_cmd *tx_cmd = (void *)dev_cmd->payload; struct iwl_trans_pcie *trans_pcie = txq->trans_pcie; struct ieee80211_hdr *hdr = (void *)skb->data; unsigned int snap_ip_tcp_hdrlen, ip_hdrlen, total_len, hdr_room; @@ -2145,6 +2146,13 @@ static int iwl_fill_data_tbs_amsdu(struct iwl_trans *trans, struct sk_buff *skb, */ skb_pull(skb, hdr_len + iv_len); + /* + * Remove the length of all the headers that we don't actually + * have in the MPDU by themselves, but that we duplicate into + * all the different MSDUs inside the A-MSDU. + */ + le16_add_cpu(&tx_cmd->len, -snap_ip_tcp_hdrlen); + tso_start(skb, &tso); while (total_len) { @@ -2155,7 +2163,7 @@ static int iwl_fill_data_tbs_amsdu(struct iwl_trans *trans, struct sk_buff *skb, unsigned int hdr_tb_len; dma_addr_t hdr_tb_phys; struct tcphdr *tcph; - u8 *iph; + u8 *iph, *subf_hdrs_start = hdr_page->pos; total_len -= data_left; @@ -2216,6 +2224,8 @@ static int iwl_fill_data_tbs_amsdu(struct iwl_trans *trans, struct sk_buff *skb, hdr_tb_len, false); trace_iwlwifi_dev_tx_tso_chunk(trans->dev, start_hdr, hdr_tb_len); + /* add this subframe's headers' length to the tx_cmd */ + le16_add_cpu(&tx_cmd->len, hdr_page->pos - subf_hdrs_start); /* prepare the start_hdr for the next subframe */ start_hdr = hdr_page->pos; @@ -2408,9 +2418,10 @@ int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb, tb1_len = len; } - /* The first TB points to bi-directional DMA data */ - memcpy(&txq->first_tb_bufs[txq->write_ptr], &dev_cmd->hdr, - IWL_FIRST_TB_SIZE); + /* + * The first TB points to bi-directional DMA data, we'll + * memcpy the data into it later. + */ iwl_pcie_txq_build_tfd(trans, txq, tb0_phys, IWL_FIRST_TB_SIZE, true); @@ -2434,6 +2445,10 @@ int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb, goto out_err; } + /* building the A-MSDU might have changed this data, so memcpy it now */ + memcpy(&txq->first_tb_bufs[txq->write_ptr], &dev_cmd->hdr, + IWL_FIRST_TB_SIZE); + tfd = iwl_pcie_get_tfd(trans_pcie, txq, txq->write_ptr); /* Set up entry for this TFD in Tx byte-count array */ iwl_pcie_txq_update_byte_cnt_tbl(trans, txq, le16_to_cpu(tx_cmd->len), From 4d6f2ac95bc55bd78c415006a67c03e787d79989 Mon Sep 17 00:00:00 2001 From: Sara Sharon Date: Wed, 7 Dec 2016 15:04:37 +0200 Subject: [PATCH 042/396] iwlwifi: mvm: fix pending frame counter calculation commit 94c3e614df2117626fccfac8f821c66e30556384 upstream. In DQA mode the check whether to decrement the pending frames counter relies on the tid status and not on the txq id. This may result in an inconsistent state of the pending frames counter in case frame is queued on a non aggregation queue but with this TID, and will be followed by a failure to remove the station and later on SYSASSERT 0x3421 when trying to remove the MAC. Such frames are for example bar and qos NDPs. Fix it by aligning the condition of incrementing the counter with the condition of decrementing it - rely on TID state for DQA mode. Also, avoid internal error like this affecting station removal for DQA mode - since we can know for sure it is an internal error. Fixes: cf961e16620f ("iwlwifi: mvm: support dqa-mode agg on non-shared queue") Signed-off-by: Sara Sharon Signed-off-by: Luca Coelho Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/intel/iwlwifi/mvm/sta.c | 31 +++++++++++++------- drivers/net/wireless/intel/iwlwifi/mvm/tx.c | 5 +++- 2 files changed, 24 insertions(+), 12 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c index 52de3c6d760c..e64aeb4a2204 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c @@ -1466,6 +1466,7 @@ int iwl_mvm_rm_sta(struct iwl_mvm *mvm, { struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); struct iwl_mvm_sta *mvm_sta = iwl_mvm_sta_from_mac80211(sta); + u8 sta_id = mvm_sta->sta_id; int ret; lockdep_assert_held(&mvm->mutex); @@ -1474,7 +1475,7 @@ int iwl_mvm_rm_sta(struct iwl_mvm *mvm, kfree(mvm_sta->dup_data); if ((vif->type == NL80211_IFTYPE_STATION && - mvmvif->ap_sta_id == mvm_sta->sta_id) || + mvmvif->ap_sta_id == sta_id) || iwl_mvm_is_dqa_supported(mvm)){ ret = iwl_mvm_drain_sta(mvm, mvm_sta, true); if (ret) @@ -1496,6 +1497,15 @@ int iwl_mvm_rm_sta(struct iwl_mvm *mvm, iwl_mvm_disable_sta_queues(mvm, vif, mvm_sta); + /* + * If pending_frames is set at this point - it must be + * driver internal logic error, since queues are empty + * and removed successuly. + * warn on it but set it to 0 anyway to avoid station + * not being removed later in the function + */ + WARN_ON(atomic_xchg(&mvm->pending_frames[sta_id], 0)); + /* * If no traffic has gone through the reserved TXQ - it * is still marked as IWL_MVM_QUEUE_RESERVED, and @@ -1506,7 +1516,7 @@ int iwl_mvm_rm_sta(struct iwl_mvm *mvm, if (WARN((*status != IWL_MVM_QUEUE_RESERVED) && (*status != IWL_MVM_QUEUE_FREE), "sta_id %d reserved txq %d status %d", - mvm_sta->sta_id, reserved_txq, *status)) { + sta_id, reserved_txq, *status)) { spin_unlock_bh(&mvm->queue_info_lock); return -EINVAL; } @@ -1516,7 +1526,7 @@ int iwl_mvm_rm_sta(struct iwl_mvm *mvm, } if (vif->type == NL80211_IFTYPE_STATION && - mvmvif->ap_sta_id == mvm_sta->sta_id) { + mvmvif->ap_sta_id == sta_id) { /* if associated - we can't remove the AP STA now */ if (vif->bss_conf.assoc) return ret; @@ -1525,7 +1535,7 @@ int iwl_mvm_rm_sta(struct iwl_mvm *mvm, mvmvif->ap_sta_id = IWL_MVM_STATION_COUNT; /* clear d0i3_ap_sta_id if no longer relevant */ - if (mvm->d0i3_ap_sta_id == mvm_sta->sta_id) + if (mvm->d0i3_ap_sta_id == sta_id) mvm->d0i3_ap_sta_id = IWL_MVM_STATION_COUNT; } } @@ -1534,7 +1544,7 @@ int iwl_mvm_rm_sta(struct iwl_mvm *mvm, * This shouldn't happen - the TDLS channel switch should be canceled * before the STA is removed. */ - if (WARN_ON_ONCE(mvm->tdls_cs.peer.sta_id == mvm_sta->sta_id)) { + if (WARN_ON_ONCE(mvm->tdls_cs.peer.sta_id == sta_id)) { mvm->tdls_cs.peer.sta_id = IWL_MVM_STATION_COUNT; cancel_delayed_work(&mvm->tdls_cs.dwork); } @@ -1544,21 +1554,20 @@ int iwl_mvm_rm_sta(struct iwl_mvm *mvm, * calls the drain worker. */ spin_lock_bh(&mvm_sta->lock); + /* * There are frames pending on the AC queues for this station. * We need to wait until all the frames are drained... */ - if (atomic_read(&mvm->pending_frames[mvm_sta->sta_id])) { - rcu_assign_pointer(mvm->fw_id_to_mac_id[mvm_sta->sta_id], + if (atomic_read(&mvm->pending_frames[sta_id])) { + rcu_assign_pointer(mvm->fw_id_to_mac_id[sta_id], ERR_PTR(-EBUSY)); spin_unlock_bh(&mvm_sta->lock); /* disable TDLS sta queues on drain complete */ if (sta->tdls) { - mvm->tfd_drained[mvm_sta->sta_id] = - mvm_sta->tfd_queue_msk; - IWL_DEBUG_TDLS(mvm, "Draining TDLS sta %d\n", - mvm_sta->sta_id); + mvm->tfd_drained[sta_id] = mvm_sta->tfd_queue_msk; + IWL_DEBUG_TDLS(mvm, "Draining TDLS sta %d\n", sta_id); } ret = iwl_mvm_drain_sta(mvm, mvm_sta, true); diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c index 1d116c06cd1c..4cb839ae3e22 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c @@ -1008,7 +1008,10 @@ static int iwl_mvm_tx_mpdu(struct iwl_mvm *mvm, struct sk_buff *skb, spin_unlock(&mvmsta->lock); /* Increase pending frames count if this isn't AMPDU */ - if (!is_ampdu) + if ((iwl_mvm_is_dqa_supported(mvm) && + mvmsta->tid_data[tx_cmd->tid_tspec].state != IWL_AGG_ON && + mvmsta->tid_data[tx_cmd->tid_tspec].state != IWL_AGG_STARTING) || + (!iwl_mvm_is_dqa_supported(mvm) && !is_ampdu)) atomic_inc(&mvm->pending_frames[mvmsta->sta_id]); return 0; From 495f91630205b441ead5461580703575c18324ec Mon Sep 17 00:00:00 2001 From: Sara Sharon Date: Sun, 1 Jan 2017 18:42:23 +0200 Subject: [PATCH 043/396] iwlwifi: mvm: fix references to first_agg_queue in DQA mode commit c56108b58ab870892277940a1def0d6b153f3e26 upstream. In DQA mode, first_agg_queue is initialized to IWL_MVM_DQA_MIN_DATA_QUEUE. This causes two bugs in the tx response flow: 1. When TX fails, we set IEEE80211_TX_STAT_AMPDU_NO_BACK regardless if we actually have aggregation open on the queue. This causes mac80211 to send a BAR frame even though there is no aggregation open. Fix that by simply checking the AMPDU flag that is set on by mac80211 for AMPDU packets. 2. When reclaiming frames in aggregation mode, we reclaim based on scheduler ssn and not the SN. The reason is that scheduler ssn may be ahead of SN due to a hole in the BA window that was filled. However, if we have aggregations open on IWL_MVM_DQA_BSS_CLIENT_QUEUE the reclaim flow will still go to the code of non-aggregation instead of the aggregation code since IWL_MVM_DQA_BSS_CLIENT_QUEUE is smaller than IWL_MVM_DQA_MIN_DATA_QUEUE, although it is a valid aggregation queue. Fix that by always using the aggregation reclaim code by default in DQA mode (currently it is implicitly used by default for all queues except the reserved BSS queue). Fixes: cf961e16620f ("iwlwifi: mvm: support dqa-mode agg on non-shared queue") Signed-off-by: Sara Sharon Signed-off-by: Luca Coelho Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/intel/iwlwifi/mvm/tx.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c index 4cb839ae3e22..0556d139b719 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c @@ -1278,8 +1278,6 @@ static void iwl_mvm_rx_tx_cmd_single(struct iwl_mvm *mvm, memset(&info->status, 0, sizeof(info->status)); - info->flags &= ~IEEE80211_TX_CTL_AMPDU; - /* inform mac80211 about what happened with the frame */ switch (status & TX_STATUS_MSK) { case TX_STATUS_SUCCESS: @@ -1302,10 +1300,11 @@ static void iwl_mvm_rx_tx_cmd_single(struct iwl_mvm *mvm, (void *)(uintptr_t)le32_to_cpu(tx_resp->initial_rate); /* Single frame failure in an AMPDU queue => send BAR */ - if (txq_id >= mvm->first_agg_queue && + if (info->flags & IEEE80211_TX_CTL_AMPDU && !(info->flags & IEEE80211_TX_STAT_ACK) && !(info->flags & IEEE80211_TX_STAT_TX_FILTERED)) info->flags |= IEEE80211_TX_STAT_AMPDU_NO_BACK; + info->flags &= ~IEEE80211_TX_CTL_AMPDU; /* W/A FW bug: seq_ctl is wrong when the status isn't success */ if (status != TX_STATUS_SUCCESS) { @@ -1340,7 +1339,7 @@ static void iwl_mvm_rx_tx_cmd_single(struct iwl_mvm *mvm, ieee80211_tx_status(mvm->hw, skb); } - if (txq_id >= mvm->first_agg_queue) { + if (iwl_mvm_is_dqa_supported(mvm) || txq_id >= mvm->first_agg_queue) { /* If this is an aggregation queue, we use the ssn since: * ssn = wifi seq_num % 256. * The seq_ctl is the sequence control of the packet to which From 1fb264cf7d54d8ac69adb72aec26933c1a7b8895 Mon Sep 17 00:00:00 2001 From: Sara Sharon Date: Wed, 30 Nov 2016 16:49:11 +0200 Subject: [PATCH 044/396] iwlwifi: mvm: synchronize firmware DMA paging memory commit 4b70f07686d75d1eb5d956812cc810944e0b29b2 upstream. When driver needs to access the contents of a streaming DMA buffer without unmapping it it should call dma_sync_single_for_cpu(). Once the call has been made, the CPU "owns" the DMA buffer and can work with it as needed. Before the device accesses the buffer, however, ownership should be transferred back to it with dma_sync_single_for_device(). Both calls weren't performed by the driver, resulting with odd paging errors on some platforms. Fix it. Fixes: a6c4fb4441f4 ("iwlwifi: mvm: Add FW paging mechanism for the UMAC on PCI") Signed-off-by: Sara Sharon Signed-off-by: Luca Coelho Signed-off-by: Greg Kroah-Hartman --- .../net/wireless/intel/iwlwifi/mvm/fw-dbg.c | 4 ++++ drivers/net/wireless/intel/iwlwifi/mvm/fw.c | 23 ++++++++++++++++--- 2 files changed, 24 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw-dbg.c b/drivers/net/wireless/intel/iwlwifi/mvm/fw-dbg.c index d89d0a1fd34e..700d244df34b 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/fw-dbg.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw-dbg.c @@ -784,12 +784,16 @@ void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm) struct iwl_fw_error_dump_paging *paging; struct page *pages = mvm->fw_paging_db[i].fw_paging_block; + dma_addr_t addr = mvm->fw_paging_db[i].fw_paging_phys; dump_data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_PAGING); dump_data->len = cpu_to_le32(sizeof(*paging) + PAGING_BLOCK_SIZE); paging = (void *)dump_data->data; paging->index = cpu_to_le32(i); + dma_sync_single_for_cpu(mvm->trans->dev, addr, + PAGING_BLOCK_SIZE, + DMA_BIDIRECTIONAL); memcpy(paging->data, page_address(pages), PAGING_BLOCK_SIZE); dump_data = iwl_fw_error_next_data(dump_data); diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c index 872066317fa5..2ec3a91a0f6b 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c @@ -214,6 +214,10 @@ static int iwl_fill_paging_mem(struct iwl_mvm *mvm, const struct fw_img *image) memcpy(page_address(mvm->fw_paging_db[0].fw_paging_block), image->sec[sec_idx].data, mvm->fw_paging_db[0].fw_paging_size); + dma_sync_single_for_device(mvm->trans->dev, + mvm->fw_paging_db[0].fw_paging_phys, + mvm->fw_paging_db[0].fw_paging_size, + DMA_BIDIRECTIONAL); IWL_DEBUG_FW(mvm, "Paging: copied %d CSS bytes to first block\n", @@ -228,9 +232,16 @@ static int iwl_fill_paging_mem(struct iwl_mvm *mvm, const struct fw_img *image) * loop stop at num_of_paging_blk since that last block is not full. */ for (idx = 1; idx < mvm->num_of_paging_blk; idx++) { - memcpy(page_address(mvm->fw_paging_db[idx].fw_paging_block), + struct iwl_fw_paging *block = &mvm->fw_paging_db[idx]; + + memcpy(page_address(block->fw_paging_block), image->sec[sec_idx].data + offset, - mvm->fw_paging_db[idx].fw_paging_size); + block->fw_paging_size); + dma_sync_single_for_device(mvm->trans->dev, + block->fw_paging_phys, + block->fw_paging_size, + DMA_BIDIRECTIONAL); + IWL_DEBUG_FW(mvm, "Paging: copied %d paging bytes to block %d\n", @@ -242,9 +253,15 @@ static int iwl_fill_paging_mem(struct iwl_mvm *mvm, const struct fw_img *image) /* copy the last paging block */ if (mvm->num_of_pages_in_last_blk > 0) { - memcpy(page_address(mvm->fw_paging_db[idx].fw_paging_block), + struct iwl_fw_paging *block = &mvm->fw_paging_db[idx]; + + memcpy(page_address(block->fw_paging_block), image->sec[sec_idx].data + offset, FW_PAGING_SIZE * mvm->num_of_pages_in_last_blk); + dma_sync_single_for_device(mvm->trans->dev, + block->fw_paging_phys, + block->fw_paging_size, + DMA_BIDIRECTIONAL); IWL_DEBUG_FW(mvm, "Paging: copied %d pages in the last block %d\n", From 3b141e2965a7bcb7b0699ad2aa30c2fb5f0ef303 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Thu, 23 Mar 2017 13:40:00 +0300 Subject: [PATCH 045/396] iwlwifi: mvm: writing zero bytes to debugfs causes a crash commit 251fe09f13bfb54c1ede66ee8bf8ddd0061c4f7c upstream. This is a static analysis fix. The warning is: drivers/net/wireless/intel/iwlwifi/mvm/fw-dbg.c:912 iwl_mvm_fw_dbg_collect() warn: integer overflows 'sizeof(*desc) + len' I guess this code is supposed to take a NUL character, but if we write zero bytes then it tries to write -1 characters and crashes. Fixes: c91b865cb14d ("iwlwifi: mvm: support description for user triggered fw dbg collection") Signed-off-by: Dan Carpenter Signed-off-by: Luca Coelho Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c index 7b7d2a146e30..0bda91ffc608 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c @@ -1056,6 +1056,8 @@ static ssize_t iwl_dbgfs_fw_dbg_collect_write(struct iwl_mvm *mvm, if (ret) return ret; + if (count == 0) + return 0; iwl_mvm_fw_dbg_collect(mvm, FW_DBG_TRIGGER_USER, buf, (count - 1), NULL); From 5ed26fad2d083ada4da3591f8039a6e47983c756 Mon Sep 17 00:00:00 2001 From: Ruslan Ruslichenko Date: Tue, 17 Jan 2017 16:13:52 +0200 Subject: [PATCH 046/396] x86/ioapic: Restore IO-APIC irq_chip retrigger callback commit a9b4f08770b415f30f2fb0f8329a370c8f554aa3 upstream. commit d32932d02e18 removed the irq_retrigger callback from the IO-APIC chip and did not add it to the new IO-APIC-IR irq chip. There is no harm because the interrupts are resent in software when the retrigger callback is NULL, but it's less efficient. So restore them. [ tglx: Massaged changelog ] Fixes: d32932d02e18 ("x86/irq: Convert IOAPIC to use hierarchical irqdomain interfaces") Signed-off-by: Ruslan Ruslichenko Cc: xe-linux-external@cisco.com Link: http://lkml.kernel.org/r/1484662432-13580-1-git-send-email-rruslich@cisco.com Signed-off-by: Thomas Gleixner Signed-off-by: Greg Kroah-Hartman --- arch/x86/kernel/apic/io_apic.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c index d1e25564b3c1..7249f1500bcb 100644 --- a/arch/x86/kernel/apic/io_apic.c +++ b/arch/x86/kernel/apic/io_apic.c @@ -1876,6 +1876,7 @@ static struct irq_chip ioapic_chip __read_mostly = { .irq_ack = irq_chip_ack_parent, .irq_eoi = ioapic_ack_level, .irq_set_affinity = ioapic_set_affinity, + .irq_retrigger = irq_chip_retrigger_hierarchy, .flags = IRQCHIP_SKIP_SET_WAKE, }; @@ -1887,6 +1888,7 @@ static struct irq_chip ioapic_ir_chip __read_mostly = { .irq_ack = irq_chip_ack_parent, .irq_eoi = ioapic_ir_ack_level, .irq_set_affinity = ioapic_set_affinity, + .irq_retrigger = irq_chip_retrigger_hierarchy, .flags = IRQCHIP_SKIP_SET_WAKE, }; From 56e524a8c305a7eff1a8898e1e4e765904dfb42a Mon Sep 17 00:00:00 2001 From: Nikola Pajkovsky Date: Tue, 15 Nov 2016 09:47:49 +0100 Subject: [PATCH 047/396] x86/pci-calgary: Fix iommu_free() comparison of unsigned expression >= 0 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 68dee8e2f2cacc54d038394e70d22411dee89da2 upstream. commit 8fd524b355da ("x86: Kill bad_dma_address variable") has killed bad_dma_address variable and used instead of macro DMA_ERROR_CODE which is always zero. Since dma_addr is unsigned, the statement dma_addr >= DMA_ERROR_CODE is always true, and not needed. arch/x86/kernel/pci-calgary_64.c: In function ‘iommu_free’: arch/x86/kernel/pci-calgary_64.c:299:2: warning: comparison of unsigned expression >= 0 is always true [-Wtype-limits] if (unlikely((dma_addr >= DMA_ERROR_CODE) && (dma_addr < badend))) { Fixes: 8fd524b355da ("x86: Kill bad_dma_address variable") Signed-off-by: Nikola Pajkovsky Cc: iommu@lists.linux-foundation.org Cc: Jon Mason Cc: Muli Ben-Yehuda Link: http://lkml.kernel.org/r/7612c0f9dd7c1290407dbf8e809def922006920b.1479161177.git.npajkovsky@suse.cz Signed-off-by: Thomas Gleixner Signed-off-by: Greg Kroah-Hartman --- arch/x86/kernel/pci-calgary_64.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/kernel/pci-calgary_64.c b/arch/x86/kernel/pci-calgary_64.c index 5d400ba1349d..d47517941bbc 100644 --- a/arch/x86/kernel/pci-calgary_64.c +++ b/arch/x86/kernel/pci-calgary_64.c @@ -296,7 +296,7 @@ static void iommu_free(struct iommu_table *tbl, dma_addr_t dma_addr, /* were we called with bad_dma_address? */ badend = DMA_ERROR_CODE + (EMERGENCY_PAGES * PAGE_SIZE); - if (unlikely((dma_addr >= DMA_ERROR_CODE) && (dma_addr < badend))) { + if (unlikely(dma_addr < badend)) { WARN(1, KERN_ERR "Calgary: driver tried unmapping bad DMA " "address 0x%Lx\n", dma_addr); return; From 1f0c69cfb2ada893fdb82d96e26911e5c98c69d1 Mon Sep 17 00:00:00 2001 From: Dave Hansen Date: Wed, 1 Feb 2017 14:56:29 -0800 Subject: [PATCH 048/396] x86/mpx: Re-add MPX to selftests Makefile commit e64d5fbe56259c94df504af8ce804cfc6a022adb upstream. Ingo pointed out that the MPX tests were no longer in the selftests Makefile. It appears that I shot myself in the foot on this one and accidentally removed them when I added the pkeys tests, probably from bungling a merge conflict. Reported-by: Ingo Molnar Signed-off-by: Dave Hansen Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Fixes: 5f23f6d082a9 ("x86/pkeys: Add self-tests") Link: http://lkml.kernel.org/r/20170201225629.C3070852@viggo.jf.intel.com Signed-off-by: Ingo Molnar Signed-off-by: Greg Kroah-Hartman --- tools/testing/selftests/x86/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/testing/selftests/x86/Makefile b/tools/testing/selftests/x86/Makefile index a89f80a5b711..6300c1a41ff6 100644 --- a/tools/testing/selftests/x86/Makefile +++ b/tools/testing/selftests/x86/Makefile @@ -5,7 +5,7 @@ include ../lib.mk .PHONY: all all_32 all_64 warn_32bit_failure clean TARGETS_C_BOTHBITS := single_step_syscall sysret_ss_attrs syscall_nt ptrace_syscall test_mremap_vdso \ - check_initial_reg_state sigreturn ldt_gdt iopl \ + check_initial_reg_state sigreturn ldt_gdt iopl mpx-mini-test \ protection_keys TARGETS_C_32BIT_ONLY := entry_from_vm86 syscall_arg_fault test_syscall_vdso unwind_vdso \ test_FCMOV test_FCOMI test_FISTTP \ From c9f6172239042b3fcc8239aee4f67172c91c7681 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Mon, 23 Jan 2017 12:07:41 -0600 Subject: [PATCH 049/396] clk: Make x86/ conditional on CONFIG_COMMON_CLK commit f35b6542c3ac3f28056d298348a81f7d56d3a041 upstream. Fix Makefile for x86 support, dependency on CONFIG_COMMON_CLK was not explicit Fixes: 701190fd7419 ('clk: x86: add support for Lynxpoint LPSS clocks') Signed-off-by: Pierre-Louis Bossart Acked-by: Andy Shevchenko Signed-off-by: Stephen Boyd Signed-off-by: Greg Kroah-Hartman --- drivers/clk/Makefile | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile index 925081ec14c0..42042c0a936c 100644 --- a/drivers/clk/Makefile +++ b/drivers/clk/Makefile @@ -87,6 +87,8 @@ obj-y += ti/ obj-$(CONFIG_CLK_UNIPHIER) += uniphier/ obj-$(CONFIG_ARCH_U8500) += ux500/ obj-$(CONFIG_COMMON_CLK_VERSATILE) += versatile/ +ifeq ($(CONFIG_COMMON_CLK), y) obj-$(CONFIG_X86) += x86/ +endif obj-$(CONFIG_ARCH_ZX) += zte/ obj-$(CONFIG_ARCH_ZYNQ) += zynq/ From 1eae95d4bc031553562c970b49e895bfc60860f5 Mon Sep 17 00:00:00 2001 From: Masami Hiramatsu Date: Wed, 1 Mar 2017 01:23:24 +0900 Subject: [PATCH 050/396] kprobes/x86: Fix kernel panic when certain exception-handling addresses are probed commit 75013fb16f8484898eaa8d0b08fed942d790f029 upstream. Fix to the exception table entry check by using probed address instead of the address of copied instruction. This bug may cause unexpected kernel panic if user probe an address where an exception can happen which should be fixup by __ex_table (e.g. copy_from_user.) Unless user puts a kprobe on such address, this doesn't cause any problem. This bug has been introduced years ago, by commit: 464846888d9a ("x86/kprobes: Fix a bug which can modify kernel code permanently"). Signed-off-by: Masami Hiramatsu Cc: Borislav Petkov Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Fixes: 464846888d9a ("x86/kprobes: Fix a bug which can modify kernel code permanently") Link: http://lkml.kernel.org/r/148829899399.28855.12581062400757221722.stgit@devbox Signed-off-by: Ingo Molnar Signed-off-by: Greg Kroah-Hartman --- arch/x86/kernel/kprobes/common.h | 2 +- arch/x86/kernel/kprobes/core.c | 6 +++--- arch/x86/kernel/kprobes/opt.c | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/arch/x86/kernel/kprobes/common.h b/arch/x86/kernel/kprobes/common.h index c6ee63f927ab..d688826e5736 100644 --- a/arch/x86/kernel/kprobes/common.h +++ b/arch/x86/kernel/kprobes/common.h @@ -67,7 +67,7 @@ #endif /* Ensure if the instruction can be boostable */ -extern int can_boost(kprobe_opcode_t *instruction); +extern int can_boost(kprobe_opcode_t *instruction, void *addr); /* Recover instruction if given address is probed */ extern unsigned long recover_probed_instruction(kprobe_opcode_t *buf, unsigned long addr); diff --git a/arch/x86/kernel/kprobes/core.c b/arch/x86/kernel/kprobes/core.c index d9d8d16b69db..b55d07b9d530 100644 --- a/arch/x86/kernel/kprobes/core.c +++ b/arch/x86/kernel/kprobes/core.c @@ -166,12 +166,12 @@ NOKPROBE_SYMBOL(skip_prefixes); * Returns non-zero if opcode is boostable. * RIP relative instructions are adjusted at copying time in 64 bits mode */ -int can_boost(kprobe_opcode_t *opcodes) +int can_boost(kprobe_opcode_t *opcodes, void *addr) { kprobe_opcode_t opcode; kprobe_opcode_t *orig_opcodes = opcodes; - if (search_exception_tables((unsigned long)opcodes)) + if (search_exception_tables((unsigned long)addr)) return 0; /* Page fault may occur on this address. */ retry: @@ -416,7 +416,7 @@ static int arch_copy_kprobe(struct kprobe *p) * __copy_instruction can modify the displacement of the instruction, * but it doesn't affect boostable check. */ - if (can_boost(p->ainsn.insn)) + if (can_boost(p->ainsn.insn, p->addr)) p->ainsn.boostable = 0; else p->ainsn.boostable = -1; diff --git a/arch/x86/kernel/kprobes/opt.c b/arch/x86/kernel/kprobes/opt.c index 3bb4c5f021f6..4d74f7386a61 100644 --- a/arch/x86/kernel/kprobes/opt.c +++ b/arch/x86/kernel/kprobes/opt.c @@ -178,7 +178,7 @@ static int copy_optimized_instructions(u8 *dest, u8 *src) while (len < RELATIVEJUMP_SIZE) { ret = __copy_instruction(dest + len, src + len); - if (!ret || !can_boost(dest + len)) + if (!ret || !can_boost(dest + len, src + len)) return -EINVAL; len += ret; } From b6cd52a0eeaf4e5dfc73d962b8a62211afa3f1bd Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Sun, 12 Mar 2017 17:07:44 +0200 Subject: [PATCH 051/396] x86/platform/intel-mid: Correct MSI IRQ line for watchdog device commit 80354c29025833acd72ddac1ffa21c6cb50128cd upstream. The interrupt line used for the watchdog is 12, according to the official Intel Edison BSP code. And indeed after fixing it we start getting an interrupt and thus the watchdog starts working again: [ 191.699951] Kernel panic - not syncing: Kernel Watchdog Signed-off-by: Andy Shevchenko Cc: Borislav Petkov Cc: David Cohen Cc: H. Peter Anvin Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Fixes: 78a3bb9e408b ("x86: intel-mid: add watchdog platform code for Merrifield") Link: http://lkml.kernel.org/r/20170312150744.45493-1-andriy.shevchenko@linux.intel.com Signed-off-by: Ingo Molnar Signed-off-by: Greg Kroah-Hartman --- arch/x86/platform/intel-mid/device_libs/platform_mrfld_wdt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/platform/intel-mid/device_libs/platform_mrfld_wdt.c b/arch/x86/platform/intel-mid/device_libs/platform_mrfld_wdt.c index 3f1f1c77d090..10bad1e55fcc 100644 --- a/arch/x86/platform/intel-mid/device_libs/platform_mrfld_wdt.c +++ b/arch/x86/platform/intel-mid/device_libs/platform_mrfld_wdt.c @@ -19,7 +19,7 @@ #include #include -#define TANGIER_EXT_TIMER0_MSI 15 +#define TANGIER_EXT_TIMER0_MSI 12 static struct platform_device wdt_dev = { .name = "intel_mid_wdt", From 39058adebbb1fa2e7eedbfa138f4abf978fede77 Mon Sep 17 00:00:00 2001 From: Jim Mattson Date: Tue, 20 Dec 2016 16:34:50 -0800 Subject: [PATCH 052/396] Revert "KVM: nested VMX: disable perf cpuid reporting" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 0b4c208d443ba2af82b4c70f99ca8df31e9a0020 upstream. This reverts commit bc6134942dbbf31c25e9bd7c876be5da81c9e1ce. A CPUID instruction executed in VMX non-root mode always causes a VM-exit, regardless of the leaf being queried. Fixes: bc6134942dbb ("KVM: nested VMX: disable perf cpuid reporting") Signed-off-by: Jim Mattson [The issue solved by bc6134942dbb has been resolved with ff651cb613b4 ("KVM: nVMX: Add nested msr load/restore algorithm").] Signed-off-by: Radim Krčmář Signed-off-by: Greg Kroah-Hartman --- arch/x86/kvm/cpuid.c | 6 ------ arch/x86/kvm/vmx.c | 2 -- 2 files changed, 8 deletions(-) diff --git a/arch/x86/kvm/cpuid.c b/arch/x86/kvm/cpuid.c index afa7bbb596cd..967e459ff1e6 100644 --- a/arch/x86/kvm/cpuid.c +++ b/arch/x86/kvm/cpuid.c @@ -846,12 +846,6 @@ void kvm_cpuid(struct kvm_vcpu *vcpu, u32 *eax, u32 *ebx, u32 *ecx, u32 *edx) if (!best) best = check_cpuid_limit(vcpu, function, index); - /* - * Perfmon not yet supported for L2 guest. - */ - if (is_guest_mode(vcpu) && function == 0xa) - best = NULL; - if (best) { *eax = best->eax; *ebx = best->ebx; diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index 43b55ef82bac..980133079949 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c @@ -8051,8 +8051,6 @@ static bool nested_vmx_exit_handled(struct kvm_vcpu *vcpu) case EXIT_REASON_TASK_SWITCH: return true; case EXIT_REASON_CPUID: - if (kvm_register_read(vcpu, VCPU_REGS_RAX) == 0xa) - return false; return true; case EXIT_REASON_HLT: return nested_cpu_has(vmcs12, CPU_BASED_HLT_EXITING); From 560a979735f49f0ba2fa28117acdfb861f05cd97 Mon Sep 17 00:00:00 2001 From: Ladi Prosek Date: Tue, 4 Apr 2017 14:18:53 +0200 Subject: [PATCH 053/396] KVM: nVMX: initialize PML fields in vmcs02 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 1fb883bb827ee8efc1cc9ea0154f953f8a219d38 upstream. L2 was running with uninitialized PML fields which led to incomplete dirty bitmap logging. This manifested as all kinds of subtle erratic behavior of the nested guest. Fixes: 843e4330573c ("KVM: VMX: Add PML support in VMX") Signed-off-by: Ladi Prosek Signed-off-by: Radim Krčmář Signed-off-by: Greg Kroah-Hartman --- arch/x86/kvm/vmx.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index 980133079949..0ffec8a8074f 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c @@ -10071,6 +10071,18 @@ static void prepare_vmcs02(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12) } + if (enable_pml) { + /* + * Conceptually we want to copy the PML address and index from + * vmcs01 here, and then back to vmcs01 on nested vmexit. But, + * since we always flush the log on each vmexit, this happens + * to be equivalent to simply resetting the fields in vmcs02. + */ + ASSERT(vmx->pml_pg); + vmcs_write64(PML_ADDRESS, page_to_phys(vmx->pml_pg)); + vmcs_write16(GUEST_PML_INDEX, PML_ENTITY_NUM - 1); + } + if (nested_cpu_has_ept(vmcs12)) { kvm_mmu_unload(vcpu); nested_ept_init_mmu_context(vcpu); From d0ee36354f7749ff6034d78c28b6fc2e20c3d968 Mon Sep 17 00:00:00 2001 From: Ladi Prosek Date: Fri, 31 Mar 2017 10:19:26 +0200 Subject: [PATCH 054/396] KVM: nVMX: do not leak PML full vmexit to L1 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit ab007cc94ff9d82f5a8db8363b3becbd946e58cf upstream. The PML feature is not exposed to guests so we should not be forwarding the vmexit either. This commit fixes BSOD 0x20001 (HYPERVISOR_ERROR) when running Hyper-V enabled Windows Server 2016 in L1 on hardware that supports PML. Fixes: 843e4330573c ("KVM: VMX: Add PML support in VMX") Signed-off-by: Ladi Prosek Reviewed-by: David Hildenbrand Signed-off-by: Radim Krčmář Signed-off-by: Greg Kroah-Hartman --- arch/x86/kvm/vmx.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index 0ffec8a8074f..89b98e07211f 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c @@ -8135,6 +8135,9 @@ static bool nested_vmx_exit_handled(struct kvm_vcpu *vcpu) return nested_cpu_has2(vmcs12, SECONDARY_EXEC_XSAVES); case EXIT_REASON_PREEMPTION_TIMER: return false; + case EXIT_REASON_PML_FULL: + /* We don't expose PML support to L1. */ + return false; default: return true; } From 30643b5ac754eb985110e5ebad33664f1d88a32f Mon Sep 17 00:00:00 2001 From: Nicholas Mc Guire Date: Mon, 23 Jan 2017 15:00:40 -0800 Subject: [PATCH 055/396] usb: dwc2: host: use msleep() for long delay commit d3fe81d2ccc41b355e494413115c0c7c18426fa1 upstream. ulseep_range() uses hrtimers and provides no advantage over msleep() for larger delays. Fix up the 100ms delays here passing the adjusted "min" value to msleep(). This helps reduce the load on the hrtimer subsystem. Link: http://lkml.org/lkml/2017/1/11/377 Fixes: commit 2938fc63e0c2 ("usb: dwc2: Properly account for the force mode delays") Signed-off-by: Nicholas Mc Guire Signed-off-by: John Youn Signed-off-by: Felipe Balbi Signed-off-by: Greg Kroah-Hartman --- drivers/usb/dwc2/core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/dwc2/core.c b/drivers/usb/dwc2/core.c index 4c0fa0b17353..f6759c61ad07 100644 --- a/drivers/usb/dwc2/core.c +++ b/drivers/usb/dwc2/core.c @@ -455,7 +455,7 @@ static void dwc2_clear_force_mode(struct dwc2_hsotg *hsotg) dwc2_writel(gusbcfg, hsotg->regs + GUSBCFG); if (dwc2_iddig_filter_enabled(hsotg)) - usleep_range(100000, 110000); + msleep(100); } /* From 8f50cb88d862d2aaa084fedc34c75b04ae4a4b16 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Sat, 7 Jan 2017 10:41:40 +0200 Subject: [PATCH 056/396] usb: host: ehci-exynos: Decrese node refcount on exynos_ehci_get_phy() error paths commit 3f6026b1dcb3c8ee71198c485a72ac674c6890dd upstream. Returning from for_each_available_child_of_node() loop requires cleaning up node refcount. Error paths lacked it so for example in case of deferred probe, the refcount of phy node was left increased. Fixes: 6d40500ac9b6 ("usb: ehci/ohci-exynos: Fix of_node_put() for child when getting PHYs") Signed-off-by: Krzysztof Kozlowski Acked-by: Alan Stern Reviewed-by: Javier Martinez Canillas Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-exynos.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/usb/host/ehci-exynos.c b/drivers/usb/host/ehci-exynos.c index 42e5b66353ef..7a603f66a9bc 100644 --- a/drivers/usb/host/ehci-exynos.c +++ b/drivers/usb/host/ehci-exynos.c @@ -77,10 +77,12 @@ static int exynos_ehci_get_phy(struct device *dev, if (IS_ERR(phy)) { ret = PTR_ERR(phy); if (ret == -EPROBE_DEFER) { + of_node_put(child); return ret; } else if (ret != -ENOSYS && ret != -ENODEV) { dev_err(dev, "Error retrieving usb2 phy: %d\n", ret); + of_node_put(child); return ret; } } From 4a36b6a7ee882cd0ffdbfb8c9ce8097b8abea973 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Sat, 7 Jan 2017 10:41:41 +0200 Subject: [PATCH 057/396] usb: host: ohci-exynos: Decrese node refcount on exynos_ehci_get_phy() error paths commit 68bd6fc3cfa98ef253e17307ccafd8ef907b5556 upstream. Returning from for_each_available_child_of_node() loop requires cleaning up node refcount. Error paths lacked it so for example in case of deferred probe, the refcount of phy node was left increased. Fixes: 6d40500ac9b6 ("usb: ehci/ohci-exynos: Fix of_node_put() for child when getting PHYs") Signed-off-by: Krzysztof Kozlowski Acked-by: Alan Stern Reviewed-by: Javier Martinez Canillas Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ohci-exynos.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/usb/host/ohci-exynos.c b/drivers/usb/host/ohci-exynos.c index 2cd105be7319..6865b919403f 100644 --- a/drivers/usb/host/ohci-exynos.c +++ b/drivers/usb/host/ohci-exynos.c @@ -66,10 +66,12 @@ static int exynos_ohci_get_phy(struct device *dev, if (IS_ERR(phy)) { ret = PTR_ERR(phy); if (ret == -EPROBE_DEFER) { + of_node_put(child); return ret; } else if (ret != -ENOSYS && ret != -ENODEV) { dev_err(dev, "Error retrieving usb2 phy: %d\n", ret); + of_node_put(child); return ret; } } From 8eb8c9b16fddec79abc084b0e9b677f66de42fcf Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Wed, 28 Dec 2016 14:56:50 -0800 Subject: [PATCH 058/396] usb: chipidea: Only read/write OTGSC from one place commit f60f8ccd54e03c1afafb2b20ceb029a0eaf7a134 upstream. With the id and vbus detection done via extcon we need to make sure we poll the status of OTGSC properly by considering what the extcon is saying, and not just what the register is saying. Let's move this hw_wait_reg() function to the only place it's used and simplify it for polling the OTGSC register. Then we can make certain we only use the hw_read_otgsc() API to read OTGSC, which will make sure we properly handle extcon events. Acked-by: Peter Chen Cc: Greg Kroah-Hartman Cc: "Ivan T. Ivanov" Fixes: 3ecb3e09b042 ("usb: chipidea: Use extcon framework for VBUS and ID detect") Signed-off-by: Stephen Boyd Signed-off-by: Peter Chen Signed-off-by: Greg Kroah-Hartman --- drivers/usb/chipidea/ci.h | 3 --- drivers/usb/chipidea/core.c | 32 -------------------------------- drivers/usb/chipidea/otg.c | 34 ++++++++++++++++++++++++++++++---- 3 files changed, 30 insertions(+), 39 deletions(-) diff --git a/drivers/usb/chipidea/ci.h b/drivers/usb/chipidea/ci.h index cd414559040f..05bc4d631cb9 100644 --- a/drivers/usb/chipidea/ci.h +++ b/drivers/usb/chipidea/ci.h @@ -428,9 +428,6 @@ int hw_port_test_set(struct ci_hdrc *ci, u8 mode); u8 hw_port_test_get(struct ci_hdrc *ci); -int hw_wait_reg(struct ci_hdrc *ci, enum ci_hw_regs reg, u32 mask, - u32 value, unsigned int timeout_ms); - void ci_platform_configure(struct ci_hdrc *ci); int dbg_create_files(struct ci_hdrc *ci); diff --git a/drivers/usb/chipidea/core.c b/drivers/usb/chipidea/core.c index 3dbb4a21ab44..6e0d614a8075 100644 --- a/drivers/usb/chipidea/core.c +++ b/drivers/usb/chipidea/core.c @@ -516,38 +516,6 @@ int hw_device_reset(struct ci_hdrc *ci) return 0; } -/** - * hw_wait_reg: wait the register value - * - * Sometimes, it needs to wait register value before going on. - * Eg, when switch to device mode, the vbus value should be lower - * than OTGSC_BSV before connects to host. - * - * @ci: the controller - * @reg: register index - * @mask: mast bit - * @value: the bit value to wait - * @timeout_ms: timeout in millisecond - * - * This function returns an error code if timeout - */ -int hw_wait_reg(struct ci_hdrc *ci, enum ci_hw_regs reg, u32 mask, - u32 value, unsigned int timeout_ms) -{ - unsigned long elapse = jiffies + msecs_to_jiffies(timeout_ms); - - while (hw_read(ci, reg, mask) != value) { - if (time_after(jiffies, elapse)) { - dev_err(ci->dev, "timeout waiting for %08x in %d\n", - mask, reg); - return -ETIMEDOUT; - } - msleep(20); - } - - return 0; -} - static irqreturn_t ci_irq(int irq, void *data) { struct ci_hdrc *ci = data; diff --git a/drivers/usb/chipidea/otg.c b/drivers/usb/chipidea/otg.c index 03b6743461d1..a829607c3e4d 100644 --- a/drivers/usb/chipidea/otg.c +++ b/drivers/usb/chipidea/otg.c @@ -104,7 +104,31 @@ void ci_handle_vbus_change(struct ci_hdrc *ci) usb_gadget_vbus_disconnect(&ci->gadget); } -#define CI_VBUS_STABLE_TIMEOUT_MS 5000 +/** + * When we switch to device mode, the vbus value should be lower + * than OTGSC_BSV before connecting to host. + * + * @ci: the controller + * + * This function returns an error code if timeout + */ +static int hw_wait_vbus_lower_bsv(struct ci_hdrc *ci) +{ + unsigned long elapse = jiffies + msecs_to_jiffies(5000); + u32 mask = OTGSC_BSV; + + while (hw_read_otgsc(ci, mask)) { + if (time_after(jiffies, elapse)) { + dev_err(ci->dev, "timeout waiting for %08x in OTGSC\n", + mask); + return -ETIMEDOUT; + } + msleep(20); + } + + return 0; +} + static void ci_handle_id_switch(struct ci_hdrc *ci) { enum ci_role role = ci_otg_role(ci); @@ -116,9 +140,11 @@ static void ci_handle_id_switch(struct ci_hdrc *ci) ci_role_stop(ci); if (role == CI_ROLE_GADGET) - /* wait vbus lower than OTGSC_BSV */ - hw_wait_reg(ci, OP_OTGSC, OTGSC_BSV, 0, - CI_VBUS_STABLE_TIMEOUT_MS); + /* + * wait vbus lower than OTGSC_BSV before connecting + * to host + */ + hw_wait_vbus_lower_bsv(ci); ci_role_start(ci, role); } From b6c17077e05673b9f4f59b682dd3c48394b415fd Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Wed, 28 Dec 2016 14:56:51 -0800 Subject: [PATCH 059/396] usb: chipidea: Handle extcon events properly commit a89b94b53371bbfa582787c2fa3378000ea4263d upstream. We're currently emulating the vbus and id interrupts in the OTGSC read API, but we also need to make sure that if we're handling the events with extcon that we don't enable the interrupts for those events in the hardware. Therefore, properly emulate this register if we're using extcon, but don't enable the interrupts. This allows me to get my cable connect/disconnect working properly without getting spurious interrupts on my device that uses an extcon for these two events. Acked-by: Peter Chen Cc: Greg Kroah-Hartman Cc: "Ivan T. Ivanov" Fixes: 3ecb3e09b042 ("usb: chipidea: Use extcon framework for VBUS and ID detect") Signed-off-by: Stephen Boyd Signed-off-by: Peter Chen Signed-off-by: Greg Kroah-Hartman --- drivers/usb/chipidea/otg.c | 46 ++++++++++++++++++++++++++++++++---- include/linux/usb/chipidea.h | 2 ++ 2 files changed, 43 insertions(+), 5 deletions(-) diff --git a/drivers/usb/chipidea/otg.c b/drivers/usb/chipidea/otg.c index a829607c3e4d..0cf149edddd8 100644 --- a/drivers/usb/chipidea/otg.c +++ b/drivers/usb/chipidea/otg.c @@ -44,12 +44,15 @@ u32 hw_read_otgsc(struct ci_hdrc *ci, u32 mask) else val &= ~OTGSC_BSVIS; - cable->changed = false; - if (cable->state) val |= OTGSC_BSV; else val &= ~OTGSC_BSV; + + if (cable->enabled) + val |= OTGSC_BSVIE; + else + val &= ~OTGSC_BSVIE; } cable = &ci->platdata->id_extcon; @@ -59,15 +62,18 @@ u32 hw_read_otgsc(struct ci_hdrc *ci, u32 mask) else val &= ~OTGSC_IDIS; - cable->changed = false; - if (cable->state) val |= OTGSC_ID; else val &= ~OTGSC_ID; + + if (cable->enabled) + val |= OTGSC_IDIE; + else + val &= ~OTGSC_IDIE; } - return val; + return val & mask; } /** @@ -77,6 +83,36 @@ u32 hw_read_otgsc(struct ci_hdrc *ci, u32 mask) */ void hw_write_otgsc(struct ci_hdrc *ci, u32 mask, u32 data) { + struct ci_hdrc_cable *cable; + + cable = &ci->platdata->vbus_extcon; + if (!IS_ERR(cable->edev)) { + if (data & mask & OTGSC_BSVIS) + cable->changed = false; + + /* Don't enable vbus interrupt if using external notifier */ + if (data & mask & OTGSC_BSVIE) { + cable->enabled = true; + data &= ~OTGSC_BSVIE; + } else if (mask & OTGSC_BSVIE) { + cable->enabled = false; + } + } + + cable = &ci->platdata->id_extcon; + if (!IS_ERR(cable->edev)) { + if (data & mask & OTGSC_IDIS) + cable->changed = false; + + /* Don't enable id interrupt if using external notifier */ + if (data & mask & OTGSC_IDIE) { + cable->enabled = true; + data &= ~OTGSC_IDIE; + } else if (mask & OTGSC_IDIE) { + cable->enabled = false; + } + } + hw_write(ci, OP_OTGSC, mask | OTGSC_INT_STATUS_BITS, data); } diff --git a/include/linux/usb/chipidea.h b/include/linux/usb/chipidea.h index 5dd75fa47dd8..f9be467d6695 100644 --- a/include/linux/usb/chipidea.h +++ b/include/linux/usb/chipidea.h @@ -14,6 +14,7 @@ struct ci_hdrc; * struct ci_hdrc_cable - structure for external connector cable state tracking * @state: current state of the line * @changed: set to true when extcon event happen + * @enabled: set to true if we've enabled the vbus or id interrupt * @edev: device which generate events * @ci: driver state of the chipidea device * @nb: hold event notification callback @@ -22,6 +23,7 @@ struct ci_hdrc; struct ci_hdrc_cable { bool state; bool changed; + bool enabled; struct extcon_dev *edev; struct ci_hdrc *ci; struct notifier_block nb; From 84443215cf54861f3013253817afaf156efb1453 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 31 Jan 2017 17:17:29 +0100 Subject: [PATCH 060/396] USB: serial: keyspan_pda: fix receive sanity checks commit c528fcb116e61afc379a2e0a0f70906b937f1e2c upstream. Make sure to check for short transfers before parsing the receive buffer to avoid acting on stale data. Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") Reviewed-by: Greg Kroah-Hartman Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/keyspan_pda.c | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/drivers/usb/serial/keyspan_pda.c b/drivers/usb/serial/keyspan_pda.c index 83523fcf6fb9..d2dab2a341b8 100644 --- a/drivers/usb/serial/keyspan_pda.c +++ b/drivers/usb/serial/keyspan_pda.c @@ -139,6 +139,7 @@ static void keyspan_pda_rx_interrupt(struct urb *urb) { struct usb_serial_port *port = urb->context; unsigned char *data = urb->transfer_buffer; + unsigned int len = urb->actual_length; int retval; int status = urb->status; struct keyspan_pda_private *priv; @@ -159,18 +160,26 @@ static void keyspan_pda_rx_interrupt(struct urb *urb) goto exit; } + if (len < 1) { + dev_warn(&port->dev, "short message received\n"); + goto exit; + } + /* see if the message is data or a status interrupt */ switch (data[0]) { case 0: /* rest of message is rx data */ - if (urb->actual_length) { - tty_insert_flip_string(&port->port, data + 1, - urb->actual_length - 1); - tty_flip_buffer_push(&port->port); - } + if (len < 2) + break; + tty_insert_flip_string(&port->port, data + 1, len - 1); + tty_flip_buffer_push(&port->port); break; case 1: /* status interrupt */ + if (len < 3) { + dev_warn(&port->dev, "short interrupt message received\n"); + break; + } dev_dbg(&port->dev, "rx int, d1=%d, d2=%d\n", data[1], data[2]); switch (data[1]) { case 1: /* modemline change */ From 9ca3010675025a512db998b1421ad0b60963c790 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 31 Jan 2017 17:17:28 +0100 Subject: [PATCH 061/396] USB: serial: digi_acceleport: fix incomplete rx sanity check commit 1b0aed2b1600f6e5c7b9acfbd610a4e351ef5232 upstream. Make sure the received data has the required headers before parsing it. Also drop the redundant urb-status check, which has already been handled by the caller. Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") Reviewed-by: Greg Kroah-Hartman Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/digi_acceleport.c | 38 +++++++++++++++++----------- 1 file changed, 23 insertions(+), 15 deletions(-) diff --git a/drivers/usb/serial/digi_acceleport.c b/drivers/usb/serial/digi_acceleport.c index 30bf0f5db82d..7ab3235febfc 100644 --- a/drivers/usb/serial/digi_acceleport.c +++ b/drivers/usb/serial/digi_acceleport.c @@ -1398,25 +1398,30 @@ static int digi_read_inb_callback(struct urb *urb) { struct usb_serial_port *port = urb->context; struct digi_port *priv = usb_get_serial_port_data(port); - int opcode = ((unsigned char *)urb->transfer_buffer)[0]; - int len = ((unsigned char *)urb->transfer_buffer)[1]; - int port_status = ((unsigned char *)urb->transfer_buffer)[2]; - unsigned char *data = ((unsigned char *)urb->transfer_buffer) + 3; + unsigned char *buf = urb->transfer_buffer; + int opcode; + int len; + int port_status; + unsigned char *data; int flag, throttled; - int status = urb->status; - - /* do not process callbacks on closed ports */ - /* but do continue the read chain */ - if (urb->status == -ENOENT) - return 0; /* short/multiple packet check */ + if (urb->actual_length < 2) { + dev_warn(&port->dev, "short packet received\n"); + return -1; + } + + opcode = buf[0]; + len = buf[1]; + if (urb->actual_length != len + 2) { - dev_err(&port->dev, "%s: INCOMPLETE OR MULTIPLE PACKET, " - "status=%d, port=%d, opcode=%d, len=%d, " - "actual_length=%d, status=%d\n", __func__, status, - priv->dp_port_num, opcode, len, urb->actual_length, - port_status); + dev_err(&port->dev, "malformed packet received: port=%d, opcode=%d, len=%d, actual_length=%u\n", + priv->dp_port_num, opcode, len, urb->actual_length); + return -1; + } + + if (opcode == DIGI_CMD_RECEIVE_DATA && len < 1) { + dev_err(&port->dev, "malformed data packet received\n"); return -1; } @@ -1430,6 +1435,9 @@ static int digi_read_inb_callback(struct urb *urb) /* receive data */ if (opcode == DIGI_CMD_RECEIVE_DATA) { + port_status = buf[2]; + data = &buf[3]; + /* get flag from port_status */ flag = 0; From 4d32e36d62627ad9730338e6f603c8b996aaf7eb Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 12 Jan 2017 14:56:22 +0100 Subject: [PATCH 062/396] USB: serial: ssu100: fix control-message error handling commit 1eac5c244f705182d1552a53e2f74e2775ed95d6 upstream. Make sure to detect short control-message transfers rather than continue with zero-initialised data when retrieving modem status and during device initialisation. Fixes: 52af95459939 ("USB: add USB serial ssu100 driver") Reviewed-by: Greg Kroah-Hartman Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/ssu100.c | 31 ++++++++++++++++++++++++------- 1 file changed, 24 insertions(+), 7 deletions(-) diff --git a/drivers/usb/serial/ssu100.c b/drivers/usb/serial/ssu100.c index 70a098de429f..886e1294b120 100644 --- a/drivers/usb/serial/ssu100.c +++ b/drivers/usb/serial/ssu100.c @@ -80,9 +80,17 @@ static inline int ssu100_setdevice(struct usb_device *dev, u8 *data) static inline int ssu100_getdevice(struct usb_device *dev, u8 *data) { - return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), - QT_SET_GET_DEVICE, 0xc0, 0, 0, - data, 3, 300); + int ret; + + ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), + QT_SET_GET_DEVICE, 0xc0, 0, 0, + data, 3, 300); + if (ret < 3) { + if (ret >= 0) + ret = -EIO; + } + + return ret; } static inline int ssu100_getregister(struct usb_device *dev, @@ -90,10 +98,17 @@ static inline int ssu100_getregister(struct usb_device *dev, unsigned short reg, u8 *data) { - return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), - QT_SET_GET_REGISTER, 0xc0, reg, - uart, data, sizeof(*data), 300); + int ret; + ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), + QT_SET_GET_REGISTER, 0xc0, reg, + uart, data, sizeof(*data), 300); + if (ret < sizeof(*data)) { + if (ret >= 0) + ret = -EIO; + } + + return ret; } @@ -289,8 +304,10 @@ static int ssu100_open(struct tty_struct *tty, struct usb_serial_port *port) QT_OPEN_CLOSE_CHANNEL, QT_TRANSFER_IN, 0x01, 0, data, 2, 300); - if (result < 0) { + if (result < 2) { dev_dbg(&port->dev, "%s - open failed %i\n", __func__, result); + if (result >= 0) + result = -EIO; kfree(data); return result; } From b07e930d1f498e3cc3677fdf89665918aa44e244 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 12 Jan 2017 14:56:13 +0100 Subject: [PATCH 063/396] USB: serial: io_edgeport: fix epic-descriptor handling commit e4457d9798adb96272468e93da663de9bd0a4198 upstream. Use a dedicated buffer for the DMA transfer and make sure to detect short transfers to avoid parsing a corrupt descriptor. Fixes: 6e8cf7751f9f ("USB: add EPIC support to the io_edgeport driver") Reviewed-by: Greg Kroah-Hartman Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/io_edgeport.c | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/drivers/usb/serial/io_edgeport.c b/drivers/usb/serial/io_edgeport.c index 36dfe9972b17..653ea2e35c31 100644 --- a/drivers/usb/serial/io_edgeport.c +++ b/drivers/usb/serial/io_edgeport.c @@ -492,20 +492,24 @@ static int get_epic_descriptor(struct edgeport_serial *ep) int result; struct usb_serial *serial = ep->serial; struct edgeport_product_info *product_info = &ep->product_info; - struct edge_compatibility_descriptor *epic = &ep->epic_descriptor; + struct edge_compatibility_descriptor *epic; struct edge_compatibility_bits *bits; struct device *dev = &serial->dev->dev; ep->is_epic = 0; + + epic = kmalloc(sizeof(*epic), GFP_KERNEL); + if (!epic) + return -ENOMEM; + result = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0), USB_REQUEST_ION_GET_EPIC_DESC, 0xC0, 0x00, 0x00, - &ep->epic_descriptor, - sizeof(struct edge_compatibility_descriptor), + epic, sizeof(*epic), 300); - - if (result > 0) { + if (result == sizeof(*epic)) { ep->is_epic = 1; + memcpy(&ep->epic_descriptor, epic, sizeof(*epic)); memset(product_info, 0, sizeof(struct edgeport_product_info)); product_info->NumPorts = epic->NumPorts; @@ -534,8 +538,16 @@ static int get_epic_descriptor(struct edgeport_serial *ep) dev_dbg(dev, " IOSPWriteLCR : %s\n", bits->IOSPWriteLCR ? "TRUE": "FALSE"); dev_dbg(dev, " IOSPSetBaudRate : %s\n", bits->IOSPSetBaudRate ? "TRUE": "FALSE"); dev_dbg(dev, " TrueEdgeport : %s\n", bits->TrueEdgeport ? "TRUE": "FALSE"); + + result = 0; + } else if (result >= 0) { + dev_warn(&serial->interface->dev, "short epic descriptor received: %d\n", + result); + result = -EIO; } + kfree(epic); + return result; } @@ -2782,7 +2794,7 @@ static int edge_startup(struct usb_serial *serial) dev_info(&serial->dev->dev, "%s detected\n", edge_serial->name); /* Read the epic descriptor */ - if (get_epic_descriptor(edge_serial) <= 0) { + if (get_epic_descriptor(edge_serial) < 0) { /* memcpy descriptor to Supports structures */ memcpy(&edge_serial->epic_descriptor.Supports, descriptor, sizeof(struct edge_compatibility_bits)); From 94bbbfe21b5a592dc5306f2203d6716734cf9b67 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 12 Jan 2017 14:56:23 +0100 Subject: [PATCH 064/396] USB: serial: ti_usb_3410_5052: fix control-message error handling commit 39712e8bfa8d3aa6ce1e60fc9d62c9b076c17a30 upstream. Make sure to detect and return an error on zero-length control-message transfers when reading from the device. This addresses a potential failure to detect an empty transmit buffer during close. Also remove a redundant check for short transfer when sending a command. Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") Reviewed-by: Greg Kroah-Hartman Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/ti_usb_3410_5052.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/drivers/usb/serial/ti_usb_3410_5052.c b/drivers/usb/serial/ti_usb_3410_5052.c index bdbddbc8bd4d..6bcb874b4832 100644 --- a/drivers/usb/serial/ti_usb_3410_5052.c +++ b/drivers/usb/serial/ti_usb_3410_5052.c @@ -1556,13 +1556,10 @@ static int ti_command_out_sync(struct ti_device *tdev, __u8 command, (USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT), value, moduleid, data, size, 1000); - if (status == size) - status = 0; + if (status < 0) + return status; - if (status > 0) - status = -ECOMM; - - return status; + return 0; } @@ -1578,8 +1575,7 @@ static int ti_command_in_sync(struct ti_device *tdev, __u8 command, if (status == size) status = 0; - - if (status > 0) + else if (status >= 0) status = -ECOMM; return status; From ca4e6525df053f0e023195b571c9d6241197bc09 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 12 Jan 2017 14:56:10 +0100 Subject: [PATCH 065/396] USB: serial: ark3116: fix open error handling commit b631433b175f1002a31020e09bbfc2e5caecf290 upstream. Fix open error handling which failed to detect errors when reading the MSR and LSR registers, something which could lead to the shadow registers being initialised from errnos. Note that calling the generic close implementation is sufficient in the error paths as the interrupt urb has not yet been submitted and the register updates have not been made. Fixes: f4c1e8d597d1 ("USB: ark3116: Make existing functions 16450-aware and add close and release functions.") Reviewed-by: Greg Kroah-Hartman Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/ark3116.c | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/drivers/usb/serial/ark3116.c b/drivers/usb/serial/ark3116.c index 7812052dc700..754fc3e41005 100644 --- a/drivers/usb/serial/ark3116.c +++ b/drivers/usb/serial/ark3116.c @@ -373,23 +373,29 @@ static int ark3116_open(struct tty_struct *tty, struct usb_serial_port *port) dev_dbg(&port->dev, "%s - usb_serial_generic_open failed: %d\n", __func__, result); - goto err_out; + goto err_free; } /* remove any data still left: also clears error state */ ark3116_read_reg(serial, UART_RX, buf); /* read modem status */ - priv->msr = ark3116_read_reg(serial, UART_MSR, buf); + result = ark3116_read_reg(serial, UART_MSR, buf); + if (result < 0) + goto err_close; + priv->msr = *buf; + /* read line status */ - priv->lsr = ark3116_read_reg(serial, UART_LSR, buf); + result = ark3116_read_reg(serial, UART_LSR, buf); + if (result < 0) + goto err_close; + priv->lsr = *buf; result = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL); if (result) { dev_err(&port->dev, "submit irq_in urb failed %d\n", result); - ark3116_close(port); - goto err_out; + goto err_close; } /* activate interrupts */ @@ -402,8 +408,15 @@ static int ark3116_open(struct tty_struct *tty, struct usb_serial_port *port) if (tty) ark3116_set_termios(tty, port, NULL); -err_out: kfree(buf); + + return 0; + +err_close: + usb_serial_generic_close(port); +err_free: + kfree(buf); + return result; } From 594c9b4b0acb9e3091c583958ee144b58d0e7bdd Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 12 Jan 2017 14:56:12 +0100 Subject: [PATCH 066/396] USB: serial: ftdi_sio: fix latency-timer error handling commit e3e574ad85a208cb179f33720bb5f12b453de33c upstream. Make sure to detect short responses when reading the latency timer to avoid using stale buffer data. Note that no heap data would currently leak through sysfs as ASYNC_LOW_LATENCY is set by default. Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") Reviewed-by: Greg Kroah-Hartman Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/ftdi_sio.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index 99a0a5f1b400..d8d13eede6d9 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -1439,10 +1439,13 @@ static int read_latency_timer(struct usb_serial_port *port) FTDI_SIO_GET_LATENCY_TIMER_REQUEST_TYPE, 0, priv->interface, buf, 1, WDR_TIMEOUT); - if (rv < 0) + if (rv < 1) { dev_err(&port->dev, "Unable to read latency timer: %i\n", rv); - else + if (rv >= 0) + rv = -EIO; + } else { priv->latency = buf[0]; + } kfree(buf); From e17c48c3280e70dc5c8a9d579613ea732591dedf Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 12 Jan 2017 14:56:20 +0100 Subject: [PATCH 067/396] USB: serial: quatech2: fix control-message error handling commit 8c34cb8ddfe808d557b51da983ff10c02793beb2 upstream. Make sure to detect short control-message transfers when fetching modem and line state in open and when retrieving registers. This specifically makes sure that an errno is returned to user space on errors in TIOCMGET instead of a zero bitmask. Also drop the unused getdevice function which also lacked appropriate error handling. Fixes: f7a33e608d9a ("USB: serial: add quatech2 usb to serial driver") Reviewed-by: Greg Kroah-Hartman Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/quatech2.c | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/drivers/usb/serial/quatech2.c b/drivers/usb/serial/quatech2.c index bd1a1307e0f0..1d17779b2203 100644 --- a/drivers/usb/serial/quatech2.c +++ b/drivers/usb/serial/quatech2.c @@ -188,22 +188,22 @@ static inline int qt2_setdevice(struct usb_device *dev, u8 *data) } -static inline int qt2_getdevice(struct usb_device *dev, u8 *data) -{ - return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), - QT_SET_GET_DEVICE, 0xc0, 0, 0, - data, 3, QT2_USB_TIMEOUT); -} - static inline int qt2_getregister(struct usb_device *dev, u8 uart, u8 reg, u8 *data) { - return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), - QT_SET_GET_REGISTER, 0xc0, reg, - uart, data, sizeof(*data), QT2_USB_TIMEOUT); + int ret; + ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), + QT_SET_GET_REGISTER, 0xc0, reg, + uart, data, sizeof(*data), QT2_USB_TIMEOUT); + if (ret < sizeof(*data)) { + if (ret >= 0) + ret = -EIO; + } + + return ret; } static inline int qt2_setregister(struct usb_device *dev, @@ -372,9 +372,11 @@ static int qt2_open(struct tty_struct *tty, struct usb_serial_port *port) 0xc0, 0, device_port, data, 2, QT2_USB_TIMEOUT); - if (status < 0) { + if (status < 2) { dev_err(&port->dev, "%s - open port failed %i\n", __func__, status); + if (status >= 0) + status = -EIO; kfree(data); return status; } From 62b8b773ebde042ef7e016c9bed6327306885fee Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 12 Jan 2017 14:56:16 +0100 Subject: [PATCH 068/396] USB: serial: mct_u232: fix modem-status error handling commit 36356a669eddb32917fc4b5c2b9b8bf80ede69de upstream. Make sure to detect short control-message transfers so that errors are logged when reading the modem status at open. Note that while this also avoids initialising the modem status using uninitialised heap data, these bits could not leak to user space as they are currently not used. Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") Reviewed-by: Greg Kroah-Hartman Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/mct_u232.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/usb/serial/mct_u232.c b/drivers/usb/serial/mct_u232.c index 885655315de1..edbc81f205c2 100644 --- a/drivers/usb/serial/mct_u232.c +++ b/drivers/usb/serial/mct_u232.c @@ -322,8 +322,12 @@ static int mct_u232_get_modem_stat(struct usb_serial_port *port, MCT_U232_GET_REQUEST_TYPE, 0, 0, buf, MCT_U232_GET_MODEM_STAT_SIZE, WDR_TIMEOUT); - if (rc < 0) { + if (rc < MCT_U232_GET_MODEM_STAT_SIZE) { dev_err(&port->dev, "Get MODEM STATus failed (error = %d)\n", rc); + + if (rc >= 0) + rc = -EIO; + *msr = 0; } else { *msr = buf[0]; From 6fa44d4ba2126f3e56c6cd39cf54991bbf3bbc46 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 12 Jan 2017 14:56:14 +0100 Subject: [PATCH 069/396] USB: serial: io_edgeport: fix descriptor error handling commit 3c0e25d883d06a1fbd1ad35257e8abaa57befb37 upstream. Make sure to detect short control-message transfers and log an error when reading incomplete manufacturer and boot descriptors. Note that the default all-zero descriptors will now be used after a short transfer is detected instead of partially initialised ones. Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") Reviewed-by: Greg Kroah-Hartman Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/io_edgeport.c | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/drivers/usb/serial/io_edgeport.c b/drivers/usb/serial/io_edgeport.c index 653ea2e35c31..464db17b5328 100644 --- a/drivers/usb/serial/io_edgeport.c +++ b/drivers/usb/serial/io_edgeport.c @@ -2105,8 +2105,7 @@ static int rom_write(struct usb_serial *serial, __u16 extAddr, __u16 addr, * rom_read * reads a number of bytes from the Edgeport device starting at the given * address. - * If successful returns the number of bytes read, otherwise it returns - * a negative error number of the problem. + * Returns zero on success or a negative error number. ****************************************************************************/ static int rom_read(struct usb_serial *serial, __u16 extAddr, __u16 addr, __u16 length, __u8 *data) @@ -2131,12 +2130,17 @@ static int rom_read(struct usb_serial *serial, __u16 extAddr, USB_REQUEST_ION_READ_ROM, 0xC0, addr, extAddr, transfer_buffer, current_length, 300); - if (result < 0) + if (result < current_length) { + if (result >= 0) + result = -EIO; break; + } memcpy(data, transfer_buffer, current_length); length -= current_length; addr += current_length; data += current_length; + + result = 0; } kfree(transfer_buffer); @@ -2590,9 +2594,10 @@ static void get_manufacturing_desc(struct edgeport_serial *edge_serial) EDGE_MANUF_DESC_LEN, (__u8 *)(&edge_serial->manuf_descriptor)); - if (response < 1) - dev_err(dev, "error in getting manufacturer descriptor\n"); - else { + if (response < 0) { + dev_err(dev, "error in getting manufacturer descriptor: %d\n", + response); + } else { char string[30]; dev_dbg(dev, "**Manufacturer Descriptor\n"); dev_dbg(dev, " RomSize: %dK\n", @@ -2649,9 +2654,10 @@ static void get_boot_desc(struct edgeport_serial *edge_serial) EDGE_BOOT_DESC_LEN, (__u8 *)(&edge_serial->boot_descriptor)); - if (response < 1) - dev_err(dev, "error in getting boot descriptor\n"); - else { + if (response < 0) { + dev_err(dev, "error in getting boot descriptor: %d\n", + response); + } else { dev_dbg(dev, "**Boot Descriptor:\n"); dev_dbg(dev, " BootCodeLength: %d\n", le16_to_cpu(edge_serial->boot_descriptor.BootCodeLength)); From 52dd14d76812be2c98f0ad54be2fd8d375f5d627 Mon Sep 17 00:00:00 2001 From: Heiko Stuebner Date: Wed, 1 Mar 2017 22:00:41 +0100 Subject: [PATCH 070/396] clk: rockchip: add "," to mux_pll_src_apll_dpll_gpll_usb480m_p on rk3036 commit 9b1b23f03abdd25ffde8bbfe5824b89bc0448c28 upstream. The mux_pll_src_apll_dpll_gpll_usb480m_p parent list was missing a "," between the 3rd and 4th parent names, making them fall together and thus lookups fail. Fix that. Fixes: 5190c08b2989 ("clk: rockchip: add clock controller for rk3036") Signed-off-by: Heiko Stuebner Signed-off-by: Stephen Boyd Signed-off-by: Greg Kroah-Hartman --- drivers/clk/rockchip/clk-rk3036.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clk/rockchip/clk-rk3036.c b/drivers/clk/rockchip/clk-rk3036.c index 924f560dcf80..dcde70f4c105 100644 --- a/drivers/clk/rockchip/clk-rk3036.c +++ b/drivers/clk/rockchip/clk-rk3036.c @@ -127,7 +127,7 @@ PNAME(mux_ddrphy_p) = { "dpll_ddr", "gpll_ddr" }; PNAME(mux_pll_src_3plls_p) = { "apll", "dpll", "gpll" }; PNAME(mux_timer_p) = { "xin24m", "pclk_peri_src" }; -PNAME(mux_pll_src_apll_dpll_gpll_usb480m_p) = { "apll", "dpll", "gpll" "usb480m" }; +PNAME(mux_pll_src_apll_dpll_gpll_usb480m_p) = { "apll", "dpll", "gpll", "usb480m" }; PNAME(mux_mmc_src_p) = { "apll", "dpll", "gpll", "xin24m" }; PNAME(mux_i2s_pre_p) = { "i2s_src", "i2s_frac", "ext_i2s", "xin12m" }; From 115fb7ec22b5422adabcd48232b68b6d2882e7f7 Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Thu, 9 Mar 2017 13:45:44 +0530 Subject: [PATCH 071/396] phy: qcom-usb-hs: Add depends on EXTCON commit 1a09b6a7c10e22c489a8b212dd6862b1fd9674ad upstream. We get the following compile errors if EXTCON is enabled as a module but this driver is builtin: drivers/built-in.o: In function `qcom_usb_hs_phy_power_off': phy-qcom-usb-hs.c:(.text+0x1089): undefined reference to `extcon_unregister_notifier' drivers/built-in.o: In function `qcom_usb_hs_phy_probe': phy-qcom-usb-hs.c:(.text+0x11b5): undefined reference to `extcon_get_edev_by_phandle' drivers/built-in.o: In function `qcom_usb_hs_phy_power_on': phy-qcom-usb-hs.c:(.text+0x128e): undefined reference to `extcon_get_state' phy-qcom-usb-hs.c:(.text+0x12a9): undefined reference to `extcon_register_notifier' so let's mark this as needing to follow the modular status of the extcon framework. Fixes: 9994a33865f4 e2427b09ba929c2b9 (phy: Add support for Qualcomm's USB HS phy") Signed-off-by: Stephen Boyd Signed-off-by: Kishon Vijay Abraham I Signed-off-by: Greg Kroah-Hartman --- drivers/phy/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig index fe00f9134d51..7dc726d7fbde 100644 --- a/drivers/phy/Kconfig +++ b/drivers/phy/Kconfig @@ -456,6 +456,7 @@ config PHY_QCOM_UFS config PHY_TUSB1210 tristate "TI TUSB1210 ULPI PHY module" depends on USB_ULPI_BUS + depends on EXTCON || !EXTCON # if EXTCON=m, this cannot be built-in select GENERIC_PHY help Support for TI TUSB1210 USB ULPI PHY. From 71fd9a94bd3fd35277c9e1cf6a373c1f7a8ec4cd Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Fri, 20 Jan 2017 12:22:31 -0800 Subject: [PATCH 072/396] serial: 8250_omap: Fix probe and remove for PM runtime commit 4e0f5cc65098ea32a1e77baae74215b9bd5276b1 upstream. Otherwise the interconnect related code implementing PM runtime will produce these errors on a failed probe: omap_uart 48066000.serial: omap_device: omap_device_enable() called from invalid state 1 omap_uart 48066000.serial: use pm_runtime_put_sync_suspend() in driver? Note that we now also need to check for priv in omap8250_runtime_suspend() as it has not yet been registered if probe fails. And we need to use pm_runtime_put_sync() to properly idle the device like we already do in omap8250_remove(). Fixes: 61929cf0169d ("tty: serial: Add 8250-core based omap driver") Signed-off-by: Tony Lindgren Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_omap.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/tty/serial/8250/8250_omap.c b/drivers/tty/serial/8250/8250_omap.c index f4eb807a2616..da31159a03ec 100644 --- a/drivers/tty/serial/8250/8250_omap.c +++ b/drivers/tty/serial/8250/8250_omap.c @@ -1237,7 +1237,8 @@ static int omap8250_probe(struct platform_device *pdev) pm_runtime_put_autosuspend(&pdev->dev); return 0; err: - pm_runtime_put(&pdev->dev); + pm_runtime_dont_use_autosuspend(&pdev->dev); + pm_runtime_put_sync(&pdev->dev); pm_runtime_disable(&pdev->dev); return ret; } @@ -1246,6 +1247,7 @@ static int omap8250_remove(struct platform_device *pdev) { struct omap8250_priv *priv = platform_get_drvdata(pdev); + pm_runtime_dont_use_autosuspend(&pdev->dev); pm_runtime_put_sync(&pdev->dev); pm_runtime_disable(&pdev->dev); serial8250_unregister_port(priv->line); @@ -1345,6 +1347,10 @@ static int omap8250_runtime_suspend(struct device *dev) struct omap8250_priv *priv = dev_get_drvdata(dev); struct uart_8250_port *up; + /* In case runtime-pm tries this before we are setup */ + if (!priv) + return 0; + up = serial8250_get_port(priv->line); /* * When using 'no_console_suspend', the console UART must not be From 76aa65a2c0fd075c71a93ea93b67f101d187fce5 Mon Sep 17 00:00:00 2001 From: Bill Kuzeja Date: Tue, 14 Mar 2017 13:28:44 -0400 Subject: [PATCH 073/396] scsi: qla2xxx: Fix crash in qla2xxx_eh_abort on bad ptr commit 5f7c2beef819d9ea2d1b814edf6f5981420e9cf8 upstream. After a Qlogic card breaks when initializing (test case), the system can crash in qla2xxx_eh_abort if processing anything but a scsi command type srb. Fixes: 1535aa75a3d8 ("scsi: qla2xxx: fix invalid DMA access after command aborts in PCI device remove") Signed-off-by: Bill Kuzeja Acked-By: Himanshu Madhani Signed-off-by: Martin K. Petersen Signed-off-by: Greg Kroah-Hartman --- drivers/scsi/qla2xxx/qla_os.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 734e592a247e..f9b52a4b8c55 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -1464,7 +1464,8 @@ qla2x00_abort_all_cmds(scsi_qla_host_t *vha, int res) /* Don't abort commands in adapter during EEH * recovery as it's not accessible/responding. */ - if (GET_CMD_SP(sp) && !ha->flags.eeh_busy) { + if (GET_CMD_SP(sp) && !ha->flags.eeh_busy && + (sp->type == SRB_SCSI_CMD)) { /* Get a reference to the sp and drop the lock. * The reference ensures this sp->done() call * - and not the call in qla2xxx_eh_abort() - From a46d03e3517990375bc4aafe7df969309245f068 Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Thu, 23 Feb 2017 09:08:02 +1100 Subject: [PATCH 074/396] scsi: mac_scsi: Fix MAC_SCSI=m option when SCSI=m commit 2559a1ef688f933835912c731bed2254146a9b04 upstream. The mac_scsi driver still gets disabled when SCSI=m. This should have been fixed back when I enabled the tristate but I didn't see the bug. Fixes: 6e9ae6d560e1 ("[PATCH] mac_scsi: Add module option to Kconfig") Signed-off-by: Finn Thain Signed-off-by: Martin K. Petersen Signed-off-by: Greg Kroah-Hartman --- drivers/scsi/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig index 3e2bdb90813c..17b1574920fd 100644 --- a/drivers/scsi/Kconfig +++ b/drivers/scsi/Kconfig @@ -1497,7 +1497,7 @@ config ATARI_SCSI config MAC_SCSI tristate "Macintosh NCR5380 SCSI" - depends on MAC && SCSI=y + depends on MAC && SCSI select SCSI_SPI_ATTRS help This is the NCR 5380 SCSI controller included on most of the 68030 From 2d652d0abd3ccda1097345d13d728b8ba1b7c68f Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Fri, 17 Feb 2017 16:03:52 +0100 Subject: [PATCH 075/396] scsi: smartpqi: fix time handling commit ed10858eadd4988260c6bc7d75fc25176342b5a7 upstream. When we have turned off RTC support, the smartpqi driver fails to build: ERROR: "rtc_time64_to_tm" [drivers/scsi/smartpqi/smartpqi.ko] undefined! This is easily avoided by using the generic 'struct tm' based helper rather than the RTC specific one. While fixing this, I noticed that even though the driver uses time64_t for storing seconds, it gets them from the old 32-bit struct timeval. To address this, we can simplify the code by calling ktime_get_real_seconds() directly. Fixes: 6c223761eb54 ("smartpqi: initial commit of Microsemi smartpqi driver") Signed-off-by: Arnd Bergmann Acked-by: Don Brace Signed-off-by: Martin K. Petersen Signed-off-by: Greg Kroah-Hartman --- drivers/scsi/smartpqi/smartpqi_init.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/drivers/scsi/smartpqi/smartpqi_init.c b/drivers/scsi/smartpqi/smartpqi_init.c index a535b2661f38..96a343ec8313 100644 --- a/drivers/scsi/smartpqi/smartpqi_init.c +++ b/drivers/scsi/smartpqi/smartpqi_init.c @@ -533,8 +533,7 @@ static int pqi_write_current_time_to_host_wellness( size_t buffer_length; time64_t local_time; unsigned int year; - struct timeval time; - struct rtc_time tm; + struct tm tm; buffer_length = sizeof(*buffer); @@ -551,9 +550,8 @@ static int pqi_write_current_time_to_host_wellness( put_unaligned_le16(sizeof(buffer->time), &buffer->time_length); - do_gettimeofday(&time); - local_time = time.tv_sec - (sys_tz.tz_minuteswest * 60); - rtc_time64_to_tm(local_time, &tm); + local_time = ktime_get_real_seconds(); + time64_to_tm(local_time, -sys_tz.tz_minuteswest * 60, &tm); year = tm.tm_year + 1900; buffer->time[0] = bin2bcd(tm.tm_hour); From b0e2e3acfe8ebe95e9d6189b94e75d685c7f6d15 Mon Sep 17 00:00:00 2001 From: Leonid Yegoshin Date: Thu, 25 Aug 2016 10:37:38 -0700 Subject: [PATCH 076/396] MIPS: R2-on-R6 MULTU/MADDU/MSUBU emulation bugfix commit d65e5677ad5b3a49c43f60ec07644dc1f87bbd2e upstream. MIPS instructions MULTU, MADDU and MSUBU emulation requires registers HI/LO to be converted to signed 32bits before 64bit sign extension on MIPS64. Bug was found on running MIPS32 R2 test application on MIPS64 R6 kernel. Fixes: b0a668fb2038 ("MIPS: kernel: mips-r2-to-r6-emul: Add R2 emulator for MIPS R6") Signed-off-by: Leonid Yegoshin Reported-by: Nikola.Veljkovic@imgtec.com Cc: paul.burton@imgtec.com Cc: yamada.masahiro@socionext.com Cc: akpm@linux-foundation.org Cc: andrea.gelmini@gelma.net Cc: macro@imgtec.com Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/14043/ Signed-off-by: Ralf Baechle Signed-off-by: Greg Kroah-Hartman --- arch/mips/kernel/mips-r2-to-r6-emul.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/arch/mips/kernel/mips-r2-to-r6-emul.c b/arch/mips/kernel/mips-r2-to-r6-emul.c index bd09853aecdf..d8227f289d7f 100644 --- a/arch/mips/kernel/mips-r2-to-r6-emul.c +++ b/arch/mips/kernel/mips-r2-to-r6-emul.c @@ -433,8 +433,8 @@ static int multu_func(struct pt_regs *regs, u32 ir) rs = regs->regs[MIPSInst_RS(ir)]; res = (u64)rt * (u64)rs; rt = res; - regs->lo = (s64)rt; - regs->hi = (s64)(res >> 32); + regs->lo = (s64)(s32)rt; + regs->hi = (s64)(s32)(res >> 32); MIPS_R2_STATS(muls); @@ -670,9 +670,9 @@ static int maddu_func(struct pt_regs *regs, u32 ir) res += ((((s64)rt) << 32) | (u32)rs); rt = res; - regs->lo = (s64)rt; + regs->lo = (s64)(s32)rt; rs = res >> 32; - regs->hi = (s64)rs; + regs->hi = (s64)(s32)rs; MIPS_R2_STATS(dsps); @@ -728,9 +728,9 @@ static int msubu_func(struct pt_regs *regs, u32 ir) res = ((((s64)rt) << 32) | (u32)rs) - res; rt = res; - regs->lo = (s64)rt; + regs->lo = (s64)(s32)rt; rs = res >> 32; - regs->hi = (s64)rs; + regs->hi = (s64)(s32)rs; MIPS_R2_STATS(dsps); From f73dfc29afa6b366158a0f3cc0844bca5fd9ca8f Mon Sep 17 00:00:00 2001 From: James Hughes Date: Mon, 24 Apr 2017 12:40:50 +0100 Subject: [PATCH 077/396] brcmfmac: Ensure pointer correctly set if skb data location changes commit 455a1eb4654c24560eb9dfc634f29cba3d87601e upstream. The incoming skb header may be resized if header space is insufficient, which might change the data adddress in the skb. Ensure that a cached pointer to that data is correctly set by moving assignment to after any possible changes. Signed-off-by: James Hughes Acked-by: Arend van Spriel Signed-off-by: Kalle Valo Signed-off-by: Arend van Spriel Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c index 5eaac13e2317..9b7c19a508ac 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c @@ -198,7 +198,7 @@ static netdev_tx_t brcmf_netdev_start_xmit(struct sk_buff *skb, int ret; struct brcmf_if *ifp = netdev_priv(ndev); struct brcmf_pub *drvr = ifp->drvr; - struct ethhdr *eh = (struct ethhdr *)(skb->data); + struct ethhdr *eh; brcmf_dbg(DATA, "Enter, bsscfgidx=%d\n", ifp->bsscfgidx); @@ -236,6 +236,8 @@ static netdev_tx_t brcmf_netdev_start_xmit(struct sk_buff *skb, goto done; } + eh = (struct ethhdr *)(skb->data); + if (eh->h_proto == htons(ETH_P_PAE)) atomic_inc(&ifp->pend_8021x_cnt); From 0b77c687d4e0bdc6db9bedace1e6886504ea43ef Mon Sep 17 00:00:00 2001 From: James Hughes Date: Tue, 25 Apr 2017 10:15:06 +0100 Subject: [PATCH 078/396] brcmfmac: Make skb header writable before use commit 9cc4b7cb86cbcc6330a3faa8cd65268cd2d3c227 upstream. The driver was making changes to the skb_header without ensuring it was writable (i.e. uncloned). This patch also removes some boiler plate header size checking/adjustment code as that is also handled by the skb_cow_header function used to make header writable. Signed-off-by: James Hughes Acked-by: Arend van Spriel Signed-off-by: Kalle Valo Signed-off-by: Arend van Spriel Signed-off-by: Greg Kroah-Hartman --- .../broadcom/brcm80211/brcmfmac/core.c | 19 +++++-------------- 1 file changed, 5 insertions(+), 14 deletions(-) diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c index 9b7c19a508ac..f877301c9454 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c @@ -211,22 +211,13 @@ static netdev_tx_t brcmf_netdev_start_xmit(struct sk_buff *skb, goto done; } - /* Make sure there's enough room for any header */ - if (skb_headroom(skb) < drvr->hdrlen) { - struct sk_buff *skb2; - - brcmf_dbg(INFO, "%s: insufficient headroom\n", + /* Make sure there's enough writable headroom*/ + ret = skb_cow_head(skb, drvr->hdrlen); + if (ret < 0) { + brcmf_err("%s: skb_cow_head failed\n", brcmf_ifname(ifp)); - drvr->bus_if->tx_realloc++; - skb2 = skb_realloc_headroom(skb, drvr->hdrlen); dev_kfree_skb(skb); - skb = skb2; - if (skb == NULL) { - brcmf_err("%s: skb_realloc_headroom failed\n", - brcmf_ifname(ifp)); - ret = -ENOMEM; - goto done; - } + goto done; } /* validate length for ether packet */ From 47b7257fc20fd7977325babbb13b9610ffca82a9 Mon Sep 17 00:00:00 2001 From: Oleg Drokin Date: Wed, 7 Dec 2016 17:41:27 -0500 Subject: [PATCH 079/396] staging/lustre/llite: move root_squash from sysfs to debugfs commit 4c13990e35b9f053857d4ad83bf0f58e612ec414 upstream. root_squash control got accidentally moved to sysfs instead of debugfs, and the write side of it was also broken expecting a userspace buffer. It contains both uid and gid values in a single file, so debugfs is a clear place for it. Reported-by: Al Viro Fixes: c948390f10ccc "fix inconsistencies of root squash feature" Signed-off-by: Oleg Drokin Reviewed-by: James Simmons Signed-off-by: Greg Kroah-Hartman --- .../staging/lustre/lustre/llite/lproc_llite.c | 27 ++++++++++--------- 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/drivers/staging/lustre/lustre/llite/lproc_llite.c b/drivers/staging/lustre/lustre/llite/lproc_llite.c index 23fda9d98bff..13ec24d44b04 100644 --- a/drivers/staging/lustre/lustre/llite/lproc_llite.c +++ b/drivers/staging/lustre/lustre/llite/lproc_llite.c @@ -924,27 +924,29 @@ static ssize_t ll_unstable_stats_seq_write(struct file *file, } LPROC_SEQ_FOPS(ll_unstable_stats); -static ssize_t root_squash_show(struct kobject *kobj, struct attribute *attr, - char *buf) +static int ll_root_squash_seq_show(struct seq_file *m, void *v) { - struct ll_sb_info *sbi = container_of(kobj, struct ll_sb_info, - ll_kobj); + struct super_block *sb = m->private; + struct ll_sb_info *sbi = ll_s2sbi(sb); struct root_squash_info *squash = &sbi->ll_squash; - return sprintf(buf, "%u:%u\n", squash->rsi_uid, squash->rsi_gid); + seq_printf(m, "%u:%u\n", squash->rsi_uid, squash->rsi_gid); + return 0; } -static ssize_t root_squash_store(struct kobject *kobj, struct attribute *attr, - const char *buffer, size_t count) +static ssize_t ll_root_squash_seq_write(struct file *file, + const char __user *buffer, + size_t count, loff_t *off) { - struct ll_sb_info *sbi = container_of(kobj, struct ll_sb_info, - ll_kobj); + struct seq_file *m = file->private_data; + struct super_block *sb = m->private; + struct ll_sb_info *sbi = ll_s2sbi(sb); struct root_squash_info *squash = &sbi->ll_squash; return lprocfs_wr_root_squash(buffer, count, squash, - ll_get_fsname(sbi->ll_sb, NULL, 0)); + ll_get_fsname(sb, NULL, 0)); } -LUSTRE_RW_ATTR(root_squash); +LPROC_SEQ_FOPS(ll_root_squash); static int ll_nosquash_nids_seq_show(struct seq_file *m, void *v) { @@ -997,6 +999,8 @@ static struct lprocfs_vars lprocfs_llite_obd_vars[] = { { "statahead_stats", &ll_statahead_stats_fops, NULL, 0 }, { "unstable_stats", &ll_unstable_stats_fops, NULL }, { "sbi_flags", &ll_sbi_flags_fops, NULL, 0 }, + { .name = "root_squash", + .fops = &ll_root_squash_fops }, { .name = "nosquash_nids", .fops = &ll_nosquash_nids_fops }, { NULL } @@ -1027,7 +1031,6 @@ static struct attribute *llite_attrs[] = { &lustre_attr_max_easize.attr, &lustre_attr_default_easize.attr, &lustre_attr_xattr_cache.attr, - &lustre_attr_root_squash.attr, NULL, }; From d8e94d091376302064c85c60e922065fca1c2c6b Mon Sep 17 00:00:00 2001 From: Igor Pylypiv Date: Mon, 30 Jan 2017 21:39:54 -0800 Subject: [PATCH 080/396] staging: wlan-ng: add missing byte order conversion commit 2c474b8579e9b67ff72b2bcefce9f53c7f4469d4 upstream. Conversion macros le16_to_cpu was removed and that caused new sparse warning sparse output: drivers/staging/wlan-ng/p80211netdev.c:241:44: warning: incorrect type in argument 2 (different base types) drivers/staging/wlan-ng/p80211netdev.c:241:44: expected unsigned short [unsigned] [usertype] fc drivers/staging/wlan-ng/p80211netdev.c:241:44: got restricted __le16 [usertype] fc Fixes: 7ad82572348c ("staging:wlan-ng:Fix sparse warning") Signed-off-by: Igor Pylypiv Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wlan-ng/p80211netdev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/wlan-ng/p80211netdev.c b/drivers/staging/wlan-ng/p80211netdev.c index 825a63a7c0e3..2e075a60f876 100644 --- a/drivers/staging/wlan-ng/p80211netdev.c +++ b/drivers/staging/wlan-ng/p80211netdev.c @@ -232,7 +232,7 @@ static int p80211_convert_to_ether(struct wlandevice *wlandev, struct sk_buff *s struct p80211_hdr_a3 *hdr; hdr = (struct p80211_hdr_a3 *)skb->data; - if (p80211_rx_typedrop(wlandev, hdr->fc)) + if (p80211_rx_typedrop(wlandev, le16_to_cpu(hdr->fc))) return CONV_TO_ETHER_SKIPPED; /* perform mcast filtering: allow my local address through but reject From 170e0abd886bd0ce5676e6393aab4b0148549d50 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Fri, 16 Dec 2016 10:09:39 +0100 Subject: [PATCH 081/396] staging: emxx_udc: remove incorrect __init annotations commit 4f3445067d5f78fb8d1970b02610f85c2f377ea4 upstream. The probe function is not marked __init, but some other functions are. This leads to a warning on older compilers (e.g. gcc-4.3), and can cause executing freed memory when built with those compilers: WARNING: drivers/staging/emxx_udc/emxx_udc.o(.text+0x2d78): Section mismatch in reference from the function nbu2ss_drv_probe() to the function .init.text:nbu2ss_drv_contest_init() This removes the annotations. Fixes: 33aa8d45a4fe ("staging: emxx_udc: Add Emma Mobile USB Gadget driver") Signed-off-by: Arnd Bergmann Signed-off-by: Greg Kroah-Hartman --- drivers/staging/emxx_udc/emxx_udc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/emxx_udc/emxx_udc.c b/drivers/staging/emxx_udc/emxx_udc.c index c3e298843b43..1055649f034c 100644 --- a/drivers/staging/emxx_udc/emxx_udc.c +++ b/drivers/staging/emxx_udc/emxx_udc.c @@ -3160,7 +3160,7 @@ static const struct { }; /*-------------------------------------------------------------------------*/ -static void __init nbu2ss_drv_ep_init(struct nbu2ss_udc *udc) +static void nbu2ss_drv_ep_init(struct nbu2ss_udc *udc) { int i; @@ -3191,7 +3191,7 @@ static void __init nbu2ss_drv_ep_init(struct nbu2ss_udc *udc) /*-------------------------------------------------------------------------*/ /* platform_driver */ -static int __init nbu2ss_drv_contest_init( +static int nbu2ss_drv_contest_init( struct platform_device *pdev, struct nbu2ss_udc *udc) { From 7aa0e14336d977101193bef85af69b203bfba24f Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 2 Jan 2017 11:37:04 +0100 Subject: [PATCH 082/396] ALSA: hda - Fix deadlock of controller device lock at unbinding commit ab949d519601880fd46e8bc1445d6a453bf2dc09 upstream. Imre Deak reported a deadlock of HD-audio driver at unbinding while it's still in probing. Since we probe the codecs asynchronously in a work, the codec driver probe may still be kicked off while the controller itself is being unbound. And, azx_remove() tries to process all pending tasks via cancel_work_sync() for fixing the other races (see commit [0b8c82190c12: ALSA: hda - Cancel probe work instead of flush at remove]), now we may meet a bizarre deadlock: Unbind snd_hda_intel via sysfs: device_release_driver() -> device_lock(snd_hda_intel) -> azx_remove() -> cancel_work_sync(azx_probe_work) azx_probe_work(): codec driver probe() -> __driver_attach() -> device_lock(snd_hda_intel) This deadlock is caused by the fact that both device_release_driver() and driver_probe_device() take both the device and its parent locks at the same time. The codec device sets the controller device as its parent, and this lock is taken before the probe() callback is called, while the controller remove() callback gets called also with the same lock. In this patch, as an ugly workaround, we unlock the controller device temporarily during cancel_work_sync() call. The race against another bind call should be still suppressed by the parent's device lock. Reported-by: Imre Deak Fixes: 0b8c82190c12 ("ALSA: hda - Cancel probe work instead of flush at remove") Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/pci/hda/hda_intel.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index bc4462694aaf..5cb7e04fa4ba 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -2155,7 +2155,20 @@ static void azx_remove(struct pci_dev *pci) /* cancel the pending probing work */ chip = card->private_data; hda = container_of(chip, struct hda_intel, chip); + /* FIXME: below is an ugly workaround. + * Both device_release_driver() and driver_probe_device() + * take *both* the device's and its parent's lock before + * calling the remove() and probe() callbacks. The codec + * probe takes the locks of both the codec itself and its + * parent, i.e. the PCI controller dev. Meanwhile, when + * the PCI controller is unbound, it takes its lock, too + * ==> ouch, a deadlock! + * As a workaround, we unlock temporarily here the controller + * device during cancel_work_sync() call. + */ + device_unlock(&pci->dev); cancel_work_sync(&hda->probe_work); + device_lock(&pci->dev); snd_card_free(card); } From 22d6b013ffcf4809b4fe03b240855c6f8eb54599 Mon Sep 17 00:00:00 2001 From: Dave Aldridge Date: Tue, 9 May 2017 02:57:35 -0600 Subject: [PATCH 083/396] sparc64: fix fault handling in NGbzero.S and GENbzero.S commit 3c7f62212018b904ae17f5636ead18a4dca3a88f upstream. When any of the functions contained in NGbzero.S and GENbzero.S vector through *bzero_from_clear_user, we may end up taking a fault when executing one of the store alternate address space instructions. If this happens, the exception handler does not restore the %asi register. This commit fixes the issue by introducing a new exception handler that ensures the %asi register is restored when a fault is handled. Orabug: 25577560 Signed-off-by: Dave Aldridge Reviewed-by: Rob Gardner Reviewed-by: Babu Moger Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- arch/sparc/kernel/head_64.S | 6 ++++++ arch/sparc/lib/GENbzero.S | 2 +- arch/sparc/lib/NGbzero.S | 2 +- 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/arch/sparc/kernel/head_64.S b/arch/sparc/kernel/head_64.S index 6aa3da152c20..9835152a0682 100644 --- a/arch/sparc/kernel/head_64.S +++ b/arch/sparc/kernel/head_64.S @@ -935,3 +935,9 @@ ENTRY(__retl_o1) retl mov %o1, %o0 ENDPROC(__retl_o1) + +ENTRY(__retl_o1_asi) + wr %o5, 0x0, %asi + retl + mov %o1, %o0 +ENDPROC(__retl_o1_asi) diff --git a/arch/sparc/lib/GENbzero.S b/arch/sparc/lib/GENbzero.S index 8e7a843ddd88..2fbf6297d57c 100644 --- a/arch/sparc/lib/GENbzero.S +++ b/arch/sparc/lib/GENbzero.S @@ -8,7 +8,7 @@ 98: x,y; \ .section __ex_table,"a";\ .align 4; \ - .word 98b, __retl_o1; \ + .word 98b, __retl_o1_asi;\ .text; \ .align 4; diff --git a/arch/sparc/lib/NGbzero.S b/arch/sparc/lib/NGbzero.S index beab29bf419b..33053bdf3766 100644 --- a/arch/sparc/lib/NGbzero.S +++ b/arch/sparc/lib/NGbzero.S @@ -8,7 +8,7 @@ 98: x,y; \ .section __ex_table,"a";\ .align 4; \ - .word 98b, __retl_o1; \ + .word 98b, __retl_o1_asi;\ .text; \ .align 4; From 3b0129d4111e53927c2bc3c6b78a2b12ad71268b Mon Sep 17 00:00:00 2001 From: "Jason A. Donenfeld" Date: Tue, 25 Apr 2017 19:08:18 +0200 Subject: [PATCH 084/396] macsec: dynamically allocate space for sglist [ Upstream commit 5294b83086cc1c35b4efeca03644cf9d12282e5b ] We call skb_cow_data, which is good anyway to ensure we can actually modify the skb as such (another error from prior). Now that we have the number of fragments required, we can safely allocate exactly that amount of memory. Fixes: c09440f7dcb3 ("macsec: introduce IEEE 802.1AE driver") Signed-off-by: Jason A. Donenfeld Acked-by: Sabrina Dubroca Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/macsec.c | 29 ++++++++++++++++++++++------- 1 file changed, 22 insertions(+), 7 deletions(-) diff --git a/drivers/net/macsec.c b/drivers/net/macsec.c index f7c6a40aae81..a5d66e205bb2 100644 --- a/drivers/net/macsec.c +++ b/drivers/net/macsec.c @@ -617,7 +617,8 @@ static void macsec_encrypt_done(struct crypto_async_request *base, int err) static struct aead_request *macsec_alloc_req(struct crypto_aead *tfm, unsigned char **iv, - struct scatterlist **sg) + struct scatterlist **sg, + int num_frags) { size_t size, iv_offset, sg_offset; struct aead_request *req; @@ -629,7 +630,7 @@ static struct aead_request *macsec_alloc_req(struct crypto_aead *tfm, size = ALIGN(size, __alignof__(struct scatterlist)); sg_offset = size; - size += sizeof(struct scatterlist) * (MAX_SKB_FRAGS + 1); + size += sizeof(struct scatterlist) * num_frags; tmp = kmalloc(size, GFP_ATOMIC); if (!tmp) @@ -649,6 +650,7 @@ static struct sk_buff *macsec_encrypt(struct sk_buff *skb, { int ret; struct scatterlist *sg; + struct sk_buff *trailer; unsigned char *iv; struct ethhdr *eth; struct macsec_eth_header *hh; @@ -723,7 +725,14 @@ static struct sk_buff *macsec_encrypt(struct sk_buff *skb, return ERR_PTR(-EINVAL); } - req = macsec_alloc_req(tx_sa->key.tfm, &iv, &sg); + ret = skb_cow_data(skb, 0, &trailer); + if (unlikely(ret < 0)) { + macsec_txsa_put(tx_sa); + kfree_skb(skb); + return ERR_PTR(ret); + } + + req = macsec_alloc_req(tx_sa->key.tfm, &iv, &sg, ret); if (!req) { macsec_txsa_put(tx_sa); kfree_skb(skb); @@ -732,7 +741,7 @@ static struct sk_buff *macsec_encrypt(struct sk_buff *skb, macsec_fill_iv(iv, secy->sci, pn); - sg_init_table(sg, MAX_SKB_FRAGS + 1); + sg_init_table(sg, ret); skb_to_sgvec(skb, sg, 0, skb->len); if (tx_sc->encrypt) { @@ -914,6 +923,7 @@ static struct sk_buff *macsec_decrypt(struct sk_buff *skb, { int ret; struct scatterlist *sg; + struct sk_buff *trailer; unsigned char *iv; struct aead_request *req; struct macsec_eth_header *hdr; @@ -924,7 +934,12 @@ static struct sk_buff *macsec_decrypt(struct sk_buff *skb, if (!skb) return ERR_PTR(-ENOMEM); - req = macsec_alloc_req(rx_sa->key.tfm, &iv, &sg); + ret = skb_cow_data(skb, 0, &trailer); + if (unlikely(ret < 0)) { + kfree_skb(skb); + return ERR_PTR(ret); + } + req = macsec_alloc_req(rx_sa->key.tfm, &iv, &sg, ret); if (!req) { kfree_skb(skb); return ERR_PTR(-ENOMEM); @@ -933,7 +948,7 @@ static struct sk_buff *macsec_decrypt(struct sk_buff *skb, hdr = (struct macsec_eth_header *)skb->data; macsec_fill_iv(iv, sci, ntohl(hdr->packet_number)); - sg_init_table(sg, MAX_SKB_FRAGS + 1); + sg_init_table(sg, ret); skb_to_sgvec(skb, sg, 0, skb->len); if (hdr->tci_an & MACSEC_TCI_E) { @@ -2709,7 +2724,7 @@ static netdev_tx_t macsec_start_xmit(struct sk_buff *skb, } #define MACSEC_FEATURES \ - (NETIF_F_SG | NETIF_F_HIGHDMA) + (NETIF_F_SG | NETIF_F_HIGHDMA | NETIF_F_FRAGLIST) static struct lock_class_key macsec_netdev_addr_lock_key; static int macsec_dev_init(struct net_device *dev) From f3235cbd5be15aa084d5561c2eb8492ed68cd7e5 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Wed, 26 Apr 2017 17:15:40 -0700 Subject: [PATCH 085/396] tcp: do not underestimate skb->truesize in tcp_trim_head() [ Upstream commit 7162fb242cb8322beb558828fd26b33c3e9fc805 ] Andrey found a way to trigger the WARN_ON_ONCE(delta < len) in skb_try_coalesce() using syzkaller and a filter attached to a TCP socket over loopback interface. I believe one issue with looped skbs is that tcp_trim_head() can end up producing skb with under estimated truesize. It hardly matters for normal conditions, since packets sent over loopback are never truncated. Bytes trimmed from skb->head should not change skb truesize, since skb->head is not reallocated. Signed-off-by: Eric Dumazet Reported-by: Andrey Konovalov Tested-by: Andrey Konovalov Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/ipv4/tcp_output.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index 65d6189140bc..dc4258fd15dc 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c @@ -1246,7 +1246,7 @@ int tcp_fragment(struct sock *sk, struct sk_buff *skb, u32 len, * eventually). The difference is that pulled data not copied, but * immediately discarded. */ -static void __pskb_trim_head(struct sk_buff *skb, int len) +static int __pskb_trim_head(struct sk_buff *skb, int len) { struct skb_shared_info *shinfo; int i, k, eat; @@ -1256,7 +1256,7 @@ static void __pskb_trim_head(struct sk_buff *skb, int len) __skb_pull(skb, eat); len -= eat; if (!len) - return; + return 0; } eat = len; k = 0; @@ -1282,23 +1282,28 @@ static void __pskb_trim_head(struct sk_buff *skb, int len) skb_reset_tail_pointer(skb); skb->data_len -= len; skb->len = skb->data_len; + return len; } /* Remove acked data from a packet in the transmit queue. */ int tcp_trim_head(struct sock *sk, struct sk_buff *skb, u32 len) { + u32 delta_truesize; + if (skb_unclone(skb, GFP_ATOMIC)) return -ENOMEM; - __pskb_trim_head(skb, len); + delta_truesize = __pskb_trim_head(skb, len); TCP_SKB_CB(skb)->seq += len; skb->ip_summed = CHECKSUM_PARTIAL; - skb->truesize -= len; - sk->sk_wmem_queued -= len; - sk_mem_uncharge(sk, len); - sock_set_flag(sk, SOCK_QUEUE_SHRUNK); + if (delta_truesize) { + skb->truesize -= delta_truesize; + sk->sk_wmem_queued -= delta_truesize; + sk_mem_uncharge(sk, delta_truesize); + sock_set_flag(sk, SOCK_QUEUE_SHRUNK); + } /* Any change of skb->len requires recalculation of tso factor. */ if (tcp_skb_pcount(skb) > 1) From 7bca0a9702edfc8d0e7e46f984ca422ffdbe0498 Mon Sep 17 00:00:00 2001 From: Yonghong Song Date: Sat, 29 Apr 2017 22:52:42 -0700 Subject: [PATCH 086/396] bpf: enhance verifier to understand stack pointer arithmetic [ Upstream commit 332270fdc8b6fba07d059a9ad44df9e1a2ad4529 ] llvm 4.0 and above generates the code like below: .... 440: (b7) r1 = 15 441: (05) goto pc+73 515: (79) r6 = *(u64 *)(r10 -152) 516: (bf) r7 = r10 517: (07) r7 += -112 518: (bf) r2 = r7 519: (0f) r2 += r1 520: (71) r1 = *(u8 *)(r8 +0) 521: (73) *(u8 *)(r2 +45) = r1 .... and the verifier complains "R2 invalid mem access 'inv'" for insn #521. This is because verifier marks register r2 as unknown value after #519 where r2 is a stack pointer and r1 holds a constant value. Teach verifier to recognize "stack_ptr + imm" and "stack_ptr + reg with const val" as valid stack_ptr with new offset. Signed-off-by: Yonghong Song Acked-by: Martin KaFai Lau Acked-by: Daniel Borkmann Signed-off-by: Alexei Starovoitov Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- kernel/bpf/verifier.c | 11 +++++++++++ samples/bpf/test_verifier.c | 18 ++++++++++++------ 2 files changed, 23 insertions(+), 6 deletions(-) diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c index 7c9f94c53441..64fcab1d8cd9 100644 --- a/kernel/bpf/verifier.c +++ b/kernel/bpf/verifier.c @@ -1747,6 +1747,17 @@ static int check_alu_op(struct bpf_verifier_env *env, struct bpf_insn *insn) dst_reg->type = PTR_TO_STACK; dst_reg->imm = insn->imm; return 0; + } else if (opcode == BPF_ADD && + BPF_CLASS(insn->code) == BPF_ALU64 && + dst_reg->type == PTR_TO_STACK && + ((BPF_SRC(insn->code) == BPF_X && + regs[insn->src_reg].type == CONST_IMM) || + BPF_SRC(insn->code) == BPF_K)) { + if (BPF_SRC(insn->code) == BPF_X) + dst_reg->imm += regs[insn->src_reg].imm; + else + dst_reg->imm += insn->imm; + return 0; } else if (opcode == BPF_ADD && BPF_CLASS(insn->code) == BPF_ALU64 && (dst_reg->type == PTR_TO_PACKET || diff --git a/samples/bpf/test_verifier.c b/samples/bpf/test_verifier.c index 369ffaad3799..dc7dec9e64ba 100644 --- a/samples/bpf/test_verifier.c +++ b/samples/bpf/test_verifier.c @@ -1218,16 +1218,22 @@ static struct bpf_test tests[] = { .result = ACCEPT, }, { - "unpriv: obfuscate stack pointer", + "stack pointer arithmetic", .insns = { - BPF_MOV64_REG(BPF_REG_2, BPF_REG_10), - BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8), - BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8), + BPF_MOV64_IMM(BPF_REG_1, 4), + BPF_JMP_IMM(BPF_JA, 0, 0, 0), + BPF_MOV64_REG(BPF_REG_7, BPF_REG_10), + BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -10), + BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -10), + BPF_MOV64_REG(BPF_REG_2, BPF_REG_7), + BPF_ALU64_REG(BPF_ADD, BPF_REG_2, BPF_REG_1), + BPF_ST_MEM(0, BPF_REG_2, 4, 0), + BPF_MOV64_REG(BPF_REG_2, BPF_REG_7), + BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, 8), + BPF_ST_MEM(0, BPF_REG_2, 4, 0), BPF_MOV64_IMM(BPF_REG_0, 0), BPF_EXIT_INSN(), }, - .errstr_unpriv = "R2 pointer arithmetic", - .result_unpriv = REJECT, .result = ACCEPT, }, { From 493d0a7be31caba12734942d14fa28bed389862a Mon Sep 17 00:00:00 2001 From: Daniel Borkmann Date: Tue, 2 May 2017 20:34:54 +0200 Subject: [PATCH 087/396] bpf, arm64: fix jit branch offset related to ldimm64 [ Upstream commit ddc665a4bb4b728b4e6ecec8db1b64efa9184b9c ] When the instruction right before the branch destination is a 64 bit load immediate, we currently calculate the wrong jump offset in the ctx->offset[] array as we only account one instruction slot for the 64 bit load immediate although it uses two BPF instructions. Fix it up by setting the offset into the right slot after we incremented the index. Before (ldimm64 test 1): [...] 00000020: 52800007 mov w7, #0x0 // #0 00000024: d2800060 mov x0, #0x3 // #3 00000028: d2800041 mov x1, #0x2 // #2 0000002c: eb01001f cmp x0, x1 00000030: 54ffff82 b.cs 0x00000020 00000034: d29fffe7 mov x7, #0xffff // #65535 00000038: f2bfffe7 movk x7, #0xffff, lsl #16 0000003c: f2dfffe7 movk x7, #0xffff, lsl #32 00000040: f2ffffe7 movk x7, #0xffff, lsl #48 00000044: d29dddc7 mov x7, #0xeeee // #61166 00000048: f2bdddc7 movk x7, #0xeeee, lsl #16 0000004c: f2ddddc7 movk x7, #0xeeee, lsl #32 00000050: f2fdddc7 movk x7, #0xeeee, lsl #48 [...] After (ldimm64 test 1): [...] 00000020: 52800007 mov w7, #0x0 // #0 00000024: d2800060 mov x0, #0x3 // #3 00000028: d2800041 mov x1, #0x2 // #2 0000002c: eb01001f cmp x0, x1 00000030: 540000a2 b.cs 0x00000044 00000034: d29fffe7 mov x7, #0xffff // #65535 00000038: f2bfffe7 movk x7, #0xffff, lsl #16 0000003c: f2dfffe7 movk x7, #0xffff, lsl #32 00000040: f2ffffe7 movk x7, #0xffff, lsl #48 00000044: d29dddc7 mov x7, #0xeeee // #61166 00000048: f2bdddc7 movk x7, #0xeeee, lsl #16 0000004c: f2ddddc7 movk x7, #0xeeee, lsl #32 00000050: f2fdddc7 movk x7, #0xeeee, lsl #48 [...] Also, add a couple of test cases to make sure JITs pass this test. Tested on Cavium ThunderX ARMv8. The added test cases all pass after the fix. Fixes: 8eee539ddea0 ("arm64: bpf: fix out-of-bounds read in bpf2a64_offset()") Reported-by: David S. Miller Signed-off-by: Daniel Borkmann Acked-by: Alexei Starovoitov Cc: Xi Wang Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- arch/arm64/net/bpf_jit_comp.c | 8 +++---- lib/test_bpf.c | 45 +++++++++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+), 4 deletions(-) diff --git a/arch/arm64/net/bpf_jit_comp.c b/arch/arm64/net/bpf_jit_comp.c index b2fc97a2c56c..9c4b57a7b265 100644 --- a/arch/arm64/net/bpf_jit_comp.c +++ b/arch/arm64/net/bpf_jit_comp.c @@ -779,14 +779,14 @@ static int build_body(struct jit_ctx *ctx) int ret; ret = build_insn(insn, ctx); - - if (ctx->image == NULL) - ctx->offset[i] = ctx->idx; - if (ret > 0) { i++; + if (ctx->image == NULL) + ctx->offset[i] = ctx->idx; continue; } + if (ctx->image == NULL) + ctx->offset[i] = ctx->idx; if (ret) return ret; } diff --git a/lib/test_bpf.c b/lib/test_bpf.c index 0362da0b66c3..2e385026915c 100644 --- a/lib/test_bpf.c +++ b/lib/test_bpf.c @@ -4656,6 +4656,51 @@ static struct bpf_test tests[] = { { }, { { 0, 1 } }, }, + { + /* Mainly testing JIT + imm64 here. */ + "JMP_JGE_X: ldimm64 test 1", + .u.insns_int = { + BPF_ALU32_IMM(BPF_MOV, R0, 0), + BPF_LD_IMM64(R1, 3), + BPF_LD_IMM64(R2, 2), + BPF_JMP_REG(BPF_JGE, R1, R2, 2), + BPF_LD_IMM64(R0, 0xffffffffffffffffUL), + BPF_LD_IMM64(R0, 0xeeeeeeeeeeeeeeeeUL), + BPF_EXIT_INSN(), + }, + INTERNAL, + { }, + { { 0, 0xeeeeeeeeU } }, + }, + { + "JMP_JGE_X: ldimm64 test 2", + .u.insns_int = { + BPF_ALU32_IMM(BPF_MOV, R0, 0), + BPF_LD_IMM64(R1, 3), + BPF_LD_IMM64(R2, 2), + BPF_JMP_REG(BPF_JGE, R1, R2, 0), + BPF_LD_IMM64(R0, 0xffffffffffffffffUL), + BPF_EXIT_INSN(), + }, + INTERNAL, + { }, + { { 0, 0xffffffffU } }, + }, + { + "JMP_JGE_X: ldimm64 test 3", + .u.insns_int = { + BPF_ALU32_IMM(BPF_MOV, R0, 1), + BPF_LD_IMM64(R1, 3), + BPF_LD_IMM64(R2, 2), + BPF_JMP_REG(BPF_JGE, R1, R2, 4), + BPF_LD_IMM64(R0, 0xffffffffffffffffUL), + BPF_LD_IMM64(R0, 0xeeeeeeeeeeeeeeeeUL), + BPF_EXIT_INSN(), + }, + INTERNAL, + { }, + { { 0, 1 } }, + }, /* BPF_JMP | BPF_JNE | BPF_X */ { "JMP_JNE_X: if (3 != 2) return 1", From 91260baa9d673bc7b4e0ca95d94e2b086a597773 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Mon, 1 May 2017 15:29:48 -0700 Subject: [PATCH 088/396] tcp: fix wraparound issue in tcp_lp [ Upstream commit a9f11f963a546fea9144f6a6d1a307e814a387e7 ] Be careful when comparing tcp_time_stamp to some u32 quantity, otherwise result can be surprising. Fixes: 7c106d7e782b ("[TCP]: TCP Low Priority congestion control") Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/ipv4/tcp_lp.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/net/ipv4/tcp_lp.c b/net/ipv4/tcp_lp.c index c67ece1390c2..7d86fc505397 100644 --- a/net/ipv4/tcp_lp.c +++ b/net/ipv4/tcp_lp.c @@ -264,13 +264,15 @@ static void tcp_lp_pkts_acked(struct sock *sk, const struct ack_sample *sample) { struct tcp_sock *tp = tcp_sk(sk); struct lp *lp = inet_csk_ca(sk); + u32 delta; if (sample->rtt_us > 0) tcp_lp_rtt_sample(sk, sample->rtt_us); /* calc inference */ - if (tcp_time_stamp > tp->rx_opt.rcv_tsecr) - lp->inference = 3 * (tcp_time_stamp - tp->rx_opt.rcv_tsecr); + delta = tcp_time_stamp - tp->rx_opt.rcv_tsecr; + if ((s32)delta > 0) + lp->inference = 3 * delta; /* test if within inference */ if (lp->last_drop && (tcp_time_stamp - lp->last_drop < lp->inference)) From 0f4ac291a7687ad4a26cbef573aeb184e341a822 Mon Sep 17 00:00:00 2001 From: David Ahern Date: Tue, 2 May 2017 14:43:44 -0700 Subject: [PATCH 089/396] net: ipv6: Do not duplicate DAD on link up [ Upstream commit 6d717134a1a6e1b34a7d0d70e953037bc2642046 ] Andrey reported a warning triggered by the rcu code: ------------[ cut here ]------------ WARNING: CPU: 1 PID: 5911 at lib/debugobjects.c:289 debug_print_object+0x175/0x210 ODEBUG: activate active (active state 1) object type: rcu_head hint: (null) Modules linked in: CPU: 1 PID: 5911 Comm: a.out Not tainted 4.11.0-rc8+ #271 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Bochs 01/01/2011 Call Trace: __dump_stack lib/dump_stack.c:16 dump_stack+0x192/0x22d lib/dump_stack.c:52 __warn+0x19f/0x1e0 kernel/panic.c:549 warn_slowpath_fmt+0xe0/0x120 kernel/panic.c:564 debug_print_object+0x175/0x210 lib/debugobjects.c:286 debug_object_activate+0x574/0x7e0 lib/debugobjects.c:442 debug_rcu_head_queue kernel/rcu/rcu.h:75 __call_rcu.constprop.76+0xff/0x9c0 kernel/rcu/tree.c:3229 call_rcu_sched+0x12/0x20 kernel/rcu/tree.c:3288 rt6_rcu_free net/ipv6/ip6_fib.c:158 rt6_release+0x1ea/0x290 net/ipv6/ip6_fib.c:188 fib6_del_route net/ipv6/ip6_fib.c:1461 fib6_del+0xa42/0xdc0 net/ipv6/ip6_fib.c:1500 __ip6_del_rt+0x100/0x160 net/ipv6/route.c:2174 ip6_del_rt+0x140/0x1b0 net/ipv6/route.c:2187 __ipv6_ifa_notify+0x269/0x780 net/ipv6/addrconf.c:5520 addrconf_ifdown+0xe60/0x1a20 net/ipv6/addrconf.c:3672 ... Andrey's reproducer program runs in a very tight loop, calling 'unshare -n' and then spawning 2 sets of 14 threads running random ioctl calls. The relevant networking sequence: 1. New network namespace created via unshare -n - ip6tnl0 device is created in down state 2. address added to ip6tnl0 - equivalent to ip -6 addr add dev ip6tnl0 fd00::bb/1 - DAD is started on the address and when it completes the host route is inserted into the FIB 3. ip6tnl0 is brought up - the new fixup_permanent_addr function restarts DAD on the address 4. exit namespace - teardown / cleanup sequence starts - once in a blue moon, lo teardown appears to happen BEFORE teardown of ip6tunl0 + down on 'lo' removes the host route from the FIB since the dst->dev for the route is loobback + host route added to rcu callback list * rcu callback has not run yet, so rt is NOT on the gc list so it has NOT been marked obsolete 5. in parallel to 4. worker_thread runs addrconf_dad_completed - DAD on the address on ip6tnl0 completes - calls ipv6_ifa_notify which inserts the host route All of that happens very quickly. The result is that a host route that has been deleted from the IPv6 FIB and added to the RCU list is re-inserted into the FIB. The exit namespace eventually gets to cleaning up ip6tnl0 which removes the host route from the FIB again, calls the rcu function for cleanup -- and triggers the double rcu trace. The root cause is duplicate DAD on the address -- steps 2 and 3. Arguably, DAD should not be started in step 2. The interface is in the down state, so it can not really send out requests for the address which makes starting DAD pointless. Since the second DAD was introduced by a recent change, seems appropriate to use it for the Fixes tag and have the fixup function only start DAD for addresses in the PREDAD state which occurs in addrconf_ifdown if the address is retained. Big thanks to Andrey for isolating a reliable reproducer for this problem. Fixes: f1705ec197e7 ("net: ipv6: Make address flushing on ifdown optional") Reported-by: Andrey Konovalov Signed-off-by: David Ahern Tested-by: Andrey Konovalov Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/ipv6/addrconf.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index cffdbdbff3a2..e0a083f49227 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -3278,7 +3278,8 @@ static int fixup_permanent_addr(struct inet6_dev *idev, idev->dev, 0, 0); } - addrconf_dad_start(ifp); + if (ifp->state == INET6_IFADDR_STATE_PREDAD) + addrconf_dad_start(ifp); return 0; } @@ -3627,7 +3628,7 @@ restart: if (keep) { /* set state to skip the notifier below */ state = INET6_IFADDR_STATE_DEAD; - ifa->state = 0; + ifa->state = INET6_IFADDR_STATE_PREDAD; if (!(ifa->flags & IFA_F_NODAD)) ifa->flags |= IFA_F_TENTATIVE; From 78f032b071c170999b1485bc9d11c1a29414060e Mon Sep 17 00:00:00 2001 From: Daniele Palmas Date: Wed, 3 May 2017 10:30:11 +0200 Subject: [PATCH 090/396] net: usb: qmi_wwan: add Telit ME910 support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [ Upstream commit 4c54dc0277d0d55a9248c43aebd31858f926a056 ] This patch adds support for Telit ME910 PID 0x1100. Signed-off-by: Daniele Palmas Acked-by: Bjørn Mork Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/usb/qmi_wwan.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c index 0d519a9582ca..34d997ca1b27 100644 --- a/drivers/net/usb/qmi_wwan.c +++ b/drivers/net/usb/qmi_wwan.c @@ -902,6 +902,7 @@ static const struct usb_device_id products[] = { {QMI_FIXED_INTF(0x2357, 0x0201, 4)}, /* TP-LINK HSUPA Modem MA180 */ {QMI_FIXED_INTF(0x2357, 0x9000, 4)}, /* TP-LINK MA260 */ {QMI_QUIRK_SET_DTR(0x1bc7, 0x1040, 2)}, /* Telit LE922A */ + {QMI_FIXED_INTF(0x1bc7, 0x1100, 3)}, /* Telit ME910 */ {QMI_FIXED_INTF(0x1bc7, 0x1200, 5)}, /* Telit LE920 */ {QMI_FIXED_INTF(0x1bc7, 0x1201, 2)}, /* Telit LE920 */ {QMI_FIXED_INTF(0x1c9e, 0x9b01, 3)}, /* XS Stick W100-2 from 4G Systems */ From 747a00193f261f952c9dac86621441ba53e20f58 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Wed, 3 May 2017 06:39:31 -0700 Subject: [PATCH 091/396] tcp: do not inherit fastopen_req from parent [ Upstream commit 8b485ce69876c65db12ed390e7f9c0d2a64eff2c ] Under fuzzer stress, it is possible that a child gets a non NULL fastopen_req pointer from its parent at accept() time, when/if parent morphs from listener to active session. We need to make sure this can not happen, by clearing the field after socket cloning. BUG: Double free or freeing an invalid pointer Unexpected shadow byte: 0xFB CPU: 3 PID: 20933 Comm: syz-executor3 Not tainted 4.11.0+ #306 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Bochs 01/01/2011 Call Trace: __dump_stack lib/dump_stack.c:16 [inline] dump_stack+0x292/0x395 lib/dump_stack.c:52 kasan_object_err+0x1c/0x70 mm/kasan/report.c:164 kasan_report_double_free+0x5c/0x70 mm/kasan/report.c:185 kasan_slab_free+0x9d/0xc0 mm/kasan/kasan.c:580 slab_free_hook mm/slub.c:1357 [inline] slab_free_freelist_hook mm/slub.c:1379 [inline] slab_free mm/slub.c:2961 [inline] kfree+0xe8/0x2b0 mm/slub.c:3882 tcp_free_fastopen_req net/ipv4/tcp.c:1077 [inline] tcp_disconnect+0xc15/0x13e0 net/ipv4/tcp.c:2328 inet_child_forget+0xb8/0x600 net/ipv4/inet_connection_sock.c:898 inet_csk_reqsk_queue_add+0x1e7/0x250 net/ipv4/inet_connection_sock.c:928 tcp_get_cookie_sock+0x21a/0x510 net/ipv4/syncookies.c:217 cookie_v4_check+0x1a19/0x28b0 net/ipv4/syncookies.c:384 tcp_v4_cookie_check net/ipv4/tcp_ipv4.c:1384 [inline] tcp_v4_do_rcv+0x731/0x940 net/ipv4/tcp_ipv4.c:1421 tcp_v4_rcv+0x2dc0/0x31c0 net/ipv4/tcp_ipv4.c:1715 ip_local_deliver_finish+0x4cc/0xc20 net/ipv4/ip_input.c:216 NF_HOOK include/linux/netfilter.h:257 [inline] ip_local_deliver+0x1ce/0x700 net/ipv4/ip_input.c:257 dst_input include/net/dst.h:492 [inline] ip_rcv_finish+0xb1d/0x20b0 net/ipv4/ip_input.c:396 NF_HOOK include/linux/netfilter.h:257 [inline] ip_rcv+0xd8c/0x19c0 net/ipv4/ip_input.c:487 __netif_receive_skb_core+0x1ad1/0x3400 net/core/dev.c:4210 __netif_receive_skb+0x2a/0x1a0 net/core/dev.c:4248 process_backlog+0xe5/0x6c0 net/core/dev.c:4868 napi_poll net/core/dev.c:5270 [inline] net_rx_action+0xe70/0x18e0 net/core/dev.c:5335 __do_softirq+0x2fb/0xb99 kernel/softirq.c:284 do_softirq_own_stack+0x1c/0x30 arch/x86/entry/entry_64.S:899 do_softirq.part.17+0x1e8/0x230 kernel/softirq.c:328 do_softirq kernel/softirq.c:176 [inline] __local_bh_enable_ip+0x1cf/0x1e0 kernel/softirq.c:181 local_bh_enable include/linux/bottom_half.h:31 [inline] rcu_read_unlock_bh include/linux/rcupdate.h:931 [inline] ip_finish_output2+0x9ab/0x15e0 net/ipv4/ip_output.c:230 ip_finish_output+0xa35/0xdf0 net/ipv4/ip_output.c:316 NF_HOOK_COND include/linux/netfilter.h:246 [inline] ip_output+0x1f6/0x7b0 net/ipv4/ip_output.c:404 dst_output include/net/dst.h:486 [inline] ip_local_out+0x95/0x160 net/ipv4/ip_output.c:124 ip_queue_xmit+0x9a8/0x1a10 net/ipv4/ip_output.c:503 tcp_transmit_skb+0x1ade/0x3470 net/ipv4/tcp_output.c:1057 tcp_write_xmit+0x79e/0x55b0 net/ipv4/tcp_output.c:2265 __tcp_push_pending_frames+0xfa/0x3a0 net/ipv4/tcp_output.c:2450 tcp_push+0x4ee/0x780 net/ipv4/tcp.c:683 tcp_sendmsg+0x128d/0x39b0 net/ipv4/tcp.c:1342 inet_sendmsg+0x164/0x5b0 net/ipv4/af_inet.c:762 sock_sendmsg_nosec net/socket.c:633 [inline] sock_sendmsg+0xca/0x110 net/socket.c:643 SYSC_sendto+0x660/0x810 net/socket.c:1696 SyS_sendto+0x40/0x50 net/socket.c:1664 entry_SYSCALL_64_fastpath+0x1f/0xbe RIP: 0033:0x446059 RSP: 002b:00007faa6761fb58 EFLAGS: 00000282 ORIG_RAX: 000000000000002c RAX: ffffffffffffffda RBX: 0000000000000017 RCX: 0000000000446059 RDX: 0000000000000001 RSI: 0000000020ba3fcd RDI: 0000000000000017 RBP: 00000000006e40a0 R08: 0000000020ba4ff0 R09: 0000000000000010 R10: 0000000020000000 R11: 0000000000000282 R12: 0000000000708150 R13: 0000000000000000 R14: 00007faa676209c0 R15: 00007faa67620700 Object at ffff88003b5bbcb8, in cache kmalloc-64 size: 64 Allocated: PID = 20909 save_stack_trace+0x16/0x20 arch/x86/kernel/stacktrace.c:59 save_stack+0x43/0xd0 mm/kasan/kasan.c:513 set_track mm/kasan/kasan.c:525 [inline] kasan_kmalloc+0xad/0xe0 mm/kasan/kasan.c:616 kmem_cache_alloc_trace+0x82/0x270 mm/slub.c:2745 kmalloc include/linux/slab.h:490 [inline] kzalloc include/linux/slab.h:663 [inline] tcp_sendmsg_fastopen net/ipv4/tcp.c:1094 [inline] tcp_sendmsg+0x221a/0x39b0 net/ipv4/tcp.c:1139 inet_sendmsg+0x164/0x5b0 net/ipv4/af_inet.c:762 sock_sendmsg_nosec net/socket.c:633 [inline] sock_sendmsg+0xca/0x110 net/socket.c:643 SYSC_sendto+0x660/0x810 net/socket.c:1696 SyS_sendto+0x40/0x50 net/socket.c:1664 entry_SYSCALL_64_fastpath+0x1f/0xbe Freed: PID = 20909 save_stack_trace+0x16/0x20 arch/x86/kernel/stacktrace.c:59 save_stack+0x43/0xd0 mm/kasan/kasan.c:513 set_track mm/kasan/kasan.c:525 [inline] kasan_slab_free+0x73/0xc0 mm/kasan/kasan.c:589 slab_free_hook mm/slub.c:1357 [inline] slab_free_freelist_hook mm/slub.c:1379 [inline] slab_free mm/slub.c:2961 [inline] kfree+0xe8/0x2b0 mm/slub.c:3882 tcp_free_fastopen_req net/ipv4/tcp.c:1077 [inline] tcp_disconnect+0xc15/0x13e0 net/ipv4/tcp.c:2328 __inet_stream_connect+0x20c/0xf90 net/ipv4/af_inet.c:593 tcp_sendmsg_fastopen net/ipv4/tcp.c:1111 [inline] tcp_sendmsg+0x23a8/0x39b0 net/ipv4/tcp.c:1139 inet_sendmsg+0x164/0x5b0 net/ipv4/af_inet.c:762 sock_sendmsg_nosec net/socket.c:633 [inline] sock_sendmsg+0xca/0x110 net/socket.c:643 SYSC_sendto+0x660/0x810 net/socket.c:1696 SyS_sendto+0x40/0x50 net/socket.c:1664 entry_SYSCALL_64_fastpath+0x1f/0xbe Fixes: e994b2f0fb92 ("tcp: do not lock listener to process SYN packets") Fixes: 7db92362d2fe ("tcp: fix potential double free issue for fastopen_req") Signed-off-by: Eric Dumazet Reported-by: Andrey Konovalov Acked-by: Wei Wang Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/ipv4/tcp_minisocks.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/ipv4/tcp_minisocks.c b/net/ipv4/tcp_minisocks.c index 8615a6b8550f..64e1ba49c3e2 100644 --- a/net/ipv4/tcp_minisocks.c +++ b/net/ipv4/tcp_minisocks.c @@ -543,6 +543,7 @@ struct sock *tcp_create_openreq_child(const struct sock *sk, newicsk->icsk_ack.last_seg_size = skb->len - newtp->tcp_header_len; newtp->rx_opt.mss_clamp = req->mss; tcp_ecn_openreq_child(newtp, req); + newtp->fastopen_req = NULL; newtp->fastopen_rsk = NULL; newtp->syn_data_acked = 0; newtp->rack.mstamp.v64 = 0; From f1906530860104b9c7e1b66302fc2029f6a92461 Mon Sep 17 00:00:00 2001 From: Alexander Potapenko Date: Wed, 3 May 2017 17:06:58 +0200 Subject: [PATCH 092/396] ipv4, ipv6: ensure raw socket message is big enough to hold an IP header [ Upstream commit 86f4c90a1c5c1493f07f2d12c1079f5bf01936f2 ] raw_send_hdrinc() and rawv6_send_hdrinc() expect that the buffer copied from the userspace contains the IPv4/IPv6 header, so if too few bytes are copied, parts of the header may remain uninitialized. This bug has been detected with KMSAN. For the record, the KMSAN report: ================================================================== BUG: KMSAN: use of unitialized memory in nf_ct_frag6_gather+0xf5a/0x44a0 inter: 0 CPU: 0 PID: 1036 Comm: probe Not tainted 4.11.0-rc5+ #2455 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Bochs 01/01/2011 Call Trace: __dump_stack lib/dump_stack.c:16 dump_stack+0x143/0x1b0 lib/dump_stack.c:52 kmsan_report+0x16b/0x1e0 mm/kmsan/kmsan.c:1078 __kmsan_warning_32+0x5c/0xa0 mm/kmsan/kmsan_instr.c:510 nf_ct_frag6_gather+0xf5a/0x44a0 net/ipv6/netfilter/nf_conntrack_reasm.c:577 ipv6_defrag+0x1d9/0x280 net/ipv6/netfilter/nf_defrag_ipv6_hooks.c:68 nf_hook_entry_hookfn ./include/linux/netfilter.h:102 nf_hook_slow+0x13f/0x3c0 net/netfilter/core.c:310 nf_hook ./include/linux/netfilter.h:212 NF_HOOK ./include/linux/netfilter.h:255 rawv6_send_hdrinc net/ipv6/raw.c:673 rawv6_sendmsg+0x2fcb/0x41a0 net/ipv6/raw.c:919 inet_sendmsg+0x3f8/0x6d0 net/ipv4/af_inet.c:762 sock_sendmsg_nosec net/socket.c:633 sock_sendmsg net/socket.c:643 SYSC_sendto+0x6a5/0x7c0 net/socket.c:1696 SyS_sendto+0xbc/0xe0 net/socket.c:1664 do_syscall_64+0x72/0xa0 arch/x86/entry/common.c:285 entry_SYSCALL64_slow_path+0x25/0x25 arch/x86/entry/entry_64.S:246 RIP: 0033:0x436e03 RSP: 002b:00007ffce48baf38 EFLAGS: 00000246 ORIG_RAX: 000000000000002c RAX: ffffffffffffffda RBX: 00000000004002b0 RCX: 0000000000436e03 RDX: 0000000000000000 RSI: 0000000000000000 RDI: 0000000000000003 RBP: 00007ffce48baf90 R08: 00007ffce48baf50 R09: 000000000000001c R10: 0000000000000000 R11: 0000000000000246 R12: 0000000000000000 R13: 0000000000401790 R14: 0000000000401820 R15: 0000000000000000 origin: 00000000d9400053 save_stack_trace+0x16/0x20 arch/x86/kernel/stacktrace.c:59 kmsan_save_stack_with_flags mm/kmsan/kmsan.c:362 kmsan_internal_poison_shadow+0xb1/0x1a0 mm/kmsan/kmsan.c:257 kmsan_poison_shadow+0x6d/0xc0 mm/kmsan/kmsan.c:270 slab_alloc_node mm/slub.c:2735 __kmalloc_node_track_caller+0x1f4/0x390 mm/slub.c:4341 __kmalloc_reserve net/core/skbuff.c:138 __alloc_skb+0x2cd/0x740 net/core/skbuff.c:231 alloc_skb ./include/linux/skbuff.h:933 alloc_skb_with_frags+0x209/0xbc0 net/core/skbuff.c:4678 sock_alloc_send_pskb+0x9ff/0xe00 net/core/sock.c:1903 sock_alloc_send_skb+0xe4/0x100 net/core/sock.c:1920 rawv6_send_hdrinc net/ipv6/raw.c:638 rawv6_sendmsg+0x2918/0x41a0 net/ipv6/raw.c:919 inet_sendmsg+0x3f8/0x6d0 net/ipv4/af_inet.c:762 sock_sendmsg_nosec net/socket.c:633 sock_sendmsg net/socket.c:643 SYSC_sendto+0x6a5/0x7c0 net/socket.c:1696 SyS_sendto+0xbc/0xe0 net/socket.c:1664 do_syscall_64+0x72/0xa0 arch/x86/entry/common.c:285 return_from_SYSCALL_64+0x0/0x6a arch/x86/entry/entry_64.S:246 ================================================================== , triggered by the following syscalls: socket(PF_INET6, SOCK_RAW, IPPROTO_RAW) = 3 sendto(3, NULL, 0, 0, {sa_family=AF_INET6, sin6_port=htons(0), inet_pton(AF_INET6, "ff00::", &sin6_addr), sin6_flowinfo=0, sin6_scope_id=0}, 28) = -1 EPERM A similar report is triggered in net/ipv4/raw.c if we use a PF_INET socket instead of a PF_INET6 one. Signed-off-by: Alexander Potapenko Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/ipv4/raw.c | 3 +++ net/ipv6/raw.c | 2 ++ 2 files changed, 5 insertions(+) diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c index ecbe5a7c2d6d..9879b73d5565 100644 --- a/net/ipv4/raw.c +++ b/net/ipv4/raw.c @@ -356,6 +356,9 @@ static int raw_send_hdrinc(struct sock *sk, struct flowi4 *fl4, rt->dst.dev->mtu); return -EMSGSIZE; } + if (length < sizeof(struct iphdr)) + return -EINVAL; + if (flags&MSG_PROBE) goto out; diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c index ced3817539c2..1a2fe5c3a366 100644 --- a/net/ipv6/raw.c +++ b/net/ipv6/raw.c @@ -630,6 +630,8 @@ static int rawv6_send_hdrinc(struct sock *sk, struct msghdr *msg, int length, ipv6_local_error(sk, EMSGSIZE, fl6, rt->dst.dev->mtu); return -EMSGSIZE; } + if (length < sizeof(struct ipv6hdr)) + return -EINVAL; if (flags&MSG_PROBE) goto out; From 5d8e07740c69fac6ebd6cc0657a41e561e50d124 Mon Sep 17 00:00:00 2001 From: Michal Schmidt Date: Thu, 4 May 2017 16:48:58 +0200 Subject: [PATCH 093/396] rtnetlink: NUL-terminate IFLA_PHYS_PORT_NAME string [ Upstream commit 77ef033b687c3e030017c94a29bf6ea3aaaef678 ] IFLA_PHYS_PORT_NAME is a string attribute, so terminate it with \0. Otherwise libnl3 fails to validate netlink messages with this attribute. "ip -detail a" assumes too that the attribute is NUL-terminated when printing it. It often was, due to padding. I noticed this as libvirtd failing to start on a system with sfc driver after upgrading it to Linux 4.11, i.e. when sfc added support for phys_port_name. Signed-off-by: Michal Schmidt Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/core/rtnetlink.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index b7f9ae7b1c5f..b490af67c6fa 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c @@ -1059,7 +1059,7 @@ static int rtnl_phys_port_name_fill(struct sk_buff *skb, struct net_device *dev) return err; } - if (nla_put(skb, IFLA_PHYS_PORT_NAME, strlen(name), name)) + if (nla_put_string(skb, IFLA_PHYS_PORT_NAME, name)) return -EMSGSIZE; return 0; From ecbd3ed2ddfe5fbae4db6aa3a0903af479e0543d Mon Sep 17 00:00:00 2001 From: WANG Cong Date: Wed, 3 May 2017 22:07:31 -0700 Subject: [PATCH 094/396] ipv6: initialize route null entry in addrconf_init() [ Upstream commit 2f460933f58eee3393aba64f0f6d14acb08d1724 ] Andrey reported a crash on init_net.ipv6.ip6_null_entry->rt6i_idev since it is always NULL. This is clearly wrong, we have code to initialize it to loopback_dev, unfortunately the order is still not correct. loopback_dev is registered very early during boot, we lose a chance to re-initialize it in notifier. addrconf_init() is called after ip6_route_init(), which means we have no chance to correct it. Fix it by moving this initialization explicitly after ipv6_add_dev(init_net.loopback_dev) in addrconf_init(). Reported-by: Andrey Konovalov Signed-off-by: Cong Wang Tested-by: Andrey Konovalov Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- include/net/ip6_route.h | 1 + net/ipv6/addrconf.c | 2 ++ net/ipv6/route.c | 26 +++++++++++++++----------- 3 files changed, 18 insertions(+), 11 deletions(-) diff --git a/include/net/ip6_route.h b/include/net/ip6_route.h index f83e78d071a3..2e347d4545cf 100644 --- a/include/net/ip6_route.h +++ b/include/net/ip6_route.h @@ -84,6 +84,7 @@ struct dst_entry *ip6_route_lookup(struct net *net, struct flowi6 *fl6, struct rt6_info *ip6_pol_route(struct net *net, struct fib6_table *table, int ifindex, struct flowi6 *fl6, int flags); +void ip6_route_init_special_entries(void); int ip6_route_init(void); void ip6_route_cleanup(void); diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index e0a083f49227..4d115b5cb231 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -6264,6 +6264,8 @@ int __init addrconf_init(void) goto errlo; } + ip6_route_init_special_entries(); + for (i = 0; i < IN6_ADDR_HSIZE; i++) INIT_HLIST_HEAD(&inet6_addr_lst[i]); diff --git a/net/ipv6/route.c b/net/ipv6/route.c index 9f1bc756799a..57081bbf21d6 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -3798,6 +3798,21 @@ static struct notifier_block ip6_route_dev_notifier = { .priority = 0, }; +void __init ip6_route_init_special_entries(void) +{ + /* Registering of the loopback is done before this portion of code, + * the loopback reference in rt6_info will not be taken, do it + * manually for init_net */ + init_net.ipv6.ip6_null_entry->dst.dev = init_net.loopback_dev; + init_net.ipv6.ip6_null_entry->rt6i_idev = in6_dev_get(init_net.loopback_dev); + #ifdef CONFIG_IPV6_MULTIPLE_TABLES + init_net.ipv6.ip6_prohibit_entry->dst.dev = init_net.loopback_dev; + init_net.ipv6.ip6_prohibit_entry->rt6i_idev = in6_dev_get(init_net.loopback_dev); + init_net.ipv6.ip6_blk_hole_entry->dst.dev = init_net.loopback_dev; + init_net.ipv6.ip6_blk_hole_entry->rt6i_idev = in6_dev_get(init_net.loopback_dev); + #endif +} + int __init ip6_route_init(void) { int ret; @@ -3824,17 +3839,6 @@ int __init ip6_route_init(void) ip6_dst_blackhole_ops.kmem_cachep = ip6_dst_ops_template.kmem_cachep; - /* Registering of the loopback is done before this portion of code, - * the loopback reference in rt6_info will not be taken, do it - * manually for init_net */ - init_net.ipv6.ip6_null_entry->dst.dev = init_net.loopback_dev; - init_net.ipv6.ip6_null_entry->rt6i_idev = in6_dev_get(init_net.loopback_dev); - #ifdef CONFIG_IPV6_MULTIPLE_TABLES - init_net.ipv6.ip6_prohibit_entry->dst.dev = init_net.loopback_dev; - init_net.ipv6.ip6_prohibit_entry->rt6i_idev = in6_dev_get(init_net.loopback_dev); - init_net.ipv6.ip6_blk_hole_entry->dst.dev = init_net.loopback_dev; - init_net.ipv6.ip6_blk_hole_entry->rt6i_idev = in6_dev_get(init_net.loopback_dev); - #endif ret = fib6_init(); if (ret) goto out_register_subsys; From 8795ee7bed243c291d30830efe925966253aa2d6 Mon Sep 17 00:00:00 2001 From: WANG Cong Date: Mon, 8 May 2017 10:12:13 -0700 Subject: [PATCH 095/396] ipv6: reorder ip6_route_dev_notifier after ipv6_dev_notf [ Upstream commit 242d3a49a2a1a71d8eb9f953db1bcaa9d698ce00 ] For each netns (except init_net), we initialize its null entry in 3 places: 1) The template itself, as we use kmemdup() 2) Code around dst_init_metrics() in ip6_route_net_init() 3) ip6_route_dev_notify(), which is supposed to initialize it after loopback registers Unfortunately the last one still happens in a wrong order because we expect to initialize net->ipv6.ip6_null_entry->rt6i_idev to net->loopback_dev's idev, thus we have to do that after we add idev to loopback. However, this notifier has priority == 0 same as ipv6_dev_notf, and ipv6_dev_notf is registered after ip6_route_dev_notifier so it is called actually after ip6_route_dev_notifier. This is similar to commit 2f460933f58e ("ipv6: initialize route null entry in addrconf_init()") which fixes init_net. Fix it by picking a smaller priority for ip6_route_dev_notifier. Also, we have to release the refcnt accordingly when unregistering loopback_dev because device exit functions are called before subsys exit functions. Acked-by: David Ahern Tested-by: David Ahern Signed-off-by: Cong Wang Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- include/net/addrconf.h | 2 ++ net/ipv6/addrconf.c | 1 + net/ipv6/route.c | 13 +++++++++++-- 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/include/net/addrconf.h b/include/net/addrconf.h index 8f998afc1384..b8ee8a113e32 100644 --- a/include/net/addrconf.h +++ b/include/net/addrconf.h @@ -20,6 +20,8 @@ #define ADDRCONF_TIMER_FUZZ (HZ / 4) #define ADDRCONF_TIMER_FUZZ_MAX (HZ) +#define ADDRCONF_NOTIFY_PRIORITY 0 + #include #include diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 4d115b5cb231..f088a1d9a618 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -3492,6 +3492,7 @@ static int addrconf_notify(struct notifier_block *this, unsigned long event, */ static struct notifier_block ipv6_dev_notf = { .notifier_call = addrconf_notify, + .priority = ADDRCONF_NOTIFY_PRIORITY, }; static void addrconf_type_change(struct net_device *dev, unsigned long event) diff --git a/net/ipv6/route.c b/net/ipv6/route.c index 57081bbf21d6..b8b475389ae4 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -3480,7 +3480,10 @@ static int ip6_route_dev_notify(struct notifier_block *this, struct net_device *dev = netdev_notifier_info_to_dev(ptr); struct net *net = dev_net(dev); - if (event == NETDEV_REGISTER && (dev->flags & IFF_LOOPBACK)) { + if (!(dev->flags & IFF_LOOPBACK)) + return NOTIFY_OK; + + if (event == NETDEV_REGISTER) { net->ipv6.ip6_null_entry->dst.dev = dev; net->ipv6.ip6_null_entry->rt6i_idev = in6_dev_get(dev); #ifdef CONFIG_IPV6_MULTIPLE_TABLES @@ -3488,6 +3491,12 @@ static int ip6_route_dev_notify(struct notifier_block *this, net->ipv6.ip6_prohibit_entry->rt6i_idev = in6_dev_get(dev); net->ipv6.ip6_blk_hole_entry->dst.dev = dev; net->ipv6.ip6_blk_hole_entry->rt6i_idev = in6_dev_get(dev); +#endif + } else if (event == NETDEV_UNREGISTER) { + in6_dev_put(net->ipv6.ip6_null_entry->rt6i_idev); +#ifdef CONFIG_IPV6_MULTIPLE_TABLES + in6_dev_put(net->ipv6.ip6_prohibit_entry->rt6i_idev); + in6_dev_put(net->ipv6.ip6_blk_hole_entry->rt6i_idev); #endif } @@ -3795,7 +3804,7 @@ static struct pernet_operations ip6_route_net_late_ops = { static struct notifier_block ip6_route_dev_notifier = { .notifier_call = ip6_route_dev_notify, - .priority = 0, + .priority = ADDRCONF_NOTIFY_PRIORITY - 10, }; void __init ip6_route_init_special_entries(void) From e37aab9c63b87dd4ece0b570d3886f7c6c03b549 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Sat, 6 May 2017 03:49:01 +0300 Subject: [PATCH 096/396] bnxt_en: allocate enough space for ->ntp_fltr_bmap [ Upstream commit ac45bd93a5035c2f39c9862b8b6ed692db0fdc87 ] We have the number of longs, but we need to calculate the number of bytes required. Fixes: c0c050c58d84 ("bnxt_en: New Broadcom ethernet driver.") Signed-off-by: Dan Carpenter Acked-by: Michael Chan Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/ethernet/broadcom/bnxt/bnxt.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c index f08a20b921e7..48ee4110ef6e 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c @@ -2867,7 +2867,8 @@ static int bnxt_alloc_ntp_fltrs(struct bnxt *bp) INIT_HLIST_HEAD(&bp->ntp_fltr_hash_tbl[i]); bp->ntp_fltr_count = 0; - bp->ntp_fltr_bmap = kzalloc(BITS_TO_LONGS(BNXT_NTP_FLTR_MAX_FLTR), + bp->ntp_fltr_bmap = kcalloc(BITS_TO_LONGS(BNXT_NTP_FLTR_MAX_FLTR), + sizeof(long), GFP_KERNEL); if (!bp->ntp_fltr_bmap) From ced0a31e667fbf618591f0a76a8213018407cde0 Mon Sep 17 00:00:00 2001 From: Daniel Borkmann Date: Mon, 8 May 2017 00:04:09 +0200 Subject: [PATCH 097/396] bpf: don't let ldimm64 leak map addresses on unprivileged [ Upstream commit 0d0e57697f162da4aa218b5feafe614fb666db07 ] The patch fixes two things at once: 1) It checks the env->allow_ptr_leaks and only prints the map address to the log if we have the privileges to do so, otherwise it just dumps 0 as we would when kptr_restrict is enabled on %pK. Given the latter is off by default and not every distro sets it, I don't want to rely on this, hence the 0 by default for unprivileged. 2) Printing of ldimm64 in the verifier log is currently broken in that we don't print the full immediate, but only the 32 bit part of the first insn part for ldimm64. Thus, fix this up as well; it's okay to access, since we verified all ldimm64 earlier already (including just constants) through replace_map_fd_with_map_ptr(). Fixes: 1be7f75d1668 ("bpf: enable non-root eBPF programs") Fixes: cbd357008604 ("bpf: verifier (add ability to receive verification log)") Reported-by: Jann Horn Signed-off-by: Daniel Borkmann Acked-by: Alexei Starovoitov Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- kernel/bpf/verifier.c | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c index 64fcab1d8cd9..44c17f47d94c 100644 --- a/kernel/bpf/verifier.c +++ b/kernel/bpf/verifier.c @@ -279,7 +279,8 @@ static const char *const bpf_jmp_string[16] = { [BPF_EXIT >> 4] = "exit", }; -static void print_bpf_insn(struct bpf_insn *insn) +static void print_bpf_insn(const struct bpf_verifier_env *env, + const struct bpf_insn *insn) { u8 class = BPF_CLASS(insn->code); @@ -343,9 +344,19 @@ static void print_bpf_insn(struct bpf_insn *insn) insn->code, bpf_ldst_string[BPF_SIZE(insn->code) >> 3], insn->src_reg, insn->imm); - } else if (BPF_MODE(insn->code) == BPF_IMM) { - verbose("(%02x) r%d = 0x%x\n", - insn->code, insn->dst_reg, insn->imm); + } else if (BPF_MODE(insn->code) == BPF_IMM && + BPF_SIZE(insn->code) == BPF_DW) { + /* At this point, we already made sure that the second + * part of the ldimm64 insn is accessible. + */ + u64 imm = ((u64)(insn + 1)->imm << 32) | (u32)insn->imm; + bool map_ptr = insn->src_reg == BPF_PSEUDO_MAP_FD; + + if (map_ptr && !env->allow_ptr_leaks) + imm = 0; + + verbose("(%02x) r%d = 0x%llx\n", insn->code, + insn->dst_reg, (unsigned long long)imm); } else { verbose("BUG_ld_%02x\n", insn->code); return; @@ -2674,7 +2685,7 @@ static int do_check(struct bpf_verifier_env *env) if (log_level) { verbose("%d: ", insn_idx); - print_bpf_insn(insn); + print_bpf_insn(env, insn); } err = ext_analyzer_insn_hook(env, insn_idx, prev_insn_idx); From 265d382cc8db2ad14eba3398041606cf44e7ec89 Mon Sep 17 00:00:00 2001 From: Jon Mason Date: Mon, 8 May 2017 17:48:35 -0400 Subject: [PATCH 098/396] net: mdio-mux: bcm-iproc: call mdiobus_free() in error path [ Upstream commit 922c60e89d52730050c6ccca218bff40cc8bcd8e ] If an error is encountered in mdio_mux_init(), the error path will call mdiobus_free(). Since mdiobus_register() has been called prior to mdio_mux_init(), the bus->state will not be MDIOBUS_UNREGISTERED. This causes a BUG_ON() in mdiobus_free(). To correct this issue, add an error path for mdio_mux_init() which calls mdiobus_unregister() prior to mdiobus_free(). Signed-off-by: Jon Mason Fixes: 98bc865a1ec8 ("net: mdio-mux: Add MDIO mux driver for iProc SoCs") Acked-by: Florian Fainelli Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/phy/mdio-mux-bcm-iproc.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/net/phy/mdio-mux-bcm-iproc.c b/drivers/net/phy/mdio-mux-bcm-iproc.c index 0a0412524cec..0a5f62e0efcc 100644 --- a/drivers/net/phy/mdio-mux-bcm-iproc.c +++ b/drivers/net/phy/mdio-mux-bcm-iproc.c @@ -203,11 +203,14 @@ static int mdio_mux_iproc_probe(struct platform_device *pdev) &md->mux_handle, md, md->mii_bus); if (rc) { dev_info(md->dev, "mdiomux initialization failed\n"); - goto out; + goto out_register; } dev_info(md->dev, "iProc mdiomux registered\n"); return 0; + +out_register: + mdiobus_unregister(bus); out: mdiobus_free(bus); return rc; From 93862955cbf485215f0677229292d0f358af55fc Mon Sep 17 00:00:00 2001 From: Jin Qian Date: Tue, 25 Apr 2017 16:28:48 -0700 Subject: [PATCH 099/396] f2fs: sanity check segment count commit b9dd46188edc2f0d1f37328637860bb65a771124 upstream. F2FS uses 4 bytes to represent block address. As a result, supported size of disk is 16 TB and it equals to 16 * 1024 * 1024 / 2 segments. Signed-off-by: Jin Qian Signed-off-by: Jaegeuk Kim Signed-off-by: Greg Kroah-Hartman --- fs/f2fs/super.c | 7 +++++++ include/linux/f2fs_fs.h | 6 ++++++ 2 files changed, 13 insertions(+) diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c index 013c6a541d6b..7e0c002c12e9 100644 --- a/fs/f2fs/super.c +++ b/fs/f2fs/super.c @@ -1405,6 +1405,13 @@ static int sanity_check_raw_super(struct f2fs_sb_info *sbi, return 1; } + if (le32_to_cpu(raw_super->segment_count) > F2FS_MAX_SEGMENT) { + f2fs_msg(sb, KERN_INFO, + "Invalid segment count (%u)", + le32_to_cpu(raw_super->segment_count)); + return 1; + } + /* check CP/SIT/NAT/SSA/MAIN_AREA area boundary */ if (sanity_check_area_boundary(sbi, bh)) return 1; diff --git a/include/linux/f2fs_fs.h b/include/linux/f2fs_fs.h index 422630b8e588..e46e7d10312b 100644 --- a/include/linux/f2fs_fs.h +++ b/include/linux/f2fs_fs.h @@ -285,6 +285,12 @@ struct f2fs_nat_block { #define SIT_VBLOCK_MAP_SIZE 64 #define SIT_ENTRY_PER_BLOCK (PAGE_SIZE / sizeof(struct f2fs_sit_entry)) +/* + * F2FS uses 4 bytes to represent block address. As a result, supported size of + * disk is 16 TB and it equals to 16 * 1024 * 1024 / 2 segments. + */ +#define F2FS_MAX_SEGMENT ((16 * 1024 * 1024) / 2) + /* * Note that f2fs_sit_entry->vblocks has the following bit-field information. * [15:10] : allocation type such as CURSEG_XXXX_TYPE From 5d7ab8339a9a9e745c672279437657654268be81 Mon Sep 17 00:00:00 2001 From: Boris Ostrovsky Date: Mon, 24 Apr 2017 15:04:53 -0400 Subject: [PATCH 100/396] xen: Revert commits da72ff5bfcb0 and 72a9b186292d commit 84d582d236dc1f9085e741affc72e9ba061a67c2 upstream. Recent discussion (http://marc.info/?l=xen-devel&m=149192184523741) established that commit 72a9b186292d ("xen: Remove event channel notification through Xen PCI platform device") (and thus commit da72ff5bfcb0 ("partially revert "xen: Remove event channel notification through Xen PCI platform device"")) are unnecessary and, in fact, prevent HVM guests from booting on Xen releases prior to 4.0 Therefore we revert both of those commits. The summary of that discussion is below: Here is the brief summary of the current situation: Before the offending commit (72a9b186292): 1) INTx does not work because of the reset_watches path. 2) The reset_watches path is only taken if you have Xen > 4.0 3) The Linux Kernel by default will use vector inject if the hypervisor support. So even INTx does not work no body running the kernel with Xen > 4.0 would notice. Unless he explicitly disabled this feature either in the kernel or in Xen (and this can only be disabled by modifying the code, not user-supported way to do it). After the offending commit (+ partial revert): 1) INTx is no longer support for HVM (only for PV guests). 2) Any HVM guest The kernel will not boot on Xen < 4.0 which does not have vector injection support. Since the only other mode supported is INTx which. So based on this summary, I think before commit (72a9b186292) we were in much better position from a user point of view. Signed-off-by: Boris Ostrovsky Reviewed-by: Juergen Gross Cc: Boris Ostrovsky Cc: Thomas Gleixner Cc: Ingo Molnar Cc: "H. Peter Anvin" Cc: x86@kernel.org Cc: Konrad Rzeszutek Wilk Cc: Bjorn Helgaas Cc: Stefano Stabellini Cc: Julien Grall Cc: Vitaly Kuznetsov Cc: Paul Gortmaker Cc: Ross Lagerwall Cc: xen-devel@lists.xenproject.org Cc: linux-kernel@vger.kernel.org Cc: linux-pci@vger.kernel.org Cc: Anthony Liguori Cc: KarimAllah Ahmed Signed-off-by: Juergen Gross Signed-off-by: Greg Kroah-Hartman --- arch/x86/include/asm/xen/events.h | 11 ++++++ arch/x86/pci/xen.c | 2 +- arch/x86/xen/enlighten.c | 21 +++++++--- arch/x86/xen/smp.c | 2 + arch/x86/xen/time.c | 5 +++ drivers/xen/events/events_base.c | 26 ++++++++----- drivers/xen/platform-pci.c | 64 +++++++++++++++++++++++++++++++ include/xen/xen.h | 3 +- 8 files changed, 117 insertions(+), 17 deletions(-) diff --git a/arch/x86/include/asm/xen/events.h b/arch/x86/include/asm/xen/events.h index 608a79d5a466..e6911caf5bbf 100644 --- a/arch/x86/include/asm/xen/events.h +++ b/arch/x86/include/asm/xen/events.h @@ -20,4 +20,15 @@ static inline int xen_irqs_disabled(struct pt_regs *regs) /* No need for a barrier -- XCHG is a barrier on x86. */ #define xchg_xen_ulong(ptr, val) xchg((ptr), (val)) +extern int xen_have_vector_callback; + +/* + * Events delivered via platform PCI interrupts are always + * routed to vcpu 0 and hence cannot be rebound. + */ +static inline bool xen_support_evtchn_rebind(void) +{ + return (!xen_hvm_domain() || xen_have_vector_callback); +} + #endif /* _ASM_X86_XEN_EVENTS_H */ diff --git a/arch/x86/pci/xen.c b/arch/x86/pci/xen.c index a00a6c07bb6f..4ea9f290c19f 100644 --- a/arch/x86/pci/xen.c +++ b/arch/x86/pci/xen.c @@ -447,7 +447,7 @@ void __init xen_msi_init(void) int __init pci_xen_hvm_init(void) { - if (!xen_feature(XENFEAT_hvm_pirqs)) + if (!xen_have_vector_callback || !xen_feature(XENFEAT_hvm_pirqs)) return 0; #ifdef CONFIG_ACPI diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c index bdd855685403..8f1f7efa848c 100644 --- a/arch/x86/xen/enlighten.c +++ b/arch/x86/xen/enlighten.c @@ -137,6 +137,8 @@ struct shared_info xen_dummy_shared_info; void *xen_initial_gdt; RESERVE_BRK(shared_info_page_brk, PAGE_SIZE); +__read_mostly int xen_have_vector_callback; +EXPORT_SYMBOL_GPL(xen_have_vector_callback); static int xen_cpu_up_prepare(unsigned int cpu); static int xen_cpu_up_online(unsigned int cpu); @@ -1521,7 +1523,10 @@ static void __init xen_pvh_early_guest_init(void) if (!xen_feature(XENFEAT_auto_translated_physmap)) return; - BUG_ON(!xen_feature(XENFEAT_hvm_callback_vector)); + if (!xen_feature(XENFEAT_hvm_callback_vector)) + return; + + xen_have_vector_callback = 1; xen_pvh_early_cpu_init(0, false); xen_pvh_set_cr_flags(0); @@ -1860,7 +1865,9 @@ static int xen_cpu_up_prepare(unsigned int cpu) xen_vcpu_setup(cpu); } - if (xen_pv_domain() || xen_feature(XENFEAT_hvm_safe_pvclock)) + if (xen_pv_domain() || + (xen_have_vector_callback && + xen_feature(XENFEAT_hvm_safe_pvclock))) xen_setup_timer(cpu); rc = xen_smp_intr_init(cpu); @@ -1876,7 +1883,9 @@ static int xen_cpu_dead(unsigned int cpu) { xen_smp_intr_free(cpu); - if (xen_pv_domain() || xen_feature(XENFEAT_hvm_safe_pvclock)) + if (xen_pv_domain() || + (xen_have_vector_callback && + xen_feature(XENFEAT_hvm_safe_pvclock))) xen_teardown_timer(cpu); return 0; @@ -1915,8 +1924,8 @@ static void __init xen_hvm_guest_init(void) xen_panic_handler_init(); - BUG_ON(!xen_feature(XENFEAT_hvm_callback_vector)); - + if (xen_feature(XENFEAT_hvm_callback_vector)) + xen_have_vector_callback = 1; xen_hvm_smp_init(); WARN_ON(xen_cpuhp_setup()); xen_unplug_emulated_devices(); @@ -1954,7 +1963,7 @@ bool xen_hvm_need_lapic(void) return false; if (!xen_hvm_domain()) return false; - if (xen_feature(XENFEAT_hvm_pirqs)) + if (xen_feature(XENFEAT_hvm_pirqs) && xen_have_vector_callback) return false; return true; } diff --git a/arch/x86/xen/smp.c b/arch/x86/xen/smp.c index 311acad7dad2..137afbbd0590 100644 --- a/arch/x86/xen/smp.c +++ b/arch/x86/xen/smp.c @@ -765,6 +765,8 @@ static void __init xen_hvm_smp_prepare_cpus(unsigned int max_cpus) void __init xen_hvm_smp_init(void) { + if (!xen_have_vector_callback) + return; smp_ops.smp_prepare_cpus = xen_hvm_smp_prepare_cpus; smp_ops.smp_send_reschedule = xen_smp_send_reschedule; smp_ops.cpu_die = xen_cpu_die; diff --git a/arch/x86/xen/time.c b/arch/x86/xen/time.c index 33d8f6a7829d..67356d29d74d 100644 --- a/arch/x86/xen/time.c +++ b/arch/x86/xen/time.c @@ -432,6 +432,11 @@ static void xen_hvm_setup_cpu_clockevents(void) void __init xen_hvm_init_time_ops(void) { + /* vector callback is needed otherwise we cannot receive interrupts + * on cpu > 0 and at this point we don't know how many cpus are + * available */ + if (!xen_have_vector_callback) + return; if (!xen_feature(XENFEAT_hvm_safe_pvclock)) { printk(KERN_INFO "Xen doesn't support pvclock on HVM," "disable pv timer\n"); diff --git a/drivers/xen/events/events_base.c b/drivers/xen/events/events_base.c index 9ecfcdcdd6d6..d5dbdb9d24d8 100644 --- a/drivers/xen/events/events_base.c +++ b/drivers/xen/events/events_base.c @@ -1314,6 +1314,9 @@ static int rebind_irq_to_cpu(unsigned irq, unsigned tcpu) if (!VALID_EVTCHN(evtchn)) return -1; + if (!xen_support_evtchn_rebind()) + return -1; + /* Send future instances of this interrupt to other vcpu. */ bind_vcpu.port = evtchn; bind_vcpu.vcpu = xen_vcpu_nr(tcpu); @@ -1647,15 +1650,20 @@ void xen_callback_vector(void) { int rc; uint64_t callback_via; - - callback_via = HVM_CALLBACK_VECTOR(HYPERVISOR_CALLBACK_VECTOR); - rc = xen_set_callback_via(callback_via); - BUG_ON(rc); - pr_info("Xen HVM callback vector for event delivery is enabled\n"); - /* in the restore case the vector has already been allocated */ - if (!test_bit(HYPERVISOR_CALLBACK_VECTOR, used_vectors)) - alloc_intr_gate(HYPERVISOR_CALLBACK_VECTOR, - xen_hvm_callback_vector); + if (xen_have_vector_callback) { + callback_via = HVM_CALLBACK_VECTOR(HYPERVISOR_CALLBACK_VECTOR); + rc = xen_set_callback_via(callback_via); + if (rc) { + pr_err("Request for Xen HVM callback vector failed\n"); + xen_have_vector_callback = 0; + return; + } + pr_info("Xen HVM callback vector for event delivery is enabled\n"); + /* in the restore case the vector has already been allocated */ + if (!test_bit(HYPERVISOR_CALLBACK_VECTOR, used_vectors)) + alloc_intr_gate(HYPERVISOR_CALLBACK_VECTOR, + xen_hvm_callback_vector); + } } #else void xen_callback_vector(void) {} diff --git a/drivers/xen/platform-pci.c b/drivers/xen/platform-pci.c index b59c9455aae1..cf9666680c8c 100644 --- a/drivers/xen/platform-pci.c +++ b/drivers/xen/platform-pci.c @@ -42,6 +42,7 @@ static unsigned long platform_mmio; static unsigned long platform_mmio_alloc; static unsigned long platform_mmiolen; +static uint64_t callback_via; static unsigned long alloc_xen_mmio(unsigned long len) { @@ -54,6 +55,51 @@ static unsigned long alloc_xen_mmio(unsigned long len) return addr; } +static uint64_t get_callback_via(struct pci_dev *pdev) +{ + u8 pin; + int irq; + + irq = pdev->irq; + if (irq < 16) + return irq; /* ISA IRQ */ + + pin = pdev->pin; + + /* We don't know the GSI. Specify the PCI INTx line instead. */ + return ((uint64_t)0x01 << 56) | /* PCI INTx identifier */ + ((uint64_t)pci_domain_nr(pdev->bus) << 32) | + ((uint64_t)pdev->bus->number << 16) | + ((uint64_t)(pdev->devfn & 0xff) << 8) | + ((uint64_t)(pin - 1) & 3); +} + +static irqreturn_t do_hvm_evtchn_intr(int irq, void *dev_id) +{ + xen_hvm_evtchn_do_upcall(); + return IRQ_HANDLED; +} + +static int xen_allocate_irq(struct pci_dev *pdev) +{ + return request_irq(pdev->irq, do_hvm_evtchn_intr, + IRQF_NOBALANCING | IRQF_TRIGGER_RISING, + "xen-platform-pci", pdev); +} + +static int platform_pci_resume(struct pci_dev *pdev) +{ + int err; + if (xen_have_vector_callback) + return 0; + err = xen_set_callback_via(callback_via); + if (err) { + dev_err(&pdev->dev, "platform_pci_resume failure!\n"); + return err; + } + return 0; +} + static int platform_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { @@ -92,6 +138,21 @@ static int platform_pci_probe(struct pci_dev *pdev, platform_mmio = mmio_addr; platform_mmiolen = mmio_len; + if (!xen_have_vector_callback) { + ret = xen_allocate_irq(pdev); + if (ret) { + dev_warn(&pdev->dev, "request_irq failed err=%d\n", ret); + goto out; + } + callback_via = get_callback_via(pdev); + ret = xen_set_callback_via(callback_via); + if (ret) { + dev_warn(&pdev->dev, "Unable to set the evtchn callback " + "err=%d\n", ret); + goto out; + } + } + max_nr_gframes = gnttab_max_grant_frames(); grant_frames = alloc_xen_mmio(PAGE_SIZE * max_nr_gframes); ret = gnttab_setup_auto_xlat_frames(grant_frames); @@ -123,6 +184,9 @@ static struct pci_driver platform_driver = { .name = DRV_NAME, .probe = platform_pci_probe, .id_table = platform_pci_tbl, +#ifdef CONFIG_PM + .resume_early = platform_pci_resume, +#endif }; static int __init platform_pci_init(void) diff --git a/include/xen/xen.h b/include/xen/xen.h index f0f0252cff9a..0c0e3ef4c45d 100644 --- a/include/xen/xen.h +++ b/include/xen/xen.h @@ -38,7 +38,8 @@ extern enum xen_domain_type xen_domain_type; */ #include #define xen_pvh_domain() (xen_pv_domain() && \ - xen_feature(XENFEAT_auto_translated_physmap)) + xen_feature(XENFEAT_auto_translated_physmap) && \ + xen_have_vector_callback) #else #define xen_pvh_domain() (0) #endif From bbd839a40dde64d9cffee083225415f94f9a8106 Mon Sep 17 00:00:00 2001 From: Maxim Altshul Date: Sun, 21 Aug 2016 14:24:24 +0300 Subject: [PATCH 101/396] wlcore: Pass win_size taken from ieee80211_sta to FW commit 42c7372a111630dab200c2f959424f5ec3bf79a4 upstream. When starting a new BA session, we must pass the win_size to the FW. To do this we take max_rx_aggregation_subframes (BA RX win size) which is stored in ieee80211_sta structure (e.g per link and not per HW) We will use the value stored per link when passing the win_size to firmware through the ACX_BA_SESSION_RX_SETUP command. Signed-off-by: Maxim Altshul Signed-off-by: Kalle Valo Signed-off-by: Amit Pundir Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/ti/wlcore/acx.c | 5 +++-- drivers/net/wireless/ti/wlcore/acx.h | 3 ++- drivers/net/wireless/ti/wlcore/main.c | 6 ++++-- 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/ti/wlcore/acx.c b/drivers/net/wireless/ti/wlcore/acx.c index 26cc23f32241..a4859993db3c 100644 --- a/drivers/net/wireless/ti/wlcore/acx.c +++ b/drivers/net/wireless/ti/wlcore/acx.c @@ -1419,7 +1419,8 @@ out: /* setup BA session receiver setting in the FW. */ int wl12xx_acx_set_ba_receiver_session(struct wl1271 *wl, u8 tid_index, - u16 ssn, bool enable, u8 peer_hlid) + u16 ssn, bool enable, u8 peer_hlid, + u8 win_size) { struct wl1271_acx_ba_receiver_setup *acx; int ret; @@ -1435,7 +1436,7 @@ int wl12xx_acx_set_ba_receiver_session(struct wl1271 *wl, u8 tid_index, acx->hlid = peer_hlid; acx->tid = tid_index; acx->enable = enable; - acx->win_size = wl->conf.ht.rx_ba_win_size; + acx->win_size = win_size; acx->ssn = ssn; ret = wlcore_cmd_configure_failsafe(wl, ACX_BA_SESSION_RX_SETUP, acx, diff --git a/drivers/net/wireless/ti/wlcore/acx.h b/drivers/net/wireless/ti/wlcore/acx.h index 6321ed472891..f46d7fdf9a00 100644 --- a/drivers/net/wireless/ti/wlcore/acx.h +++ b/drivers/net/wireless/ti/wlcore/acx.h @@ -1113,7 +1113,8 @@ int wl1271_acx_set_ht_information(struct wl1271 *wl, int wl12xx_acx_set_ba_initiator_policy(struct wl1271 *wl, struct wl12xx_vif *wlvif); int wl12xx_acx_set_ba_receiver_session(struct wl1271 *wl, u8 tid_index, - u16 ssn, bool enable, u8 peer_hlid); + u16 ssn, bool enable, u8 peer_hlid, + u8 win_size); int wl12xx_acx_tsf_info(struct wl1271 *wl, struct wl12xx_vif *wlvif, u64 *mactime); int wl1271_acx_ps_rx_streaming(struct wl1271 *wl, struct wl12xx_vif *wlvif, diff --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c index 471521a0db7b..5438975c7ff2 100644 --- a/drivers/net/wireless/ti/wlcore/main.c +++ b/drivers/net/wireless/ti/wlcore/main.c @@ -5285,7 +5285,9 @@ static int wl1271_op_ampdu_action(struct ieee80211_hw *hw, } ret = wl12xx_acx_set_ba_receiver_session(wl, tid, *ssn, true, - hlid); + hlid, + params->buf_size); + if (!ret) { *ba_bitmap |= BIT(tid); wl->ba_rx_session_count++; @@ -5306,7 +5308,7 @@ static int wl1271_op_ampdu_action(struct ieee80211_hw *hw, } ret = wl12xx_acx_set_ba_receiver_session(wl, tid, 0, false, - hlid); + hlid, 0); if (!ret) { *ba_bitmap &= ~BIT(tid); wl->ba_rx_session_count--; From 347d07bf3add9bc1a7d52fad2f8efea61aa75c38 Mon Sep 17 00:00:00 2001 From: Maxim Altshul Date: Sun, 21 Aug 2016 14:24:25 +0300 Subject: [PATCH 102/396] wlcore: Add RX_BA_WIN_SIZE_CHANGE_EVENT event commit e7ee74b56f23ba447d3124f2eccc32033cca501d upstream. This event is used by the Firmware to limit the RX BA win size for a specific link. The event handler updates the new size in the mac's sta->sta struct. BA sessions opened for that link will use the new restricted win_size. This limitation remains until a new update is received or until the link is closed. Signed-off-by: Maxim Altshul Signed-off-by: Kalle Valo Signed-off-by: Amit Pundir Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/ti/wl18xx/event.c | 28 ++++++++++++++++++++++++++ drivers/net/wireless/ti/wl18xx/event.h | 1 + drivers/net/wireless/ti/wl18xx/main.c | 3 ++- 3 files changed, 31 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/ti/wl18xx/event.c b/drivers/net/wireless/ti/wl18xx/event.c index b36ce185c9f2..86fa0fc69084 100644 --- a/drivers/net/wireless/ti/wl18xx/event.c +++ b/drivers/net/wireless/ti/wl18xx/event.c @@ -218,5 +218,33 @@ int wl18xx_process_mailbox_events(struct wl1271 *wl) if (vector & FW_LOGGER_INDICATION) wlcore_event_fw_logger(wl); + if (vector & RX_BA_WIN_SIZE_CHANGE_EVENT_ID) { + struct wl12xx_vif *wlvif; + struct ieee80211_vif *vif; + struct ieee80211_sta *sta; + u8 link_id = mbox->rx_ba_link_id; + u8 win_size = mbox->rx_ba_win_size; + const u8 *addr; + + wlvif = wl->links[link_id].wlvif; + vif = wl12xx_wlvif_to_vif(wlvif); + + /* Update RX aggregation window size and call + * MAC routine to stop active RX aggregations for this link + */ + if (wlvif->bss_type != BSS_TYPE_AP_BSS) + addr = vif->bss_conf.bssid; + else + addr = wl->links[link_id].addr; + + sta = ieee80211_find_sta(vif, addr); + if (sta) { + sta->max_rx_aggregation_subframes = win_size; + ieee80211_stop_rx_ba_session(vif, + wl->links[link_id].ba_bitmap, + addr); + } + } + return 0; } diff --git a/drivers/net/wireless/ti/wl18xx/event.h b/drivers/net/wireless/ti/wl18xx/event.h index ce8ea9c04052..4af297fbb529 100644 --- a/drivers/net/wireless/ti/wl18xx/event.h +++ b/drivers/net/wireless/ti/wl18xx/event.h @@ -38,6 +38,7 @@ enum { REMAIN_ON_CHANNEL_COMPLETE_EVENT_ID = BIT(18), DFS_CHANNELS_CONFIG_COMPLETE_EVENT = BIT(19), PERIODIC_SCAN_REPORT_EVENT_ID = BIT(20), + RX_BA_WIN_SIZE_CHANGE_EVENT_ID = BIT(21), SMART_CONFIG_SYNC_EVENT_ID = BIT(22), SMART_CONFIG_DECODE_EVENT_ID = BIT(23), TIME_SYNC_EVENT_ID = BIT(24), diff --git a/drivers/net/wireless/ti/wl18xx/main.c b/drivers/net/wireless/ti/wl18xx/main.c index 06d6943b257c..5bdf7a03e3dd 100644 --- a/drivers/net/wireless/ti/wl18xx/main.c +++ b/drivers/net/wireless/ti/wl18xx/main.c @@ -1041,7 +1041,8 @@ static int wl18xx_boot(struct wl1271 *wl) SMART_CONFIG_SYNC_EVENT_ID | SMART_CONFIG_DECODE_EVENT_ID | TIME_SYNC_EVENT_ID | - FW_LOGGER_INDICATION; + FW_LOGGER_INDICATION | + RX_BA_WIN_SIZE_CHANGE_EVENT_ID; wl->ap_event_mask = MAX_TX_FAILURE_EVENT_ID; From 48d9fa1ece5ee453d4c08a7feec74c966939a25c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicolai=20H=C3=A4hnle?= Date: Sat, 18 Feb 2017 22:59:56 +0100 Subject: [PATCH 103/396] drm/ttm: fix use-after-free races in vm fault handling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 3089c1df10e2931b1d72d2ffa7d86431084c86b3 upstream. The vm fault handler relies on the fact that the VMA owns a reference to the BO. However, once mmap_sem is released, other tasks are free to destroy the VMA, which can lead to the BO being freed. Fix two code paths where that can happen, both related to vm fault retries. Found via a lock debugging warning which flagged &bo->wu_mutex as locked while being destroyed. Fixes: cbe12e74ee4e ("drm/ttm: Allow vm fault retries") Signed-off-by: Nicolai Hähnle Reviewed-by: Christian König Signed-off-by: Alex Deucher Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/ttm/ttm_bo_vm.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/drivers/gpu/drm/ttm/ttm_bo_vm.c b/drivers/gpu/drm/ttm/ttm_bo_vm.c index a6ed9d5e5167..750733a8cce2 100644 --- a/drivers/gpu/drm/ttm/ttm_bo_vm.c +++ b/drivers/gpu/drm/ttm/ttm_bo_vm.c @@ -66,8 +66,11 @@ static int ttm_bo_vm_fault_idle(struct ttm_buffer_object *bo, if (vmf->flags & FAULT_FLAG_RETRY_NOWAIT) goto out_unlock; + ttm_bo_reference(bo); up_read(&vma->vm_mm->mmap_sem); (void) fence_wait(bo->moving, true); + ttm_bo_unreserve(bo); + ttm_bo_unref(&bo); goto out_unlock; } @@ -120,8 +123,10 @@ static int ttm_bo_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf) if (vmf->flags & FAULT_FLAG_ALLOW_RETRY) { if (!(vmf->flags & FAULT_FLAG_RETRY_NOWAIT)) { + ttm_bo_reference(bo); up_read(&vma->vm_mm->mmap_sem); (void) ttm_bo_wait_unreserved(bo); + ttm_bo_unref(&bo); } return VM_FAULT_RETRY; @@ -166,6 +171,13 @@ static int ttm_bo_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf) ret = ttm_bo_vm_fault_idle(bo, vma, vmf); if (unlikely(ret != 0)) { retval = ret; + + if (retval == VM_FAULT_RETRY && + !(vmf->flags & FAULT_FLAG_RETRY_NOWAIT)) { + /* The BO has already been unreserved. */ + return retval; + } + goto out_unlock; } From 6a7620744e89c99b5f9aeaf083766d48b0500d87 Mon Sep 17 00:00:00 2001 From: Ilya Dryomov Date: Tue, 18 Apr 2017 18:43:20 +0200 Subject: [PATCH 104/396] block: get rid of blk_integrity_revalidate() commit 19b7ccf8651df09d274671b53039c672a52ad84d upstream. Commit 25520d55cdb6 ("block: Inline blk_integrity in struct gendisk") introduced blk_integrity_revalidate(), which seems to assume ownership of the stable pages flag and unilaterally clears it if no blk_integrity profile is registered: if (bi->profile) disk->queue->backing_dev_info->capabilities |= BDI_CAP_STABLE_WRITES; else disk->queue->backing_dev_info->capabilities &= ~BDI_CAP_STABLE_WRITES; It's called from revalidate_disk() and rescan_partitions(), making it impossible to enable stable pages for drivers that support partitions and don't use blk_integrity: while the call in revalidate_disk() can be trivially worked around (see zram, which doesn't support partitions and hence gets away with zram_revalidate_disk()), rescan_partitions() can be triggered from userspace at any time. This breaks rbd, where the ceph messenger is responsible for generating/verifying CRCs. Since blk_integrity_{un,}register() "must" be used for (un)registering the integrity profile with the block layer, move BDI_CAP_STABLE_WRITES setting there. This way drivers that call blk_integrity_register() and use integrity infrastructure won't interfere with drivers that don't but still want stable pages. Fixes: 25520d55cdb6 ("block: Inline blk_integrity in struct gendisk") Cc: "Martin K. Petersen" Cc: Christoph Hellwig Cc: Mike Snitzer Tested-by: Dan Williams Signed-off-by: Ilya Dryomov [idryomov@gmail.com: backport to < 4.11: bdi is embedded in queue] Signed-off-by: Jens Axboe Signed-off-by: Greg Kroah-Hartman --- block/blk-integrity.c | 19 ++----------------- block/partition-generic.c | 1 - fs/block_dev.c | 1 - include/linux/genhd.h | 2 -- 4 files changed, 2 insertions(+), 21 deletions(-) diff --git a/block/blk-integrity.c b/block/blk-integrity.c index d69c5c79f98e..319f2e4f4a8b 100644 --- a/block/blk-integrity.c +++ b/block/blk-integrity.c @@ -417,7 +417,7 @@ void blk_integrity_register(struct gendisk *disk, struct blk_integrity *template bi->tuple_size = template->tuple_size; bi->tag_size = template->tag_size; - blk_integrity_revalidate(disk); + disk->queue->backing_dev_info.capabilities |= BDI_CAP_STABLE_WRITES; } EXPORT_SYMBOL(blk_integrity_register); @@ -430,26 +430,11 @@ EXPORT_SYMBOL(blk_integrity_register); */ void blk_integrity_unregister(struct gendisk *disk) { - blk_integrity_revalidate(disk); + disk->queue->backing_dev_info.capabilities &= ~BDI_CAP_STABLE_WRITES; memset(&disk->queue->integrity, 0, sizeof(struct blk_integrity)); } EXPORT_SYMBOL(blk_integrity_unregister); -void blk_integrity_revalidate(struct gendisk *disk) -{ - struct blk_integrity *bi = &disk->queue->integrity; - - if (!(disk->flags & GENHD_FL_UP)) - return; - - if (bi->profile) - disk->queue->backing_dev_info.capabilities |= - BDI_CAP_STABLE_WRITES; - else - disk->queue->backing_dev_info.capabilities &= - ~BDI_CAP_STABLE_WRITES; -} - void blk_integrity_add(struct gendisk *disk) { if (kobject_init_and_add(&disk->integrity_kobj, &integrity_ktype, diff --git a/block/partition-generic.c b/block/partition-generic.c index 71d9ed9df8da..a2437c006640 100644 --- a/block/partition-generic.c +++ b/block/partition-generic.c @@ -447,7 +447,6 @@ rescan: if (disk->fops->revalidate_disk) disk->fops->revalidate_disk(disk); - blk_integrity_revalidate(disk); check_disk_size_change(disk, bdev); bdev->bd_invalidated = 0; if (!get_capacity(disk) || !(state = check_partition(disk, bdev))) diff --git a/fs/block_dev.c b/fs/block_dev.c index 092a2eed1628..9ad527ff9974 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c @@ -1165,7 +1165,6 @@ int revalidate_disk(struct gendisk *disk) if (disk->fops->revalidate_disk) ret = disk->fops->revalidate_disk(disk); - blk_integrity_revalidate(disk); bdev = bdget_disk(disk, 0); if (!bdev) return ret; diff --git a/include/linux/genhd.h b/include/linux/genhd.h index e0341af6950e..3c99fb6727ca 100644 --- a/include/linux/genhd.h +++ b/include/linux/genhd.h @@ -731,11 +731,9 @@ static inline void part_nr_sects_write(struct hd_struct *part, sector_t size) #if defined(CONFIG_BLK_DEV_INTEGRITY) extern void blk_integrity_add(struct gendisk *); extern void blk_integrity_del(struct gendisk *); -extern void blk_integrity_revalidate(struct gendisk *); #else /* CONFIG_BLK_DEV_INTEGRITY */ static inline void blk_integrity_add(struct gendisk *disk) { } static inline void blk_integrity_del(struct gendisk *disk) { } -static inline void blk_integrity_revalidate(struct gendisk *disk) { } #endif /* CONFIG_BLK_DEV_INTEGRITY */ #else /* CONFIG_BLOCK */ From 58cd97ff374b7c6c39c9a78595a5eb75a56a08ac Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sun, 14 May 2017 14:00:37 +0200 Subject: [PATCH 105/396] Linux 4.9.28 --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 35d6b4e76264..9460a63087b8 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ VERSION = 4 PATCHLEVEL = 9 -SUBLEVEL = 27 +SUBLEVEL = 28 EXTRAVERSION = NAME = Roaring Lionus From df5d32089a3e84f342f43f20f766ef48419449f4 Mon Sep 17 00:00:00 2001 From: Jiebing Li Date: Tue, 10 Mar 2015 11:27:10 +0800 Subject: [PATCH 106/396] ANDROID: usb: f_mtp: return error code if transfer error in receive_file_work function receive_file_work() function should report error if it detect the urb is not successfully transfered. Patchset: mtp Change-Id: I66898afe6b6ea2c33e6ea4c5ccf47d3a56d002dc Signed-off-by: Du, Changbin Signed-off-by: Wang, Yu Signed-off-by: Russ Weight --- drivers/usb/gadget/function/f_mtp.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/usb/gadget/function/f_mtp.c b/drivers/usb/gadget/function/f_mtp.c index d6aa2ea0efc8..1f7201480913 100644 --- a/drivers/usb/gadget/function/f_mtp.c +++ b/drivers/usb/gadget/function/f_mtp.c @@ -873,6 +873,10 @@ static void receive_file_work(struct work_struct *data) usb_ep_dequeue(dev->ep_out, read_req); break; } + if (read_req->status) { + r = read_req->status; + break; + } /* if xfer_file_length is 0xFFFFFFFF, then we read until * we get a zero length packet */ From 3bbd898081171cba749be5a219a90f5b30a3cf47 Mon Sep 17 00:00:00 2001 From: Jiebing Li Date: Tue, 10 Mar 2015 11:25:50 +0800 Subject: [PATCH 107/396] ANDROID: usb: gadget: fix NULL pointer issue in mtp_read() pointer dev->ep_out->desc is set to NULL if MTP function is disabled during read operation. So we need to do pointer check before access it and add spin lock protection in case it's modified at another place in future. Patchset: mtp Change-Id: I96d3d685e93276c9065a1aa7b0cbbdc2e159aa6f Signed-off-by: Jiebing Li Signed-off-by: Wang, Yu Signed-off-by: Russ Weight --- drivers/usb/gadget/function/f_mtp.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/drivers/usb/gadget/function/f_mtp.c b/drivers/usb/gadget/function/f_mtp.c index 1f7201480913..9515b2a7d0e0 100644 --- a/drivers/usb/gadget/function/f_mtp.c +++ b/drivers/usb/gadget/function/f_mtp.c @@ -541,14 +541,10 @@ static ssize_t mtp_read(struct file *fp, char __user *buf, ssize_t r = count; unsigned xfer; int ret = 0; - size_t len; + size_t len = 0; DBG(cdev, "mtp_read(%zu)\n", count); - len = usb_ep_align_maybe(cdev->gadget, dev->ep_out, count); - if (len > MTP_BULK_BUFFER_SIZE) - return -EINVAL; - /* we will block until we're online */ DBG(cdev, "mtp_read: waiting for online state\n"); ret = wait_event_interruptible(dev->read_wq, @@ -558,6 +554,14 @@ static ssize_t mtp_read(struct file *fp, char __user *buf, goto done; } spin_lock_irq(&dev->lock); + if (dev->ep_out->desc) { + len = usb_ep_align_maybe(cdev->gadget, dev->ep_out, count); + if (len > MTP_BULK_BUFFER_SIZE) { + spin_unlock_irq(&dev->lock); + return -EINVAL; + } + } + if (dev->state == STATE_CANCELED) { /* report cancelation to userspace */ dev->state = STATE_READY; From 15a97d3c46c78589db87083fb07d7262df99b1dc Mon Sep 17 00:00:00 2001 From: Tim Murray Date: Fri, 2 Sep 2016 16:04:41 -0700 Subject: [PATCH 108/396] ANDROID: lowmemorykiller: account for unevictable pages lowmemorykiller was not taking into account unevictable pages when deciding what level to kill. If significant amounts of memory were pinned, this caused lowmemorykiller to effectively stop at a much higher level than it should. bug 31255977 Change-Id: I763ecbfef8c56d65bb8f6147ae810692bd81b6e2 Signed-off-by: Tim Murray --- drivers/staging/android/lowmemorykiller.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/staging/android/lowmemorykiller.c b/drivers/staging/android/lowmemorykiller.c index 6dcde85f05dc..2b14acc6bc8a 100644 --- a/drivers/staging/android/lowmemorykiller.c +++ b/drivers/staging/android/lowmemorykiller.c @@ -96,6 +96,7 @@ static unsigned long lowmem_scan(struct shrinker *s, struct shrink_control *sc) int other_free = global_page_state(NR_FREE_PAGES) - totalreserve_pages; int other_file = global_node_page_state(NR_FILE_PAGES) - global_node_page_state(NR_SHMEM) - + global_node_page_state(NR_UNEVICTABLE) - total_swapcache_pages(); if (lowmem_adj_size < array_size) From a56a105ea76353249a44315cc542d1a1cb56e0f7 Mon Sep 17 00:00:00 2001 From: Daniel Rosenberg Date: Mon, 15 May 2017 14:03:15 -0700 Subject: [PATCH 109/396] ANDROID: sdcardfs: Move top to its own struct Move top, and the associated data, to its own struct. This way, we can properly track refcounts on top without interfering with the inode's accounting. Signed-off-by: Daniel Rosenberg Bug: 38045152 Change-Id: I1968e480d966c3f234800b72e43670ca11e1d3fd --- fs/sdcardfs/dentry.c | 15 +++++ fs/sdcardfs/derived_perm.c | 130 +++++++++++++++++++------------------ fs/sdcardfs/inode.c | 54 ++++++++------- fs/sdcardfs/lookup.c | 5 +- fs/sdcardfs/main.c | 8 +-- fs/sdcardfs/packagelist.c | 2 +- fs/sdcardfs/sdcardfs.h | 110 ++++++++++++++++++++----------- fs/sdcardfs/super.c | 49 ++++++++++++-- 8 files changed, 236 insertions(+), 137 deletions(-) diff --git a/fs/sdcardfs/dentry.c b/fs/sdcardfs/dentry.c index ae2b4babe2e5..a23168179716 100644 --- a/fs/sdcardfs/dentry.c +++ b/fs/sdcardfs/dentry.c @@ -34,6 +34,8 @@ static int sdcardfs_d_revalidate(struct dentry *dentry, unsigned int flags) struct dentry *parent_lower_dentry = NULL; struct dentry *lower_cur_parent_dentry = NULL; struct dentry *lower_dentry = NULL; + struct inode *inode; + struct sdcardfs_inode_data *data; if (flags & LOOKUP_RCU) return -ECHILD; @@ -103,6 +105,19 @@ static int sdcardfs_d_revalidate(struct dentry *dentry, unsigned int flags) spin_unlock(&dentry->d_lock); spin_unlock(&lower_dentry->d_lock); } + if (!err) + goto out; + + /* If our top's inode is gone, we may be out of date */ + inode = d_inode(dentry); + if (inode) { + data = top_data_get(SDCARDFS_I(inode)); + if (data->abandoned) { + d_drop(dentry); + err = 0; + } + data_put(data); + } out: dput(parent_dentry); diff --git a/fs/sdcardfs/derived_perm.c b/fs/sdcardfs/derived_perm.c index 5a0ef3889846..1239d1cd208b 100644 --- a/fs/sdcardfs/derived_perm.c +++ b/fs/sdcardfs/derived_perm.c @@ -26,28 +26,28 @@ static void inherit_derived_state(struct inode *parent, struct inode *child) struct sdcardfs_inode_info *pi = SDCARDFS_I(parent); struct sdcardfs_inode_info *ci = SDCARDFS_I(child); - ci->perm = PERM_INHERIT; - ci->userid = pi->userid; - ci->d_uid = pi->d_uid; - ci->under_android = pi->under_android; - ci->under_cache = pi->under_cache; - ci->under_obb = pi->under_obb; - set_top(ci, pi->top); + ci->data->perm = PERM_INHERIT; + ci->data->userid = pi->data->userid; + ci->data->d_uid = pi->data->d_uid; + ci->data->under_android = pi->data->under_android; + ci->data->under_cache = pi->data->under_cache; + ci->data->under_obb = pi->data->under_obb; + set_top(ci, pi->top_data); } /* helper function for derived state */ void setup_derived_state(struct inode *inode, perm_t perm, userid_t userid, - uid_t uid, bool under_android, - struct inode *top) + uid_t uid, bool under_android, + struct sdcardfs_inode_data *top) { struct sdcardfs_inode_info *info = SDCARDFS_I(inode); - info->perm = perm; - info->userid = userid; - info->d_uid = uid; - info->under_android = under_android; - info->under_cache = false; - info->under_obb = false; + info->data->perm = perm; + info->data->userid = userid; + info->data->d_uid = uid; + info->data->under_android = under_android; + info->data->under_cache = false; + info->data->under_obb = false; set_top(info, top); } @@ -58,7 +58,8 @@ void get_derived_permission_new(struct dentry *parent, struct dentry *dentry, const struct qstr *name) { struct sdcardfs_inode_info *info = SDCARDFS_I(d_inode(dentry)); - struct sdcardfs_inode_info *parent_info = SDCARDFS_I(d_inode(parent)); + struct sdcardfs_inode_data *parent_data = + SDCARDFS_I(d_inode(parent))->data; appid_t appid; unsigned long user_num; int err; @@ -82,60 +83,61 @@ void get_derived_permission_new(struct dentry *parent, struct dentry *dentry, if (!S_ISDIR(d_inode(dentry)->i_mode)) return; /* Derive custom permissions based on parent and current node */ - switch (parent_info->perm) { + switch (parent_data->perm) { case PERM_INHERIT: case PERM_ANDROID_PACKAGE_CACHE: /* Already inherited above */ break; case PERM_PRE_ROOT: /* Legacy internal layout places users at top level */ - info->perm = PERM_ROOT; + info->data->perm = PERM_ROOT; err = kstrtoul(name->name, 10, &user_num); if (err) - info->userid = 0; + info->data->userid = 0; else - info->userid = user_num; - set_top(info, &info->vfs_inode); + info->data->userid = user_num; + set_top(info, info->data); break; case PERM_ROOT: /* Assume masked off by default. */ if (qstr_case_eq(name, &q_Android)) { /* App-specific directories inside; let anyone traverse */ - info->perm = PERM_ANDROID; - info->under_android = true; - set_top(info, &info->vfs_inode); + info->data->perm = PERM_ANDROID; + info->data->under_android = true; + set_top(info, info->data); } break; case PERM_ANDROID: if (qstr_case_eq(name, &q_data)) { /* App-specific directories inside; let anyone traverse */ - info->perm = PERM_ANDROID_DATA; - set_top(info, &info->vfs_inode); + info->data->perm = PERM_ANDROID_DATA; + set_top(info, info->data); } else if (qstr_case_eq(name, &q_obb)) { /* App-specific directories inside; let anyone traverse */ - info->perm = PERM_ANDROID_OBB; - info->under_obb = true; - set_top(info, &info->vfs_inode); + info->data->perm = PERM_ANDROID_OBB; + info->data->under_obb = true; + set_top(info, info->data); /* Single OBB directory is always shared */ } else if (qstr_case_eq(name, &q_media)) { /* App-specific directories inside; let anyone traverse */ - info->perm = PERM_ANDROID_MEDIA; - set_top(info, &info->vfs_inode); + info->data->perm = PERM_ANDROID_MEDIA; + set_top(info, info->data); } break; case PERM_ANDROID_OBB: case PERM_ANDROID_DATA: case PERM_ANDROID_MEDIA: - info->perm = PERM_ANDROID_PACKAGE; + info->data->perm = PERM_ANDROID_PACKAGE; appid = get_appid(name->name); - if (appid != 0 && !is_excluded(name->name, parent_info->userid)) - info->d_uid = multiuser_get_uid(parent_info->userid, appid); - set_top(info, &info->vfs_inode); + if (appid != 0 && !is_excluded(name->name, parent_data->userid)) + info->data->d_uid = + multiuser_get_uid(parent_data->userid, appid); + set_top(info, info->data); break; case PERM_ANDROID_PACKAGE: if (qstr_case_eq(name, &q_cache)) { - info->perm = PERM_ANDROID_PACKAGE_CACHE; - info->under_cache = true; + info->data->perm = PERM_ANDROID_PACKAGE_CACHE; + info->data->under_cache = true; } break; } @@ -166,7 +168,8 @@ void fixup_lower_ownership(struct dentry *dentry, const char *name) struct inode *delegated_inode = NULL; int error; struct sdcardfs_inode_info *info; - struct sdcardfs_inode_info *info_top; + struct sdcardfs_inode_data *info_d; + struct sdcardfs_inode_data *info_top; perm_t perm; struct sdcardfs_sb_info *sbi = SDCARDFS_SB(dentry->d_sb); uid_t uid = sbi->options.fs_low_uid; @@ -174,15 +177,16 @@ void fixup_lower_ownership(struct dentry *dentry, const char *name) struct iattr newattrs; info = SDCARDFS_I(d_inode(dentry)); - perm = info->perm; - if (info->under_obb) { + info_d = info->data; + perm = info_d->perm; + if (info_d->under_obb) { perm = PERM_ANDROID_OBB; - } else if (info->under_cache) { + } else if (info_d->under_cache) { perm = PERM_ANDROID_PACKAGE_CACHE; } else if (perm == PERM_INHERIT) { - info_top = SDCARDFS_I(grab_top(info)); + info_top = top_data_get(info); perm = info_top->perm; - release_top(info); + data_put(info_top); } switch (perm) { @@ -192,7 +196,7 @@ void fixup_lower_ownership(struct dentry *dentry, const char *name) case PERM_ANDROID_MEDIA: case PERM_ANDROID_PACKAGE: case PERM_ANDROID_PACKAGE_CACHE: - uid = multiuser_get_uid(info->userid, uid); + uid = multiuser_get_uid(info_d->userid, uid); break; case PERM_ANDROID_OBB: uid = AID_MEDIA_OBB; @@ -207,24 +211,24 @@ void fixup_lower_ownership(struct dentry *dentry, const char *name) case PERM_ANDROID_DATA: case PERM_ANDROID_MEDIA: if (S_ISDIR(d_inode(dentry)->i_mode)) - gid = multiuser_get_uid(info->userid, AID_MEDIA_RW); + gid = multiuser_get_uid(info_d->userid, AID_MEDIA_RW); else - gid = multiuser_get_uid(info->userid, get_type(name)); + gid = multiuser_get_uid(info_d->userid, get_type(name)); break; case PERM_ANDROID_OBB: gid = AID_MEDIA_OBB; break; case PERM_ANDROID_PACKAGE: - if (uid_is_app(info->d_uid)) - gid = multiuser_get_ext_gid(info->d_uid); + if (uid_is_app(info_d->d_uid)) + gid = multiuser_get_ext_gid(info_d->d_uid); else - gid = multiuser_get_uid(info->userid, AID_MEDIA_RW); + gid = multiuser_get_uid(info_d->userid, AID_MEDIA_RW); break; case PERM_ANDROID_PACKAGE_CACHE: - if (uid_is_app(info->d_uid)) - gid = multiuser_get_ext_cache_gid(info->d_uid); + if (uid_is_app(info_d->d_uid)) + gid = multiuser_get_ext_cache_gid(info_d->d_uid); else - gid = multiuser_get_uid(info->userid, AID_MEDIA_RW); + gid = multiuser_get_uid(info_d->userid, AID_MEDIA_RW); break; case PERM_PRE_ROOT: default: @@ -257,11 +261,13 @@ retry_deleg: sdcardfs_put_lower_path(dentry, &path); } -static int descendant_may_need_fixup(struct sdcardfs_inode_info *info, struct limit_search *limit) +static int descendant_may_need_fixup(struct sdcardfs_inode_data *data, + struct limit_search *limit) { - if (info->perm == PERM_ROOT) - return (limit->flags & BY_USERID)?info->userid == limit->userid:1; - if (info->perm == PERM_PRE_ROOT || info->perm == PERM_ANDROID) + if (data->perm == PERM_ROOT) + return (limit->flags & BY_USERID) ? + data->userid == limit->userid : 1; + if (data->perm == PERM_PRE_ROOT || data->perm == PERM_ANDROID) return 1; return 0; } @@ -292,7 +298,7 @@ static void __fixup_perms_recursive(struct dentry *dentry, struct limit_search * } info = SDCARDFS_I(d_inode(dentry)); - if (needs_fixup(info->perm)) { + if (needs_fixup(info->data->perm)) { list_for_each_entry(child, &dentry->d_subdirs, d_child) { spin_lock_nested(&child->d_lock, depth + 1); if (!(limit->flags & BY_NAME) || qstr_case_eq(&child->d_name, &limit->name)) { @@ -305,7 +311,7 @@ static void __fixup_perms_recursive(struct dentry *dentry, struct limit_search * } spin_unlock(&child->d_lock); } - } else if (descendant_may_need_fixup(info, limit)) { + } else if (descendant_may_need_fixup(info->data, limit)) { list_for_each_entry(child, &dentry->d_subdirs, d_child) { __fixup_perms_recursive(child, limit, depth + 1); } @@ -349,12 +355,12 @@ int need_graft_path(struct dentry *dentry) struct sdcardfs_sb_info *sbi = SDCARDFS_SB(dentry->d_sb); struct qstr obb = QSTR_LITERAL("obb"); - if (parent_info->perm == PERM_ANDROID && + if (parent_info->data->perm == PERM_ANDROID && qstr_case_eq(&dentry->d_name, &obb)) { /* /Android/obb is the base obbpath of DERIVED_UNIFIED */ if (!(sbi->options.multiuser == false - && parent_info->userid == 0)) { + && parent_info->data->userid == 0)) { ret = 1; } } @@ -415,11 +421,11 @@ int is_base_obbpath(struct dentry *dentry) spin_lock(&SDCARDFS_D(dentry)->lock); if (sbi->options.multiuser) { - if (parent_info->perm == PERM_PRE_ROOT && + if (parent_info->data->perm == PERM_PRE_ROOT && qstr_case_eq(&dentry->d_name, &q_obb)) { ret = 1; } - } else if (parent_info->perm == PERM_ANDROID && + } else if (parent_info->data->perm == PERM_ANDROID && qstr_case_eq(&dentry->d_name, &q_obb)) { ret = 1; } diff --git a/fs/sdcardfs/inode.c b/fs/sdcardfs/inode.c index 4d558b87fe42..d48da4126dac 100644 --- a/fs/sdcardfs/inode.c +++ b/fs/sdcardfs/inode.c @@ -23,7 +23,8 @@ #include /* Do not directly use this function. Use OVERRIDE_CRED() instead. */ -const struct cred *override_fsids(struct sdcardfs_sb_info *sbi, struct sdcardfs_inode_info *info) +const struct cred *override_fsids(struct sdcardfs_sb_info *sbi, + struct sdcardfs_inode_data *data) { struct cred *cred; const struct cred *old_cred; @@ -33,10 +34,10 @@ const struct cred *override_fsids(struct sdcardfs_sb_info *sbi, struct sdcardfs_ if (!cred) return NULL; - if (info->under_obb) + if (data->under_obb) uid = AID_MEDIA_OBB; else - uid = multiuser_get_uid(info->userid, sbi->options.fs_low_uid); + uid = multiuser_get_uid(data->userid, sbi->options.fs_low_uid); cred->fsuid = make_kuid(&init_user_ns, uid); cred->fsgid = make_kgid(&init_user_ns, sbi->options.fs_low_gid); @@ -96,7 +97,8 @@ static int sdcardfs_create(struct inode *dir, struct dentry *dentry, if (err) goto out; - err = sdcardfs_interpose(dentry, dir->i_sb, &lower_path, SDCARDFS_I(dir)->userid); + err = sdcardfs_interpose(dentry, dir->i_sb, &lower_path, + SDCARDFS_I(dir)->data->userid); if (err) goto out; fsstack_copy_attr_times(dir, sdcardfs_lower_inode(dir)); @@ -267,7 +269,7 @@ static int sdcardfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode struct path lower_path; struct sdcardfs_sb_info *sbi = SDCARDFS_SB(dentry->d_sb); const struct cred *saved_cred = NULL; - struct sdcardfs_inode_info *pi = SDCARDFS_I(dir); + struct sdcardfs_inode_data *pd = SDCARDFS_I(dir)->data; int touch_err = 0; struct fs_struct *saved_fs; struct fs_struct *copied_fs; @@ -336,7 +338,7 @@ static int sdcardfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode make_nomedia_in_obb = 1; } - err = sdcardfs_interpose(dentry, dir->i_sb, &lower_path, pi->userid); + err = sdcardfs_interpose(dentry, dir->i_sb, &lower_path, pd->userid); if (err) { unlock_dir(lower_parent_dentry); goto out; @@ -349,12 +351,13 @@ static int sdcardfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode fixup_lower_ownership(dentry, dentry->d_name.name); unlock_dir(lower_parent_dentry); if ((!sbi->options.multiuser) && (qstr_case_eq(&dentry->d_name, &q_obb)) - && (pi->perm == PERM_ANDROID) && (pi->userid == 0)) + && (pd->perm == PERM_ANDROID) && (pd->userid == 0)) make_nomedia_in_obb = 1; /* When creating /Android/data and /Android/obb, mark them as .nomedia */ if (make_nomedia_in_obb || - ((pi->perm == PERM_ANDROID) && (qstr_case_eq(&dentry->d_name, &q_data)))) { + ((pd->perm == PERM_ANDROID) + && (qstr_case_eq(&dentry->d_name, &q_data)))) { REVERT_CRED(saved_cred); OVERRIDE_CRED(SDCARDFS_SB(dir->i_sb), saved_cred, SDCARDFS_I(d_inode(dentry))); set_fs_pwd(current->fs, &lower_path); @@ -620,7 +623,7 @@ static int sdcardfs_permission(struct vfsmount *mnt, struct inode *inode, int ma { int err; struct inode tmp; - struct inode *top = grab_top(SDCARDFS_I(inode)); + struct sdcardfs_inode_data *top = top_data_get(SDCARDFS_I(inode)); if (!top) return -EINVAL; @@ -637,10 +640,11 @@ static int sdcardfs_permission(struct vfsmount *mnt, struct inode *inode, int ma * locks must be dealt with to avoid undefined behavior. */ copy_attrs(&tmp, inode); - tmp.i_uid = make_kuid(&init_user_ns, SDCARDFS_I(top)->d_uid); - tmp.i_gid = make_kgid(&init_user_ns, get_gid(mnt, SDCARDFS_I(top))); - tmp.i_mode = (inode->i_mode & S_IFMT) | get_mode(mnt, SDCARDFS_I(top)); - release_top(SDCARDFS_I(inode)); + tmp.i_uid = make_kuid(&init_user_ns, top->d_uid); + tmp.i_gid = make_kgid(&init_user_ns, get_gid(mnt, top)); + tmp.i_mode = (inode->i_mode & S_IFMT) + | get_mode(mnt, SDCARDFS_I(inode), top); + data_put(top); tmp.i_sb = inode->i_sb; if (IS_POSIXACL(inode)) pr_warn("%s: This may be undefined behavior...\n", __func__); @@ -692,11 +696,12 @@ static int sdcardfs_setattr(struct vfsmount *mnt, struct dentry *dentry, struct struct dentry *parent; struct inode tmp; struct dentry tmp_d; - struct inode *top; + struct sdcardfs_inode_data *top; + const struct cred *saved_cred = NULL; inode = d_inode(dentry); - top = grab_top(SDCARDFS_I(inode)); + top = top_data_get(SDCARDFS_I(inode)); if (!top) return -EINVAL; @@ -714,11 +719,12 @@ static int sdcardfs_setattr(struct vfsmount *mnt, struct dentry *dentry, struct * */ copy_attrs(&tmp, inode); - tmp.i_uid = make_kuid(&init_user_ns, SDCARDFS_I(top)->d_uid); - tmp.i_gid = make_kgid(&init_user_ns, get_gid(mnt, SDCARDFS_I(top))); - tmp.i_mode = (inode->i_mode & S_IFMT) | get_mode(mnt, SDCARDFS_I(top)); + tmp.i_uid = make_kuid(&init_user_ns, top->d_uid); + tmp.i_gid = make_kgid(&init_user_ns, get_gid(mnt, top)); + tmp.i_mode = (inode->i_mode & S_IFMT) + | get_mode(mnt, SDCARDFS_I(inode), top); tmp.i_size = i_size_read(inode); - release_top(SDCARDFS_I(inode)); + data_put(top); tmp.i_sb = inode->i_sb; tmp_d.d_inode = &tmp; @@ -821,17 +827,17 @@ static int sdcardfs_fillattr(struct vfsmount *mnt, struct inode *inode, struct kstat *stat) { struct sdcardfs_inode_info *info = SDCARDFS_I(inode); - struct inode *top = grab_top(info); + struct sdcardfs_inode_data *top = top_data_get(info); if (!top) return -EINVAL; stat->dev = inode->i_sb->s_dev; stat->ino = inode->i_ino; - stat->mode = (inode->i_mode & S_IFMT) | get_mode(mnt, SDCARDFS_I(top)); + stat->mode = (inode->i_mode & S_IFMT) | get_mode(mnt, info, top); stat->nlink = inode->i_nlink; - stat->uid = make_kuid(&init_user_ns, SDCARDFS_I(top)->d_uid); - stat->gid = make_kgid(&init_user_ns, get_gid(mnt, SDCARDFS_I(top))); + stat->uid = make_kuid(&init_user_ns, top->d_uid); + stat->gid = make_kgid(&init_user_ns, get_gid(mnt, top)); stat->rdev = inode->i_rdev; stat->size = i_size_read(inode); stat->atime = inode->i_atime; @@ -839,7 +845,7 @@ static int sdcardfs_fillattr(struct vfsmount *mnt, stat->ctime = inode->i_ctime; stat->blksize = (1 << inode->i_blkbits); stat->blocks = inode->i_blocks; - release_top(info); + data_put(top); return 0; } diff --git a/fs/sdcardfs/lookup.c b/fs/sdcardfs/lookup.c index 706329dd1ca3..17761c546617 100644 --- a/fs/sdcardfs/lookup.c +++ b/fs/sdcardfs/lookup.c @@ -71,7 +71,7 @@ struct inode_data { static int sdcardfs_inode_test(struct inode *inode, void *candidate_data/*void *candidate_lower_inode*/) { struct inode *current_lower_inode = sdcardfs_lower_inode(inode); - userid_t current_userid = SDCARDFS_I(inode)->userid; + userid_t current_userid = SDCARDFS_I(inode)->data->userid; if (current_lower_inode == ((struct inode_data *)candidate_data)->lower_inode && current_userid == ((struct inode_data *)candidate_data)->id) @@ -438,7 +438,8 @@ struct dentry *sdcardfs_lookup(struct inode *dir, struct dentry *dentry, goto out; } - ret = __sdcardfs_lookup(dentry, flags, &lower_parent_path, SDCARDFS_I(dir)->userid); + ret = __sdcardfs_lookup(dentry, flags, &lower_parent_path, + SDCARDFS_I(dir)->data->userid); if (IS_ERR(ret)) goto out; if (ret) diff --git a/fs/sdcardfs/main.c b/fs/sdcardfs/main.c index 953d2156d2e9..3c5b51d49d21 100644 --- a/fs/sdcardfs/main.c +++ b/fs/sdcardfs/main.c @@ -327,13 +327,13 @@ static int sdcardfs_read_super(struct vfsmount *mnt, struct super_block *sb, mutex_lock(&sdcardfs_super_list_lock); if (sb_info->options.multiuser) { setup_derived_state(d_inode(sb->s_root), PERM_PRE_ROOT, - sb_info->options.fs_user_id, AID_ROOT, - false, d_inode(sb->s_root)); + sb_info->options.fs_user_id, AID_ROOT, + false, SDCARDFS_I(d_inode(sb->s_root))->data); snprintf(sb_info->obbpath_s, PATH_MAX, "%s/obb", dev_name); } else { setup_derived_state(d_inode(sb->s_root), PERM_ROOT, - sb_info->options.fs_user_id, AID_ROOT, - false, d_inode(sb->s_root)); + sb_info->options.fs_user_id, AID_ROOT, + false, SDCARDFS_I(d_inode(sb->s_root))->data); snprintf(sb_info->obbpath_s, PATH_MAX, "%s/Android/obb", dev_name); } fixup_tmp_permissions(d_inode(sb->s_root)); diff --git a/fs/sdcardfs/packagelist.c b/fs/sdcardfs/packagelist.c index 5ea6469638d8..00a0f656acc7 100644 --- a/fs/sdcardfs/packagelist.c +++ b/fs/sdcardfs/packagelist.c @@ -156,7 +156,7 @@ int check_caller_access_to_name(struct inode *parent_node, const struct qstr *na struct qstr q_android_secure = QSTR_LITERAL("android_secure"); /* Always block security-sensitive files at root */ - if (parent_node && SDCARDFS_I(parent_node)->perm == PERM_ROOT) { + if (parent_node && SDCARDFS_I(parent_node)->data->perm == PERM_ROOT) { if (qstr_case_eq(name, &q_autorun) || qstr_case_eq(name, &q__android_secure) || qstr_case_eq(name, &q_android_secure)) { diff --git a/fs/sdcardfs/sdcardfs.h b/fs/sdcardfs/sdcardfs.h index 380982b4a567..3687b22a2e6b 100644 --- a/fs/sdcardfs/sdcardfs.h +++ b/fs/sdcardfs/sdcardfs.h @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include @@ -81,7 +82,8 @@ */ #define fixup_tmp_permissions(x) \ do { \ - (x)->i_uid = make_kuid(&init_user_ns, SDCARDFS_I(x)->d_uid); \ + (x)->i_uid = make_kuid(&init_user_ns, \ + SDCARDFS_I(x)->data->d_uid); \ (x)->i_gid = make_kgid(&init_user_ns, AID_SDCARD_RW); \ (x)->i_mode = ((x)->i_mode & S_IFMT) | 0775;\ } while (0) @@ -97,14 +99,14 @@ */ #define OVERRIDE_CRED(sdcardfs_sbi, saved_cred, info) \ do { \ - saved_cred = override_fsids(sdcardfs_sbi, info); \ + saved_cred = override_fsids(sdcardfs_sbi, info->data); \ if (!saved_cred) \ return -ENOMEM; \ } while (0) #define OVERRIDE_CRED_PTR(sdcardfs_sbi, saved_cred, info) \ do { \ - saved_cred = override_fsids(sdcardfs_sbi, info); \ + saved_cred = override_fsids(sdcardfs_sbi, info->data); \ if (!saved_cred) \ return ERR_PTR(-ENOMEM); \ } while (0) @@ -142,9 +144,11 @@ typedef enum { struct sdcardfs_sb_info; struct sdcardfs_mount_options; struct sdcardfs_inode_info; +struct sdcardfs_inode_data; /* Do not directly use this function. Use OVERRIDE_CRED() instead. */ -const struct cred *override_fsids(struct sdcardfs_sb_info *sbi, struct sdcardfs_inode_info *info); +const struct cred *override_fsids(struct sdcardfs_sb_info *sbi, + struct sdcardfs_inode_data *data); /* Do not directly use this function, use REVERT_CRED() instead. */ void revert_fsids(const struct cred *old_cred); @@ -178,18 +182,26 @@ struct sdcardfs_file_info { const struct vm_operations_struct *lower_vm_ops; }; -/* sdcardfs inode data in memory */ -struct sdcardfs_inode_info { - struct inode *lower_inode; - /* state derived based on current position in hierachy */ +struct sdcardfs_inode_data { + struct kref refcount; + bool abandoned; + perm_t perm; userid_t userid; uid_t d_uid; bool under_android; bool under_cache; bool under_obb; +}; + +/* sdcardfs inode data in memory */ +struct sdcardfs_inode_info { + struct inode *lower_inode; + /* state derived based on current position in hierarchy */ + struct sdcardfs_inode_data *data; + /* top folder for ownership */ - struct inode *top; + struct sdcardfs_inode_data *top_data; struct inode vfs_inode; }; @@ -351,39 +363,56 @@ SDCARDFS_DENT_FUNC(orig_path) static inline bool sbinfo_has_sdcard_magic(struct sdcardfs_sb_info *sbinfo) { - return sbinfo && sbinfo->sb && sbinfo->sb->s_magic == SDCARDFS_SUPER_MAGIC; + return sbinfo && sbinfo->sb + && sbinfo->sb->s_magic == SDCARDFS_SUPER_MAGIC; } -/* grab a refererence if we aren't linking to ourself */ -static inline void set_top(struct sdcardfs_inode_info *info, struct inode *top) +static inline struct sdcardfs_inode_data *data_get( + struct sdcardfs_inode_data *data) { - struct inode *old_top = NULL; - - BUG_ON(IS_ERR_OR_NULL(top)); - if (info->top && info->top != &info->vfs_inode) - old_top = info->top; - if (top != &info->vfs_inode) - igrab(top); - info->top = top; - iput(old_top); + if (data) + kref_get(&data->refcount); + return data; } -static inline struct inode *grab_top(struct sdcardfs_inode_info *info) +static inline struct sdcardfs_inode_data *top_data_get( + struct sdcardfs_inode_info *info) { - struct inode *top = info->top; + return data_get(info->top_data); +} + +extern void data_release(struct kref *ref); + +static inline void data_put(struct sdcardfs_inode_data *data) +{ + kref_put(&data->refcount, data_release); +} + +static inline void release_own_data(struct sdcardfs_inode_info *info) +{ + /* + * This happens exactly once per inode. At this point, the inode that + * originally held this data is about to be freed, and all references + * to it are held as a top value, and will likely be released soon. + */ + info->data->abandoned = true; + data_put(info->data); +} + +static inline void set_top(struct sdcardfs_inode_info *info, + struct sdcardfs_inode_data *top) +{ + struct sdcardfs_inode_data *old_top = info->top_data; if (top) - return igrab(top); - else - return NULL; + data_get(top); + info->top_data = top; + if (old_top) + data_put(old_top); } -static inline void release_top(struct sdcardfs_inode_info *info) -{ - iput(info->top); -} - -static inline int get_gid(struct vfsmount *mnt, struct sdcardfs_inode_info *info) +static inline int get_gid(struct vfsmount *mnt, + struct sdcardfs_inode_data *data) { struct sdcardfs_vfsmount_options *opts = mnt->data; @@ -396,10 +425,12 @@ static inline int get_gid(struct vfsmount *mnt, struct sdcardfs_inode_info *info */ return AID_SDCARD_RW; else - return multiuser_get_uid(info->userid, opts->gid); + return multiuser_get_uid(data->userid, opts->gid); } -static inline int get_mode(struct vfsmount *mnt, struct sdcardfs_inode_info *info) +static inline int get_mode(struct vfsmount *mnt, + struct sdcardfs_inode_info *info, + struct sdcardfs_inode_data *data) { int owner_mode; int filtered_mode; @@ -407,12 +438,12 @@ static inline int get_mode(struct vfsmount *mnt, struct sdcardfs_inode_info *inf int visible_mode = 0775 & ~opts->mask; - if (info->perm == PERM_PRE_ROOT) { + if (data->perm == PERM_PRE_ROOT) { /* Top of multi-user view should always be visible to ensure * secondary users can traverse inside. */ visible_mode = 0711; - } else if (info->under_android) { + } else if (data->under_android) { /* Block "other" access to Android directories, since only apps * belonging to a specific user should be in there; we still * leave +x open for the default view. @@ -481,8 +512,9 @@ struct limit_search { userid_t userid; }; -extern void setup_derived_state(struct inode *inode, perm_t perm, userid_t userid, - uid_t uid, bool under_android, struct inode *top); +extern void setup_derived_state(struct inode *inode, perm_t perm, + userid_t userid, uid_t uid, bool under_android, + struct sdcardfs_inode_data *top); extern void get_derived_permission(struct dentry *parent, struct dentry *dentry); extern void get_derived_permission_new(struct dentry *parent, struct dentry *dentry, const struct qstr *name); extern void fixup_perms_recursive(struct dentry *dentry, struct limit_search *limit); @@ -601,7 +633,7 @@ static inline void sdcardfs_copy_and_fix_attrs(struct inode *dest, const struct { dest->i_mode = (src->i_mode & S_IFMT) | S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH; /* 0775 */ - dest->i_uid = make_kuid(&init_user_ns, SDCARDFS_I(dest)->d_uid); + dest->i_uid = make_kuid(&init_user_ns, SDCARDFS_I(dest)->data->d_uid); dest->i_gid = make_kgid(&init_user_ns, AID_SDCARD_RW); dest->i_rdev = src->i_rdev; dest->i_atime = src->i_atime; diff --git a/fs/sdcardfs/super.c b/fs/sdcardfs/super.c index 8a9c9c7adca2..7f4539b4b249 100644 --- a/fs/sdcardfs/super.c +++ b/fs/sdcardfs/super.c @@ -26,6 +26,23 @@ */ static struct kmem_cache *sdcardfs_inode_cachep; +/* + * To support the top references, we must track some data separately. + * An sdcardfs_inode_info always has a reference to its data, and once set up, + * also has a reference to its top. The top may be itself, in which case it + * holds two references to its data. When top is changed, it takes a ref to the + * new data and then drops the ref to the old data. + */ +static struct kmem_cache *sdcardfs_inode_data_cachep; + +void data_release(struct kref *ref) +{ + struct sdcardfs_inode_data *data = + container_of(ref, struct sdcardfs_inode_data, refcount); + + kmem_cache_free(sdcardfs_inode_data_cachep, data); +} + /* final actions when unmounting a file system */ static void sdcardfs_put_super(struct super_block *sb) { @@ -166,6 +183,7 @@ static void sdcardfs_evict_inode(struct inode *inode) struct inode *lower_inode; truncate_inode_pages(&inode->i_data, 0); + set_top(SDCARDFS_I(inode), NULL); clear_inode(inode); /* * Decrement a reference to a lower_inode, which was incremented @@ -173,13 +191,13 @@ static void sdcardfs_evict_inode(struct inode *inode) */ lower_inode = sdcardfs_lower_inode(inode); sdcardfs_set_lower_inode(inode, NULL); - set_top(SDCARDFS_I(inode), inode); iput(lower_inode); } static struct inode *sdcardfs_alloc_inode(struct super_block *sb) { struct sdcardfs_inode_info *i; + struct sdcardfs_inode_data *d; i = kmem_cache_alloc(sdcardfs_inode_cachep, GFP_KERNEL); if (!i) @@ -188,6 +206,16 @@ static struct inode *sdcardfs_alloc_inode(struct super_block *sb) /* memset everything up to the inode to 0 */ memset(i, 0, offsetof(struct sdcardfs_inode_info, vfs_inode)); + d = kmem_cache_alloc(sdcardfs_inode_data_cachep, + GFP_KERNEL | __GFP_ZERO); + if (!d) { + kmem_cache_free(sdcardfs_inode_cachep, i); + return NULL; + } + + i->data = d; + kref_init(&d->refcount); + i->vfs_inode.i_version = 1; return &i->vfs_inode; } @@ -196,6 +224,7 @@ static void i_callback(struct rcu_head *head) { struct inode *inode = container_of(head, struct inode, i_rcu); + release_own_data(SDCARDFS_I(inode)); kmem_cache_free(sdcardfs_inode_cachep, SDCARDFS_I(inode)); } @@ -214,20 +243,30 @@ static void init_once(void *obj) int sdcardfs_init_inode_cache(void) { - int err = 0; - sdcardfs_inode_cachep = kmem_cache_create("sdcardfs_inode_cache", sizeof(struct sdcardfs_inode_info), 0, SLAB_RECLAIM_ACCOUNT, init_once); + if (!sdcardfs_inode_cachep) - err = -ENOMEM; - return err; + return -ENOMEM; + + sdcardfs_inode_data_cachep = + kmem_cache_create("sdcardfs_inode_data_cache", + sizeof(struct sdcardfs_inode_data), 0, + SLAB_RECLAIM_ACCOUNT, NULL); + if (!sdcardfs_inode_data_cachep) { + kmem_cache_destroy(sdcardfs_inode_cachep); + return -ENOMEM; + } + + return 0; } /* sdcardfs inode cache destructor */ void sdcardfs_destroy_inode_cache(void) { + kmem_cache_destroy(sdcardfs_inode_data_cachep); kmem_cache_destroy(sdcardfs_inode_cachep); } From f2b8de98f737a1c9a1a1c58b4cbbcc139f917a35 Mon Sep 17 00:00:00 2001 From: Juergen Gross Date: Wed, 10 May 2017 06:08:44 +0200 Subject: [PATCH 110/396] xen: adjust early dom0 p2m handling to xen hypervisor behavior commit 69861e0a52f8733355ce246f0db15e1b240ad667 upstream. When booted as pv-guest the p2m list presented by the Xen is already mapped to virtual addresses. In dom0 case the hypervisor might make use of 2M- or 1G-pages for this mapping. Unfortunately while being properly aligned in virtual and machine address space, those pages might not be aligned properly in guest physical address space. So when trying to obtain the guest physical address of such a page pud_pfn() and pmd_pfn() must be avoided as those will mask away guest physical address bits not being zero in this special case. Signed-off-by: Juergen Gross Reviewed-by: Jan Beulich Signed-off-by: Juergen Gross Signed-off-by: Greg Kroah-Hartman --- arch/x86/xen/mmu.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/arch/x86/xen/mmu.c b/arch/x86/xen/mmu.c index 7d5afdb417cc..418f1b8576cf 100644 --- a/arch/x86/xen/mmu.c +++ b/arch/x86/xen/mmu.c @@ -2028,7 +2028,8 @@ static unsigned long __init xen_read_phys_ulong(phys_addr_t addr) /* * Translate a virtual address to a physical one without relying on mapped - * page tables. + * page tables. Don't rely on big pages being aligned in (guest) physical + * space! */ static phys_addr_t __init xen_early_virt_to_phys(unsigned long vaddr) { @@ -2049,7 +2050,7 @@ static phys_addr_t __init xen_early_virt_to_phys(unsigned long vaddr) sizeof(pud))); if (!pud_present(pud)) return 0; - pa = pud_pfn(pud) << PAGE_SHIFT; + pa = pud_val(pud) & PTE_PFN_MASK; if (pud_large(pud)) return pa + (vaddr & ~PUD_MASK); @@ -2057,7 +2058,7 @@ static phys_addr_t __init xen_early_virt_to_phys(unsigned long vaddr) sizeof(pmd))); if (!pmd_present(pmd)) return 0; - pa = pmd_pfn(pmd) << PAGE_SHIFT; + pa = pmd_val(pmd) & PTE_PFN_MASK; if (pmd_large(pmd)) return pa + (vaddr & ~PMD_MASK); From a4e52cc7d81b387e7285aaf4b8d74562f05f99b9 Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Tue, 11 Apr 2017 16:24:16 -0700 Subject: [PATCH 111/396] target: Fix compare_and_write_callback handling for non GOOD status commit a71a5dc7f833943998e97ca8fa6a4c708a0ed1a9 upstream. Following the bugfix for handling non SAM_STAT_GOOD COMPARE_AND_WRITE status during COMMIT phase in commit 9b2792c3da1, the same bug exists for the READ phase as well. This would manifest first as a lost SCSI response, and eventual hung task during fabric driver logout or re-login, as existing shutdown logic waited for the COMPARE_AND_WRITE se_cmd->cmd_kref to reach zero. To address this bug, compare_and_write_callback() has been changed to set post_ret = 1 and return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE as necessary to signal failure status. Reported-by: Bill Borsari Cc: Bill Borsari Tested-by: Gary Guo Cc: Gary Guo Signed-off-by: Nicholas Bellinger Signed-off-by: Greg Kroah-Hartman --- drivers/target/target_core_sbc.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/target/target_core_sbc.c b/drivers/target/target_core_sbc.c index a53fb23a0411..b3b1461ec60d 100644 --- a/drivers/target/target_core_sbc.c +++ b/drivers/target/target_core_sbc.c @@ -506,8 +506,11 @@ static sense_reason_t compare_and_write_callback(struct se_cmd *cmd, bool succes * been failed with a non-zero SCSI status. */ if (cmd->scsi_status) { - pr_err("compare_and_write_callback: non zero scsi_status:" + pr_debug("compare_and_write_callback: non zero scsi_status:" " 0x%02x\n", cmd->scsi_status); + *post_ret = 1; + if (cmd->scsi_status == SAM_STAT_CHECK_CONDITION) + ret = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; goto out; } From f788fa43d87a4a2575deafb54e5333b06d34399d Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Thu, 4 May 2017 15:50:47 -0700 Subject: [PATCH 112/396] target/fileio: Fix zero-length READ and WRITE handling commit 59ac9c078141b8fd0186c0b18660a1b2c24e724e upstream. This patch fixes zero-length READ and WRITE handling in target/FILEIO, which was broken a long time back by: Since: commit d81cb44726f050d7cf1be4afd9cb45d153b52066 Author: Paolo Bonzini Date: Mon Sep 17 16:36:11 2012 -0700 target: go through normal processing for all zero-length commands which moved zero-length READ and WRITE completion out of target-core, to doing submission into backend driver code. To address this, go ahead and invoke target_complete_cmd() for any non negative return value in fd_do_rw(). Signed-off-by: Bart Van Assche Reviewed-by: Hannes Reinecke Reviewed-by: Christoph Hellwig Cc: Andy Grover Cc: David Disseldorp Signed-off-by: Nicholas Bellinger Signed-off-by: Greg Kroah-Hartman --- drivers/target/target_core_file.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/target/target_core_file.c b/drivers/target/target_core_file.c index d545993df18b..29f807b29e74 100644 --- a/drivers/target/target_core_file.c +++ b/drivers/target/target_core_file.c @@ -594,8 +594,7 @@ fd_execute_rw(struct se_cmd *cmd, struct scatterlist *sgl, u32 sgl_nents, if (ret < 0) return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; - if (ret) - target_complete_cmd(cmd, SAM_STAT_GOOD); + target_complete_cmd(cmd, SAM_STAT_GOOD); return 0; } From bb1f06f53bcb111d8f2d5d58f9ae68c4a9cef81e Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Tue, 25 Apr 2017 10:55:12 -0700 Subject: [PATCH 113/396] iscsi-target: Set session_fall_back_to_erl0 when forcing reinstatement commit 197b806ae5db60c6f609d74da04ddb62ea5e1b00 upstream. While testing modification of per se_node_acl queue_depth forcing session reinstatement via lio_target_nacl_cmdsn_depth_store() -> core_tpg_set_initiator_node_queue_depth(), a hung task bug triggered when changing cmdsn_depth invoked session reinstatement while an iscsi login was already waiting for session reinstatement to complete. This can happen when an outstanding se_cmd descriptor is taking a long time to complete, and session reinstatement from iscsi login or cmdsn_depth change occurs concurrently. To address this bug, explicitly set session_fall_back_to_erl0 = 1 when forcing session reinstatement, so session reinstatement is not attempted if an active session is already being shutdown. This patch has been tested with two scenarios. The first when iscsi login is blocked waiting for iscsi session reinstatement to complete followed by queue_depth change via configfs, and second when queue_depth change via configfs us blocked followed by a iscsi login driven session reinstatement. Note this patch depends on commit d36ad77f702 to handle multiple sessions per se_node_acl when changing cmdsn_depth, and for pre v4.5 kernels will need to be included for stable as well. Reported-by: Gary Guo Tested-by: Gary Guo Cc: Gary Guo Signed-off-by: Nicholas Bellinger Signed-off-by: Greg Kroah-Hartman --- drivers/target/iscsi/iscsi_target.c | 1 + drivers/target/iscsi/iscsi_target_configfs.c | 1 + drivers/target/iscsi/iscsi_target_login.c | 1 + 3 files changed, 3 insertions(+) diff --git a/drivers/target/iscsi/iscsi_target.c b/drivers/target/iscsi/iscsi_target.c index b7d747e92c7a..40e50f2d209d 100644 --- a/drivers/target/iscsi/iscsi_target.c +++ b/drivers/target/iscsi/iscsi_target.c @@ -4671,6 +4671,7 @@ int iscsit_release_sessions_for_tpg(struct iscsi_portal_group *tpg, int force) continue; } atomic_set(&sess->session_reinstatement, 1); + atomic_set(&sess->session_fall_back_to_erl0, 1); spin_unlock(&sess->conn_lock); list_move_tail(&se_sess->sess_list, &free_list); diff --git a/drivers/target/iscsi/iscsi_target_configfs.c b/drivers/target/iscsi/iscsi_target_configfs.c index e980e2d0c2db..7e70fe849f0d 100644 --- a/drivers/target/iscsi/iscsi_target_configfs.c +++ b/drivers/target/iscsi/iscsi_target_configfs.c @@ -1530,6 +1530,7 @@ static void lio_tpg_close_session(struct se_session *se_sess) return; } atomic_set(&sess->session_reinstatement, 1); + atomic_set(&sess->session_fall_back_to_erl0, 1); spin_unlock(&sess->conn_lock); iscsit_stop_time2retain_timer(sess); diff --git a/drivers/target/iscsi/iscsi_target_login.c b/drivers/target/iscsi/iscsi_target_login.c index 15f79a2ca34a..96c55bc10ac9 100644 --- a/drivers/target/iscsi/iscsi_target_login.c +++ b/drivers/target/iscsi/iscsi_target_login.c @@ -204,6 +204,7 @@ int iscsi_check_for_session_reinstatement(struct iscsi_conn *conn) initiatorname_param->value) && (sess_p->sess_ops->SessionType == sessiontype))) { atomic_set(&sess_p->session_reinstatement, 1); + atomic_set(&sess_p->session_fall_back_to_erl0, 1); spin_unlock(&sess_p->conn_lock); iscsit_inc_session_usage_count(sess_p); iscsit_stop_time2retain_timer(sess_p); From 853469d53e86bcce076ab65a06d3092664ec8990 Mon Sep 17 00:00:00 2001 From: Roger Quadros Date: Fri, 7 Apr 2017 17:57:12 +0300 Subject: [PATCH 114/396] usb: xhci: bInterval quirk for TI TUSB73x0 commit 69307ccb9ad7ccb653e332de68effdeaaab6907d upstream. As per [1] issue #4, "The periodic EP scheduler always tries to schedule the EPs that have large intervals (interval equal to or greater than 128 microframes) into different microframes. So it maintains an internal counter and increments for each large interval EP added. When the counter is greater than 128, the scheduler rejects the new EP. So when the hub re-enumerated 128 times, it triggers this condition." This results in Bandwidth error when devices with periodic endpoints (ISO/INT) having bInterval > 7 are plugged and unplugged several times on a TUSB73x0 XHCI host. Workaround this issue by limiting the bInterval to 7 (i.e. interval to 6) for High-speed or faster periodic endpoints. [1] - http://www.ti.com/lit/er/sllz076/sllz076.pdf Signed-off-by: Roger Quadros Signed-off-by: Mathias Nyman Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/xhci-mem.c | 11 +++++++++++ drivers/usb/host/xhci-pci.c | 3 +++ drivers/usb/host/xhci.h | 1 + 3 files changed, 15 insertions(+) diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index 7064892ff4a6..87848ce95b6f 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c @@ -1494,6 +1494,17 @@ int xhci_endpoint_init(struct xhci_hcd *xhci, */ max_esit_payload = xhci_get_max_esit_payload(udev, ep); interval = xhci_get_endpoint_interval(udev, ep); + + /* Periodic endpoint bInterval limit quirk */ + if (usb_endpoint_xfer_int(&ep->desc) || + usb_endpoint_xfer_isoc(&ep->desc)) { + if ((xhci->quirks & XHCI_LIMIT_ENDPOINT_INTERVAL_7) && + udev->speed >= USB_SPEED_HIGH && + interval >= 7) { + interval = 6; + } + } + mult = xhci_get_endpoint_mult(udev, ep); max_packet = GET_MAX_PACKET(usb_endpoint_maxp(&ep->desc)); max_burst = xhci_get_endpoint_max_burst(udev, ep); diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c index 954abfd5014d..93f566cb968b 100644 --- a/drivers/usb/host/xhci-pci.c +++ b/drivers/usb/host/xhci-pci.c @@ -199,6 +199,9 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci) pdev->device == 0x1042) xhci->quirks |= XHCI_BROKEN_STREAMS; + if (pdev->vendor == PCI_VENDOR_ID_TI && pdev->device == 0x8241) + xhci->quirks |= XHCI_LIMIT_ENDPOINT_INTERVAL_7; + if (xhci->quirks & XHCI_RESET_ON_RESUME) xhci_dbg_trace(xhci, trace_xhci_dbg_quirks, "QUIRK: Resetting on resume"); diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index f97b009ffc40..328fe06752ec 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -1659,6 +1659,7 @@ struct xhci_hcd { #define XHCI_MISSING_CAS (1 << 24) /* For controller with a broken Port Disable implementation */ #define XHCI_BROKEN_PORT_PED (1 << 25) +#define XHCI_LIMIT_ENDPOINT_INTERVAL_7 (1 << 26) unsigned int num_active_eps; unsigned int limit_active_eps; From 91cd8f900c75dd095528c90c56a1c4a6452aa105 Mon Sep 17 00:00:00 2001 From: Peter Chen Date: Wed, 19 Apr 2017 16:55:52 +0300 Subject: [PATCH 115/396] usb: host: xhci: print correct command ring address commit 6fc091fb0459ade939a795bfdcaf645385b951d4 upstream. Print correct command ring address using 'val_64'. Signed-off-by: Peter Chen Signed-off-by: Mathias Nyman Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/xhci-mem.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index 87848ce95b6f..709b52841c87 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c @@ -2486,7 +2486,7 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags) (xhci->cmd_ring->first_seg->dma & (u64) ~CMD_RING_RSVD_BITS) | xhci->cmd_ring->cycle_state; xhci_dbg_trace(xhci, trace_xhci_dbg_init, - "// Setting command ring address to 0x%x", val); + "// Setting command ring address to 0x%016llx", val_64); xhci_write_64(xhci, val_64, &xhci->op_regs->cmd_ring); xhci_dbg_cmd_ptrs(xhci); From c31ff3ceb32616145d16862c7e897a59dc919882 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Tue, 18 Apr 2017 20:07:56 +0200 Subject: [PATCH 116/396] USB: serial: ftdi_sio: add device ID for Microsemi/Arrow SF2PLUS Dev Kit commit 31c5d1922b90ddc1da6a6ddecef7cd31f17aa32b upstream. This development kit has an FT4232 on it with a custom USB VID/PID. The FT4232 provides four UARTs, but only two are used. The UART 0 is used by the FlashPro5 programmer and UART 2 is connected to the SmartFusion2 CortexM3 SoC UART port. Note that the USB VID is registered to Actel according to Linux USB VID database, but that was acquired by Microsemi. Signed-off-by: Marek Vasut Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/ftdi_sio.c | 1 + drivers/usb/serial/ftdi_sio_ids.h | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index d8d13eede6d9..1dc75db16cbd 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -873,6 +873,7 @@ static const struct usb_device_id id_table_combined[] = { { USB_DEVICE_AND_INTERFACE_INFO(MICROCHIP_VID, MICROCHIP_USB_BOARD_PID, USB_CLASS_VENDOR_SPEC, USB_SUBCLASS_VENDOR_SPEC, 0x00) }, + { USB_DEVICE_INTERFACE_NUMBER(ACTEL_VID, MICROSEMI_ARROW_SF2PLUS_BOARD_PID, 2) }, { USB_DEVICE(JETI_VID, JETI_SPC1201_PID) }, { USB_DEVICE(MARVELL_VID, MARVELL_SHEEVAPLUG_PID), .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h index 48ee04c94a75..71fb9e59db71 100644 --- a/drivers/usb/serial/ftdi_sio_ids.h +++ b/drivers/usb/serial/ftdi_sio_ids.h @@ -873,6 +873,12 @@ #define FIC_VID 0x1457 #define FIC_NEO1973_DEBUG_PID 0x5118 +/* + * Actel / Microsemi + */ +#define ACTEL_VID 0x1514 +#define MICROSEMI_ARROW_SF2PLUS_BOARD_PID 0x2008 + /* Olimex */ #define OLIMEX_VID 0x15BA #define OLIMEX_ARM_USB_OCD_PID 0x0003 From 5ffe717f351ddf63161b6390b1ea90a5c3733994 Mon Sep 17 00:00:00 2001 From: Ajay Kaher Date: Tue, 28 Mar 2017 08:09:32 -0400 Subject: [PATCH 117/396] USB: Proper handling of Race Condition when two USB class drivers try to call init_usb_class simultaneously commit 2f86a96be0ccb1302b7eee7855dbee5ce4dc5dfb upstream. There is race condition when two USB class drivers try to call init_usb_class at the same time and leads to crash. code path: probe->usb_register_dev->init_usb_class To solve this, mutex locking has been added in init_usb_class() and destroy_usb_class(). As pointed by Alan, removed "if (usb_class)" test from destroy_usb_class() because usb_class can never be NULL there. Signed-off-by: Ajay Kaher Acked-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/file.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/usb/core/file.c b/drivers/usb/core/file.c index 822ced9639aa..422ce7b20d73 100644 --- a/drivers/usb/core/file.c +++ b/drivers/usb/core/file.c @@ -27,6 +27,7 @@ #define MAX_USB_MINORS 256 static const struct file_operations *usb_minors[MAX_USB_MINORS]; static DECLARE_RWSEM(minor_rwsem); +static DEFINE_MUTEX(init_usb_class_mutex); static int usb_open(struct inode *inode, struct file *file) { @@ -109,8 +110,9 @@ static void release_usb_class(struct kref *kref) static void destroy_usb_class(void) { - if (usb_class) - kref_put(&usb_class->kref, release_usb_class); + mutex_lock(&init_usb_class_mutex); + kref_put(&usb_class->kref, release_usb_class); + mutex_unlock(&init_usb_class_mutex); } int usb_major_init(void) @@ -171,7 +173,10 @@ int usb_register_dev(struct usb_interface *intf, if (intf->minor >= 0) return -EADDRINUSE; + mutex_lock(&init_usb_class_mutex); retval = init_usb_class(); + mutex_unlock(&init_usb_class_mutex); + if (retval) return retval; From 6312a84dc8b5896efbbb4255061bf6b3b6c5922d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Mork?= Date: Fri, 21 Apr 2017 10:01:29 +0200 Subject: [PATCH 118/396] USB: Revert "cdc-wdm: fix "out-of-sync" due to missing notifications" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 19445816996d1a89682c37685fe95959631d9f32 upstream. This reverts commit 833415a3e781 ("cdc-wdm: fix "out-of-sync" due to missing notifications") There have been several reports of wdm_read returning unexpected EIO errors with QMI devices using the qmi_wwan driver. The reporters confirm that reverting prevents these errors. I have been unable to reproduce the bug myself, and have no explanation to offer either. But reverting is the safe choice here, given that the commit was an attempt to work around a firmware problem. Living with a firmware problem is still better than adding driver bugs. Reported-by: Kasper Holtze Reported-by: Aleksander Morgado Reported-by: Daniele Palmas Fixes: 833415a3e781 ("cdc-wdm: fix "out-of-sync" due to missing notifications") Signed-off-by: Bjørn Mork Acked-by: Oliver Neukum Signed-off-by: Greg Kroah-Hartman --- drivers/usb/class/cdc-wdm.c | 103 ++---------------------------------- 1 file changed, 4 insertions(+), 99 deletions(-) diff --git a/drivers/usb/class/cdc-wdm.c b/drivers/usb/class/cdc-wdm.c index 0a6369510f2d..0b845e550fbd 100644 --- a/drivers/usb/class/cdc-wdm.c +++ b/drivers/usb/class/cdc-wdm.c @@ -58,7 +58,6 @@ MODULE_DEVICE_TABLE (usb, wdm_ids); #define WDM_SUSPENDING 8 #define WDM_RESETTING 9 #define WDM_OVERFLOW 10 -#define WDM_DRAIN_ON_OPEN 11 #define WDM_MAX 16 @@ -182,7 +181,7 @@ static void wdm_in_callback(struct urb *urb) "nonzero urb status received: -ESHUTDOWN\n"); goto skip_error; case -EPIPE: - dev_dbg(&desc->intf->dev, + dev_err(&desc->intf->dev, "nonzero urb status received: -EPIPE\n"); break; default: @@ -210,25 +209,6 @@ static void wdm_in_callback(struct urb *urb) desc->reslength = length; } } - - /* - * Handling devices with the WDM_DRAIN_ON_OPEN flag set: - * If desc->resp_count is unset, then the urb was submitted - * without a prior notification. If the device returned any - * data, then this implies that it had messages queued without - * notifying us. Continue reading until that queue is flushed. - */ - if (!desc->resp_count) { - if (!length) { - /* do not propagate the expected -EPIPE */ - desc->rerr = 0; - goto unlock; - } - dev_dbg(&desc->intf->dev, "got %d bytes without notification\n", length); - set_bit(WDM_RESPONDING, &desc->flags); - usb_submit_urb(desc->response, GFP_ATOMIC); - } - skip_error: set_bit(WDM_READ, &desc->flags); wake_up(&desc->wait); @@ -243,7 +223,6 @@ skip_error: service_outstanding_interrupt(desc); } -unlock: spin_unlock(&desc->iuspin); } @@ -686,17 +665,6 @@ static int wdm_open(struct inode *inode, struct file *file) dev_err(&desc->intf->dev, "Error submitting int urb - %d\n", rv); rv = usb_translate_errors(rv); - } else if (test_bit(WDM_DRAIN_ON_OPEN, &desc->flags)) { - /* - * Some devices keep pending messages queued - * without resending notifications. We must - * flush the message queue before we can - * assume a one-to-one relationship between - * notifications and messages in the queue - */ - dev_dbg(&desc->intf->dev, "draining queued data\n"); - set_bit(WDM_RESPONDING, &desc->flags); - rv = usb_submit_urb(desc->response, GFP_KERNEL); } } else { rv = 0; @@ -803,8 +771,7 @@ static void wdm_rxwork(struct work_struct *work) /* --- hotplug --- */ static int wdm_create(struct usb_interface *intf, struct usb_endpoint_descriptor *ep, - u16 bufsize, int (*manage_power)(struct usb_interface *, int), - bool drain_on_open) + u16 bufsize, int (*manage_power)(struct usb_interface *, int)) { int rv = -ENOMEM; struct wdm_device *desc; @@ -891,68 +858,6 @@ static int wdm_create(struct usb_interface *intf, struct usb_endpoint_descriptor desc->manage_power = manage_power; - /* - * "drain_on_open" enables a hack to work around a firmware - * issue observed on network functions, in particular MBIM - * functions. - * - * Quoting section 7 of the CDC-WMC r1.1 specification: - * - * "The firmware shall interpret GetEncapsulatedResponse as a - * request to read response bytes. The firmware shall send - * the next wLength bytes from the response. The firmware - * shall allow the host to retrieve data using any number of - * GetEncapsulatedResponse requests. The firmware shall - * return a zero- length reply if there are no data bytes - * available. - * - * The firmware shall send ResponseAvailable notifications - * periodically, using any appropriate algorithm, to inform - * the host that there is data available in the reply - * buffer. The firmware is allowed to send ResponseAvailable - * notifications even if there is no data available, but - * this will obviously reduce overall performance." - * - * These requirements, although they make equally sense, are - * often not implemented by network functions. Some firmwares - * will queue data indefinitely, without ever resending a - * notification. The result is that the driver and firmware - * loses "syncronization" if the driver ever fails to respond - * to a single notification, something which easily can happen - * on release(). When this happens, the driver will appear to - * never receive notifications for the most current data. Each - * notification will only cause a single read, which returns - * the oldest data in the firmware's queue. - * - * The "drain_on_open" hack resolves the situation by draining - * data from the firmware until none is returned, without a - * prior notification. - * - * This will inevitably race with the firmware, risking that - * we read data from the device before handling the associated - * notification. To make things worse, some of the devices - * needing the hack do not implement the "return zero if no - * data is available" requirement either. Instead they return - * an error on the subsequent read in this case. This means - * that "winning" the race can cause an unexpected EIO to - * userspace. - * - * "winning" the race is more likely on resume() than on - * open(), and the unexpected error is more harmful in the - * middle of an open session. The hack is therefore only - * applied on open(), and not on resume() where it logically - * would be equally necessary. So we define open() as the only - * driver <-> device "syncronization point". Should we happen - * to lose a notification after open(), then syncronization - * will be lost until release() - * - * The hack should not be enabled for CDC WDM devices - * conforming to the CDC-WMC r1.1 specification. This is - * ensured by setting drain_on_open to false in wdm_probe(). - */ - if (drain_on_open) - set_bit(WDM_DRAIN_ON_OPEN, &desc->flags); - spin_lock(&wdm_device_list_lock); list_add(&desc->device_list, &wdm_device_list); spin_unlock(&wdm_device_list_lock); @@ -1006,7 +911,7 @@ static int wdm_probe(struct usb_interface *intf, const struct usb_device_id *id) goto err; ep = &iface->endpoint[0].desc; - rv = wdm_create(intf, ep, maxcom, &wdm_manage_power, false); + rv = wdm_create(intf, ep, maxcom, &wdm_manage_power); err: return rv; @@ -1038,7 +943,7 @@ struct usb_driver *usb_cdc_wdm_register(struct usb_interface *intf, { int rv = -EINVAL; - rv = wdm_create(intf, ep, bufsize, manage_power, true); + rv = wdm_create(intf, ep, bufsize, manage_power); if (rv < 0) goto err; From 3eff228fdd43a9d5f242c6a8e5d69a1cb68a27eb Mon Sep 17 00:00:00 2001 From: Malcolm Priestley Date: Sat, 22 Apr 2017 11:14:58 +0100 Subject: [PATCH 119/396] staging: vt6656: use off stack for in buffer USB transfers. commit 05c0cf88bec588a7cb34de569acd871ceef26760 upstream. Since 4.9 mandated USB buffers to be heap allocated. This causes the driver to fail. Create buffer for USB transfers. Signed-off-by: Malcolm Priestley Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6656/usbpipe.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/drivers/staging/vt6656/usbpipe.c b/drivers/staging/vt6656/usbpipe.c index e9b6b21f7422..1c7eca7baf97 100644 --- a/drivers/staging/vt6656/usbpipe.c +++ b/drivers/staging/vt6656/usbpipe.c @@ -75,15 +75,28 @@ int vnt_control_in(struct vnt_private *priv, u8 request, u16 value, u16 index, u16 length, u8 *buffer) { int status; + u8 *usb_buffer; if (test_bit(DEVICE_FLAGS_DISCONNECTED, &priv->flags)) return STATUS_FAILURE; mutex_lock(&priv->usb_lock); + usb_buffer = kmalloc(length, GFP_KERNEL); + if (!usb_buffer) { + mutex_unlock(&priv->usb_lock); + return -ENOMEM; + } + status = usb_control_msg(priv->usb, - usb_rcvctrlpipe(priv->usb, 0), request, 0xc0, value, - index, buffer, length, USB_CTL_WAIT); + usb_rcvctrlpipe(priv->usb, 0), + request, 0xc0, value, + index, usb_buffer, length, USB_CTL_WAIT); + + if (status == length) + memcpy(buffer, usb_buffer, length); + + kfree(usb_buffer); mutex_unlock(&priv->usb_lock); From 83f66c9a602613a79c56a1ae5a8c6152fb57ea8d Mon Sep 17 00:00:00 2001 From: Malcolm Priestley Date: Sat, 22 Apr 2017 11:14:57 +0100 Subject: [PATCH 120/396] staging: vt6656: use off stack for out buffer USB transfers. commit 12ecd24ef93277e4e5feaf27b0b18f2d3828bc5e upstream. Since 4.9 mandated USB buffers be heap allocated this causes the driver to fail. Since there is a wide range of buffer sizes use kmemdup to create allocated buffer. Signed-off-by: Malcolm Priestley Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6656/usbpipe.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/drivers/staging/vt6656/usbpipe.c b/drivers/staging/vt6656/usbpipe.c index 1c7eca7baf97..f759aa8a342d 100644 --- a/drivers/staging/vt6656/usbpipe.c +++ b/drivers/staging/vt6656/usbpipe.c @@ -47,15 +47,25 @@ int vnt_control_out(struct vnt_private *priv, u8 request, u16 value, u16 index, u16 length, u8 *buffer) { int status = 0; + u8 *usb_buffer; if (test_bit(DEVICE_FLAGS_DISCONNECTED, &priv->flags)) return STATUS_FAILURE; mutex_lock(&priv->usb_lock); + usb_buffer = kmemdup(buffer, length, GFP_KERNEL); + if (!usb_buffer) { + mutex_unlock(&priv->usb_lock); + return -ENOMEM; + } + status = usb_control_msg(priv->usb, - usb_sndctrlpipe(priv->usb, 0), request, 0x40, value, - index, buffer, length, USB_CTL_WAIT); + usb_sndctrlpipe(priv->usb, 0), + request, 0x40, value, + index, usb_buffer, length, USB_CTL_WAIT); + + kfree(usb_buffer); mutex_unlock(&priv->usb_lock); From 55f9811b98f25724ab828fba0f4f8dd5302de405 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 26 Apr 2017 12:23:04 +0200 Subject: [PATCH 121/396] staging: gdm724x: gdm_mux: fix use-after-free on module unload commit b58f45c8fc301fe83ee28cad3e64686c19e78f1c upstream. Make sure to deregister the USB driver before releasing the tty driver to avoid use-after-free in the USB disconnect callback where the tty devices are deregistered. Fixes: 61e121047645 ("staging: gdm7240: adding LTE USB driver") Cc: Won Kang Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/staging/gdm724x/gdm_mux.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/staging/gdm724x/gdm_mux.c b/drivers/staging/gdm724x/gdm_mux.c index 400969170d1c..f03e43b1b5f6 100644 --- a/drivers/staging/gdm724x/gdm_mux.c +++ b/drivers/staging/gdm724x/gdm_mux.c @@ -664,9 +664,8 @@ static int __init gdm_usb_mux_init(void) static void __exit gdm_usb_mux_exit(void) { - unregister_lte_tty_driver(); - usb_deregister(&gdm_mux_driver); + unregister_lte_tty_driver(); } module_init(gdm_usb_mux_init); From 2bdc2e8c29e930e1417f30b49574ed9cef00904c Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Fri, 17 Feb 2017 11:09:08 +0000 Subject: [PATCH 122/396] staging: comedi: jr3_pci: fix possible null pointer dereference commit 45292be0b3db0b7f8286683b376e2d9f949d11f9 upstream. For some reason, the driver does not consider allocation of the subdevice private data to be a fatal error when attaching the COMEDI device. It tests the subdevice private data pointer for validity at certain points, but omits some crucial tests. In particular, `jr3_pci_auto_attach()` calls `jr3_pci_alloc_spriv()` to allocate and initialize the subdevice private data, but the same function subsequently dereferences the pointer to access the `next_time_min` and `next_time_max` members without checking it first. The other missing test is in the timer expiry routine `jr3_pci_poll_dev()`, but it will crash before it gets that far. Fix the bug by returning `-ENOMEM` from `jr3_pci_auto_attach()` as soon as one of the calls to `jr3_pci_alloc_spriv()` returns `NULL`. The COMEDI core will subsequently call `jr3_pci_detach()` to clean up. Signed-off-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/jr3_pci.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/drivers/staging/comedi/drivers/jr3_pci.c b/drivers/staging/comedi/drivers/jr3_pci.c index 70390de66e0e..25909a936e7c 100644 --- a/drivers/staging/comedi/drivers/jr3_pci.c +++ b/drivers/staging/comedi/drivers/jr3_pci.c @@ -727,11 +727,12 @@ static int jr3_pci_auto_attach(struct comedi_device *dev, s->insn_read = jr3_pci_ai_insn_read; spriv = jr3_pci_alloc_spriv(dev, s); - if (spriv) { - /* Channel specific range and maxdata */ - s->range_table_list = spriv->range_table_list; - s->maxdata_list = spriv->maxdata_list; - } + if (!spriv) + return -ENOMEM; + + /* Channel specific range and maxdata */ + s->range_table_list = spriv->range_table_list; + s->maxdata_list = spriv->maxdata_list; } /* Reset DSP card */ From a54ab7420ac742399c150c90e6c9219ab3d9b977 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Fri, 17 Feb 2017 11:09:09 +0000 Subject: [PATCH 123/396] staging: comedi: jr3_pci: cope with jiffies wraparound commit 8ec04a491825e08068e92bed0bba7821893b6433 upstream. The timer expiry routine `jr3_pci_poll_dev()` checks for expiry by checking whether the absolute value of `jiffies` (stored in local variable `now`) is greater than the expected expiry time in jiffy units. This will fail when `jiffies` wraps around. Also, it seems to make sense to handle the expiry one jiffy earlier than the current test. Use `time_after_eq()` to check for expiry. Signed-off-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/jr3_pci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/comedi/drivers/jr3_pci.c b/drivers/staging/comedi/drivers/jr3_pci.c index 25909a936e7c..eb0a095efe9c 100644 --- a/drivers/staging/comedi/drivers/jr3_pci.c +++ b/drivers/staging/comedi/drivers/jr3_pci.c @@ -611,7 +611,7 @@ static void jr3_pci_poll_dev(unsigned long data) s = &dev->subdevices[i]; spriv = s->private; - if (now > spriv->next_time_min) { + if (time_after_eq(now, spriv->next_time_min)) { struct jr3_pci_poll_delay sub_delay; sub_delay = jr3_pci_poll_subdevice(s); From af534bf9540e4684e95489f65eda1635932b8916 Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Mon, 3 Apr 2017 22:48:40 -0500 Subject: [PATCH 124/396] usb: misc: add missing continue in switch commit 2c930e3d0aed1505e86e0928d323df5027817740 upstream. Add missing continue in switch. Addresses-Coverity-ID: 1248733 Signed-off-by: Gustavo A. R. Silva Acked-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/misc/usbtest.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/usb/misc/usbtest.c b/drivers/usb/misc/usbtest.c index 5c8210dc6fd9..d94927e5623b 100644 --- a/drivers/usb/misc/usbtest.c +++ b/drivers/usb/misc/usbtest.c @@ -159,6 +159,7 @@ get_endpoints(struct usbtest_dev *dev, struct usb_interface *intf) case USB_ENDPOINT_XFER_INT: if (dev->info->intr) goto try_intr; + continue; case USB_ENDPOINT_XFER_ISOC: if (dev->info->iso) goto try_iso; From 5c51e4b65fca4648a57719ea6b0173261fe523ba Mon Sep 17 00:00:00 2001 From: Romain Izard Date: Fri, 10 Mar 2017 14:11:41 +0100 Subject: [PATCH 125/396] usb: gadget: legacy gadgets are optional commit 6e253d0fbc665b36192b8ed3cecdbb65b413a1eb upstream. With commit bc49d1d17dcf ("usb: gadget: don't couple configfs to legacy gadgets"),it is possible to build a modular kernel with both built-in configfs support and modular legacy gadget drivers. But when building a kernel without modules, it is also necessary to be able to build with configfs but without any legacy gadget driver. This was a possible configuration when the USB_CONFIGFS was a part of the choice options, but not anymore. Mark the choice for legacy gadget drivers as optional restores this. Fixes: bc49d1d17dcf ("usb: gadget: don't couple configfs to legacy gadgets") Signed-off-by: Romain Izard Signed-off-by: Felipe Balbi Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig index 8ad203296079..f3ee80ece682 100644 --- a/drivers/usb/gadget/Kconfig +++ b/drivers/usb/gadget/Kconfig @@ -460,6 +460,7 @@ config USB_CONFIGFS_F_TCM choice tristate "USB Gadget Drivers" default USB_ETH + optional help A Linux "Gadget Driver" talks to the USB Peripheral Controller driver through the abstract "gadget" API. Some other operating From 5a001a687f7c56f11132a72b4fbe89955564c9a6 Mon Sep 17 00:00:00 2001 From: Alexey Brodkin Date: Thu, 13 Apr 2017 15:33:34 +0300 Subject: [PATCH 126/396] usb: Make sure usb/phy/of gets built-in commit 3d6159640da9c9175d1ca42f151fc1a14caded59 upstream. DWC3 driver uses of_usb_get_phy_mode() which is implemented in drivers/usb/phy/of.c and in bare minimal configuration it might not be pulled in kernel binary. In case of ARC or ARM this could be easily reproduced with "allnodefconfig" +CONFIG_USB=m +CONFIG_USB_DWC3=m. On building all ends-up with: ---------------------->8------------------ Kernel: arch/arm/boot/Image is ready Kernel: arch/arm/boot/zImage is ready Building modules, stage 2. MODPOST 5 modules ERROR: "of_usb_get_phy_mode" [drivers/usb/dwc3/dwc3.ko] undefined! make[1]: *** [__modpost] Error 1 make: *** [modules] Error 2 ---------------------->8------------------ Signed-off-by: Alexey Brodkin Cc: Greg Kroah-Hartman Cc: Masahiro Yamada Cc: Geert Uytterhoeven Cc: Nicolas Pitre Cc: Thomas Gleixner Cc: Felipe Balbi Cc: Felix Fietkau Cc: Jeremy Kerr Cc: linux-snps-arc@lists.infradead.org Signed-off-by: Greg Kroah-Hartman Signed-off-by: Greg Kroah-Hartman --- drivers/Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/Makefile b/drivers/Makefile index 194d20bee7dc..733bf0b2613f 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -101,6 +101,7 @@ obj-$(CONFIG_USB_PHY) += usb/ obj-$(CONFIG_USB) += usb/ obj-$(CONFIG_PCI) += usb/ obj-$(CONFIG_USB_GADGET) += usb/ +obj-$(CONFIG_OF) += usb/ obj-$(CONFIG_SERIO) += input/serio/ obj-$(CONFIG_GAMEPORT) += input/gameport/ obj-$(CONFIG_INPUT) += input/ From 181b0de7f7cc80bfaca75b69872e4648fc03c782 Mon Sep 17 00:00:00 2001 From: Guenter Roeck Date: Mon, 20 Mar 2017 11:16:11 -0700 Subject: [PATCH 127/396] usb: hub: Fix error loop seen after hub communication errors commit 245b2eecee2aac6fdc77dcafaa73c33f9644c3c7 upstream. While stress testing a usb controller using a bind/unbind looop, the following error loop was observed. usb 7-1.2: new low-speed USB device number 3 using xhci-hcd usb 7-1.2: hub failed to enable device, error -108 usb 7-1-port2: cannot disable (err = -22) usb 7-1-port2: couldn't allocate usb_device usb 7-1-port2: cannot disable (err = -22) hub 7-1:1.0: hub_ext_port_status failed (err = -22) hub 7-1:1.0: hub_ext_port_status failed (err = -22) hub 7-1:1.0: activate --> -22 hub 7-1:1.0: hub_ext_port_status failed (err = -22) hub 7-1:1.0: hub_ext_port_status failed (err = -22) hub 7-1:1.0: activate --> -22 hub 7-1:1.0: hub_ext_port_status failed (err = -22) hub 7-1:1.0: hub_ext_port_status failed (err = -22) hub 7-1:1.0: activate --> -22 hub 7-1:1.0: hub_ext_port_status failed (err = -22) hub 7-1:1.0: hub_ext_port_status failed (err = -22) hub 7-1:1.0: activate --> -22 hub 7-1:1.0: hub_ext_port_status failed (err = -22) hub 7-1:1.0: hub_ext_port_status failed (err = -22) hub 7-1:1.0: activate --> -22 hub 7-1:1.0: hub_ext_port_status failed (err = -22) hub 7-1:1.0: hub_ext_port_status failed (err = -22) hub 7-1:1.0: activate --> -22 hub 7-1:1.0: hub_ext_port_status failed (err = -22) hub 7-1:1.0: hub_ext_port_status failed (err = -22) hub 7-1:1.0: activate --> -22 hub 7-1:1.0: hub_ext_port_status failed (err = -22) hub 7-1:1.0: hub_ext_port_status failed (err = -22) hub 7-1:1.0: activate --> -22 hub 7-1:1.0: hub_ext_port_status failed (err = -22) hub 7-1:1.0: hub_ext_port_status failed (err = -22) ** 57 printk messages dropped ** hub 7-1:1.0: activate --> -22 ** 82 printk messages dropped ** hub 7-1:1.0: hub_ext_port_status failed (err = -22) This continues forever. After adding tracebacks into the code, the call sequence leading to this is found to be as follows. [] hub_activate+0x368/0x7b8 [] hub_resume+0x2c/0x3c [] usb_resume_interface.isra.6+0x128/0x158 [] usb_suspend_both+0x1e8/0x288 [] usb_runtime_suspend+0x3c/0x98 [] __rpm_callback+0x48/0x7c [] rpm_callback+0xa8/0xd4 [] rpm_suspend+0x84/0x758 [] rpm_idle+0x2c8/0x498 [] __pm_runtime_idle+0x60/0xac [] usb_autopm_put_interface+0x6c/0x7c [] hub_event+0x10ac/0x12ac [] process_one_work+0x390/0x6b8 [] worker_thread+0x480/0x610 [] kthread+0x164/0x178 [] ret_from_fork+0x10/0x40 kick_hub_wq() is called from hub_activate() even after failures to communicate with the hub. This results in an endless sequence of hub event -> hub activate -> wq trigger -> hub event -> ... Provide two solutions for the problem. - Only trigger the hub event queue if communication with the hub is successful. - After a suspend failure, only resume already suspended interfaces if the communication with the device is still possible. Each of the changes fixes the observed problem. Use both to improve robustness. Acked-by: Alan Stern Signed-off-by: Guenter Roeck Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/driver.c | 18 ++++++++++++++++++ drivers/usb/core/hub.c | 5 ++++- 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c index dadd1e8dfe09..3f6873b2ce32 100644 --- a/drivers/usb/core/driver.c +++ b/drivers/usb/core/driver.c @@ -1328,6 +1328,24 @@ static int usb_suspend_both(struct usb_device *udev, pm_message_t msg) */ if (udev->parent && !PMSG_IS_AUTO(msg)) status = 0; + + /* + * If the device is inaccessible, don't try to resume + * suspended interfaces and just return the error. + */ + if (status && status != -EBUSY) { + int err; + u16 devstat; + + err = usb_get_status(udev, USB_RECIP_DEVICE, 0, + &devstat); + if (err) { + dev_err(&udev->dev, + "Failed to suspend device, error %d\n", + status); + goto done; + } + } } /* If the suspend failed, resume interfaces that did get suspended */ diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 35fb2bef0e45..a5768b6fe0e8 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -1064,6 +1064,9 @@ static void hub_activate(struct usb_hub *hub, enum hub_activation_type type) portstatus = portchange = 0; status = hub_port_status(hub, port1, &portstatus, &portchange); + if (status) + goto abort; + if (udev || (portstatus & USB_PORT_STAT_CONNECTION)) dev_dbg(&port_dev->dev, "status %04x change %04x\n", portstatus, portchange); @@ -1196,7 +1199,7 @@ static void hub_activate(struct usb_hub *hub, enum hub_activation_type type) /* Scan all ports that need attention */ kick_hub_wq(hub); - + abort: if (type == HUB_INIT2 || type == HUB_INIT3) { /* Allow autosuspend if it was suppressed */ disconnected: From 219a99dd219841ce659ddfc34ec6f191b73db109 Mon Sep 17 00:00:00 2001 From: Guenter Roeck Date: Mon, 20 Mar 2017 14:30:50 -0700 Subject: [PATCH 128/396] usb: hub: Do not attempt to autosuspend disconnected devices commit f5cccf49428447dfbc9edb7a04bb8fc316269781 upstream. While running a bind/unbind stress test with the dwc3 usb driver on rk3399, the following crash was observed. Unable to handle kernel NULL pointer dereference at virtual address 00000218 pgd = ffffffc00165f000 [00000218] *pgd=000000000174f003, *pud=000000000174f003, *pmd=0000000001750003, *pte=00e8000001751713 Internal error: Oops: 96000005 [#1] PREEMPT SMP Modules linked in: uinput uvcvideo videobuf2_vmalloc cmac ipt_MASQUERADE nf_nat_masquerade_ipv4 iptable_nat nf_nat_ipv4 nf_nat rfcomm xt_mark fuse bridge stp llc zram btusb btrtl btbcm btintel bluetooth ip6table_filter mwifiex_pcie mwifiex cfg80211 cdc_ether usbnet r8152 mii joydev snd_seq_midi snd_seq_midi_event snd_rawmidi snd_seq snd_seq_device ppp_async ppp_generic slhc tun CPU: 1 PID: 29814 Comm: kworker/1:1 Not tainted 4.4.52 #507 Hardware name: Google Kevin (DT) Workqueue: pm pm_runtime_work task: ffffffc0ac540000 ti: ffffffc0af4d4000 task.ti: ffffffc0af4d4000 PC is at autosuspend_check+0x74/0x174 LR is at autosuspend_check+0x70/0x174 ... Call trace: [] autosuspend_check+0x74/0x174 [] usb_runtime_idle+0x20/0x40 [] __rpm_callback+0x48/0x7c [] rpm_idle+0x1e8/0x498 [] pm_runtime_work+0x88/0xcc [] process_one_work+0x390/0x6b8 [] worker_thread+0x480/0x610 [] kthread+0x164/0x178 [] ret_from_fork+0x10/0x40 Source: (gdb) l *0xffffffc00080dcc0 0xffffffc00080dcc0 is in autosuspend_check (drivers/usb/core/driver.c:1778). 1773 /* We don't need to check interfaces that are 1774 * disabled for runtime PM. Either they are unbound 1775 * or else their drivers don't support autosuspend 1776 * and so they are permanently active. 1777 */ 1778 if (intf->dev.power.disable_depth) 1779 continue; 1780 if (atomic_read(&intf->dev.power.usage_count) > 0) 1781 return -EBUSY; 1782 w |= intf->needs_remote_wakeup; Code analysis shows that intf is set to NULL in usb_disable_device() prior to setting actconfig to NULL. At the same time, usb_runtime_idle() does not lock the usb device, and neither does any of the functions in the traceback. This means that there is no protection against a race condition where usb_disable_device() is removing dev->actconfig->interface[] pointers while those are being accessed from autosuspend_check(). To solve the problem, synchronize and validate device state between autosuspend_check() and usb_disconnect(). Acked-by: Alan Stern Signed-off-by: Guenter Roeck Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/driver.c | 3 +++ drivers/usb/core/hub.c | 6 ++++++ 2 files changed, 9 insertions(+) diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c index 3f6873b2ce32..0bb380a9fcf7 100644 --- a/drivers/usb/core/driver.c +++ b/drivers/usb/core/driver.c @@ -1778,6 +1778,9 @@ static int autosuspend_check(struct usb_device *udev) int w, i; struct usb_interface *intf; + if (udev->state == USB_STATE_NOTATTACHED) + return -ENODEV; + /* Fail if autosuspend is disabled, or any interfaces are in use, or * any interface drivers require remote wakeup but it isn't available. */ diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index a5768b6fe0e8..579900640faa 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -2085,6 +2085,12 @@ void usb_disconnect(struct usb_device **pdev) dev_info(&udev->dev, "USB disconnect, device number %d\n", udev->devnum); + /* + * Ensure that the pm runtime code knows that the USB device + * is in the process of being disconnected. + */ + pm_runtime_barrier(&udev->dev); + usb_lock_device(udev); hub_disconnect_children(udev); From acb6dc6aa7447828355a50cf5cb542bec1398aaf Mon Sep 17 00:00:00 2001 From: Ashish Kalra Date: Wed, 19 Apr 2017 20:50:15 +0530 Subject: [PATCH 129/396] x86/boot: Fix BSS corruption/overwrite bug in early x86 kernel startup commit d594aa0277e541bb997aef0bc0a55172d8138340 upstream. The minimum size for a new stack (512 bytes) setup for arch/x86/boot components when the bootloader does not setup/provide a stack for the early boot components is not "enough". The setup code executing as part of early kernel startup code, uses the stack beyond 512 bytes and accidentally overwrites and corrupts part of the BSS section. This is exposed mostly in the early video setup code, where it was corrupting BSS variables like force_x, force_y, which in-turn affected kernel parameters such as screen_info (screen_info.orig_video_cols) and later caused an exception/panic in console_init(). Most recent boot loaders setup the stack for early boot components, so this stack overwriting into BSS section issue has not been exposed. Signed-off-by: Ashish Kalra Cc: Andy Lutomirski Cc: Borislav Petkov Cc: Brian Gerst Cc: Denys Vlasenko Cc: H. Peter Anvin Cc: Josh Poimboeuf Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Link: http://lkml.kernel.org/r/20170419152015.10011-1-ashishkalra@Ashishs-MacBook-Pro.local Signed-off-by: Ingo Molnar Signed-off-by: Greg Kroah-Hartman --- arch/x86/boot/boot.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/boot/boot.h b/arch/x86/boot/boot.h index e5612f3e3b57..d7ac721a8a96 100644 --- a/arch/x86/boot/boot.h +++ b/arch/x86/boot/boot.h @@ -16,7 +16,7 @@ #ifndef BOOT_BOOT_H #define BOOT_BOOT_H -#define STACK_SIZE 512 /* Minimum number of bytes for stack */ +#define STACK_SIZE 1024 /* Minimum number of bytes for stack */ #ifndef __ASSEMBLY__ From e65c6aa108607501271f2af80f3947f315fb56ca Mon Sep 17 00:00:00 2001 From: Andy Lutomirski Date: Wed, 22 Mar 2017 14:32:29 -0700 Subject: [PATCH 130/396] selftests/x86/ldt_gdt_32: Work around a glibc sigaction() bug commit 65973dd3fd31151823f4b8c289eebbb3fb7e6bc0 upstream. i386 glibc is buggy and calls the sigaction syscall incorrectly. This is asymptomatic for normal programs, but it blows up on programs that do evil things with segmentation. The ldt_gdt self-test is an example of such an evil program. This doesn't appear to be a regression -- I think I just got lucky with the uninitialized memory that glibc threw at the kernel when I wrote the test. This hackish fix manually issues sigaction(2) syscalls to undo the damage. Without the fix, ldt_gdt_32 segfaults; with the fix, it passes for me. See: https://sourceware.org/bugzilla/show_bug.cgi?id=21269 Signed-off-by: Andy Lutomirski Cc: Boris Ostrovsky Cc: Borislav Petkov Cc: Brian Gerst Cc: Denys Vlasenko Cc: H. Peter Anvin Cc: Josh Poimboeuf Cc: Juergen Gross Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Garnier Cc: Thomas Gleixner Link: http://lkml.kernel.org/r/aaab0f9f93c9af25396f01232608c163a760a668.1490218061.git.luto@kernel.org Signed-off-by: Ingo Molnar Signed-off-by: Greg Kroah-Hartman --- tools/testing/selftests/x86/ldt_gdt.c | 46 +++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/tools/testing/selftests/x86/ldt_gdt.c b/tools/testing/selftests/x86/ldt_gdt.c index 4af47079cf04..e717fed80219 100644 --- a/tools/testing/selftests/x86/ldt_gdt.c +++ b/tools/testing/selftests/x86/ldt_gdt.c @@ -403,6 +403,51 @@ static void *threadproc(void *ctx) } } +#ifdef __i386__ + +#ifndef SA_RESTORE +#define SA_RESTORER 0x04000000 +#endif + +/* + * The UAPI header calls this 'struct sigaction', which conflicts with + * glibc. Sigh. + */ +struct fake_ksigaction { + void *handler; /* the real type is nasty */ + unsigned long sa_flags; + void (*sa_restorer)(void); + unsigned char sigset[8]; +}; + +static void fix_sa_restorer(int sig) +{ + struct fake_ksigaction ksa; + + if (syscall(SYS_rt_sigaction, sig, NULL, &ksa, 8) == 0) { + /* + * glibc has a nasty bug: it sometimes writes garbage to + * sa_restorer. This interacts quite badly with anything + * that fiddles with SS because it can trigger legacy + * stack switching. Patch it up. See: + * + * https://sourceware.org/bugzilla/show_bug.cgi?id=21269 + */ + if (!(ksa.sa_flags & SA_RESTORER) && ksa.sa_restorer) { + ksa.sa_restorer = NULL; + if (syscall(SYS_rt_sigaction, sig, &ksa, NULL, + sizeof(ksa.sigset)) != 0) + err(1, "rt_sigaction"); + } + } +} +#else +static void fix_sa_restorer(int sig) +{ + /* 64-bit glibc works fine. */ +} +#endif + static void sethandler(int sig, void (*handler)(int, siginfo_t *, void *), int flags) { @@ -414,6 +459,7 @@ static void sethandler(int sig, void (*handler)(int, siginfo_t *, void *), if (sigaction(sig, &sa, 0)) err(1, "sigaction"); + fix_sa_restorer(sig); } static jmp_buf jmpbuf; From e0c871792cc6f1ded64ec087779b08c825d76170 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Tue, 9 May 2017 18:00:43 +0100 Subject: [PATCH 131/396] x86, pmem: Fix cache flushing for iovec write < 8 bytes commit 8376efd31d3d7c44bd05be337adde023cc531fa1 upstream. Commit 11e63f6d920d added cache flushing for unaligned writes from an iovec, covering the first and last cache line of a >= 8 byte write and the first cache line of a < 8 byte write. But an unaligned write of 2-7 bytes can still cover two cache lines, so make sure we flush both in that case. Fixes: 11e63f6d920d ("x86, pmem: fix broken __copy_user_nocache ...") Signed-off-by: Ben Hutchings Signed-off-by: Dan Williams Signed-off-by: Greg Kroah-Hartman --- arch/x86/include/asm/pmem.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/include/asm/pmem.h b/arch/x86/include/asm/pmem.h index 529bb4a6487a..e2904373010d 100644 --- a/arch/x86/include/asm/pmem.h +++ b/arch/x86/include/asm/pmem.h @@ -103,7 +103,7 @@ static inline size_t arch_copy_from_iter_pmem(void *addr, size_t bytes, if (bytes < 8) { if (!IS_ALIGNED(dest, 4) || (bytes != 4)) - arch_wb_cache_pmem(addr, 1); + arch_wb_cache_pmem(addr, bytes); } else { if (!IS_ALIGNED(dest, 8)) { dest = ALIGN(dest, boot_cpu_data.x86_clflush_size); From 0750e8b865ee02988c19e1fdae41d05184148f2c Mon Sep 17 00:00:00 2001 From: Richard Weinberger Date: Sat, 1 Apr 2017 00:41:57 +0200 Subject: [PATCH 132/396] um: Fix PTRACE_POKEUSER on x86_64 commit 9abc74a22d85ab29cef9896a2582a530da7e79bf upstream. This is broken since ever but sadly nobody noticed. Recent versions of GDB set DR_CONTROL unconditionally and UML dies due to a heap corruption. It turns out that the PTRACE_POKEUSER was copy&pasted from i386 and assumes that addresses are 4 bytes long. Fix that by using 8 as address size in the calculation. Reported-by: jie cao Signed-off-by: Richard Weinberger Signed-off-by: Greg Kroah-Hartman --- arch/x86/um/ptrace_64.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/um/ptrace_64.c b/arch/x86/um/ptrace_64.c index e30202b1716e..7c1601798169 100644 --- a/arch/x86/um/ptrace_64.c +++ b/arch/x86/um/ptrace_64.c @@ -125,7 +125,7 @@ int poke_user(struct task_struct *child, long addr, long data) else if ((addr >= offsetof(struct user, u_debugreg[0])) && (addr <= offsetof(struct user, u_debugreg[7]))) { addr -= offsetof(struct user, u_debugreg[0]); - addr = addr >> 2; + addr = addr >> 3; if ((addr == 4) || (addr == 5)) return -EIO; child->thread.arch.debugregs[addr] = data; From f99985cdee6443805180300d971351b12283f09c Mon Sep 17 00:00:00 2001 From: Vince Weaver Date: Tue, 2 May 2017 14:08:50 -0400 Subject: [PATCH 133/396] perf/x86: Fix Broadwell-EP DRAM RAPL events commit 33b88e708e7dfa58dc896da2a98f5719d2eb315c upstream. It appears as though the Broadwell-EP DRAM units share the special units quirk with Haswell-EP/KNL. Without this patch, you get really high results (a single DRAM using 20W of power). The powercap driver in drivers/powercap/intel_rapl.c already has this change. Signed-off-by: Vince Weaver Cc: Alexander Shishkin Cc: Arnaldo Carvalho de Melo Cc: Jiri Olsa Cc: Kan Liang Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Stephane Eranian Cc: Stephane Eranian Cc: Thomas Gleixner Cc: linux-kernel@vger.kernel.org Signed-off-by: Ingo Molnar Signed-off-by: Greg Kroah-Hartman --- arch/x86/events/intel/rapl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/events/intel/rapl.c b/arch/x86/events/intel/rapl.c index 0a535cea8ff3..8b902b67342a 100644 --- a/arch/x86/events/intel/rapl.c +++ b/arch/x86/events/intel/rapl.c @@ -759,7 +759,7 @@ static const struct x86_cpu_id rapl_cpu_match[] __initconst = { X86_RAPL_MODEL_MATCH(INTEL_FAM6_BROADWELL_CORE, hsw_rapl_init), X86_RAPL_MODEL_MATCH(INTEL_FAM6_BROADWELL_GT3E, hsw_rapl_init), - X86_RAPL_MODEL_MATCH(INTEL_FAM6_BROADWELL_X, hsw_rapl_init), + X86_RAPL_MODEL_MATCH(INTEL_FAM6_BROADWELL_X, hsx_rapl_init), X86_RAPL_MODEL_MATCH(INTEL_FAM6_BROADWELL_XEON_D, hsw_rapl_init), X86_RAPL_MODEL_MATCH(INTEL_FAM6_XEON_PHI_KNL, knl_rapl_init), From bdf1d5b4c12959f4473e60cde44bfa1a2ebbf44f Mon Sep 17 00:00:00 2001 From: David Hildenbrand Date: Thu, 23 Mar 2017 11:46:03 +0100 Subject: [PATCH 134/396] KVM: x86: fix user triggerable warning in kvm_apic_accept_events() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 28bf28887976d8881a3a59491896c718fade7355 upstream. If we already entered/are about to enter SMM, don't allow switching to INIT/SIPI_RECEIVED, otherwise the next call to kvm_apic_accept_events() will report a warning. Same applies if we are already in MP state INIT_RECEIVED and SMM is requested to be turned on. Refuse to set the VCPU events in this case. Fixes: cd7764fe9f73 ("KVM: x86: latch INITs while in system management mode") Reported-by: Dmitry Vyukov Signed-off-by: David Hildenbrand Signed-off-by: Radim Krčmář Signed-off-by: Greg Kroah-Hartman --- arch/x86/kvm/x86.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index e5bc139d1ba7..43c152853969 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -3051,6 +3051,12 @@ static int kvm_vcpu_ioctl_x86_set_vcpu_events(struct kvm_vcpu *vcpu, (events->exception.nr > 31 || events->exception.nr == NMI_VECTOR)) return -EINVAL; + /* INITs are latched while in SMM */ + if (events->flags & KVM_VCPUEVENT_VALID_SMM && + (events->smi.smm || events->smi.pending) && + vcpu->arch.mp_state == KVM_MP_STATE_INIT_RECEIVED) + return -EINVAL; + process_nmi(vcpu); vcpu->arch.exception.pending = events->exception.injected; vcpu->arch.exception.nr = events->exception.nr; @@ -7162,6 +7168,12 @@ int kvm_arch_vcpu_ioctl_set_mpstate(struct kvm_vcpu *vcpu, mp_state->mp_state != KVM_MP_STATE_RUNNABLE) return -EINVAL; + /* INITs are latched while in SMM */ + if ((is_smm(vcpu) || vcpu->arch.smi_pending) && + (mp_state->mp_state == KVM_MP_STATE_SIPI_RECEIVED || + mp_state->mp_state == KVM_MP_STATE_INIT_RECEIVED)) + return -EINVAL; + if (mp_state->mp_state == KVM_MP_STATE_SIPI_RECEIVED) { vcpu->arch.mp_state = KVM_MP_STATE_INIT_RECEIVED; set_bit(KVM_APIC_SIPI, &vcpu->arch.apic->pending_events); From 7b0d4391d0f4970601b21f56c540fc368bb8be06 Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Tue, 18 Apr 2017 17:59:58 +0200 Subject: [PATCH 135/396] KVM: arm/arm64: fix races in kvm_psci_vcpu_on commit 6c7a5dce22b3f3cc44be098e2837fa6797edb8b8 upstream. Fix potential races in kvm_psci_vcpu_on() by taking the kvm->lock mutex. In general, it's a bad idea to allow more than one PSCI_CPU_ON to process the same target VCPU at the same time. One such problem that may arise is that one PSCI_CPU_ON could be resetting the target vcpu, which fills the entire sys_regs array with a temporary value including the MPIDR register, while another looks up the VCPU based on the MPIDR value, resulting in no target VCPU found. Resolves both races found with the kvm-unit-tests/arm/psci unit test. Reviewed-by: Marc Zyngier Reviewed-by: Christoffer Dall Reported-by: Levente Kurusa Suggested-by: Christoffer Dall Signed-off-by: Andrew Jones Signed-off-by: Christoffer Dall Signed-off-by: Greg Kroah-Hartman --- arch/arm/kvm/psci.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/arch/arm/kvm/psci.c b/arch/arm/kvm/psci.c index c2b131527a64..a08d7a93aebb 100644 --- a/arch/arm/kvm/psci.c +++ b/arch/arm/kvm/psci.c @@ -208,9 +208,10 @@ int kvm_psci_version(struct kvm_vcpu *vcpu) static int kvm_psci_0_2_call(struct kvm_vcpu *vcpu) { - int ret = 1; + struct kvm *kvm = vcpu->kvm; unsigned long psci_fn = vcpu_get_reg(vcpu, 0) & ~((u32) 0); unsigned long val; + int ret = 1; switch (psci_fn) { case PSCI_0_2_FN_PSCI_VERSION: @@ -230,7 +231,9 @@ static int kvm_psci_0_2_call(struct kvm_vcpu *vcpu) break; case PSCI_0_2_FN_CPU_ON: case PSCI_0_2_FN64_CPU_ON: + mutex_lock(&kvm->lock); val = kvm_psci_vcpu_on(vcpu); + mutex_unlock(&kvm->lock); break; case PSCI_0_2_FN_AFFINITY_INFO: case PSCI_0_2_FN64_AFFINITY_INFO: @@ -279,6 +282,7 @@ static int kvm_psci_0_2_call(struct kvm_vcpu *vcpu) static int kvm_psci_0_1_call(struct kvm_vcpu *vcpu) { + struct kvm *kvm = vcpu->kvm; unsigned long psci_fn = vcpu_get_reg(vcpu, 0) & ~((u32) 0); unsigned long val; @@ -288,7 +292,9 @@ static int kvm_psci_0_1_call(struct kvm_vcpu *vcpu) val = PSCI_RET_SUCCESS; break; case KVM_PSCI_FN_CPU_ON: + mutex_lock(&kvm->lock); val = kvm_psci_vcpu_on(vcpu); + mutex_unlock(&kvm->lock); break; default: val = PSCI_RET_NOT_SUPPORTED; From 884ba252f3f16c577d7e5f6996c3e73a834b19fe Mon Sep 17 00:00:00 2001 From: Marc Zyngier Date: Thu, 27 Apr 2017 19:06:48 +0100 Subject: [PATCH 136/396] arm64: KVM: Fix decoding of Rt/Rt2 when trapping AArch32 CP accesses commit c667186f1c01ca8970c785888868b7ffd74e51ee upstream. Our 32bit CP14/15 handling inherited some of the ARMv7 code for handling the trapped system registers, completely missing the fact that the fields for Rt and Rt2 are now 5 bit wide, and not 4... Let's fix it, and provide an accessor for the most common Rt case. Reviewed-by: Christoffer Dall Signed-off-by: Marc Zyngier Signed-off-by: Christoffer Dall Signed-off-by: Greg Kroah-Hartman --- arch/arm64/include/asm/kvm_emulate.h | 6 ++++++ arch/arm64/kvm/sys_regs.c | 8 ++++---- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/arch/arm64/include/asm/kvm_emulate.h b/arch/arm64/include/asm/kvm_emulate.h index f5ea0ba70f07..fe39e6841326 100644 --- a/arch/arm64/include/asm/kvm_emulate.h +++ b/arch/arm64/include/asm/kvm_emulate.h @@ -240,6 +240,12 @@ static inline u8 kvm_vcpu_trap_get_fault_type(const struct kvm_vcpu *vcpu) return kvm_vcpu_get_hsr(vcpu) & ESR_ELx_FSC_TYPE; } +static inline int kvm_vcpu_sys_get_rt(struct kvm_vcpu *vcpu) +{ + u32 esr = kvm_vcpu_get_hsr(vcpu); + return (esr & ESR_ELx_SYS64_ISS_RT_MASK) >> ESR_ELx_SYS64_ISS_RT_SHIFT; +} + static inline unsigned long kvm_vcpu_get_mpidr_aff(struct kvm_vcpu *vcpu) { return vcpu_sys_reg(vcpu, MPIDR_EL1) & MPIDR_HWID_BITMASK; diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c index 87e7e6608cd8..7cee552ce0bf 100644 --- a/arch/arm64/kvm/sys_regs.c +++ b/arch/arm64/kvm/sys_regs.c @@ -1573,8 +1573,8 @@ static int kvm_handle_cp_64(struct kvm_vcpu *vcpu, { struct sys_reg_params params; u32 hsr = kvm_vcpu_get_hsr(vcpu); - int Rt = (hsr >> 5) & 0xf; - int Rt2 = (hsr >> 10) & 0xf; + int Rt = kvm_vcpu_sys_get_rt(vcpu); + int Rt2 = (hsr >> 10) & 0x1f; params.is_aarch32 = true; params.is_32bit = false; @@ -1625,7 +1625,7 @@ static int kvm_handle_cp_32(struct kvm_vcpu *vcpu, { struct sys_reg_params params; u32 hsr = kvm_vcpu_get_hsr(vcpu); - int Rt = (hsr >> 5) & 0xf; + int Rt = kvm_vcpu_sys_get_rt(vcpu); params.is_aarch32 = true; params.is_32bit = true; @@ -1740,7 +1740,7 @@ int kvm_handle_sys_reg(struct kvm_vcpu *vcpu, struct kvm_run *run) { struct sys_reg_params params; unsigned long esr = kvm_vcpu_get_hsr(vcpu); - int Rt = (esr >> 5) & 0x1f; + int Rt = kvm_vcpu_sys_get_rt(vcpu); int ret; trace_kvm_handle_sys_reg(esr); From 9b2fb8ad5ba1b528e2f2927898403b0df40fd09b Mon Sep 17 00:00:00 2001 From: Mike Snitzer Date: Sat, 22 Apr 2017 17:22:09 -0400 Subject: [PATCH 137/396] block: fix blk_integrity_register to use template's interval_exp if not 0 commit 2859323e35ab5fc42f351fbda23ab544eaa85945 upstream. When registering an integrity profile: if the template's interval_exp is not 0 use it, otherwise use the ilog2() of logical block size of the provided gendisk. This fixes a long-standing DM linear target bug where it cannot pass integrity data to the underlying device if its logical block size conflicts with the underlying device's logical block size. Reported-by: Mikulas Patocka Signed-off-by: Mike Snitzer Acked-by: Martin K. Petersen Signed-off-by: Jens Axboe Signed-off-by: Greg Kroah-Hartman --- block/blk-integrity.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/block/blk-integrity.c b/block/blk-integrity.c index 319f2e4f4a8b..478f572cb1e7 100644 --- a/block/blk-integrity.c +++ b/block/blk-integrity.c @@ -412,7 +412,8 @@ void blk_integrity_register(struct gendisk *disk, struct blk_integrity *template bi->flags = BLK_INTEGRITY_VERIFY | BLK_INTEGRITY_GENERATE | template->flags; - bi->interval_exp = ilog2(queue_logical_block_size(disk->queue)); + bi->interval_exp = template->interval_exp ? : + ilog2(queue_logical_block_size(disk->queue)); bi->profile = template->profile ? template->profile : &nop_profile; bi->tuple_size = template->tuple_size; bi->tag_size = template->tag_size; From bcc70358396abb905f448a5c43f54dda457a0959 Mon Sep 17 00:00:00 2001 From: Stephan Mueller Date: Mon, 24 Apr 2017 11:15:23 +0200 Subject: [PATCH 138/396] crypto: algif_aead - Require setkey before accept(2) commit 2a2a251f110576b1d89efbd0662677d7e7db21a8 upstream. Some cipher implementations will crash if you try to use them without calling setkey first. This patch adds a check so that the accept(2) call will fail with -ENOKEY if setkey hasn't been done on the socket yet. Fixes: 400c40cf78da ("crypto: algif - add AEAD support") Signed-off-by: Stephan Mueller Signed-off-by: Herbert Xu Signed-off-by: Greg Kroah-Hartman --- crypto/algif_aead.c | 157 +++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 149 insertions(+), 8 deletions(-) diff --git a/crypto/algif_aead.c b/crypto/algif_aead.c index fde8d885f7b6..6c11537ca404 100644 --- a/crypto/algif_aead.c +++ b/crypto/algif_aead.c @@ -44,6 +44,11 @@ struct aead_async_req { char iv[]; }; +struct aead_tfm { + struct crypto_aead *aead; + bool has_key; +}; + struct aead_ctx { struct aead_sg_list tsgl; struct aead_async_rsgl first_rsgl; @@ -732,24 +737,146 @@ static struct proto_ops algif_aead_ops = { .poll = aead_poll, }; +static int aead_check_key(struct socket *sock) +{ + int err = 0; + struct sock *psk; + struct alg_sock *pask; + struct aead_tfm *tfm; + struct sock *sk = sock->sk; + struct alg_sock *ask = alg_sk(sk); + + lock_sock(sk); + if (ask->refcnt) + goto unlock_child; + + psk = ask->parent; + pask = alg_sk(ask->parent); + tfm = pask->private; + + err = -ENOKEY; + lock_sock_nested(psk, SINGLE_DEPTH_NESTING); + if (!tfm->has_key) + goto unlock; + + if (!pask->refcnt++) + sock_hold(psk); + + ask->refcnt = 1; + sock_put(psk); + + err = 0; + +unlock: + release_sock(psk); +unlock_child: + release_sock(sk); + + return err; +} + +static int aead_sendmsg_nokey(struct socket *sock, struct msghdr *msg, + size_t size) +{ + int err; + + err = aead_check_key(sock); + if (err) + return err; + + return aead_sendmsg(sock, msg, size); +} + +static ssize_t aead_sendpage_nokey(struct socket *sock, struct page *page, + int offset, size_t size, int flags) +{ + int err; + + err = aead_check_key(sock); + if (err) + return err; + + return aead_sendpage(sock, page, offset, size, flags); +} + +static int aead_recvmsg_nokey(struct socket *sock, struct msghdr *msg, + size_t ignored, int flags) +{ + int err; + + err = aead_check_key(sock); + if (err) + return err; + + return aead_recvmsg(sock, msg, ignored, flags); +} + +static struct proto_ops algif_aead_ops_nokey = { + .family = PF_ALG, + + .connect = sock_no_connect, + .socketpair = sock_no_socketpair, + .getname = sock_no_getname, + .ioctl = sock_no_ioctl, + .listen = sock_no_listen, + .shutdown = sock_no_shutdown, + .getsockopt = sock_no_getsockopt, + .mmap = sock_no_mmap, + .bind = sock_no_bind, + .accept = sock_no_accept, + .setsockopt = sock_no_setsockopt, + + .release = af_alg_release, + .sendmsg = aead_sendmsg_nokey, + .sendpage = aead_sendpage_nokey, + .recvmsg = aead_recvmsg_nokey, + .poll = aead_poll, +}; + static void *aead_bind(const char *name, u32 type, u32 mask) { - return crypto_alloc_aead(name, type, mask); + struct aead_tfm *tfm; + struct crypto_aead *aead; + + tfm = kzalloc(sizeof(*tfm), GFP_KERNEL); + if (!tfm) + return ERR_PTR(-ENOMEM); + + aead = crypto_alloc_aead(name, type, mask); + if (IS_ERR(aead)) { + kfree(tfm); + return ERR_CAST(aead); + } + + tfm->aead = aead; + + return tfm; } static void aead_release(void *private) { - crypto_free_aead(private); + struct aead_tfm *tfm = private; + + crypto_free_aead(tfm->aead); + kfree(tfm); } static int aead_setauthsize(void *private, unsigned int authsize) { - return crypto_aead_setauthsize(private, authsize); + struct aead_tfm *tfm = private; + + return crypto_aead_setauthsize(tfm->aead, authsize); } static int aead_setkey(void *private, const u8 *key, unsigned int keylen) { - return crypto_aead_setkey(private, key, keylen); + struct aead_tfm *tfm = private; + int err; + + err = crypto_aead_setkey(tfm->aead, key, keylen); + tfm->has_key = !err; + + return err; } static void aead_sock_destruct(struct sock *sk) @@ -766,12 +893,14 @@ static void aead_sock_destruct(struct sock *sk) af_alg_release_parent(sk); } -static int aead_accept_parent(void *private, struct sock *sk) +static int aead_accept_parent_nokey(void *private, struct sock *sk) { struct aead_ctx *ctx; struct alg_sock *ask = alg_sk(sk); - unsigned int len = sizeof(*ctx) + crypto_aead_reqsize(private); - unsigned int ivlen = crypto_aead_ivsize(private); + struct aead_tfm *tfm = private; + struct crypto_aead *aead = tfm->aead; + unsigned int len = sizeof(*ctx) + crypto_aead_reqsize(aead); + unsigned int ivlen = crypto_aead_ivsize(aead); ctx = sock_kmalloc(sk, len, GFP_KERNEL); if (!ctx) @@ -798,7 +927,7 @@ static int aead_accept_parent(void *private, struct sock *sk) ask->private = ctx; - aead_request_set_tfm(&ctx->aead_req, private); + aead_request_set_tfm(&ctx->aead_req, aead); aead_request_set_callback(&ctx->aead_req, CRYPTO_TFM_REQ_MAY_BACKLOG, af_alg_complete, &ctx->completion); @@ -807,13 +936,25 @@ static int aead_accept_parent(void *private, struct sock *sk) return 0; } +static int aead_accept_parent(void *private, struct sock *sk) +{ + struct aead_tfm *tfm = private; + + if (!tfm->has_key) + return -ENOKEY; + + return aead_accept_parent_nokey(private, sk); +} + static const struct af_alg_type algif_type_aead = { .bind = aead_bind, .release = aead_release, .setkey = aead_setkey, .setauthsize = aead_setauthsize, .accept = aead_accept_parent, + .accept_nokey = aead_accept_parent_nokey, .ops = &algif_aead_ops, + .ops_nokey = &algif_aead_ops_nokey, .name = "aead", .owner = THIS_MODULE }; From 36dffff240d937d626bea9196c027df076fbff34 Mon Sep 17 00:00:00 2001 From: Gary R Hook Date: Thu, 20 Apr 2017 15:24:09 -0500 Subject: [PATCH 139/396] crypto: ccp - Use only the relevant interrupt bits commit 56467cb11cf8ae4db9003f54b3d3425b5f07a10a upstream. Each CCP queue can product interrupts for 4 conditions: operation complete, queue empty, error, and queue stopped. This driver only works with completion and error events. Signed-off-by: Gary R Hook Signed-off-by: Herbert Xu Signed-off-by: Greg Kroah-Hartman --- drivers/crypto/ccp/ccp-dev-v5.c | 9 +++++---- drivers/crypto/ccp/ccp-dev.h | 5 ++--- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/crypto/ccp/ccp-dev-v5.c b/drivers/crypto/ccp/ccp-dev-v5.c index a388bf2d67f4..c85af39cc84d 100644 --- a/drivers/crypto/ccp/ccp-dev-v5.c +++ b/drivers/crypto/ccp/ccp-dev-v5.c @@ -740,7 +740,7 @@ static int ccp5_init(struct ccp_device *ccp) ioread32(cmd_q->reg_status); /* Clear the interrupts */ - iowrite32(ALL_INTERRUPTS, cmd_q->reg_interrupt_status); + iowrite32(SUPPORTED_INTERRUPTS, cmd_q->reg_interrupt_status); } dev_dbg(dev, "Requesting an IRQ...\n"); @@ -824,7 +824,7 @@ static int ccp5_init(struct ccp_device *ccp) /* Enable interrupts */ for (i = 0; i < ccp->cmd_q_count; i++) { cmd_q = &ccp->cmd_q[i]; - iowrite32(ALL_INTERRUPTS, cmd_q->reg_int_enable); + iowrite32(SUPPORTED_INTERRUPTS, cmd_q->reg_int_enable); } dev_dbg(dev, "Registering device...\n"); @@ -884,7 +884,7 @@ static void ccp5_destroy(struct ccp_device *ccp) iowrite32(cmd_q->qcontrol & ~CMD5_Q_RUN, cmd_q->reg_control); /* Disable the interrupts */ - iowrite32(ALL_INTERRUPTS, cmd_q->reg_interrupt_status); + iowrite32(SUPPORTED_INTERRUPTS, cmd_q->reg_interrupt_status); /* Clear the interrupt status */ iowrite32(0x00, cmd_q->reg_int_enable); @@ -944,7 +944,8 @@ static irqreturn_t ccp5_irq_handler(int irq, void *data) cmd_q->int_rcvd = 1; /* Acknowledge the interrupt and wake the kthread */ - iowrite32(ALL_INTERRUPTS, cmd_q->reg_interrupt_status); + iowrite32(SUPPORTED_INTERRUPTS, + cmd_q->reg_interrupt_status); wake_up_interruptible(&cmd_q->int_queue); } } diff --git a/drivers/crypto/ccp/ccp-dev.h b/drivers/crypto/ccp/ccp-dev.h index 340aef14d616..a0d7979836a5 100644 --- a/drivers/crypto/ccp/ccp-dev.h +++ b/drivers/crypto/ccp/ccp-dev.h @@ -109,9 +109,8 @@ #define INT_COMPLETION 0x1 #define INT_ERROR 0x2 #define INT_QUEUE_STOPPED 0x4 -#define ALL_INTERRUPTS (INT_COMPLETION| \ - INT_ERROR| \ - INT_QUEUE_STOPPED) +#define INT_EMPTY_QUEUE 0x8 +#define SUPPORTED_INTERRUPTS (INT_COMPLETION | INT_ERROR) #define LSB_REGION_WIDTH 5 #define MAX_LSB_CNT 8 From 93424b2b63e0765c32e723173689a2d2b78d19ba Mon Sep 17 00:00:00 2001 From: Gary R Hook Date: Thu, 20 Apr 2017 15:24:22 -0500 Subject: [PATCH 140/396] crypto: ccp - Disable interrupts early on unload commit 116591fe3eef11c6f06b662c9176385f13891183 upstream. Ensure that we disable interrupts first when shutting down the driver. Signed-off-by: Gary R Hook Signed-off-by: Herbert Xu Signed-off-by: Greg Kroah-Hartman --- drivers/crypto/ccp/ccp-dev-v5.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/crypto/ccp/ccp-dev-v5.c b/drivers/crypto/ccp/ccp-dev-v5.c index c85af39cc84d..a6cb07810d6a 100644 --- a/drivers/crypto/ccp/ccp-dev-v5.c +++ b/drivers/crypto/ccp/ccp-dev-v5.c @@ -884,10 +884,10 @@ static void ccp5_destroy(struct ccp_device *ccp) iowrite32(cmd_q->qcontrol & ~CMD5_Q_RUN, cmd_q->reg_control); /* Disable the interrupts */ - iowrite32(SUPPORTED_INTERRUPTS, cmd_q->reg_interrupt_status); + iowrite32(0x00, cmd_q->reg_int_enable); /* Clear the interrupt status */ - iowrite32(0x00, cmd_q->reg_int_enable); + iowrite32(SUPPORTED_INTERRUPTS, cmd_q->reg_interrupt_status); ioread32(cmd_q->reg_int_status); ioread32(cmd_q->reg_status); } From a0a232489c0fd8f41016f221cfca6644a34b7b9a Mon Sep 17 00:00:00 2001 From: Gary R Hook Date: Fri, 21 Apr 2017 10:50:05 -0500 Subject: [PATCH 141/396] crypto: ccp - Change ISR handler method for a v3 CCP commit 7b537b24e76a1e8e6d7ea91483a45d5b1426809b upstream. The CCP has the ability to perform several operations simultaneously, but only one interrupt. When implemented as a PCI device and using MSI-X/MSI interrupts, use a tasklet model to service interrupts. By disabling and enabling interrupts from the CCP, coupled with the queuing that tasklets provide, we can ensure that all events (occurring on the device) are recognized and serviced. This change fixes a problem wherein 2 or more busy queues can cause notification bits to change state while a (CCP) interrupt is being serviced, but after the queue state has been evaluated. This results in the event being 'lost' and the queue hanging, waiting to be serviced. Since the status bits are never fully de-asserted, the CCP never generates another interrupt (all bits zero -> one or more bits one), and no further CCP operations will be executed. Signed-off-by: Gary R Hook Signed-off-by: Herbert Xu Signed-off-by: Greg Kroah-Hartman --- drivers/crypto/ccp/ccp-dev-v3.c | 120 +++++++++++++++++++------------- drivers/crypto/ccp/ccp-dev.h | 3 + drivers/crypto/ccp/ccp-pci.c | 2 + 3 files changed, 75 insertions(+), 50 deletions(-) diff --git a/drivers/crypto/ccp/ccp-dev-v3.c b/drivers/crypto/ccp/ccp-dev-v3.c index 8d2dbacc6161..e68966bbfa58 100644 --- a/drivers/crypto/ccp/ccp-dev-v3.c +++ b/drivers/crypto/ccp/ccp-dev-v3.c @@ -315,17 +315,73 @@ static int ccp_perform_ecc(struct ccp_op *op) return ccp_do_cmd(op, cr, ARRAY_SIZE(cr)); } +static void ccp_disable_queue_interrupts(struct ccp_device *ccp) +{ + iowrite32(0x00, ccp->io_regs + IRQ_MASK_REG); +} + +static void ccp_enable_queue_interrupts(struct ccp_device *ccp) +{ + iowrite32(ccp->qim, ccp->io_regs + IRQ_MASK_REG); +} + +static void ccp_irq_bh(unsigned long data) +{ + struct ccp_device *ccp = (struct ccp_device *)data; + struct ccp_cmd_queue *cmd_q; + u32 q_int, status; + unsigned int i; + + status = ioread32(ccp->io_regs + IRQ_STATUS_REG); + + for (i = 0; i < ccp->cmd_q_count; i++) { + cmd_q = &ccp->cmd_q[i]; + + q_int = status & (cmd_q->int_ok | cmd_q->int_err); + if (q_int) { + cmd_q->int_status = status; + cmd_q->q_status = ioread32(cmd_q->reg_status); + cmd_q->q_int_status = ioread32(cmd_q->reg_int_status); + + /* On error, only save the first error value */ + if ((q_int & cmd_q->int_err) && !cmd_q->cmd_error) + cmd_q->cmd_error = CMD_Q_ERROR(cmd_q->q_status); + + cmd_q->int_rcvd = 1; + + /* Acknowledge the interrupt and wake the kthread */ + iowrite32(q_int, ccp->io_regs + IRQ_STATUS_REG); + wake_up_interruptible(&cmd_q->int_queue); + } + } + ccp_enable_queue_interrupts(ccp); +} + +static irqreturn_t ccp_irq_handler(int irq, void *data) +{ + struct device *dev = data; + struct ccp_device *ccp = dev_get_drvdata(dev); + + ccp_disable_queue_interrupts(ccp); + if (ccp->use_tasklet) + tasklet_schedule(&ccp->irq_tasklet); + else + ccp_irq_bh((unsigned long)ccp); + + return IRQ_HANDLED; +} + static int ccp_init(struct ccp_device *ccp) { struct device *dev = ccp->dev; struct ccp_cmd_queue *cmd_q; struct dma_pool *dma_pool; char dma_pool_name[MAX_DMAPOOL_NAME_LEN]; - unsigned int qmr, qim, i; + unsigned int qmr, i; int ret; /* Find available queues */ - qim = 0; + ccp->qim = 0; qmr = ioread32(ccp->io_regs + Q_MASK_REG); for (i = 0; i < MAX_HW_QUEUES; i++) { if (!(qmr & (1 << i))) @@ -370,7 +426,7 @@ static int ccp_init(struct ccp_device *ccp) init_waitqueue_head(&cmd_q->int_queue); /* Build queue interrupt mask (two interrupts per queue) */ - qim |= cmd_q->int_ok | cmd_q->int_err; + ccp->qim |= cmd_q->int_ok | cmd_q->int_err; #ifdef CONFIG_ARM64 /* For arm64 set the recommended queue cache settings */ @@ -388,14 +444,14 @@ static int ccp_init(struct ccp_device *ccp) dev_notice(dev, "%u command queues available\n", ccp->cmd_q_count); /* Disable and clear interrupts until ready */ - iowrite32(0x00, ccp->io_regs + IRQ_MASK_REG); + ccp_disable_queue_interrupts(ccp); for (i = 0; i < ccp->cmd_q_count; i++) { cmd_q = &ccp->cmd_q[i]; ioread32(cmd_q->reg_int_status); ioread32(cmd_q->reg_status); } - iowrite32(qim, ccp->io_regs + IRQ_STATUS_REG); + iowrite32(ccp->qim, ccp->io_regs + IRQ_STATUS_REG); /* Request an irq */ ret = ccp->get_irq(ccp); @@ -408,6 +464,11 @@ static int ccp_init(struct ccp_device *ccp) init_waitqueue_head(&ccp->sb_queue); init_waitqueue_head(&ccp->suspend_queue); + /* Initialize the ISR tasklet? */ + if (ccp->use_tasklet) + tasklet_init(&ccp->irq_tasklet, ccp_irq_bh, + (unsigned long)ccp); + dev_dbg(dev, "Starting threads...\n"); /* Create a kthread for each queue */ for (i = 0; i < ccp->cmd_q_count; i++) { @@ -430,7 +491,7 @@ static int ccp_init(struct ccp_device *ccp) dev_dbg(dev, "Enabling interrupts...\n"); /* Enable interrupts */ - iowrite32(qim, ccp->io_regs + IRQ_MASK_REG); + ccp_enable_queue_interrupts(ccp); dev_dbg(dev, "Registering device...\n"); ccp_add_device(ccp); @@ -467,7 +528,7 @@ static void ccp_destroy(struct ccp_device *ccp) { struct ccp_cmd_queue *cmd_q; struct ccp_cmd *cmd; - unsigned int qim, i; + unsigned int i; /* Unregister the DMA engine */ ccp_dmaengine_unregister(ccp); @@ -478,22 +539,15 @@ static void ccp_destroy(struct ccp_device *ccp) /* Remove this device from the list of available units */ ccp_del_device(ccp); - /* Build queue interrupt mask (two interrupt masks per queue) */ - qim = 0; - for (i = 0; i < ccp->cmd_q_count; i++) { - cmd_q = &ccp->cmd_q[i]; - qim |= cmd_q->int_ok | cmd_q->int_err; - } - /* Disable and clear interrupts */ - iowrite32(0x00, ccp->io_regs + IRQ_MASK_REG); + ccp_disable_queue_interrupts(ccp); for (i = 0; i < ccp->cmd_q_count; i++) { cmd_q = &ccp->cmd_q[i]; ioread32(cmd_q->reg_int_status); ioread32(cmd_q->reg_status); } - iowrite32(qim, ccp->io_regs + IRQ_STATUS_REG); + iowrite32(ccp->qim, ccp->io_regs + IRQ_STATUS_REG); /* Stop the queue kthreads */ for (i = 0; i < ccp->cmd_q_count; i++) @@ -520,40 +574,6 @@ static void ccp_destroy(struct ccp_device *ccp) } } -static irqreturn_t ccp_irq_handler(int irq, void *data) -{ - struct device *dev = data; - struct ccp_device *ccp = dev_get_drvdata(dev); - struct ccp_cmd_queue *cmd_q; - u32 q_int, status; - unsigned int i; - - status = ioread32(ccp->io_regs + IRQ_STATUS_REG); - - for (i = 0; i < ccp->cmd_q_count; i++) { - cmd_q = &ccp->cmd_q[i]; - - q_int = status & (cmd_q->int_ok | cmd_q->int_err); - if (q_int) { - cmd_q->int_status = status; - cmd_q->q_status = ioread32(cmd_q->reg_status); - cmd_q->q_int_status = ioread32(cmd_q->reg_int_status); - - /* On error, only save the first error value */ - if ((q_int & cmd_q->int_err) && !cmd_q->cmd_error) - cmd_q->cmd_error = CMD_Q_ERROR(cmd_q->q_status); - - cmd_q->int_rcvd = 1; - - /* Acknowledge the interrupt and wake the kthread */ - iowrite32(q_int, ccp->io_regs + IRQ_STATUS_REG); - wake_up_interruptible(&cmd_q->int_queue); - } - } - - return IRQ_HANDLED; -} - static const struct ccp_actions ccp3_actions = { .aes = ccp_perform_aes, .xts_aes = ccp_perform_xts_aes, diff --git a/drivers/crypto/ccp/ccp-dev.h b/drivers/crypto/ccp/ccp-dev.h index a0d7979836a5..8ac7ae17e1f4 100644 --- a/drivers/crypto/ccp/ccp-dev.h +++ b/drivers/crypto/ccp/ccp-dev.h @@ -332,7 +332,10 @@ struct ccp_device { void *dev_specific; int (*get_irq)(struct ccp_device *ccp); void (*free_irq)(struct ccp_device *ccp); + unsigned int qim; unsigned int irq; + bool use_tasklet; + struct tasklet_struct irq_tasklet; /* I/O area used for device communication. The register mapping * starts at an offset into the mapped bar. diff --git a/drivers/crypto/ccp/ccp-pci.c b/drivers/crypto/ccp/ccp-pci.c index 28a9996c1085..e880d4cf4ada 100644 --- a/drivers/crypto/ccp/ccp-pci.c +++ b/drivers/crypto/ccp/ccp-pci.c @@ -69,6 +69,7 @@ static int ccp_get_msix_irqs(struct ccp_device *ccp) goto e_irq; } } + ccp->use_tasklet = true; return 0; @@ -100,6 +101,7 @@ static int ccp_get_msi_irq(struct ccp_device *ccp) dev_notice(dev, "unable to allocate MSI IRQ (%d)\n", ret); goto e_msi; } + ccp->use_tasklet = true; return 0; From f8d05099ec72a943a71b2c95959d37dbef13b7f1 Mon Sep 17 00:00:00 2001 From: Gary R Hook Date: Fri, 21 Apr 2017 10:50:14 -0500 Subject: [PATCH 142/396] crypto: ccp - Change ISR handler method for a v5 CCP commit 6263b51eb3190d30351360fd168959af7e3a49a9 upstream. The CCP has the ability to perform several operations simultaneously, but only one interrupt. When implemented as a PCI device and using MSI-X/MSI interrupts, use a tasklet model to service interrupts. By disabling and enabling interrupts from the CCP, coupled with the queuing that tasklets provide, we can ensure that all events (occurring on the device) are recognized and serviced. This change fixes a problem wherein 2 or more busy queues can cause notification bits to change state while a (CCP) interrupt is being serviced, but after the queue state has been evaluated. This results in the event being 'lost' and the queue hanging, waiting to be serviced. Since the status bits are never fully de-asserted, the CCP never generates another interrupt (all bits zero -> one or more bits one), and no further CCP operations will be executed. Signed-off-by: Gary R Hook Signed-off-by: Herbert Xu Signed-off-by: Greg Kroah-Hartman --- drivers/crypto/ccp/ccp-dev-v5.c | 111 +++++++++++++++++++------------- 1 file changed, 67 insertions(+), 44 deletions(-) diff --git a/drivers/crypto/ccp/ccp-dev-v5.c b/drivers/crypto/ccp/ccp-dev-v5.c index a6cb07810d6a..2c0ce5f605b3 100644 --- a/drivers/crypto/ccp/ccp-dev-v5.c +++ b/drivers/crypto/ccp/ccp-dev-v5.c @@ -644,6 +644,65 @@ static int ccp_assign_lsbs(struct ccp_device *ccp) return rc; } +static void ccp5_disable_queue_interrupts(struct ccp_device *ccp) +{ + unsigned int i; + + for (i = 0; i < ccp->cmd_q_count; i++) + iowrite32(0x0, ccp->cmd_q[i].reg_int_enable); +} + +static void ccp5_enable_queue_interrupts(struct ccp_device *ccp) +{ + unsigned int i; + + for (i = 0; i < ccp->cmd_q_count; i++) + iowrite32(SUPPORTED_INTERRUPTS, ccp->cmd_q[i].reg_int_enable); +} + +static void ccp5_irq_bh(unsigned long data) +{ + struct ccp_device *ccp = (struct ccp_device *)data; + u32 status; + unsigned int i; + + for (i = 0; i < ccp->cmd_q_count; i++) { + struct ccp_cmd_queue *cmd_q = &ccp->cmd_q[i]; + + status = ioread32(cmd_q->reg_interrupt_status); + + if (status) { + cmd_q->int_status = status; + cmd_q->q_status = ioread32(cmd_q->reg_status); + cmd_q->q_int_status = ioread32(cmd_q->reg_int_status); + + /* On error, only save the first error value */ + if ((status & INT_ERROR) && !cmd_q->cmd_error) + cmd_q->cmd_error = CMD_Q_ERROR(cmd_q->q_status); + + cmd_q->int_rcvd = 1; + + /* Acknowledge the interrupt and wake the kthread */ + iowrite32(status, cmd_q->reg_interrupt_status); + wake_up_interruptible(&cmd_q->int_queue); + } + } + ccp5_enable_queue_interrupts(ccp); +} + +static irqreturn_t ccp5_irq_handler(int irq, void *data) +{ + struct device *dev = data; + struct ccp_device *ccp = dev_get_drvdata(dev); + + ccp5_disable_queue_interrupts(ccp); + if (ccp->use_tasklet) + tasklet_schedule(&ccp->irq_tasklet); + else + ccp5_irq_bh((unsigned long)ccp); + return IRQ_HANDLED; +} + static int ccp5_init(struct ccp_device *ccp) { struct device *dev = ccp->dev; @@ -728,18 +787,17 @@ static int ccp5_init(struct ccp_device *ccp) dev_notice(dev, "%u command queues available\n", ccp->cmd_q_count); /* Turn off the queues and disable interrupts until ready */ + ccp5_disable_queue_interrupts(ccp); for (i = 0; i < ccp->cmd_q_count; i++) { cmd_q = &ccp->cmd_q[i]; cmd_q->qcontrol = 0; /* Start with nothing */ iowrite32(cmd_q->qcontrol, cmd_q->reg_control); - /* Disable the interrupts */ - iowrite32(0x00, cmd_q->reg_int_enable); ioread32(cmd_q->reg_int_status); ioread32(cmd_q->reg_status); - /* Clear the interrupts */ + /* Clear the interrupt status */ iowrite32(SUPPORTED_INTERRUPTS, cmd_q->reg_interrupt_status); } @@ -750,6 +808,10 @@ static int ccp5_init(struct ccp_device *ccp) dev_err(dev, "unable to allocate an IRQ\n"); goto e_pool; } + /* Initialize the ISR tasklet */ + if (ccp->use_tasklet) + tasklet_init(&ccp->irq_tasklet, ccp5_irq_bh, + (unsigned long)ccp); /* Initialize the queue used to suspend */ init_waitqueue_head(&ccp->suspend_queue); @@ -821,11 +883,7 @@ static int ccp5_init(struct ccp_device *ccp) } dev_dbg(dev, "Enabling interrupts...\n"); - /* Enable interrupts */ - for (i = 0; i < ccp->cmd_q_count; i++) { - cmd_q = &ccp->cmd_q[i]; - iowrite32(SUPPORTED_INTERRUPTS, cmd_q->reg_int_enable); - } + ccp5_enable_queue_interrupts(ccp); dev_dbg(dev, "Registering device...\n"); /* Put this on the unit list to make it available */ @@ -877,15 +935,13 @@ static void ccp5_destroy(struct ccp_device *ccp) ccp_del_device(ccp); /* Disable and clear interrupts */ + ccp5_disable_queue_interrupts(ccp); for (i = 0; i < ccp->cmd_q_count; i++) { cmd_q = &ccp->cmd_q[i]; /* Turn off the run bit */ iowrite32(cmd_q->qcontrol & ~CMD5_Q_RUN, cmd_q->reg_control); - /* Disable the interrupts */ - iowrite32(0x00, cmd_q->reg_int_enable); - /* Clear the interrupt status */ iowrite32(SUPPORTED_INTERRUPTS, cmd_q->reg_interrupt_status); ioread32(cmd_q->reg_int_status); @@ -920,39 +976,6 @@ static void ccp5_destroy(struct ccp_device *ccp) } } -static irqreturn_t ccp5_irq_handler(int irq, void *data) -{ - struct device *dev = data; - struct ccp_device *ccp = dev_get_drvdata(dev); - u32 status; - unsigned int i; - - for (i = 0; i < ccp->cmd_q_count; i++) { - struct ccp_cmd_queue *cmd_q = &ccp->cmd_q[i]; - - status = ioread32(cmd_q->reg_interrupt_status); - - if (status) { - cmd_q->int_status = status; - cmd_q->q_status = ioread32(cmd_q->reg_status); - cmd_q->q_int_status = ioread32(cmd_q->reg_int_status); - - /* On error, only save the first error value */ - if ((status & INT_ERROR) && !cmd_q->cmd_error) - cmd_q->cmd_error = CMD_Q_ERROR(cmd_q->q_status); - - cmd_q->int_rcvd = 1; - - /* Acknowledge the interrupt and wake the kthread */ - iowrite32(SUPPORTED_INTERRUPTS, - cmd_q->reg_interrupt_status); - wake_up_interruptible(&cmd_q->int_queue); - } - } - - return IRQ_HANDLED; -} - static void ccp5_config(struct ccp_device *ccp) { /* Public side */ From f6ec18eb7425a334689584fcf5849107858fbd25 Mon Sep 17 00:00:00 2001 From: Somasundaram Krishnasamy Date: Fri, 7 Apr 2017 12:14:55 -0700 Subject: [PATCH 143/396] dm era: save spacemap metadata root after the pre-commit commit 117aceb030307dcd431fdcff87ce988d3016c34a upstream. When committing era metadata to disk, it doesn't always save the latest spacemap metadata root in superblock. Due to this, metadata is getting corrupted sometimes when reopening the device. The correct order of update should be, pre-commit (shadows spacemap root), save the spacemap root (newly shadowed block) to in-core superblock and then the final commit. Signed-off-by: Somasundaram Krishnasamy Signed-off-by: Mike Snitzer Signed-off-by: Greg Kroah-Hartman --- drivers/md/dm-era-target.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/md/dm-era-target.c b/drivers/md/dm-era-target.c index bf2b2676cb8a..80e3df1f1f7d 100644 --- a/drivers/md/dm-era-target.c +++ b/drivers/md/dm-era-target.c @@ -961,18 +961,18 @@ static int metadata_commit(struct era_metadata *md) } } - r = save_sm_root(md); - if (r) { - DMERR("%s: save_sm_root failed", __func__); - return r; - } - r = dm_tm_pre_commit(md->tm); if (r) { DMERR("%s: pre commit failed", __func__); return r; } + r = save_sm_root(md); + if (r) { + DMERR("%s: save_sm_root failed", __func__); + return r; + } + r = superblock_lock(md, &sblock); if (r) { DMERR("%s: superblock lock failed", __func__); From f32e35bc3d542cb53a4226cca5ac803dc4dbe892 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Thu, 27 Apr 2017 10:11:19 -0700 Subject: [PATCH 144/396] dm rq: check blk_mq_register_dev() return value in dm_mq_init_request_queue() commit 23a601248958fa4142d49294352fe8d1fdf3e509 upstream. Otherwise the request-based DM blk-mq request_queue will be put into service without being properly exported via sysfs. Signed-off-by: Bart Van Assche Reviewed-by: Hannes Reinecke Cc: Christoph Hellwig Signed-off-by: Mike Snitzer Signed-off-by: Greg Kroah-Hartman --- drivers/md/dm-rq.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/md/dm-rq.c b/drivers/md/dm-rq.c index 2c965424d383..ba7c4c685db3 100644 --- a/drivers/md/dm-rq.c +++ b/drivers/md/dm-rq.c @@ -997,10 +997,14 @@ int dm_mq_init_request_queue(struct mapped_device *md, struct dm_table *t) dm_init_md_queue(md); /* backfill 'mq' sysfs registration normally done in blk_register_queue */ - blk_mq_register_dev(disk_to_dev(md->disk), q); + err = blk_mq_register_dev(disk_to_dev(md->disk), q); + if (err) + goto out_cleanup_queue; return 0; +out_cleanup_queue: + blk_cleanup_queue(q); out_tag_set: blk_mq_free_tag_set(md->tag_set); out_kfree_tag_set: From 1773131ec4b945a286b1cdb692bb632958408b3b Mon Sep 17 00:00:00 2001 From: Dennis Yang Date: Tue, 18 Apr 2017 15:27:06 +0800 Subject: [PATCH 145/396] dm thin: fix a memory leak when passing discard bio down commit 948f581a53b704b984aa20df009f0a2b4cf7f907 upstream. dm-thin does not free the discard_parent bio after all chained sub bios finished. The following kmemleak report could be observed after pool with discard_passdown option processes discard bios in linux v4.11-rc7. To fix this, we drop the discard_parent bio reference when its endio (passdown_endio) called. unreferenced object 0xffff8803d6b29700 (size 256): comm "kworker/u8:0", pid 30349, jiffies 4379504020 (age 143002.776s) hex dump (first 32 bytes): 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 01 00 00 00 00 00 00 f0 00 00 00 00 00 00 00 00 ................ backtrace: [] kmemleak_alloc+0x49/0xa0 [] kmem_cache_alloc+0xb4/0x100 [] mempool_alloc_slab+0x10/0x20 [] mempool_alloc+0x55/0x150 [] bio_alloc_bioset+0xb9/0x260 [] process_prepared_discard_passdown_pt1+0x40/0x1c0 [dm_thin_pool] [] break_up_discard_bio+0x1a9/0x200 [dm_thin_pool] [] process_discard_cell_passdown+0x24/0x40 [dm_thin_pool] [] process_discard_bio+0xdd/0xf0 [dm_thin_pool] [] do_worker+0xa76/0xd50 [dm_thin_pool] [] process_one_work+0x139/0x370 [] worker_thread+0x61/0x450 [] kthread+0xd6/0xf0 [] ret_from_fork+0x3f/0x70 [] 0xffffffffffffffff Signed-off-by: Dennis Yang Signed-off-by: Mike Snitzer Signed-off-by: Greg Kroah-Hartman --- drivers/md/dm-thin.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/md/dm-thin.c b/drivers/md/dm-thin.c index d1c05c12a9db..be869a990e38 100644 --- a/drivers/md/dm-thin.c +++ b/drivers/md/dm-thin.c @@ -1070,6 +1070,7 @@ static void passdown_endio(struct bio *bio) * to unmap (we ignore err). */ queue_passdown_pt2(bio->bi_private); + bio_put(bio); } static void process_prepared_discard_passdown_pt1(struct dm_thin_new_mapping *m) From 9f43f70dcc56ac294aeb8c0b29766a7a1cb1aec0 Mon Sep 17 00:00:00 2001 From: Alex Williamson Date: Thu, 13 Apr 2017 14:10:15 -0600 Subject: [PATCH 146/396] vfio/type1: Remove locked page accounting workqueue commit 0cfef2b7410b64d7a430947e0b533314c4f97153 upstream. If the mmap_sem is contented then the vfio type1 IOMMU backend will defer locked page accounting updates to a workqueue task. This has a few problems and depending on which side the user tries to play, they might be over-penalized for unmaps that haven't yet been accounted or race the workqueue to enter more mappings than they're allowed. The original intent of this workqueue mechanism seems to be focused on reducing latency through the ioctl, but we cannot do so at the cost of correctness. Remove this workqueue mechanism and update the callers to allow for failure. We can also now recheck the limit under write lock to make sure we don't exceed it. vfio_pin_pages_remote() also now necessarily includes an unwind path which we can jump to directly if the consecutive page pinning finds that we're exceeding the user's memory limits. This avoids the current lazy approach which does accounting and mapping up to the fault, only to return an error on the next iteration to unwind the entire vfio_dma. Reviewed-by: Peter Xu Reviewed-by: Kirti Wankhede Signed-off-by: Alex Williamson Signed-off-by: Greg Kroah-Hartman --- drivers/vfio/vfio_iommu_type1.c | 100 ++++++++++++++------------------ 1 file changed, 43 insertions(+), 57 deletions(-) diff --git a/drivers/vfio/vfio_iommu_type1.c b/drivers/vfio/vfio_iommu_type1.c index 2ba19424e4a1..1d48e62f4f52 100644 --- a/drivers/vfio/vfio_iommu_type1.c +++ b/drivers/vfio/vfio_iommu_type1.c @@ -130,57 +130,36 @@ static void vfio_unlink_dma(struct vfio_iommu *iommu, struct vfio_dma *old) rb_erase(&old->node, &iommu->dma_list); } -struct vwork { - struct mm_struct *mm; - long npage; - struct work_struct work; -}; - -/* delayed decrement/increment for locked_vm */ -static void vfio_lock_acct_bg(struct work_struct *work) +static int vfio_lock_acct(long npage, bool *lock_cap) { - struct vwork *vwork = container_of(work, struct vwork, work); - struct mm_struct *mm; + int ret; - mm = vwork->mm; - down_write(&mm->mmap_sem); - mm->locked_vm += vwork->npage; - up_write(&mm->mmap_sem); - mmput(mm); - kfree(vwork); -} + if (!npage) + return 0; -static void vfio_lock_acct(long npage) -{ - struct vwork *vwork; - struct mm_struct *mm; + if (!current->mm) + return -ESRCH; /* process exited */ - if (!current->mm || !npage) - return; /* process exited or nothing to do */ + ret = down_write_killable(¤t->mm->mmap_sem); + if (!ret) { + if (npage > 0) { + if (lock_cap ? !*lock_cap : !capable(CAP_IPC_LOCK)) { + unsigned long limit; + + limit = rlimit(RLIMIT_MEMLOCK) >> PAGE_SHIFT; + + if (current->mm->locked_vm + npage > limit) + ret = -ENOMEM; + } + } + + if (!ret) + current->mm->locked_vm += npage; - if (down_write_trylock(¤t->mm->mmap_sem)) { - current->mm->locked_vm += npage; up_write(¤t->mm->mmap_sem); - return; } - /* - * Couldn't get mmap_sem lock, so must setup to update - * mm->locked_vm later. If locked_vm were atomic, we - * wouldn't need this silliness - */ - vwork = kmalloc(sizeof(struct vwork), GFP_KERNEL); - if (!vwork) - return; - mm = get_task_mm(current); - if (!mm) { - kfree(vwork); - return; - } - INIT_WORK(&vwork->work, vfio_lock_acct_bg); - vwork->mm = mm; - vwork->npage = npage; - schedule_work(&vwork->work); + return ret; } /* @@ -262,9 +241,9 @@ static int vaddr_get_pfn(unsigned long vaddr, int prot, unsigned long *pfn) static long vfio_pin_pages(unsigned long vaddr, long npage, int prot, unsigned long *pfn_base) { - unsigned long limit = rlimit(RLIMIT_MEMLOCK) >> PAGE_SHIFT; + unsigned long pfn = 0, limit = rlimit(RLIMIT_MEMLOCK) >> PAGE_SHIFT; bool lock_cap = capable(CAP_IPC_LOCK); - long ret, i; + long ret, i = 1; bool rsvd; if (!current->mm) @@ -283,16 +262,11 @@ static long vfio_pin_pages(unsigned long vaddr, long npage, return -ENOMEM; } - if (unlikely(disable_hugepages)) { - if (!rsvd) - vfio_lock_acct(1); - return 1; - } + if (unlikely(disable_hugepages)) + goto out; /* Lock all the consecutive pages from pfn_base */ - for (i = 1, vaddr += PAGE_SIZE; i < npage; i++, vaddr += PAGE_SIZE) { - unsigned long pfn = 0; - + for (vaddr += PAGE_SIZE; i < npage; i++, vaddr += PAGE_SIZE) { ret = vaddr_get_pfn(vaddr, prot, &pfn); if (ret) break; @@ -308,12 +282,24 @@ static long vfio_pin_pages(unsigned long vaddr, long npage, put_pfn(pfn, prot); pr_warn("%s: RLIMIT_MEMLOCK (%ld) exceeded\n", __func__, limit << PAGE_SHIFT); - break; + ret = -ENOMEM; + goto unpin_out; } } +out: if (!rsvd) - vfio_lock_acct(i); + ret = vfio_lock_acct(i, &lock_cap); + +unpin_out: + if (ret) { + if (!rsvd) { + for (pfn = *pfn_base ; i ; pfn++, i--) + put_pfn(pfn, prot); + } + + return ret; + } return i; } @@ -328,7 +314,7 @@ static long vfio_unpin_pages(unsigned long pfn, long npage, unlocked += put_pfn(pfn++, prot); if (do_accounting) - vfio_lock_acct(-unlocked); + vfio_lock_acct(-unlocked, NULL); return unlocked; } @@ -390,7 +376,7 @@ static void vfio_unmap_unpin(struct vfio_iommu *iommu, struct vfio_dma *dma) cond_resched(); } - vfio_lock_acct(-unlocked); + vfio_lock_acct(-unlocked, NULL); } static void vfio_remove_dma(struct vfio_iommu *iommu, struct vfio_dma *dma) From 377178321690105cd4d42b33486881843ea6f8e8 Mon Sep 17 00:00:00 2001 From: Ding Tianhong Date: Sat, 29 Apr 2017 10:38:48 +0800 Subject: [PATCH 147/396] iov_iter: don't revert iov buffer if csum error commit a6a5993243550b09f620941dea741b7421fdf79c upstream. The patch 327868212381 (make skb_copy_datagram_msg() et.al. preserve ->msg_iter on error) will revert the iov buffer if copy to iter failed, but it didn't copy any datagram if the skb_checksum_complete error, so no need to revert any data at this place. v2: Sabrina notice that return -EFAULT when checksum error is not correct here, it would confuse the caller about the return value, so fix it. Fixes: 327868212381 ("make skb_copy_datagram_msg() et.al. preserve->msg_iter on error") Signed-off-by: Ding Tianhong Acked-by: Al Viro Signed-off-by: Wei Yongjun Signed-off-by: Al Viro Signed-off-by: Greg Kroah-Hartman --- net/core/datagram.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/net/core/datagram.c b/net/core/datagram.c index 963732e775df..58dfa23d12ca 100644 --- a/net/core/datagram.c +++ b/net/core/datagram.c @@ -740,7 +740,7 @@ int skb_copy_and_csum_datagram_msg(struct sk_buff *skb, if (msg_data_left(msg) < chunk) { if (__skb_checksum_complete(skb)) - goto csum_error; + return -EINVAL; if (skb_copy_datagram_msg(skb, hlen, msg, chunk)) goto fault; } else { @@ -748,15 +748,16 @@ int skb_copy_and_csum_datagram_msg(struct sk_buff *skb, if (skb_copy_and_csum_datagram(skb, hlen, &msg->msg_iter, chunk, &csum)) goto fault; - if (csum_fold(csum)) - goto csum_error; + + if (csum_fold(csum)) { + iov_iter_revert(&msg->msg_iter, chunk); + return -EINVAL; + } + if (unlikely(skb->ip_summed == CHECKSUM_COMPLETE)) netdev_rx_csum_fault(skb->dev); } return 0; -csum_error: - iov_iter_revert(&msg->msg_iter, chunk); - return -EINVAL; fault: return -EFAULT; } From ecb0ab0f89c78c1bbe8386aac875f0b60753762d Mon Sep 17 00:00:00 2001 From: Jack Morgenstein Date: Sun, 19 Mar 2017 10:55:57 +0200 Subject: [PATCH 148/396] IB/core: Fix sysfs registration error flow commit b312be3d87e4c80872cbea869e569175c5eb0f9a upstream. The kernel commit cited below restructured ib device management so that the device kobject is initialized in ib_alloc_device. As part of the restructuring, the kobject is now initialized in procedure ib_alloc_device, and is later added to the device hierarchy in the ib_register_device call stack, in procedure ib_device_register_sysfs (which calls device_add). However, in the ib_device_register_sysfs error flow, if an error occurs following the call to device_add, the cleanup procedure device_unregister is called. This call results in the device object being deleted -- which results in various use-after-free crashes. The correct cleanup call is device_del -- which undoes device_add without deleting the device object. The device object will then (correctly) be deleted in the ib_register_device caller's error cleanup flow, when the caller invokes ib_dealloc_device. Fixes: 55aeed06544f6 ("IB/core: Make ib_alloc_device init the kobject") Signed-off-by: Jack Morgenstein Signed-off-by: Leon Romanovsky Signed-off-by: Doug Ledford Signed-off-by: Greg Kroah-Hartman --- drivers/infiniband/core/sysfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/infiniband/core/sysfs.c b/drivers/infiniband/core/sysfs.c index c1fb545e8d78..42de5f22da93 100644 --- a/drivers/infiniband/core/sysfs.c +++ b/drivers/infiniband/core/sysfs.c @@ -1301,7 +1301,7 @@ err_put: free_port_list_attributes(device); err_unregister: - device_unregister(class_dev); + device_del(class_dev); err: return ret; From 7a227630ab893f1aac6da6a540ebc2c6a7dce115 Mon Sep 17 00:00:00 2001 From: "Michael J. Ruhl" Date: Sun, 9 Apr 2017 10:15:51 -0700 Subject: [PATCH 149/396] IB/core: For multicast functions, verify that LIDs are multicast LIDs commit 8561eae60ff9417a50fa1fb2b83ae950dc5c1e21 upstream. The Infiniband spec defines "A multicast address is defined by a MGID and a MLID" (section 10.5). Currently the MLID value is not validated. Add check to verify that the MLID value is in the correct address range. Fixes: 0c33aeedb2cf ("[IB] Add checks to multicast attach and detach") Reviewed-by: Ira Weiny Reviewed-by: Dasaratharaman Chandramouli Signed-off-by: Michael J. Ruhl Signed-off-by: Dennis Dalessandro Reviewed-by: Leon Romanovsky Signed-off-by: Doug Ledford Signed-off-by: Greg Kroah-Hartman --- drivers/infiniband/core/verbs.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/infiniband/core/verbs.c b/drivers/infiniband/core/verbs.c index 83687646da68..0e64b52af5b2 100644 --- a/drivers/infiniband/core/verbs.c +++ b/drivers/infiniband/core/verbs.c @@ -1516,7 +1516,9 @@ int ib_attach_mcast(struct ib_qp *qp, union ib_gid *gid, u16 lid) if (!qp->device->attach_mcast) return -ENOSYS; - if (gid->raw[0] != 0xff || qp->qp_type != IB_QPT_UD) + if (gid->raw[0] != 0xff || qp->qp_type != IB_QPT_UD || + lid < be16_to_cpu(IB_MULTICAST_LID_BASE) || + lid == be16_to_cpu(IB_LID_PERMISSIVE)) return -EINVAL; ret = qp->device->attach_mcast(qp, gid, lid); @@ -1532,7 +1534,9 @@ int ib_detach_mcast(struct ib_qp *qp, union ib_gid *gid, u16 lid) if (!qp->device->detach_mcast) return -ENOSYS; - if (gid->raw[0] != 0xff || qp->qp_type != IB_QPT_UD) + if (gid->raw[0] != 0xff || qp->qp_type != IB_QPT_UD || + lid < be16_to_cpu(IB_MULTICAST_LID_BASE) || + lid == be16_to_cpu(IB_LID_PERMISSIVE)) return -EINVAL; ret = qp->device->detach_mcast(qp, gid, lid); From d20bfe223d3e63bb42aa581d779a1f8074b0c287 Mon Sep 17 00:00:00 2001 From: Shamir Rabinovitch Date: Wed, 29 Mar 2017 06:21:59 -0400 Subject: [PATCH 150/396] IB/IPoIB: ibX: failed to create mcg debug file commit 771a52584096c45e4565e8aabb596eece9d73d61 upstream. When udev renames the netdev devices, ipoib debugfs entries does not get renamed. As a result, if subsequent probe of ipoib device reuse the name then creating a debugfs entry for the new device would fail. Also, moved ipoib_create_debug_files and ipoib_delete_debug_files as part of ipoib event handling in order to avoid any race condition between these. Fixes: 1732b0ef3b3a ([IPoIB] add path record information in debugfs) Signed-off-by: Vijay Kumar Signed-off-by: Shamir Rabinovitch Reviewed-by: Mark Bloch Signed-off-by: Doug Ledford Signed-off-by: Greg Kroah-Hartman --- drivers/infiniband/ulp/ipoib/ipoib_fs.c | 3 ++ drivers/infiniband/ulp/ipoib/ipoib_main.c | 44 ++++++++++++++++++++--- drivers/infiniband/ulp/ipoib/ipoib_vlan.c | 3 -- 3 files changed, 42 insertions(+), 8 deletions(-) diff --git a/drivers/infiniband/ulp/ipoib/ipoib_fs.c b/drivers/infiniband/ulp/ipoib/ipoib_fs.c index 6bd5740e2691..09396bd7b02d 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_fs.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_fs.c @@ -281,8 +281,11 @@ void ipoib_delete_debug_files(struct net_device *dev) { struct ipoib_dev_priv *priv = netdev_priv(dev); + WARN_ONCE(!priv->mcg_dentry, "null mcg debug file\n"); + WARN_ONCE(!priv->path_dentry, "null path debug file\n"); debugfs_remove(priv->mcg_dentry); debugfs_remove(priv->path_dentry); + priv->mcg_dentry = priv->path_dentry = NULL; } int ipoib_register_debugfs(void) diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c index 3ef7b8f049c4..08c4b0287304 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_main.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c @@ -108,6 +108,33 @@ static struct ib_client ipoib_client = { .get_net_dev_by_params = ipoib_get_net_dev_by_params, }; +#ifdef CONFIG_INFINIBAND_IPOIB_DEBUG +static int ipoib_netdev_event(struct notifier_block *this, + unsigned long event, void *ptr) +{ + struct netdev_notifier_info *ni = ptr; + struct net_device *dev = ni->dev; + + if (dev->netdev_ops->ndo_open != ipoib_open) + return NOTIFY_DONE; + + switch (event) { + case NETDEV_REGISTER: + ipoib_create_debug_files(dev); + break; + case NETDEV_CHANGENAME: + ipoib_delete_debug_files(dev); + ipoib_create_debug_files(dev); + break; + case NETDEV_UNREGISTER: + ipoib_delete_debug_files(dev); + break; + } + + return NOTIFY_DONE; +} +#endif + int ipoib_open(struct net_device *dev) { struct ipoib_dev_priv *priv = netdev_priv(dev); @@ -1655,8 +1682,6 @@ void ipoib_dev_cleanup(struct net_device *dev) ASSERT_RTNL(); - ipoib_delete_debug_files(dev); - /* Delete any child interfaces first */ list_for_each_entry_safe(cpriv, tcpriv, &priv->child_intfs, list) { /* Stop GC on child */ @@ -2074,8 +2099,6 @@ static struct net_device *ipoib_add_port(const char *format, goto register_failed; } - ipoib_create_debug_files(priv->dev); - if (ipoib_cm_add_mode_attr(priv->dev)) goto sysfs_failed; if (ipoib_add_pkey_attr(priv->dev)) @@ -2090,7 +2113,6 @@ static struct net_device *ipoib_add_port(const char *format, return priv->dev; sysfs_failed: - ipoib_delete_debug_files(priv->dev); unregister_netdev(priv->dev); register_failed: @@ -2175,6 +2197,12 @@ static void ipoib_remove_one(struct ib_device *device, void *client_data) kfree(dev_list); } +#ifdef CONFIG_INFINIBAND_IPOIB_DEBUG +static struct notifier_block ipoib_netdev_notifier = { + .notifier_call = ipoib_netdev_event, +}; +#endif + static int __init ipoib_init_module(void) { int ret; @@ -2227,6 +2255,9 @@ static int __init ipoib_init_module(void) if (ret) goto err_client; +#ifdef CONFIG_INFINIBAND_IPOIB_DEBUG + register_netdevice_notifier(&ipoib_netdev_notifier); +#endif return 0; err_client: @@ -2244,6 +2275,9 @@ err_fs: static void __exit ipoib_cleanup_module(void) { +#ifdef CONFIG_INFINIBAND_IPOIB_DEBUG + unregister_netdevice_notifier(&ipoib_netdev_notifier); +#endif ipoib_netlink_fini(); ib_unregister_client(&ipoib_client); ib_sa_unregister_client(&ipoib_sa_client); diff --git a/drivers/infiniband/ulp/ipoib/ipoib_vlan.c b/drivers/infiniband/ulp/ipoib/ipoib_vlan.c index a2f9f29c6ab5..57eadd2b7a71 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_vlan.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_vlan.c @@ -87,8 +87,6 @@ int __ipoib_vlan_add(struct ipoib_dev_priv *ppriv, struct ipoib_dev_priv *priv, goto register_failed; } - ipoib_create_debug_files(priv->dev); - /* RTNL childs don't need proprietary sysfs entries */ if (type == IPOIB_LEGACY_CHILD) { if (ipoib_cm_add_mode_attr(priv->dev)) @@ -109,7 +107,6 @@ int __ipoib_vlan_add(struct ipoib_dev_priv *ppriv, struct ipoib_dev_priv *priv, sysfs_failed: result = -ENOMEM; - ipoib_delete_debug_files(priv->dev); unregister_netdevice(priv->dev); register_failed: From 9ae6b33dcbb48f82857d5765fcad429961f8f46c Mon Sep 17 00:00:00 2001 From: Jack Morgenstein Date: Tue, 21 Mar 2017 12:57:05 +0200 Subject: [PATCH 151/396] IB/mlx4: Fix ib device initialization error flow commit 99e68909d5aba1861897fe7afc3306c3c81b6de0 upstream. In mlx4_ib_add, procedure mlx4_ib_alloc_eqs is called to allocate EQs. However, in the mlx4_ib_add error flow, procedure mlx4_ib_free_eqs is not called to free the allocated EQs. Fixes: e605b743f33d ("IB/mlx4: Increase the number of vectors (EQs) available for ULPs") Signed-off-by: Jack Morgenstein Signed-off-by: Leon Romanovsky Signed-off-by: Doug Ledford Signed-off-by: Greg Kroah-Hartman --- drivers/infiniband/hw/mlx4/main.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/infiniband/hw/mlx4/main.c b/drivers/infiniband/hw/mlx4/main.c index 46ad99595fd2..f2a885eee4bb 100644 --- a/drivers/infiniband/hw/mlx4/main.c +++ b/drivers/infiniband/hw/mlx4/main.c @@ -2926,6 +2926,7 @@ err_counter: mlx4_ib_delete_counters_table(ibdev, &ibdev->counters_table[i]); err_map: + mlx4_ib_free_eqs(dev, ibdev); iounmap(ibdev->uar_map); err_uar: From 43c54927f6f4e0dba5714dbcd53fea44114cd7cf Mon Sep 17 00:00:00 2001 From: Jack Morgenstein Date: Tue, 21 Mar 2017 12:57:06 +0200 Subject: [PATCH 152/396] IB/mlx4: Reduce SRIOV multicast cleanup warning message to debug level commit fb7a91746af18b2ebf596778b38a709cdbc488d3 upstream. A warning message during SRIOV multicast cleanup should have actually been a debug level message. The condition generating the warning does no harm and can fill the message log. In some cases, during testing, some tests were so intense as to swamp the message log with these warning messages, causing a stall in the console message log output task. This stall caused an NMI to be sent to all CPUs (so that they all dumped their stacks into the message log). Aside from the message flood causing an NMI, the tests all passed. Once the message flood which caused the NMI is removed (by reducing the warning message to debug level), the NMI no longer occurs. Sample message log (console log) output illustrating the flood and resultant NMI (snippets with comments and modified with ... instead of hex digits, to satisfy checkpatch.pl): _mlx4_ib_mcg_port_cleanup: ... WARNING: group refcount 1!!!... *** About 4000 almost identical lines in less than one second *** _mlx4_ib_mcg_port_cleanup: ... WARNING: group refcount 1!!!... INFO: rcu_sched detected stalls on CPUs/tasks: { 17} (...) *** { 17} above indicates that CPU 17 was the one that stalled *** sending NMI to all CPUs: ... NMI backtrace for cpu 17 CPU: 17 PID: 45909 Comm: kworker/17:2 Hardware name: HP ProLiant DL360p Gen8, BIOS P71 09/08/2013 Workqueue: events fb_flashcursor task: ffff880478...... ti: ffff88064e...... task.ti: ffff88064e...... RIP: 0010:[ffffffff81......] [ffffffff81......] io_serial_in+0x15/0x20 RSP: 0018:ffff88064e257cb0 EFLAGS: 00000002 RAX: 0000000000...... RBX: ffffffff81...... RCX: 0000000000...... RDX: 0000000000...... RSI: 0000000000...... RDI: ffffffff81...... RBP: ffff88064e...... R08: ffffffff81...... R09: 0000000000...... R10: 0000000000...... R11: ffff88064e...... R12: 0000000000...... R13: 0000000000...... R14: ffffffff81...... R15: 0000000000...... FS: 0000000000......(0000) GS:ffff8804af......(0000) knlGS:000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080...... CR2: 00007f2a2f...... CR3: 0000000001...... CR4: 0000000000...... DR0: 0000000000...... DR1: 0000000000...... DR2: 0000000000...... DR3: 0000000000...... DR6: 00000000ff...... DR7: 0000000000...... Stack: ffff88064e...... ffffffff81...... ffffffff81...... 0000000000...... ffffffff81...... ffff88064e...... ffffffff81...... ffffffff81...... ffffffff81...... ffff88064e...... ffffffff81...... 0000000000...... Call Trace: [] wait_for_xmitr+0x3b/0xa0 [] serial8250_console_putchar+0x1c/0x30 [] ? serial8250_console_write+0x140/0x140 [] uart_console_write+0x3a/0x80 [] serial8250_console_write+0xae/0x140 [] call_console_drivers.constprop.15+0x91/0xf0 [] console_unlock+0x3bf/0x400 [] fb_flashcursor+0x5d/0x140 [] ? bit_clear+0x120/0x120 [] process_one_work+0x17b/0x470 [] worker_thread+0x11b/0x400 [] ? rescuer_thread+0x400/0x400 [] kthread+0xcf/0xe0 [] ? kthread_create_on_node+0x140/0x140 [] ret_from_fork+0x58/0x90 [] ? kthread_create_on_node+0x140/0x140 Code: 48 89 e5 d3 e6 48 63 f6 48 03 77 10 8b 06 5d c3 66 0f 1f 44 00 00 66 66 66 6 As indicated in the stack trace above, the console output task got swamped. Fixes: b9c5d6a64358 ("IB/mlx4: Add multicast group (MCG) paravirtualization for SR-IOV") Signed-off-by: Jack Morgenstein Signed-off-by: Leon Romanovsky Signed-off-by: Doug Ledford Signed-off-by: Greg Kroah-Hartman --- drivers/infiniband/hw/mlx4/mcg.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/infiniband/hw/mlx4/mcg.c b/drivers/infiniband/hw/mlx4/mcg.c index a21d37f02f35..e6ea81c9644a 100644 --- a/drivers/infiniband/hw/mlx4/mcg.c +++ b/drivers/infiniband/hw/mlx4/mcg.c @@ -1102,7 +1102,8 @@ static void _mlx4_ib_mcg_port_cleanup(struct mlx4_ib_demux_ctx *ctx, int destroy while ((p = rb_first(&ctx->mcg_table)) != NULL) { group = rb_entry(p, struct mcast_group, node); if (atomic_read(&group->refcount)) - mcg_warn_group(group, "group refcount %d!!! (pointer %p)\n", atomic_read(&group->refcount), group); + mcg_debug_group(group, "group refcount %d!!! (pointer %p)\n", + atomic_read(&group->refcount), group); force_clean_group(group); } From e3cea38357ea66d63b1c42500c69ca88a3f0c44f Mon Sep 17 00:00:00 2001 From: Mike Marciniszyn Date: Sun, 9 Apr 2017 10:16:35 -0700 Subject: [PATCH 153/396] IB/hfi1: Prevent kernel QP post send hard lockups commit b6eac931b9bb2bce4db7032c35b41e5e34ec22a5 upstream. The driver progress routines can call cond_resched() when a timeslice is exhausted and irqs are enabled. If the ULP had been holding a spin lock without disabling irqs and the post send directly called the progress routine, the cond_resched() could yield allowing another thread from the same ULP to deadlock on that same lock. Correct by replacing the current hfi1_do_send() calldown with a unique one for post send and adding an argument to hfi1_do_send() to indicate that the send engine is running in a thread. If the routine is not running in a thread, avoid calling cond_resched(). Fixes: Commit 831464ce4b74 ("IB/hfi1: Don't call cond_resched in atomic mode when sending packets") Reviewed-by: Dennis Dalessandro Signed-off-by: Mike Marciniszyn Signed-off-by: Dennis Dalessandro Signed-off-by: Doug Ledford Signed-off-by: Greg Kroah-Hartman --- drivers/infiniband/hw/hfi1/ruc.c | 26 ++++++++++++++++---------- drivers/infiniband/hw/hfi1/verbs.c | 4 ++-- drivers/infiniband/hw/hfi1/verbs.h | 6 ++++-- 3 files changed, 22 insertions(+), 14 deletions(-) diff --git a/drivers/infiniband/hw/hfi1/ruc.c b/drivers/infiniband/hw/hfi1/ruc.c index a1576aea4756..9f768b48321f 100644 --- a/drivers/infiniband/hw/hfi1/ruc.c +++ b/drivers/infiniband/hw/hfi1/ruc.c @@ -1,5 +1,5 @@ /* - * Copyright(c) 2015, 2016 Intel Corporation. + * Copyright(c) 2015 - 2017 Intel Corporation. * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. @@ -833,23 +833,29 @@ void hfi1_make_ruc_header(struct rvt_qp *qp, struct ib_other_headers *ohdr, /* when sending, force a reschedule every one of these periods */ #define SEND_RESCHED_TIMEOUT (5 * HZ) /* 5s in jiffies */ +void hfi1_do_send_from_rvt(struct rvt_qp *qp) +{ + hfi1_do_send(qp, false); +} + void _hfi1_do_send(struct work_struct *work) { struct iowait *wait = container_of(work, struct iowait, iowork); struct rvt_qp *qp = iowait_to_qp(wait); - hfi1_do_send(qp); + hfi1_do_send(qp, true); } /** * hfi1_do_send - perform a send on a QP * @work: contains a pointer to the QP + * @in_thread: true if in a workqueue thread * * Process entries in the send work queue until credit or queue is * exhausted. Only allow one CPU to send a packet per QP. * Otherwise, two threads could send packets out of order. */ -void hfi1_do_send(struct rvt_qp *qp) +void hfi1_do_send(struct rvt_qp *qp, bool in_thread) { struct hfi1_pkt_state ps; struct hfi1_qp_priv *priv = qp->priv; @@ -917,8 +923,10 @@ void hfi1_do_send(struct rvt_qp *qp) qp->s_hdrwords = 0; /* allow other tasks to run */ if (unlikely(time_after(jiffies, timeout))) { - if (workqueue_congested(cpu, - ps.ppd->hfi1_wq)) { + if (!in_thread || + workqueue_congested( + cpu, + ps.ppd->hfi1_wq)) { spin_lock_irqsave( &qp->s_lock, ps.flags); @@ -931,11 +939,9 @@ void hfi1_do_send(struct rvt_qp *qp) *ps.ppd->dd->send_schedule); return; } - if (!irqs_disabled()) { - cond_resched(); - this_cpu_inc( - *ps.ppd->dd->send_schedule); - } + cond_resched(); + this_cpu_inc( + *ps.ppd->dd->send_schedule); timeout = jiffies + (timeout_int) / 8; } spin_lock_irqsave(&qp->s_lock, ps.flags); diff --git a/drivers/infiniband/hw/hfi1/verbs.c b/drivers/infiniband/hw/hfi1/verbs.c index 4b7a16ceb362..01a380efea6b 100644 --- a/drivers/infiniband/hw/hfi1/verbs.c +++ b/drivers/infiniband/hw/hfi1/verbs.c @@ -1,5 +1,5 @@ /* - * Copyright(c) 2015, 2016 Intel Corporation. + * Copyright(c) 2015 - 2017 Intel Corporation. * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. @@ -1697,7 +1697,7 @@ int hfi1_register_ib_device(struct hfi1_devdata *dd) dd->verbs_dev.rdi.driver_f.qp_priv_free = qp_priv_free; dd->verbs_dev.rdi.driver_f.free_all_qps = free_all_qps; dd->verbs_dev.rdi.driver_f.notify_qp_reset = notify_qp_reset; - dd->verbs_dev.rdi.driver_f.do_send = hfi1_do_send; + dd->verbs_dev.rdi.driver_f.do_send = hfi1_do_send_from_rvt; dd->verbs_dev.rdi.driver_f.schedule_send = hfi1_schedule_send; dd->verbs_dev.rdi.driver_f.schedule_send_no_lock = _hfi1_schedule_send; dd->verbs_dev.rdi.driver_f.get_pmtu_from_attr = get_pmtu_from_attr; diff --git a/drivers/infiniband/hw/hfi1/verbs.h b/drivers/infiniband/hw/hfi1/verbs.h index 1c3815d89eb7..bac84f820a54 100644 --- a/drivers/infiniband/hw/hfi1/verbs.h +++ b/drivers/infiniband/hw/hfi1/verbs.h @@ -1,5 +1,5 @@ /* - * Copyright(c) 2015, 2016 Intel Corporation. + * Copyright(c) 2015 - 2017 Intel Corporation. * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. @@ -372,7 +372,9 @@ void hfi1_make_ruc_header(struct rvt_qp *qp, struct ib_other_headers *ohdr, void _hfi1_do_send(struct work_struct *work); -void hfi1_do_send(struct rvt_qp *qp); +void hfi1_do_send_from_rvt(struct rvt_qp *qp); + +void hfi1_do_send(struct rvt_qp *qp, bool in_thread); void hfi1_send_complete(struct rvt_qp *qp, struct rvt_swqe *wqe, enum ib_wc_status status); From 7929b50dedd131be308f8b3cd54b6cb1c4c5b949 Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Fri, 24 Mar 2017 14:15:52 +0200 Subject: [PATCH 154/396] perf auxtrace: Fix no_size logic in addr_filter__resolve_kernel_syms() commit c3a0bbc7ad7598dec5a204868bdf8a2b1b51df14 upstream. Address filtering with kernel symbols incorrectly resulted in the error "Cannot determine size of symbol" because the no_size logic was the wrong way around. Signed-off-by: Adrian Hunter Tested-by: Andi Kleen Link: http://lkml.kernel.org/r/1490357752-27942-1-git-send-email-adrian.hunter@intel.com Signed-off-by: Arnaldo Carvalho de Melo Signed-off-by: Greg Kroah-Hartman --- tools/perf/util/auxtrace.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/perf/util/auxtrace.c b/tools/perf/util/auxtrace.c index c5a6e0b12452..78bd632f144d 100644 --- a/tools/perf/util/auxtrace.c +++ b/tools/perf/util/auxtrace.c @@ -1826,7 +1826,7 @@ static int addr_filter__resolve_kernel_syms(struct addr_filter *filt) filt->addr = start; if (filt->range && !filt->size && !filt->sym_to) { filt->size = size; - no_size = !!size; + no_size = !size; } } @@ -1840,7 +1840,7 @@ static int addr_filter__resolve_kernel_syms(struct addr_filter *filt) if (err) return err; filt->size = start + size - filt->addr; - no_size = !!size; + no_size = !size; } /* The very last symbol in kallsyms does not imply a particular size */ From b2764f851db69a3320f59205d78265d5c72c03cd Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Sun, 30 Apr 2017 00:10:50 -0400 Subject: [PATCH 155/396] ext4: evict inline data when writing to memory map commit 7b4cc9787fe35b3ee2dfb1c35e22eafc32e00c33 upstream. Currently the case of writing via mmap to a file with inline data is not handled. This is maybe a rare case since it requires a writable memory map of a very small file, but it is trivial to trigger with on inline_data filesystem, and it causes the 'BUG_ON(ext4_test_inode_state(inode, EXT4_STATE_MAY_INLINE_DATA));' in ext4_writepages() to be hit: mkfs.ext4 -O inline_data /dev/vdb mount /dev/vdb /mnt xfs_io -f /mnt/file \ -c 'pwrite 0 1' \ -c 'mmap -w 0 1m' \ -c 'mwrite 0 1' \ -c 'fsync' kernel BUG at fs/ext4/inode.c:2723! invalid opcode: 0000 [#1] SMP CPU: 1 PID: 2532 Comm: xfs_io Not tainted 4.11.0-rc1-xfstests-00301-g071d9acf3d1f #633 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.10.2-20170228_101828-anatol 04/01/2014 task: ffff88003d3a8040 task.stack: ffffc90000300000 RIP: 0010:ext4_writepages+0xc89/0xf8a RSP: 0018:ffffc90000303ca0 EFLAGS: 00010283 RAX: 0000028410000000 RBX: ffff8800383fa3b0 RCX: ffffffff812afcdc RDX: 00000a9d00000246 RSI: ffffffff81e660e0 RDI: 0000000000000246 RBP: ffffc90000303dc0 R08: 0000000000000002 R09: 869618e8f99b4fa5 R10: 00000000852287a2 R11: 00000000a03b49f4 R12: ffff88003808e698 R13: 0000000000000000 R14: 7fffffffffffffff R15: 7fffffffffffffff FS: 00007fd3e53094c0(0000) GS:ffff88003e400000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 00007fd3e4c51000 CR3: 000000003d554000 CR4: 00000000003406e0 Call Trace: ? _raw_spin_unlock+0x27/0x2a ? kvm_clock_read+0x1e/0x20 do_writepages+0x23/0x2c ? do_writepages+0x23/0x2c __filemap_fdatawrite_range+0x80/0x87 filemap_write_and_wait_range+0x67/0x8c ext4_sync_file+0x20e/0x472 vfs_fsync_range+0x8e/0x9f ? syscall_trace_enter+0x25b/0x2d0 vfs_fsync+0x1c/0x1e do_fsync+0x31/0x4a SyS_fsync+0x10/0x14 do_syscall_64+0x69/0x131 entry_SYSCALL64_slow_path+0x25/0x25 We could try to be smart and keep the inline data in this case, or at least support delayed allocation when allocating the block, but these solutions would be more complicated and don't seem worthwhile given how rare this case seems to be. So just fix the bug by calling ext4_convert_inline_data() when we're asked to make a page writable, so that any inline data gets evicted, with the block allocated immediately. Reported-by: Nick Alcock Reviewed-by: Andreas Dilger Signed-off-by: Eric Biggers Signed-off-by: Theodore Ts'o Signed-off-by: Greg Kroah-Hartman --- fs/ext4/inode.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index c78fce404654..01329688fb9e 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -5686,6 +5686,11 @@ int ext4_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf) file_update_time(vma->vm_file); down_read(&EXT4_I(inode)->i_mmap_sem); + + ret = ext4_convert_inline_data(inode); + if (ret) + goto out_ret; + /* Delalloc case is easy... */ if (test_opt(inode->i_sb, DELALLOC) && !ext4_should_journal_data(inode) && From 127adc188c62ffd3d3e78e1f057ab7669b37c10f Mon Sep 17 00:00:00 2001 From: Martin Brandenburg Date: Tue, 25 Apr 2017 15:37:56 -0400 Subject: [PATCH 156/396] orangefs: fix bounds check for listxattr commit a956af337b9ff25822d9ce1a59c6ed0c09fc14b9 upstream. Signed-off-by: Martin Brandenburg Signed-off-by: Mike Marshall Signed-off-by: Greg Kroah-Hartman --- fs/orangefs/xattr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/orangefs/xattr.c b/fs/orangefs/xattr.c index 74a81b1daaac..fba4db7d0512 100644 --- a/fs/orangefs/xattr.c +++ b/fs/orangefs/xattr.c @@ -358,7 +358,7 @@ try_again: returned_count = new_op->downcall.resp.listxattr.returned_count; if (returned_count < 0 || - returned_count >= ORANGEFS_MAX_XATTR_LISTLEN) { + returned_count > ORANGEFS_MAX_XATTR_LISTLEN) { gossip_err("%s: impossible value for returned_count:%d:\n", __func__, returned_count); From 59f496104112ccea4e55ad10e248301460054cc8 Mon Sep 17 00:00:00 2001 From: Martin Brandenburg Date: Tue, 25 Apr 2017 15:37:57 -0400 Subject: [PATCH 157/396] orangefs: clean up oversize xattr validation commit e675c5ec51fe2554719a7b6bcdbef0a770f2c19b upstream. Also don't check flags as this has been validated by the VFS already. Fix an off-by-one error in the max size checking. Stop logging just because userspace wants to write attributes which do not fit. This and the previous commit fix xfstests generic/020. Signed-off-by: Martin Brandenburg Signed-off-by: Mike Marshall Signed-off-by: Greg Kroah-Hartman --- fs/orangefs/xattr.c | 24 +++++++----------------- 1 file changed, 7 insertions(+), 17 deletions(-) diff --git a/fs/orangefs/xattr.c b/fs/orangefs/xattr.c index fba4db7d0512..237c9c04dc3b 100644 --- a/fs/orangefs/xattr.c +++ b/fs/orangefs/xattr.c @@ -76,11 +76,8 @@ ssize_t orangefs_inode_getxattr(struct inode *inode, const char *name, if (S_ISLNK(inode->i_mode)) return -EOPNOTSUPP; - if (strlen(name) >= ORANGEFS_MAX_XATTR_NAMELEN) { - gossip_err("Invalid key length (%d)\n", - (int)strlen(name)); + if (strlen(name) > ORANGEFS_MAX_XATTR_NAMELEN) return -EINVAL; - } fsuid = from_kuid(&init_user_ns, current_fsuid()); fsgid = from_kgid(&init_user_ns, current_fsgid()); @@ -172,6 +169,9 @@ static int orangefs_inode_removexattr(struct inode *inode, const char *name, struct orangefs_kernel_op_s *new_op = NULL; int ret = -ENOMEM; + if (strlen(name) > ORANGEFS_MAX_XATTR_NAMELEN) + return -EINVAL; + down_write(&orangefs_inode->xattr_sem); new_op = op_alloc(ORANGEFS_VFS_OP_REMOVEXATTR); if (!new_op) @@ -231,23 +231,13 @@ int orangefs_inode_setxattr(struct inode *inode, const char *name, "%s: name %s, buffer_size %zd\n", __func__, name, size); - if (size >= ORANGEFS_MAX_XATTR_VALUELEN || - flags < 0) { - gossip_err("orangefs_inode_setxattr: bogus values of size(%d), flags(%d)\n", - (int)size, - flags); + if (size > ORANGEFS_MAX_XATTR_VALUELEN) + return -EINVAL; + if (strlen(name) > ORANGEFS_MAX_XATTR_NAMELEN) return -EINVAL; - } internal_flag = convert_to_internal_xattr_flags(flags); - if (strlen(name) >= ORANGEFS_MAX_XATTR_NAMELEN) { - gossip_err - ("orangefs_inode_setxattr: bogus key size (%d)\n", - (int)(strlen(name))); - return -EINVAL; - } - /* This is equivalent to a removexattr */ if (size == 0 && value == NULL) { gossip_debug(GOSSIP_XATTR_DEBUG, From 63907bb781e730e54dde7a8d0f93af72264ece19 Mon Sep 17 00:00:00 2001 From: Martin Brandenburg Date: Tue, 25 Apr 2017 15:37:58 -0400 Subject: [PATCH 158/396] orangefs: do not set getattr_time on orangefs_lookup commit 17930b252cd6f31163c259eaa99dd8aa630fb9ba upstream. Since orangefs_lookup calls orangefs_iget which calls orangefs_inode_getattr, getattr_time will get set. Signed-off-by: Martin Brandenburg Signed-off-by: Mike Marshall Signed-off-by: Greg Kroah-Hartman --- fs/orangefs/namei.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/fs/orangefs/namei.c b/fs/orangefs/namei.c index a290ff6ec756..7c315938e9c2 100644 --- a/fs/orangefs/namei.c +++ b/fs/orangefs/namei.c @@ -193,8 +193,6 @@ static struct dentry *orangefs_lookup(struct inode *dir, struct dentry *dentry, goto out; } - ORANGEFS_I(inode)->getattr_time = jiffies - 1; - gossip_debug(GOSSIP_NAME_DEBUG, "%s:%s:%d " "Found good inode [%lu] with count [%d]\n", From 1777e888bd402ea53095e0d53d305ad22b0c452b Mon Sep 17 00:00:00 2001 From: Martin Brandenburg Date: Tue, 25 Apr 2017 15:38:04 -0400 Subject: [PATCH 159/396] orangefs: do not check possibly stale size on truncate commit 53950ef541675df48c219a8d665111a0e68dfc2f upstream. Let the server figure this out because our size might be out of date or not present. The bug was that xfs_io -f -t -c "pread -v 0 100" /mnt/foo echo "Test" > /mnt/foo xfs_io -f -t -c "pread -v 0 100" /mnt/foo fails because the second truncate did not happen if nothing had requested the size after the write in echo. Thus i_size was zero (not present) and the orangefs_setattr though i_size was zero and there was nothing to do. Signed-off-by: Martin Brandenburg Signed-off-by: Mike Marshall Signed-off-by: Greg Kroah-Hartman --- fs/orangefs/inode.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/fs/orangefs/inode.c b/fs/orangefs/inode.c index ef3b4eb54cf2..08ecdeebd6f7 100644 --- a/fs/orangefs/inode.c +++ b/fs/orangefs/inode.c @@ -223,8 +223,7 @@ int orangefs_setattr(struct dentry *dentry, struct iattr *iattr) if (ret) goto out; - if ((iattr->ia_valid & ATTR_SIZE) && - iattr->ia_size != i_size_read(inode)) { + if (iattr->ia_valid & ATTR_SIZE) { ret = orangefs_setattr_size(inode, iattr); if (ret) goto out; From 9a6bb7b5637eb3dc9b16085d05e176edf27665e6 Mon Sep 17 00:00:00 2001 From: Michal Hocko Date: Mon, 8 May 2017 15:57:24 -0700 Subject: [PATCH 160/396] fs/xattr.c: zero out memory copied to userspace in getxattr commit 81be3dee96346fbe08c31be5ef74f03f6b63cf68 upstream. getxattr uses vmalloc to allocate memory if kzalloc fails. This is filled by vfs_getxattr and then copied to the userspace. vmalloc, however, doesn't zero out the memory so if the specific implementation of the xattr handler is sloppy we can theoretically expose a kernel memory. There is no real sign this is really the case but let's make sure this will not happen and use vzalloc instead. Fixes: 779302e67835 ("fs/xattr.c:getxattr(): improve handling of allocation failures") Link: http://lkml.kernel.org/r/20170306103327.2766-1-mhocko@kernel.org Acked-by: Kees Cook Reported-by: Vlastimil Babka Signed-off-by: Michal Hocko Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- fs/xattr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/xattr.c b/fs/xattr.c index 2d13b4e62fae..ed8c374570ed 100644 --- a/fs/xattr.c +++ b/fs/xattr.c @@ -530,7 +530,7 @@ getxattr(struct dentry *d, const char __user *name, void __user *value, size = XATTR_SIZE_MAX; kvalue = kzalloc(size, GFP_KERNEL | __GFP_NOWARN); if (!kvalue) { - kvalue = vmalloc(size); + kvalue = vzalloc(size); if (!kvalue) return -ENOMEM; } From 091784ae973837a11d9d894f2aee63a44af641af Mon Sep 17 00:00:00 2001 From: Luis Henriques Date: Fri, 28 Apr 2017 11:14:04 +0100 Subject: [PATCH 161/396] ceph: fix memory leak in __ceph_setxattr() commit eeca958dce0a9231d1969f86196653eb50fcc9b3 upstream. The ceph_inode_xattr needs to be released when removing an xattr. Easily reproducible running the 'generic/020' test from xfstests or simply by doing: attr -s attr0 -V 0 /mnt/test && attr -r attr0 /mnt/test While there, also fix the error path. Here's the kmemleak splat: unreferenced object 0xffff88001f86fbc0 (size 64): comm "attr", pid 244, jiffies 4294904246 (age 98.464s) hex dump (first 32 bytes): 40 fa 86 1f 00 88 ff ff 80 32 38 1f 00 88 ff ff @........28..... 00 01 00 00 00 00 ad de 00 02 00 00 00 00 ad de ................ backtrace: [] kmemleak_alloc+0x49/0xa0 [] kmem_cache_alloc+0x9b/0xf0 [] __ceph_setxattr+0x17e/0x820 [] ceph_set_xattr_handler+0x37/0x40 [] __vfs_removexattr+0x4b/0x60 [] vfs_removexattr+0x77/0xd0 [] removexattr+0x41/0x60 [] path_removexattr+0x75/0xa0 [] SyS_lremovexattr+0xb/0x10 [] entry_SYSCALL_64_fastpath+0x13/0x94 [] 0xffffffffffffffff Signed-off-by: Luis Henriques Reviewed-by: "Yan, Zheng" Signed-off-by: Ilya Dryomov Signed-off-by: Greg Kroah-Hartman --- fs/ceph/xattr.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/fs/ceph/xattr.c b/fs/ceph/xattr.c index febc28f9e2c2..75267cdd5dfd 100644 --- a/fs/ceph/xattr.c +++ b/fs/ceph/xattr.c @@ -392,6 +392,7 @@ static int __set_xattr(struct ceph_inode_info *ci, if (update_xattr) { int err = 0; + if (xattr && (flags & XATTR_CREATE)) err = -EEXIST; else if (!xattr && (flags & XATTR_REPLACE)) @@ -399,12 +400,14 @@ static int __set_xattr(struct ceph_inode_info *ci, if (err) { kfree(name); kfree(val); + kfree(*newxattr); return err; } if (update_xattr < 0) { if (xattr) __remove_xattr(ci, xattr); kfree(name); + kfree(*newxattr); return 0; } } From 945d0ecdd9bddf87809525cbc202a1186a65be8c Mon Sep 17 00:00:00 2001 From: Andrey Ryabinin Date: Wed, 3 May 2017 14:56:02 -0700 Subject: [PATCH 162/396] fs/block_dev: always invalidate cleancache in invalidate_bdev() commit a5f6a6a9c72eac38a7fadd1a038532bc8516337c upstream. invalidate_bdev() calls cleancache_invalidate_inode() iff ->nrpages != 0 which doen't make any sense. Make sure that invalidate_bdev() always calls cleancache_invalidate_inode() regardless of mapping->nrpages value. Fixes: c515e1fd361c ("mm/fs: add hooks to support cleancache") Link: http://lkml.kernel.org/r/20170424164135.22350-3-aryabinin@virtuozzo.com Signed-off-by: Andrey Ryabinin Reviewed-by: Jan Kara Acked-by: Konrad Rzeszutek Wilk Cc: Alexander Viro Cc: Ross Zwisler Cc: Jens Axboe Cc: Johannes Weiner Cc: Alexey Kuznetsov Cc: Christoph Hellwig Cc: Nikolay Borisov Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- fs/block_dev.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/fs/block_dev.c b/fs/block_dev.c index 9ad527ff9974..2924bddb4a94 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c @@ -102,12 +102,11 @@ void invalidate_bdev(struct block_device *bdev) { struct address_space *mapping = bdev->bd_inode->i_mapping; - if (mapping->nrpages == 0) - return; - - invalidate_bh_lrus(); - lru_add_drain_all(); /* make sure all lru add caches are flushed */ - invalidate_mapping_pages(mapping, 0, -1); + if (mapping->nrpages) { + invalidate_bh_lrus(); + lru_add_drain_all(); /* make sure all lru add caches are flushed */ + invalidate_mapping_pages(mapping, 0, -1); + } /* 99% of the time, we don't need to flush the cleancache on the bdev. * But, for the strange corners, lets be cautious */ From 4e434d4fe28a40d437573f25c9326b230217f017 Mon Sep 17 00:00:00 2001 From: Vlastimil Babka Date: Mon, 8 May 2017 15:59:46 -0700 Subject: [PATCH 163/396] mm: prevent potential recursive reclaim due to clearing PF_MEMALLOC commit 62be1511b1db8066220b18b7d4da2e6b9fdc69fb upstream. Patch series "more robust PF_MEMALLOC handling" This series aims to unify the setting and clearing of PF_MEMALLOC, which prevents recursive reclaim. There are some places that clear the flag unconditionally from current->flags, which may result in clearing a pre-existing flag. This already resulted in a bug report that Patch 1 fixes (without the new helpers, to make backporting easier). Patch 2 introduces the new helpers, modelled after existing memalloc_noio_* and memalloc_nofs_* helpers, and converts mm core to use them. Patches 3 and 4 convert non-mm code. This patch (of 4): __alloc_pages_direct_compact() sets PF_MEMALLOC to prevent deadlock during page migration by lock_page() (see the comment in __unmap_and_move()). Then it unconditionally clears the flag, which can clear a pre-existing PF_MEMALLOC flag and result in recursive reclaim. This was not a problem until commit a8161d1ed609 ("mm, page_alloc: restructure direct compaction handling in slowpath"), because direct compation was called only after direct reclaim, which was skipped when PF_MEMALLOC flag was set. Even now it's only a theoretical issue, as the new callsite of __alloc_pages_direct_compact() is reached only for costly orders and when gfp_pfmemalloc_allowed() is true, which means either __GFP_NOMEMALLOC is in gfp_flags or in_interrupt() is true. There is no such known context, but let's play it safe and make __alloc_pages_direct_compact() robust for cases where PF_MEMALLOC is already set. Fixes: a8161d1ed609 ("mm, page_alloc: restructure direct compaction handling in slowpath") Link: http://lkml.kernel.org/r/20170405074700.29871-2-vbabka@suse.cz Signed-off-by: Vlastimil Babka Reported-by: Andrey Ryabinin Acked-by: Michal Hocko Acked-by: Hillf Danton Cc: Mel Gorman Cc: Johannes Weiner Cc: Boris Brezillon Cc: Chris Leech Cc: "David S. Miller" Cc: Eric Dumazet Cc: Josef Bacik Cc: Lee Duncan Cc: Michal Hocko Cc: Richard Weinberger Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- mm/page_alloc.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/mm/page_alloc.c b/mm/page_alloc.c index e5b159b88e39..5b06fb385dd7 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -3125,6 +3125,7 @@ __alloc_pages_direct_compact(gfp_t gfp_mask, unsigned int order, enum compact_priority prio, enum compact_result *compact_result) { struct page *page; + unsigned int noreclaim_flag = current->flags & PF_MEMALLOC; if (!order) return NULL; @@ -3132,7 +3133,7 @@ __alloc_pages_direct_compact(gfp_t gfp_mask, unsigned int order, current->flags |= PF_MEMALLOC; *compact_result = try_to_compact_pages(gfp_mask, order, alloc_flags, ac, prio); - current->flags &= ~PF_MEMALLOC; + current->flags = (current->flags & ~PF_MEMALLOC) | noreclaim_flag; if (*compact_result <= COMPACT_INACTIVE) return NULL; From 4f5e1c48e80b5be66a5078369f9dddf6e178b37e Mon Sep 17 00:00:00 2001 From: Sachin Prabhu Date: Wed, 26 Apr 2017 14:05:46 +0100 Subject: [PATCH 164/396] Fix match_prepath() commit cd8c42968ee651b69e00f8661caff32b0086e82d upstream. Incorrect return value for shares not using the prefix path means that we will never match superblocks for these shares. Fixes: commit c1d8b24d1819 ("Compare prepaths when comparing superblocks") Signed-off-by: Sachin Prabhu Reviewed-by: Pavel Shilovsky Signed-off-by: Steve French Signed-off-by: Greg Kroah-Hartman --- fs/cifs/connect.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index b8015de88e8c..1a545695f547 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -2839,16 +2839,14 @@ match_prepath(struct super_block *sb, struct cifs_mnt_data *mnt_data) { struct cifs_sb_info *old = CIFS_SB(sb); struct cifs_sb_info *new = mnt_data->cifs_sb; + bool old_set = old->mnt_cifs_flags & CIFS_MOUNT_USE_PREFIX_PATH; + bool new_set = new->mnt_cifs_flags & CIFS_MOUNT_USE_PREFIX_PATH; - if (old->mnt_cifs_flags & CIFS_MOUNT_USE_PREFIX_PATH) { - if (!(new->mnt_cifs_flags & CIFS_MOUNT_USE_PREFIX_PATH)) - return 0; - /* The prepath should be null terminated strings */ - if (strcmp(new->prepath, old->prepath)) - return 0; - + if (old_set && new_set && !strcmp(new->prepath, old->prepath)) return 1; - } + else if (!old_set && !new_set) + return 1; + return 0; } From 2ac2ad9fb04537160a35af7fefe8560f968ac896 Mon Sep 17 00:00:00 2001 From: Steve French Date: Tue, 2 May 2017 13:35:20 -0500 Subject: [PATCH 165/396] Set unicode flag on cifs echo request to avoid Mac error commit 26c9cb668c7fbf9830516b75d8bee70b699ed449 upstream. Mac requires the unicode flag to be set for cifs, even for the smb echo request (which doesn't have strings). Without this Mac rejects the periodic echo requests (when mounting with cifs) that we use to check if server is down Signed-off-by: Steve French Signed-off-by: Greg Kroah-Hartman --- fs/cifs/cifssmb.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index 586fdac05ec2..1f91c9dadd5b 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c @@ -717,6 +717,9 @@ CIFSSMBEcho(struct TCP_Server_Info *server) if (rc) return rc; + if (server->capabilities & CAP_UNICODE) + smb->hdr.Flags2 |= SMBFLG2_UNICODE; + /* set up echo request */ smb->hdr.Tid = 0xffff; smb->hdr.WordCount = 1; From 8dd4e3ff1bfb707c073e05df57ad0305a6ce7979 Mon Sep 17 00:00:00 2001 From: Steve French Date: Wed, 3 May 2017 21:12:20 -0500 Subject: [PATCH 166/396] SMB3: Work around mount failure when using SMB3 dialect to Macs commit 7db0a6efdc3e990cdfd4b24820d010e9eb7890ad upstream. Macs send the maximum buffer size in response on ioctl to validate negotiate security information, which causes us to fail the mount as the response buffer is larger than the expected response. Changed ioctl response processing to allow for padding of validate negotiate ioctl response and limit the maximum response size to maximum buffer size. Signed-off-by: Steve French Signed-off-by: Greg Kroah-Hartman --- fs/cifs/smb2pdu.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c index 802185386851..7c1c6c39d582 100644 --- a/fs/cifs/smb2pdu.c +++ b/fs/cifs/smb2pdu.c @@ -569,8 +569,12 @@ int smb3_validate_negotiate(const unsigned int xid, struct cifs_tcon *tcon) } if (rsplen != sizeof(struct validate_negotiate_info_rsp)) { - cifs_dbg(VFS, "invalid size of protocol negotiate response\n"); - return -EIO; + cifs_dbg(VFS, "invalid protocol negotiate response size: %d\n", + rsplen); + + /* relax check since Mac returns max bufsize allowed on ioctl */ + if (rsplen > CIFSMaxBufSize) + return -EIO; } /* check validate negotiate info response matches what we got earlier */ @@ -1670,8 +1674,12 @@ SMB2_ioctl(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid, * than one credit. Windows typically sets this smaller, but for some * ioctls it may be useful to allow server to send more. No point * limiting what the server can send as long as fits in one credit + * Unfortunately - we can not handle more than CIFS_MAX_MSG_SIZE + * (by default, note that it can be overridden to make max larger) + * in responses (except for read responses which can be bigger. + * We may want to bump this limit up */ - req->MaxOutputResponse = cpu_to_le32(0xFF00); /* < 64K uses 1 credit */ + req->MaxOutputResponse = cpu_to_le32(CIFSMaxBufSize); if (is_fsctl) req->Flags = cpu_to_le32(SMB2_0_IOCTL_IS_FSCTL); From 87c0604d860ffcef347510a798dbb5fe681a4b65 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Jacke?= Date: Wed, 3 May 2017 23:47:44 +0200 Subject: [PATCH 167/396] CIFS: fix mapping of SFM_SPACE and SFM_PERIOD commit b704e70b7cf48f9b67c07d585168e102dfa30bb4 upstream. - trailing space maps to 0xF028 - trailing period maps to 0xF029 This fix corrects the mapping of file names which have a trailing character that would otherwise be illegal (period or space) but is allowed by POSIX. Signed-off-by: Bjoern Jacke Signed-off-by: Steve French Signed-off-by: Greg Kroah-Hartman --- fs/cifs/cifs_unicode.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fs/cifs/cifs_unicode.h b/fs/cifs/cifs_unicode.h index 479bc0a941f3..a61b9166622c 100644 --- a/fs/cifs/cifs_unicode.h +++ b/fs/cifs/cifs_unicode.h @@ -64,8 +64,8 @@ #define SFM_LESSTHAN ((__u16) 0xF023) #define SFM_PIPE ((__u16) 0xF027) #define SFM_SLASH ((__u16) 0xF026) -#define SFM_PERIOD ((__u16) 0xF028) -#define SFM_SPACE ((__u16) 0xF029) +#define SFM_SPACE ((__u16) 0xF028) +#define SFM_PERIOD ((__u16) 0xF029) /* * Mapping mechanism to use when one of the seven reserved characters is From 449a74439d1525b43357be9da42b84fcdbd6b5a9 Mon Sep 17 00:00:00 2001 From: David Disseldorp Date: Wed, 3 May 2017 17:39:09 +0200 Subject: [PATCH 168/396] cifs: fix leak in FSCTL_ENUM_SNAPS response handling commit 0e5c795592930d51fd30d53a2e7b73cba022a29b upstream. The server may respond with success, and an output buffer less than sizeof(struct smb_snapshot_array) in length. Do not leak the output buffer in this case. Fixes: 834170c85978 ("Enable previous version support") Signed-off-by: David Disseldorp Signed-off-by: Steve French Signed-off-by: Greg Kroah-Hartman --- fs/cifs/smb2ops.c | 1 + 1 file changed, 1 insertion(+) diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c index 007abf7195af..36334fe3266c 100644 --- a/fs/cifs/smb2ops.c +++ b/fs/cifs/smb2ops.c @@ -924,6 +924,7 @@ smb3_enum_snapshots(const unsigned int xid, struct cifs_tcon *tcon, } if (snapshot_in.snapshot_array_size < sizeof(struct smb_snapshot_array)) { rc = -ERANGE; + kfree(retbuf); return rc; } From 411346640ccd04ea8571eb5871659b0bd33b007e Mon Sep 17 00:00:00 2001 From: David Disseldorp Date: Wed, 3 May 2017 17:39:08 +0200 Subject: [PATCH 169/396] cifs: fix CIFS_ENUMERATE_SNAPSHOTS oops commit 6026685de33b0db5b2b6b0e9b41b3a1a3261033c upstream. As with 618763958b22, an open directory may have a NULL private_data pointer prior to readdir. CIFS_ENUMERATE_SNAPSHOTS must check for this before dereference. Fixes: 834170c85978 ("Enable previous version support") Signed-off-by: David Disseldorp Signed-off-by: Steve French Signed-off-by: Greg Kroah-Hartman --- fs/cifs/ioctl.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/fs/cifs/ioctl.c b/fs/cifs/ioctl.c index 001528781b6b..b52b7ffa6d34 100644 --- a/fs/cifs/ioctl.c +++ b/fs/cifs/ioctl.c @@ -268,6 +268,8 @@ long cifs_ioctl(struct file *filep, unsigned int command, unsigned long arg) rc = smb_mnt_get_fsinfo(xid, tcon, (void __user *)arg); break; case CIFS_ENUMERATE_SNAPSHOTS: + if (pSMBFile == NULL) + break; if (arg == 0) { rc = -EINVAL; goto cifs_ioc_exit; From f13d96bf98c2ba94968bbaf207f2af02290a979a Mon Sep 17 00:00:00 2001 From: Rabin Vincent Date: Wed, 3 May 2017 17:54:01 +0200 Subject: [PATCH 170/396] CIFS: fix oplock break deadlocks commit 3998e6b87d4258a70df358296d6f1c7234012bfe upstream. When the final cifsFileInfo_put() is called from cifsiod and an oplock break work is queued, lockdep complains loudly: ============================================= [ INFO: possible recursive locking detected ] 4.11.0+ #21 Not tainted --------------------------------------------- kworker/0:2/78 is trying to acquire lock: ("cifsiod"){++++.+}, at: flush_work+0x215/0x350 but task is already holding lock: ("cifsiod"){++++.+}, at: process_one_work+0x255/0x8e0 other info that might help us debug this: Possible unsafe locking scenario: CPU0 ---- lock("cifsiod"); lock("cifsiod"); *** DEADLOCK *** May be due to missing lock nesting notation 2 locks held by kworker/0:2/78: #0: ("cifsiod"){++++.+}, at: process_one_work+0x255/0x8e0 #1: ((&wdata->work)){+.+...}, at: process_one_work+0x255/0x8e0 stack backtrace: CPU: 0 PID: 78 Comm: kworker/0:2 Not tainted 4.11.0+ #21 Workqueue: cifsiod cifs_writev_complete Call Trace: dump_stack+0x85/0xc2 __lock_acquire+0x17dd/0x2260 ? match_held_lock+0x20/0x2b0 ? trace_hardirqs_off_caller+0x86/0x130 ? mark_lock+0xa6/0x920 lock_acquire+0xcc/0x260 ? lock_acquire+0xcc/0x260 ? flush_work+0x215/0x350 flush_work+0x236/0x350 ? flush_work+0x215/0x350 ? destroy_worker+0x170/0x170 __cancel_work_timer+0x17d/0x210 ? ___preempt_schedule+0x16/0x18 cancel_work_sync+0x10/0x20 cifsFileInfo_put+0x338/0x7f0 cifs_writedata_release+0x2a/0x40 ? cifs_writedata_release+0x2a/0x40 cifs_writev_complete+0x29d/0x850 ? preempt_count_sub+0x18/0xd0 process_one_work+0x304/0x8e0 worker_thread+0x9b/0x6a0 kthread+0x1b2/0x200 ? process_one_work+0x8e0/0x8e0 ? kthread_create_on_node+0x40/0x40 ret_from_fork+0x31/0x40 This is a real warning. Since the oplock is queued on the same workqueue this can deadlock if there is only one worker thread active for the workqueue (which will be the case during memory pressure when the rescuer thread is handling it). Furthermore, there is at least one other kind of hang possible due to the oplock break handling if there is only worker. (This can be reproduced without introducing memory pressure by having passing 1 for the max_active parameter of cifsiod.) cifs_oplock_break() can wait indefintely in the filemap_fdatawait() while the cifs_writev_complete() work is blocked: sysrq: SysRq : Show Blocked State task PC stack pid father kworker/0:1 D 0 16 2 0x00000000 Workqueue: cifsiod cifs_oplock_break Call Trace: __schedule+0x562/0xf40 ? mark_held_locks+0x4a/0xb0 schedule+0x57/0xe0 io_schedule+0x21/0x50 wait_on_page_bit+0x143/0x190 ? add_to_page_cache_lru+0x150/0x150 __filemap_fdatawait_range+0x134/0x190 ? do_writepages+0x51/0x70 filemap_fdatawait_range+0x14/0x30 filemap_fdatawait+0x3b/0x40 cifs_oplock_break+0x651/0x710 ? preempt_count_sub+0x18/0xd0 process_one_work+0x304/0x8e0 worker_thread+0x9b/0x6a0 kthread+0x1b2/0x200 ? process_one_work+0x8e0/0x8e0 ? kthread_create_on_node+0x40/0x40 ret_from_fork+0x31/0x40 dd D 0 683 171 0x00000000 Call Trace: __schedule+0x562/0xf40 ? mark_held_locks+0x29/0xb0 schedule+0x57/0xe0 io_schedule+0x21/0x50 wait_on_page_bit+0x143/0x190 ? add_to_page_cache_lru+0x150/0x150 __filemap_fdatawait_range+0x134/0x190 ? do_writepages+0x51/0x70 filemap_fdatawait_range+0x14/0x30 filemap_fdatawait+0x3b/0x40 filemap_write_and_wait+0x4e/0x70 cifs_flush+0x6a/0xb0 filp_close+0x52/0xa0 __close_fd+0xdc/0x150 SyS_close+0x33/0x60 entry_SYSCALL_64_fastpath+0x1f/0xbe Showing all locks held in the system: 2 locks held by kworker/0:1/16: #0: ("cifsiod"){.+.+.+}, at: process_one_work+0x255/0x8e0 #1: ((&cfile->oplock_break)){+.+.+.}, at: process_one_work+0x255/0x8e0 Showing busy workqueues and worker pools: workqueue cifsiod: flags=0xc pwq 0: cpus=0 node=0 flags=0x0 nice=0 active=1/1 in-flight: 16:cifs_oplock_break delayed: cifs_writev_complete, cifs_echo_request pool 0: cpus=0 node=0 flags=0x0 nice=0 hung=0s workers=3 idle: 750 3 Fix these problems by creating a a new workqueue (with a rescuer) for the oplock break work. Signed-off-by: Rabin Vincent Signed-off-by: Steve French Signed-off-by: Greg Kroah-Hartman --- fs/cifs/cifsfs.c | 15 +++++++++++++-- fs/cifs/cifsglob.h | 1 + fs/cifs/misc.c | 2 +- fs/cifs/smb2misc.c | 5 +++-- 4 files changed, 18 insertions(+), 5 deletions(-) diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index 15261ba464c5..c0c253005b76 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c @@ -87,6 +87,7 @@ extern mempool_t *cifs_req_poolp; extern mempool_t *cifs_mid_poolp; struct workqueue_struct *cifsiod_wq; +struct workqueue_struct *cifsoplockd_wq; __u32 cifs_lock_secret; /* @@ -1283,9 +1284,16 @@ init_cifs(void) goto out_clean_proc; } + cifsoplockd_wq = alloc_workqueue("cifsoplockd", + WQ_FREEZABLE|WQ_MEM_RECLAIM, 0); + if (!cifsoplockd_wq) { + rc = -ENOMEM; + goto out_destroy_cifsiod_wq; + } + rc = cifs_fscache_register(); if (rc) - goto out_destroy_wq; + goto out_destroy_cifsoplockd_wq; rc = cifs_init_inodecache(); if (rc) @@ -1333,7 +1341,9 @@ out_destroy_inodecache: cifs_destroy_inodecache(); out_unreg_fscache: cifs_fscache_unregister(); -out_destroy_wq: +out_destroy_cifsoplockd_wq: + destroy_workqueue(cifsoplockd_wq); +out_destroy_cifsiod_wq: destroy_workqueue(cifsiod_wq); out_clean_proc: cifs_proc_clean(); @@ -1356,6 +1366,7 @@ exit_cifs(void) cifs_destroy_mids(); cifs_destroy_inodecache(); cifs_fscache_unregister(); + destroy_workqueue(cifsoplockd_wq); destroy_workqueue(cifsiod_wq); cifs_proc_clean(); } diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h index b3830f7ab260..48ef401c3c61 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h @@ -1651,6 +1651,7 @@ void cifs_oplock_break(struct work_struct *work); extern const struct slow_work_ops cifs_oplock_break_ops; extern struct workqueue_struct *cifsiod_wq; +extern struct workqueue_struct *cifsoplockd_wq; extern __u32 cifs_lock_secret; extern mempool_t *cifs_mid_poolp; diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c index c6729156f9a0..5419afea0a36 100644 --- a/fs/cifs/misc.c +++ b/fs/cifs/misc.c @@ -492,7 +492,7 @@ is_valid_oplock_break(char *buffer, struct TCP_Server_Info *srv) CIFS_INODE_DOWNGRADE_OPLOCK_TO_L2, &pCifsInode->flags); - queue_work(cifsiod_wq, + queue_work(cifsoplockd_wq, &netfile->oplock_break); netfile->oplock_break_cancelled = false; diff --git a/fs/cifs/smb2misc.c b/fs/cifs/smb2misc.c index 97307808ae42..967dfe656ced 100644 --- a/fs/cifs/smb2misc.c +++ b/fs/cifs/smb2misc.c @@ -494,7 +494,7 @@ smb2_tcon_has_lease(struct cifs_tcon *tcon, struct smb2_lease_break *rsp, else cfile->oplock_break_cancelled = true; - queue_work(cifsiod_wq, &cfile->oplock_break); + queue_work(cifsoplockd_wq, &cfile->oplock_break); kfree(lw); return true; } @@ -638,7 +638,8 @@ smb2_is_valid_oplock_break(char *buffer, struct TCP_Server_Info *server) CIFS_INODE_DOWNGRADE_OPLOCK_TO_L2, &cinode->flags); spin_unlock(&cfile->file_info_lock); - queue_work(cifsiod_wq, &cfile->oplock_break); + queue_work(cifsoplockd_wq, + &cfile->oplock_break); spin_unlock(&tcon->open_file_lock); spin_unlock(&cifs_tcp_ses_lock); From 6f3b2eed8c9ad3656c60295589c1a17709e456ca Mon Sep 17 00:00:00 2001 From: David Disseldorp Date: Thu, 4 May 2017 00:41:13 +0200 Subject: [PATCH 171/396] cifs: fix CIFS_IOC_GET_MNT_INFO oops commit d8a6e505d6bba2250852fbc1c1c86fe68aaf9af3 upstream. An open directory may have a NULL private_data pointer prior to readdir. Fixes: 0de1f4c6f6c0 ("Add way to query server fs info for smb3") Signed-off-by: David Disseldorp Signed-off-by: Steve French Signed-off-by: Greg Kroah-Hartman --- fs/cifs/ioctl.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/fs/cifs/ioctl.c b/fs/cifs/ioctl.c index b52b7ffa6d34..bdba9e7a9438 100644 --- a/fs/cifs/ioctl.c +++ b/fs/cifs/ioctl.c @@ -264,6 +264,8 @@ long cifs_ioctl(struct file *filep, unsigned int command, unsigned long arg) rc = -EOPNOTSUPP; break; case CIFS_IOC_GET_MNT_INFO: + if (pSMBFile == NULL) + break; tcon = tlink_tcon(pSMBFile->tlink); rc = smb_mnt_get_fsinfo(xid, tcon, (void __user *)arg); break; From 1c5d8b377e58ba7d56435b4e1e355aef7999ef75 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Jacke?= Date: Fri, 5 May 2017 04:36:16 +0200 Subject: [PATCH 172/396] CIFS: add misssing SFM mapping for doublequote commit 85435d7a15294f9f7ef23469e6aaf7c5dfcc54f0 upstream. SFM is mapping doublequote to 0xF020 Without this patch creating files with doublequote fails to Windows/Mac Signed-off-by: Bjoern Jacke Signed-off-by: Steve French Signed-off-by: Greg Kroah-Hartman --- fs/cifs/cifs_unicode.c | 6 ++++++ fs/cifs/cifs_unicode.h | 1 + 2 files changed, 7 insertions(+) diff --git a/fs/cifs/cifs_unicode.c b/fs/cifs/cifs_unicode.c index 02b071bf3732..a0b3e7d1be48 100644 --- a/fs/cifs/cifs_unicode.c +++ b/fs/cifs/cifs_unicode.c @@ -83,6 +83,9 @@ convert_sfm_char(const __u16 src_char, char *target) case SFM_COLON: *target = ':'; break; + case SFM_DOUBLEQUOTE: + *target = '"'; + break; case SFM_ASTERISK: *target = '*'; break; @@ -418,6 +421,9 @@ static __le16 convert_to_sfm_char(char src_char, bool end_of_string) case ':': dest_char = cpu_to_le16(SFM_COLON); break; + case '"': + dest_char = cpu_to_le16(SFM_DOUBLEQUOTE); + break; case '*': dest_char = cpu_to_le16(SFM_ASTERISK); break; diff --git a/fs/cifs/cifs_unicode.h b/fs/cifs/cifs_unicode.h index a61b9166622c..07ade707fa60 100644 --- a/fs/cifs/cifs_unicode.h +++ b/fs/cifs/cifs_unicode.h @@ -57,6 +57,7 @@ * not conflict (although almost does) with the mapping above. */ +#define SFM_DOUBLEQUOTE ((__u16) 0xF020) #define SFM_ASTERISK ((__u16) 0xF021) #define SFM_QUESTION ((__u16) 0xF025) #define SFM_COLON ((__u16) 0xF022) From 6240377c574b06c5ef900cab3be2625e482ae8bf Mon Sep 17 00:00:00 2001 From: "Jason A. Donenfeld" Date: Fri, 7 Apr 2017 02:33:30 +0200 Subject: [PATCH 173/396] padata: free correct variable commit 07a77929ba672d93642a56dc2255dd21e6e2290b upstream. The author meant to free the variable that was just allocated, instead of the one that failed to be allocated, but made a simple typo. This patch rectifies that. Signed-off-by: Jason A. Donenfeld Signed-off-by: Herbert Xu Signed-off-by: Greg Kroah-Hartman --- kernel/padata.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/padata.c b/kernel/padata.c index b4a3c0ae649b..e4a8f8d9b31a 100644 --- a/kernel/padata.c +++ b/kernel/padata.c @@ -358,7 +358,7 @@ static int padata_setup_cpumasks(struct parallel_data *pd, cpumask_and(pd->cpumask.pcpu, pcpumask, cpu_online_mask); if (!alloc_cpumask_var(&pd->cpumask.cbcpu, GFP_KERNEL)) { - free_cpumask_var(pd->cpumask.cbcpu); + free_cpumask_var(pd->cpumask.pcpu); return -ENOMEM; } From 8dd114ef78c855814558472ed13e99357e098e33 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Fri, 17 Mar 2017 12:48:09 -0600 Subject: [PATCH 174/396] device-dax: fix cdev leak commit ed01e50acdd3e4a640cf9ebd28a7e810c3ceca97 upstream. If device_add() fails, cleanup the cdev. Otherwise, we leak a kobj_map() with a stale device number. As Jason points out, there is a small possibility that userspace has opened and mapped the device in the time between cdev_add() and the device_add() failure. We need a new kill_dax_dev() helper to invalidate any established mappings. Fixes: ba09c01d2fa8 ("dax: convert to the cdev api") Reported-by: Jason Gunthorpe Signed-off-by: Dan Williams Signed-off-by: Logan Gunthorpe Reviewed-by: Johannes Thumshirn Signed-off-by: Greg Kroah-Hartman Signed-off-by: Greg Kroah-Hartman --- drivers/dax/dax.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/drivers/dax/dax.c b/drivers/dax/dax.c index 193224889e41..586f9543de73 100644 --- a/drivers/dax/dax.c +++ b/drivers/dax/dax.c @@ -553,13 +553,10 @@ static void dax_dev_release(struct device *dev) kfree(dax_dev); } -static void unregister_dax_dev(void *dev) +static void kill_dax_dev(struct dax_dev *dax_dev) { - struct dax_dev *dax_dev = to_dax_dev(dev); struct cdev *cdev = &dax_dev->cdev; - dev_dbg(dev, "%s\n", __func__); - /* * Note, rcu is not protecting the liveness of dax_dev, rcu is * ensuring that any fault handlers that might have seen @@ -571,6 +568,15 @@ static void unregister_dax_dev(void *dev) synchronize_srcu(&dax_srcu); unmap_mapping_range(dax_dev->inode->i_mapping, 0, 0, 1); cdev_del(cdev); +} + +static void unregister_dax_dev(void *dev) +{ + struct dax_dev *dax_dev = to_dax_dev(dev); + + dev_dbg(dev, "%s\n", __func__); + + kill_dax_dev(dax_dev); device_unregister(dev); } @@ -647,6 +653,7 @@ struct dax_dev *devm_create_dax_dev(struct dax_region *dax_region, dev_set_name(dev, "dax%d.%d", dax_region->id, dax_dev->id); rc = device_add(dev); if (rc) { + kill_dax_dev(dax_dev); put_device(dev); return ERR_PTR(rc); } From 64a599ac5dcca722e9bcec3fe1e42d9f1774f229 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Fri, 7 Apr 2017 10:58:37 -0700 Subject: [PATCH 175/396] fscrypt: fix context consistency check when key(s) unavailable commit 272f98f6846277378e1758a49a49d7bf39343c02 upstream. To mitigate some types of offline attacks, filesystem encryption is designed to enforce that all files in an encrypted directory tree use the same encryption policy (i.e. the same encryption context excluding the nonce). However, the fscrypt_has_permitted_context() function which enforces this relies on comparing struct fscrypt_info's, which are only available when we have the encryption keys. This can cause two incorrect behaviors: 1. If we have the parent directory's key but not the child's key, or vice versa, then fscrypt_has_permitted_context() returned false, causing applications to see EPERM or ENOKEY. This is incorrect if the encryption contexts are in fact consistent. Although we'd normally have either both keys or neither key in that case since the master_key_descriptors would be the same, this is not guaranteed because keys can be added or removed from keyrings at any time. 2. If we have neither the parent's key nor the child's key, then fscrypt_has_permitted_context() returned true, causing applications to see no error (or else an error for some other reason). This is incorrect if the encryption contexts are in fact inconsistent, since in that case we should deny access. To fix this, retrieve and compare the fscrypt_contexts if we are unable to set up both fscrypt_infos. While this slightly hurts performance when accessing an encrypted directory tree without the key, this isn't a case we really need to be optimizing for; access *with* the key is much more important. Furthermore, the performance hit is barely noticeable given that we are already retrieving the fscrypt_context and doing two keyring searches in fscrypt_get_encryption_info(). If we ever actually wanted to optimize this case we might start by caching the fscrypt_contexts. Signed-off-by: Eric Biggers Signed-off-by: Theodore Ts'o Signed-off-by: Greg Kroah-Hartman --- fs/crypto/policy.c | 87 ++++++++++++++++++++++++++++++++++++---------- 1 file changed, 68 insertions(+), 19 deletions(-) diff --git a/fs/crypto/policy.c b/fs/crypto/policy.c index abc18847b98d..bb4e209bd809 100644 --- a/fs/crypto/policy.c +++ b/fs/crypto/policy.c @@ -161,27 +161,61 @@ int fscrypt_get_policy(struct inode *inode, struct fscrypt_policy *policy) } EXPORT_SYMBOL(fscrypt_get_policy); +/** + * fscrypt_has_permitted_context() - is a file's encryption policy permitted + * within its directory? + * + * @parent: inode for parent directory + * @child: inode for file being looked up, opened, or linked into @parent + * + * Filesystems must call this before permitting access to an inode in a + * situation where the parent directory is encrypted (either before allowing + * ->lookup() to succeed, or for a regular file before allowing it to be opened) + * and before any operation that involves linking an inode into an encrypted + * directory, including link, rename, and cross rename. It enforces the + * constraint that within a given encrypted directory tree, all files use the + * same encryption policy. The pre-access check is needed to detect potentially + * malicious offline violations of this constraint, while the link and rename + * checks are needed to prevent online violations of this constraint. + * + * Return: 1 if permitted, 0 if forbidden. If forbidden, the caller must fail + * the filesystem operation with EPERM. + */ int fscrypt_has_permitted_context(struct inode *parent, struct inode *child) { - struct fscrypt_info *parent_ci, *child_ci; + const struct fscrypt_operations *cops = parent->i_sb->s_cop; + const struct fscrypt_info *parent_ci, *child_ci; + struct fscrypt_context parent_ctx, child_ctx; int res; - if ((parent == NULL) || (child == NULL)) { - printk(KERN_ERR "parent %p child %p\n", parent, child); - BUG_ON(1); - } - /* No restrictions on file types which are never encrypted */ if (!S_ISREG(child->i_mode) && !S_ISDIR(child->i_mode) && !S_ISLNK(child->i_mode)) return 1; - /* no restrictions if the parent directory is not encrypted */ - if (!parent->i_sb->s_cop->is_encrypted(parent)) + /* No restrictions if the parent directory is unencrypted */ + if (!cops->is_encrypted(parent)) return 1; - /* if the child directory is not encrypted, this is always a problem */ - if (!parent->i_sb->s_cop->is_encrypted(child)) + + /* Encrypted directories must not contain unencrypted files */ + if (!cops->is_encrypted(child)) return 0; + + /* + * Both parent and child are encrypted, so verify they use the same + * encryption policy. Compare the fscrypt_info structs if the keys are + * available, otherwise retrieve and compare the fscrypt_contexts. + * + * Note that the fscrypt_context retrieval will be required frequently + * when accessing an encrypted directory tree without the key. + * Performance-wise this is not a big deal because we already don't + * really optimize for file access without the key (to the extent that + * such access is even possible), given that any attempted access + * already causes a fscrypt_context retrieval and keyring search. + * + * In any case, if an unexpected error occurs, fall back to "forbidden". + */ + res = fscrypt_get_encryption_info(parent); if (res) return 0; @@ -190,17 +224,32 @@ int fscrypt_has_permitted_context(struct inode *parent, struct inode *child) return 0; parent_ci = parent->i_crypt_info; child_ci = child->i_crypt_info; - if (!parent_ci && !child_ci) - return 1; - if (!parent_ci || !child_ci) + + if (parent_ci && child_ci) { + return memcmp(parent_ci->ci_master_key, child_ci->ci_master_key, + FS_KEY_DESCRIPTOR_SIZE) == 0 && + (parent_ci->ci_data_mode == child_ci->ci_data_mode) && + (parent_ci->ci_filename_mode == + child_ci->ci_filename_mode) && + (parent_ci->ci_flags == child_ci->ci_flags); + } + + res = cops->get_context(parent, &parent_ctx, sizeof(parent_ctx)); + if (res != sizeof(parent_ctx)) return 0; - return (memcmp(parent_ci->ci_master_key, - child_ci->ci_master_key, - FS_KEY_DESCRIPTOR_SIZE) == 0 && - (parent_ci->ci_data_mode == child_ci->ci_data_mode) && - (parent_ci->ci_filename_mode == child_ci->ci_filename_mode) && - (parent_ci->ci_flags == child_ci->ci_flags)); + res = cops->get_context(child, &child_ctx, sizeof(child_ctx)); + if (res != sizeof(child_ctx)) + return 0; + + return memcmp(parent_ctx.master_key_descriptor, + child_ctx.master_key_descriptor, + FS_KEY_DESCRIPTOR_SIZE) == 0 && + (parent_ctx.contents_encryption_mode == + child_ctx.contents_encryption_mode) && + (parent_ctx.filenames_encryption_mode == + child_ctx.filenames_encryption_mode) && + (parent_ctx.flags == child_ctx.flags); } EXPORT_SYMBOL(fscrypt_has_permitted_context); From c5689e0ab6e18d4b8b01ffc00f36be5a8a70aa41 Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Mon, 3 Apr 2017 08:20:59 +0200 Subject: [PATCH 176/396] serial: samsung: Use right device for DMA-mapping calls commit 768d64f491a530062ddad50e016fb27125f8bd7c upstream. Driver should provide its own struct device for all DMA-mapping calls instead of extracting device pointer from DMA engine channel. Although this is harmless from the driver operation perspective on ARM architecture, it is always good to use the DMA mapping API in a proper way. This patch fixes following DMA API debug warning: WARNING: CPU: 0 PID: 0 at lib/dma-debug.c:1241 check_sync+0x520/0x9f4 samsung-uart 12c20000.serial: DMA-API: device driver tries to sync DMA memory it has not allocated [device address=0x000000006df0f580] [size=64 bytes] Modules linked in: CPU: 0 PID: 0 Comm: swapper/0 Not tainted 4.11.0-rc1-00137-g07ca963 #51 Hardware name: SAMSUNG EXYNOS (Flattened Device Tree) [] (unwind_backtrace) from [] (show_stack+0x20/0x24) [] (show_stack) from [] (dump_stack+0x84/0xa0) [] (dump_stack) from [] (__warn+0x14c/0x180) [] (__warn) from [] (warn_slowpath_fmt+0x48/0x50) [] (warn_slowpath_fmt) from [] (check_sync+0x520/0x9f4) [] (check_sync) from [] (debug_dma_sync_single_for_device+0x88/0xc8) [] (debug_dma_sync_single_for_device) from [] (s3c24xx_serial_start_tx_dma+0x100/0x2f8) [] (s3c24xx_serial_start_tx_dma) from [] (s3c24xx_serial_tx_chars+0x198/0x33c) Reported-by: Seung-Woo Kim Fixes: 62c37eedb74c8 ("serial: samsung: add dma reqest/release functions") Signed-off-by: Marek Szyprowski Reviewed-by: Bartlomiej Zolnierkiewicz Reviewed-by: Krzysztof Kozlowski Reviewed-by: Shuah Khan Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/samsung.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/drivers/tty/serial/samsung.c b/drivers/tty/serial/samsung.c index 3e2ef4fd7382..d65f92bcd0f1 100644 --- a/drivers/tty/serial/samsung.c +++ b/drivers/tty/serial/samsung.c @@ -906,14 +906,13 @@ static int s3c24xx_serial_request_dma(struct s3c24xx_uart_port *p) return -ENOMEM; } - dma->rx_addr = dma_map_single(dma->rx_chan->device->dev, dma->rx_buf, + dma->rx_addr = dma_map_single(p->port.dev, dma->rx_buf, dma->rx_size, DMA_FROM_DEVICE); spin_lock_irqsave(&p->port.lock, flags); /* TX buffer */ - dma->tx_addr = dma_map_single(dma->tx_chan->device->dev, - p->port.state->xmit.buf, + dma->tx_addr = dma_map_single(p->port.dev, p->port.state->xmit.buf, UART_XMIT_SIZE, DMA_TO_DEVICE); spin_unlock_irqrestore(&p->port.lock, flags); @@ -927,7 +926,7 @@ static void s3c24xx_serial_release_dma(struct s3c24xx_uart_port *p) if (dma->rx_chan) { dmaengine_terminate_all(dma->rx_chan); - dma_unmap_single(dma->rx_chan->device->dev, dma->rx_addr, + dma_unmap_single(p->port.dev, dma->rx_addr, dma->rx_size, DMA_FROM_DEVICE); kfree(dma->rx_buf); dma_release_channel(dma->rx_chan); @@ -936,7 +935,7 @@ static void s3c24xx_serial_release_dma(struct s3c24xx_uart_port *p) if (dma->tx_chan) { dmaengine_terminate_all(dma->tx_chan); - dma_unmap_single(dma->tx_chan->device->dev, dma->tx_addr, + dma_unmap_single(p->port.dev, dma->tx_addr, UART_XMIT_SIZE, DMA_TO_DEVICE); dma_release_channel(dma->tx_chan); dma->tx_chan = NULL; From f8d2751b0012367c757b43b8e07ab81c051aba5a Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Mon, 10 Apr 2017 11:21:38 +0200 Subject: [PATCH 177/396] serial: omap: fix runtime-pm handling on unbind commit 099bd73dc17ed77aa8c98323e043613b6e8f54fc upstream. An unbalanced and misplaced synchronous put was used to suspend the device on driver unbind, something which with a likewise misplaced pm_runtime_disable leads to external aborts when an open port is being removed. Unhandled fault: external abort on non-linefetch (0x1028) at 0xfa024010 ... [] (serial_omap_set_mctrl) from [] (uart_update_mctrl+0x50/0x60) [] (uart_update_mctrl) from [] (uart_shutdown+0xbc/0x138) [] (uart_shutdown) from [] (uart_hangup+0x94/0x190) [] (uart_hangup) from [] (__tty_hangup+0x404/0x41c) [] (__tty_hangup) from [] (tty_vhangup+0x1c/0x20) [] (tty_vhangup) from [] (uart_remove_one_port+0xec/0x260) [] (uart_remove_one_port) from [] (serial_omap_remove+0x40/0x60) [] (serial_omap_remove) from [] (platform_drv_remove+0x34/0x4c) Fix this up by resuming the device before deregistering the port and by suspending and disabling runtime pm only after the port has been removed. Also make sure to disable autosuspend before disabling runtime pm so that the usage count is balanced and device actually suspended before returning. Note that due to a negative autosuspend delay being set in probe, the unbalanced put would actually suspend the device on first driver unbind, while rebinding and again unbinding would result in a negative power.usage_count. Fixes: 7e9c8e7dbf3b ("serial: omap: make sure to suspend device before remove") Cc: Felipe Balbi Cc: Santosh Shilimkar Signed-off-by: Johan Hovold Acked-by: Tony Lindgren Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/omap-serial.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c index a2a529994ba5..d31f8af3aacf 100644 --- a/drivers/tty/serial/omap-serial.c +++ b/drivers/tty/serial/omap-serial.c @@ -1725,9 +1725,13 @@ static int serial_omap_remove(struct platform_device *dev) { struct uart_omap_port *up = platform_get_drvdata(dev); + pm_runtime_get_sync(up->dev); + + uart_remove_one_port(&serial_omap_reg, &up->port); + + pm_runtime_dont_use_autosuspend(up->dev); pm_runtime_put_sync(up->dev); pm_runtime_disable(up->dev); - uart_remove_one_port(&serial_omap_reg, &up->port); pm_qos_remove_request(&up->pm_qos_request); device_init_wakeup(&dev->dev, false); From e38a4c3b0b4a3df1abbe7ae9c175eed62286f963 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Mon, 10 Apr 2017 11:21:39 +0200 Subject: [PATCH 178/396] serial: omap: suspend device on probe errors commit 77e6fe7fd2b7cba0bf2f2dc8cde51d7b9a35bf74 upstream. Make sure to actually suspend the device before returning after a failed (or deferred) probe. Note that autosuspend must be disabled before runtime pm is disabled in order to balance the usage count due to a negative autosuspend delay as well as to make the final put suspend the device synchronously. Fixes: 388bc2622680 ("omap-serial: Fix the error handling in the omap_serial probe") Cc: Shubhrajyoti D Signed-off-by: Johan Hovold Acked-by: Tony Lindgren Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/omap-serial.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c index d31f8af3aacf..44e5b5bf713b 100644 --- a/drivers/tty/serial/omap-serial.c +++ b/drivers/tty/serial/omap-serial.c @@ -1712,7 +1712,8 @@ static int serial_omap_probe(struct platform_device *pdev) return 0; err_add_port: - pm_runtime_put(&pdev->dev); + pm_runtime_dont_use_autosuspend(&pdev->dev); + pm_runtime_put_sync(&pdev->dev); pm_runtime_disable(&pdev->dev); pm_qos_remove_request(&up->pm_qos_request); device_init_wakeup(up->dev, false); From 89c91ea375816c2a34c4035c7feb40db3f053ae9 Mon Sep 17 00:00:00 2001 From: Wang YanQing Date: Wed, 22 Feb 2017 19:37:08 +0800 Subject: [PATCH 179/396] tty: pty: Fix ldisc flush after userspace become aware of the data already commit 77dae6134440420bac334581a3ccee94cee1c054 upstream. While using emacs, cat or others' commands in konsole with recent kernels, I have met many times that CTRL-C freeze konsole. After konsole freeze I can't type anything, then I have to open a new one, it is very annoying. See bug report: https://bugs.kde.org/show_bug.cgi?id=175283 The platform in that bug report is Solaris, but now the pty in linux has the same problem or the same behavior as Solaris :) It has high possibility to trigger the problem follow steps below: Note: In my test, BigFile is a text file whose size is bigger than 1G 1:open konsole 1:cat BigFile 2:CTRL-C After some digging, I find out the reason is that commit 1d1d14da12e7 ("pty: Fix buffer flush deadlock") changes the behavior of pty_flush_buffer. Thread A Thread B -------- -------- 1:n_tty_poll return POLLIN 2:CTRL-C trigger pty_flush_buffer tty_buffer_flush n_tty_flush_buffer 3:attempt to check count of chars: ioctl(fd, TIOCINQ, &available) available is equal to 0 4:read(fd, buffer, avaiable) return 0 5:konsole close fd Yes, I know we could use the same patch included in the BUG report as a workaround for linux platform too. But I think the data in ldisc is belong to application of another side, we shouldn't clear it when we want to flush write buffer of this side in pty_flush_buffer. So I think it is better to disable ldisc flush in pty_flush_buffer, because its new hehavior bring no benefit except that it mess up the behavior between POLLIN, and TIOCINQ or FIONREAD. Also I find no flush_buffer function in others' tty driver has the same behavior as current pty_flush_buffer. Fixes: 1d1d14da12e7 ("pty: Fix buffer flush deadlock") Signed-off-by: Wang YanQing Signed-off-by: Greg Kroah-Hartman --- drivers/tty/pty.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/drivers/tty/pty.c b/drivers/tty/pty.c index a23fa5ed1d67..2b907385b4a8 100644 --- a/drivers/tty/pty.c +++ b/drivers/tty/pty.c @@ -216,16 +216,11 @@ static int pty_signal(struct tty_struct *tty, int sig) static void pty_flush_buffer(struct tty_struct *tty) { struct tty_struct *to = tty->link; - struct tty_ldisc *ld; if (!to) return; - ld = tty_ldisc_ref(to); - tty_buffer_flush(to, ld); - if (ld) - tty_ldisc_deref(ld); - + tty_buffer_flush(to, NULL); if (to->packet) { spin_lock_irq(&tty->ctrl_lock); tty->ctrl_status |= TIOCPKT_FLUSHWRITE; From 518ca84479d7b6a12e77327d1914d0de21f45b29 Mon Sep 17 00:00:00 2001 From: Szymon Janc Date: Mon, 24 Apr 2017 18:25:04 -0700 Subject: [PATCH 180/396] Bluetooth: Fix user channel for 32bit userspace on 64bit kernel commit ab89f0bdd63a3721f7cd3f064f39fc4ac7ca14d4 upstream. Running 32bit userspace on 64bit kernel results in MSG_CMSG_COMPAT being defined as 0x80000000. This results in sendmsg failure if used from 32bit userspace running on 64bit kernel. Fix this by accounting for MSG_CMSG_COMPAT in flags check in hci_sock_sendmsg. Signed-off-by: Szymon Janc Signed-off-by: Marko Kiiskila Signed-off-by: Marcel Holtmann Signed-off-by: Greg Kroah-Hartman --- net/bluetooth/hci_sock.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/bluetooth/hci_sock.c b/net/bluetooth/hci_sock.c index 48f9471e7c85..c88a6007e643 100644 --- a/net/bluetooth/hci_sock.c +++ b/net/bluetooth/hci_sock.c @@ -1680,7 +1680,8 @@ static int hci_sock_sendmsg(struct socket *sock, struct msghdr *msg, if (msg->msg_flags & MSG_OOB) return -EOPNOTSUPP; - if (msg->msg_flags & ~(MSG_DONTWAIT|MSG_NOSIGNAL|MSG_ERRQUEUE)) + if (msg->msg_flags & ~(MSG_DONTWAIT|MSG_NOSIGNAL|MSG_ERRQUEUE| + MSG_CMSG_COMPAT)) return -EINVAL; if (len < 4 || len > HCI_MAX_FRAME_SIZE) From f2f6d77fabe250965b3a5a097ccea7766db0a457 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 29 Mar 2017 18:15:27 +0200 Subject: [PATCH 181/396] Bluetooth: hci_bcm: add missing tty-device sanity check commit 95065a61e9bf25fb85295127fba893200c2bbbd8 upstream. Make sure to check the tty-device pointer before looking up the sibling platform device to avoid dereferencing a NULL-pointer when the tty is one end of a Unix98 pty. Fixes: 0395ffc1ee05 ("Bluetooth: hci_bcm: Add PM for BCM devices") Cc: Frederic Danis Signed-off-by: Johan Hovold Signed-off-by: Marcel Holtmann Signed-off-by: Greg Kroah-Hartman --- drivers/bluetooth/hci_bcm.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/bluetooth/hci_bcm.c b/drivers/bluetooth/hci_bcm.c index 8f6c23c20c52..deed58013555 100644 --- a/drivers/bluetooth/hci_bcm.c +++ b/drivers/bluetooth/hci_bcm.c @@ -287,6 +287,9 @@ static int bcm_open(struct hci_uart *hu) hu->priv = bcm; + if (!hu->tty->dev) + goto out; + mutex_lock(&bcm_device_lock); list_for_each(p, &bcm_device_list) { struct bcm_device *dev = list_entry(p, struct bcm_device, list); @@ -307,7 +310,7 @@ static int bcm_open(struct hci_uart *hu) } mutex_unlock(&bcm_device_lock); - +out: return 0; } From 6e7de39ef9a4fde0a9dd712e7cc4c923a76212ae Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 29 Mar 2017 18:15:28 +0200 Subject: [PATCH 182/396] Bluetooth: hci_intel: add missing tty-device sanity check commit dcb9cfaa5ea9aa0ec08aeb92582ccfe3e4c719a9 upstream. Make sure to check the tty-device pointer before looking up the sibling platform device to avoid dereferencing a NULL-pointer when the tty is one end of a Unix98 pty. Fixes: 74cdad37cd24 ("Bluetooth: hci_intel: Add runtime PM support") Fixes: 1ab1f239bf17 ("Bluetooth: hci_intel: Add support for platform driver") Cc: Loic Poulain Signed-off-by: Johan Hovold Signed-off-by: Marcel Holtmann Signed-off-by: Greg Kroah-Hartman --- drivers/bluetooth/hci_intel.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/drivers/bluetooth/hci_intel.c b/drivers/bluetooth/hci_intel.c index 9e271286c5e5..73306384af6c 100644 --- a/drivers/bluetooth/hci_intel.c +++ b/drivers/bluetooth/hci_intel.c @@ -307,6 +307,9 @@ static int intel_set_power(struct hci_uart *hu, bool powered) struct list_head *p; int err = -ENODEV; + if (!hu->tty->dev) + return err; + mutex_lock(&intel_device_list_lock); list_for_each(p, &intel_device_list) { @@ -379,6 +382,9 @@ static void intel_busy_work(struct work_struct *work) struct intel_data *intel = container_of(work, struct intel_data, busy_work); + if (!intel->hu->tty->dev) + return; + /* Link is busy, delay the suspend */ mutex_lock(&intel_device_list_lock); list_for_each(p, &intel_device_list) { @@ -889,6 +895,8 @@ done: list_for_each(p, &intel_device_list) { struct intel_device *dev = list_entry(p, struct intel_device, list); + if (!hu->tty->dev) + break; if (hu->tty->dev->parent == dev->pdev->dev.parent) { if (device_may_wakeup(&dev->pdev->dev)) { set_bit(STATE_LPM_ENABLED, &intel->flags); @@ -1056,6 +1064,9 @@ static int intel_enqueue(struct hci_uart *hu, struct sk_buff *skb) BT_DBG("hu %p skb %p", hu, skb); + if (!hu->tty->dev) + goto out_enqueue; + /* Be sure our controller is resumed and potential LPM transaction * completed before enqueuing any packet. */ @@ -1072,7 +1083,7 @@ static int intel_enqueue(struct hci_uart *hu, struct sk_buff *skb) } } mutex_unlock(&intel_device_list_lock); - +out_enqueue: skb_queue_tail(&intel->txq, skb); return 0; From 46ba11b007c1988cd12ac5f40224b4393689a86b Mon Sep 17 00:00:00 2001 From: Joeseph Chang Date: Mon, 27 Mar 2017 20:22:09 -0600 Subject: [PATCH 183/396] ipmi: Fix kernel panic at ipmi_ssif_thread() commit 6de65fcfdb51835789b245203d1bfc8d14cb1e06 upstream. msg_written_handler() may set ssif_info->multi_data to NULL when using ipmitool to write fru. Before setting ssif_info->multi_data to NULL, add new local pointer "data_to_send" and store correct i2c data pointer to it to fix NULL pointer kernel panic and incorrect ssif_info->multi_pos. Signed-off-by: Joeseph Chang Signed-off-by: Corey Minyard Signed-off-by: Greg Kroah-Hartman --- drivers/char/ipmi/ipmi_ssif.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/char/ipmi/ipmi_ssif.c b/drivers/char/ipmi/ipmi_ssif.c index 5673ffff00be..6958b5ce9145 100644 --- a/drivers/char/ipmi/ipmi_ssif.c +++ b/drivers/char/ipmi/ipmi_ssif.c @@ -892,6 +892,7 @@ static void msg_written_handler(struct ssif_info *ssif_info, int result, * for details on the intricacies of this. */ int left; + unsigned char *data_to_send; ssif_inc_stat(ssif_info, sent_messages_parts); @@ -900,6 +901,7 @@ static void msg_written_handler(struct ssif_info *ssif_info, int result, left = 32; /* Length byte. */ ssif_info->multi_data[ssif_info->multi_pos] = left; + data_to_send = ssif_info->multi_data + ssif_info->multi_pos; ssif_info->multi_pos += left; if (left < 32) /* @@ -913,7 +915,7 @@ static void msg_written_handler(struct ssif_info *ssif_info, int result, rv = ssif_i2c_send(ssif_info, msg_written_handler, I2C_SMBUS_WRITE, SSIF_IPMI_MULTI_PART_REQUEST_MIDDLE, - ssif_info->multi_data + ssif_info->multi_pos, + data_to_send, I2C_SMBUS_BLOCK_DATA); if (rv < 0) { /* request failed, just return the error. */ From 5b6e7f353290ca9b042090e0913caa71c2180d35 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Mon, 24 Apr 2017 15:43:05 -0700 Subject: [PATCH 184/396] libnvdimm, region: fix flush hint detection crash commit bc042fdfbb92b5b13421316b4548e2d6e98eed37 upstream. In the case where a dimm does not have any associated flush hints the ndrd->flush_wpq array may be uninitialized leading to crashes with the following signature: BUG: unable to handle kernel NULL pointer dereference at 0000000000000010 IP: region_visible+0x10f/0x160 [libnvdimm] Call Trace: internal_create_group+0xbe/0x2f0 sysfs_create_groups+0x40/0x80 device_add+0x2d8/0x650 nd_async_device_register+0x12/0x40 [libnvdimm] async_run_entry_fn+0x39/0x170 process_one_work+0x212/0x6c0 ? process_one_work+0x197/0x6c0 worker_thread+0x4e/0x4a0 kthread+0x10c/0x140 ? process_one_work+0x6c0/0x6c0 ? kthread_create_on_node+0x60/0x60 ret_from_fork+0x31/0x40 Reviewed-by: Jeff Moyer Fixes: f284a4f23752 ("libnvdimm: introduce nvdimm_flush() and nvdimm_has_flush()") Signed-off-by: Dan Williams Signed-off-by: Greg Kroah-Hartman --- drivers/nvdimm/region_devs.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/drivers/nvdimm/region_devs.c b/drivers/nvdimm/region_devs.c index 9cf6f1a88fce..f62306246ca4 100644 --- a/drivers/nvdimm/region_devs.c +++ b/drivers/nvdimm/region_devs.c @@ -968,17 +968,20 @@ EXPORT_SYMBOL_GPL(nvdimm_flush); */ int nvdimm_has_flush(struct nd_region *nd_region) { - struct nd_region_data *ndrd = dev_get_drvdata(&nd_region->dev); int i; /* no nvdimm == flushing capability unknown */ if (nd_region->ndr_mappings == 0) return -ENXIO; - for (i = 0; i < nd_region->ndr_mappings; i++) - /* flush hints present, flushing required */ - if (ndrd_get_flush_wpq(ndrd, i, 0)) + for (i = 0; i < nd_region->ndr_mappings; i++) { + struct nd_mapping *nd_mapping = &nd_region->mapping[i]; + struct nvdimm *nvdimm = nd_mapping->nvdimm; + + /* flush hints present / available */ + if (nvdimm->num_flush) return 1; + } /* * The platform defines dimm devices without hints, assume From c171b24fe508e0a3e9d2935f321b82541d0f09c0 Mon Sep 17 00:00:00 2001 From: Toshi Kani Date: Tue, 25 Apr 2017 17:04:13 -0600 Subject: [PATCH 185/396] libnvdimm, pmem: fix a NULL pointer BUG in nd_pmem_notify commit b2518c78ce76896f0f8f7940bf02104b227e1709 upstream. The following BUG was observed when nd_pmem_notify() was called for a BTT device. The use of a pmem_device pointer is not valid with BTT. BUG: unable to handle kernel NULL pointer dereference at 0000000000000030 IP: nd_pmem_notify+0x30/0xf0 [nd_pmem] Call Trace: nd_device_notify+0x40/0x50 child_notify+0x10/0x20 device_for_each_child+0x50/0x90 nd_region_notify+0x20/0x30 nd_device_notify+0x40/0x50 nvdimm_region_notify+0x27/0x30 acpi_nfit_scrub+0x341/0x590 [nfit] process_one_work+0x197/0x450 worker_thread+0x4e/0x4a0 kthread+0x109/0x140 Fix nd_pmem_notify() by setting nd_region and badblocks pointers properly for BTT. Cc: Vishal Verma Fixes: 719994660c24 ("libnvdimm: async notification support") Signed-off-by: Toshi Kani Signed-off-by: Dan Williams Signed-off-by: Greg Kroah-Hartman --- drivers/nvdimm/pmem.c | 37 +++++++++++++++++++++++++------------ 1 file changed, 25 insertions(+), 12 deletions(-) diff --git a/drivers/nvdimm/pmem.c b/drivers/nvdimm/pmem.c index 24618431a14b..b4808590870c 100644 --- a/drivers/nvdimm/pmem.c +++ b/drivers/nvdimm/pmem.c @@ -383,12 +383,12 @@ static void nd_pmem_shutdown(struct device *dev) static void nd_pmem_notify(struct device *dev, enum nvdimm_event event) { - struct pmem_device *pmem = dev_get_drvdata(dev); - struct nd_region *nd_region = to_region(pmem); + struct nd_region *nd_region; resource_size_t offset = 0, end_trunc = 0; struct nd_namespace_common *ndns; struct nd_namespace_io *nsio; struct resource res; + struct badblocks *bb; if (event != NVDIMM_REVALIDATE_POISON) return; @@ -397,20 +397,33 @@ static void nd_pmem_notify(struct device *dev, enum nvdimm_event event) struct nd_btt *nd_btt = to_nd_btt(dev); ndns = nd_btt->ndns; - } else if (is_nd_pfn(dev)) { - struct nd_pfn *nd_pfn = to_nd_pfn(dev); - struct nd_pfn_sb *pfn_sb = nd_pfn->pfn_sb; + nd_region = to_nd_region(ndns->dev.parent); + nsio = to_nd_namespace_io(&ndns->dev); + bb = &nsio->bb; + } else { + struct pmem_device *pmem = dev_get_drvdata(dev); - ndns = nd_pfn->ndns; - offset = pmem->data_offset + __le32_to_cpu(pfn_sb->start_pad); - end_trunc = __le32_to_cpu(pfn_sb->end_trunc); - } else - ndns = to_ndns(dev); + nd_region = to_region(pmem); + bb = &pmem->bb; + + if (is_nd_pfn(dev)) { + struct nd_pfn *nd_pfn = to_nd_pfn(dev); + struct nd_pfn_sb *pfn_sb = nd_pfn->pfn_sb; + + ndns = nd_pfn->ndns; + offset = pmem->data_offset + + __le32_to_cpu(pfn_sb->start_pad); + end_trunc = __le32_to_cpu(pfn_sb->end_trunc); + } else { + ndns = to_ndns(dev); + } + + nsio = to_nd_namespace_io(&ndns->dev); + } - nsio = to_nd_namespace_io(&ndns->dev); res.start = nsio->res.start + offset; res.end = nsio->res.end - end_trunc; - nvdimm_badblocks_populate(nd_region, &pmem->bb, &res); + nvdimm_badblocks_populate(nd_region, bb, &res); } MODULE_ALIAS("pmem"); From 1a1029507258719abe70770f4c6986c594bbffea Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Thu, 4 May 2017 19:54:42 -0700 Subject: [PATCH 186/396] libnvdimm, pfn: fix 'npfns' vs section alignment commit d5483feda85a8f39ee2e940e279547c686aac30c upstream. Fix failures to create namespaces due to the vmem_altmap not advertising enough free space to store the memmap. WARNING: CPU: 15 PID: 8022 at arch/x86/mm/init_64.c:656 arch_add_memory+0xde/0xf0 [..] Call Trace: dump_stack+0x63/0x83 __warn+0xcb/0xf0 warn_slowpath_null+0x1d/0x20 arch_add_memory+0xde/0xf0 devm_memremap_pages+0x244/0x440 pmem_attach_disk+0x37e/0x490 [nd_pmem] nd_pmem_probe+0x7e/0xa0 [nd_pmem] nvdimm_bus_probe+0x71/0x120 [libnvdimm] driver_probe_device+0x2bb/0x460 bind_store+0x114/0x160 drv_attr_store+0x25/0x30 In commit 658922e57b84 "libnvdimm, pfn: fix memmap reservation sizing" we arranged for the capacity to be allocated, but failed to also update the 'npfns' parameter. This leads to cases where there is enough capacity reserved to hold all the allocated sections, but vmemmap_populate_hugepages() still encounters -ENOMEM from altmap_alloc_block_buf(). This fix is a stop-gap until we can teach the core memory hotplug implementation to permit sub-section hotplug. Fixes: 658922e57b84 ("libnvdimm, pfn: fix memmap reservation sizing") Reported-by: Anisha Allada Signed-off-by: Dan Williams Signed-off-by: Greg Kroah-Hartman --- drivers/nvdimm/pfn_devs.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/nvdimm/pfn_devs.c b/drivers/nvdimm/pfn_devs.c index 6c033c9a2f06..78cb3e2359bd 100644 --- a/drivers/nvdimm/pfn_devs.c +++ b/drivers/nvdimm/pfn_devs.c @@ -538,7 +538,8 @@ static struct vmem_altmap *__nvdimm_setup_pfn(struct nd_pfn *nd_pfn, nd_pfn->npfns = le64_to_cpu(pfn_sb->npfns); altmap = NULL; } else if (nd_pfn->mode == PFN_MODE_PMEM) { - nd_pfn->npfns = (resource_size(res) - offset) / PAGE_SIZE; + nd_pfn->npfns = PFN_SECTION_ALIGN_UP((resource_size(res) + - offset) / PAGE_SIZE); if (le64_to_cpu(nd_pfn->pfn_sb->npfns) > nd_pfn->npfns) dev_info(&nd_pfn->dev, "number of pfns truncated from %lld to %ld\n", @@ -625,7 +626,8 @@ static int nd_pfn_init(struct nd_pfn *nd_pfn) */ start += start_pad; size = resource_size(&nsio->res); - npfns = (size - start_pad - end_trunc - SZ_8K) / SZ_4K; + npfns = PFN_SECTION_ALIGN_UP((size - start_pad - end_trunc - SZ_8K) + / PAGE_SIZE); if (nd_pfn->mode == PFN_MODE_PMEM) { /* * vmemmap_populate_hugepages() allocates the memmap array in From a4de9300862540cc9bb8ef9b665405bed79c28e7 Mon Sep 17 00:00:00 2001 From: Ankit Kumar Date: Thu, 27 Apr 2017 17:03:13 +0530 Subject: [PATCH 187/396] pstore: Fix flags to enable dumps on powerpc commit 041939c1ec54208b42f5cd819209173d52a29d34 upstream. After commit c950fd6f201a kernel registers pstore write based on flag set. Pstore write for powerpc is broken as flags(PSTORE_FLAGS_DMESG) is not set for powerpc architecture. On panic, kernel doesn't write message to /fs/pstore/dmesg*(Entry doesn't gets created at all). This patch enables pstore write for powerpc architecture by setting PSTORE_FLAGS_DMESG flag. Fixes: c950fd6f201a ("pstore: Split pstore fragile flags") Signed-off-by: Ankit Kumar Signed-off-by: Kees Cook Signed-off-by: Greg Kroah-Hartman --- arch/powerpc/kernel/nvram_64.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/powerpc/kernel/nvram_64.c b/arch/powerpc/kernel/nvram_64.c index 34d2c595de23..73622673eee3 100644 --- a/arch/powerpc/kernel/nvram_64.c +++ b/arch/powerpc/kernel/nvram_64.c @@ -561,6 +561,7 @@ static ssize_t nvram_pstore_read(u64 *id, enum pstore_type_id *type, static struct pstore_info nvram_pstore_info = { .owner = THIS_MODULE, .name = "nvram", + .flags = PSTORE_FLAGS_DMESG, .open = nvram_pstore_open, .read = nvram_pstore_read, .write = nvram_pstore_write, From 9ee8502bd2cc83b5c11e2f255ad233ed823d9909 Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Mon, 6 Mar 2017 12:42:12 -0800 Subject: [PATCH 188/396] pstore: Shut down worker when unregistering commit 6330d5534786d5315d56d558aa6d20740f97d80a upstream. When built as a module and running with update_ms >= 0, pstore will Oops during module unload since the work timer is still running. This makes sure the worker is stopped before unloading. Signed-off-by: Kees Cook Signed-off-by: Greg Kroah-Hartman --- fs/pstore/platform.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/fs/pstore/platform.c b/fs/pstore/platform.c index 14984d902a99..43033a3d66d5 100644 --- a/fs/pstore/platform.c +++ b/fs/pstore/platform.c @@ -704,6 +704,7 @@ int pstore_register(struct pstore_info *psi) if (psi->flags & PSTORE_FLAGS_PMSG) pstore_register_pmsg(); + /* Start watching for new records, if desired. */ if (pstore_update_ms >= 0) { pstore_timer.expires = jiffies + msecs_to_jiffies(pstore_update_ms); @@ -726,6 +727,11 @@ EXPORT_SYMBOL_GPL(pstore_register); void pstore_unregister(struct pstore_info *psi) { + /* Stop timer and make sure all work has finished. */ + pstore_update_ms = -1; + del_timer_sync(&pstore_timer); + flush_work(&pstore_work); + if (psi->flags & PSTORE_FLAGS_PMSG) pstore_unregister_pmsg(); if (psi->flags & PSTORE_FLAGS_FTRACE) @@ -825,7 +831,9 @@ static void pstore_timefunc(unsigned long dummy) schedule_work(&pstore_work); } - mod_timer(&pstore_timer, jiffies + msecs_to_jiffies(pstore_update_ms)); + if (pstore_update_ms >= 0) + mod_timer(&pstore_timer, + jiffies + msecs_to_jiffies(pstore_update_ms)); } module_param(backend, charp, 0444); From f5eea276d8de10a32e68721707ae8f2fdfaa0960 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sat, 20 May 2017 14:28:55 +0200 Subject: [PATCH 189/396] Linux 4.9.29 --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 9460a63087b8..c12e501a18b8 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ VERSION = 4 PATCHLEVEL = 9 -SUBLEVEL = 28 +SUBLEVEL = 29 EXTRAVERSION = NAME = Roaring Lionus From 760b55c0cab98e39d4520f58f1d62227cae88686 Mon Sep 17 00:00:00 2001 From: Daniel Mack Date: Wed, 23 Nov 2016 16:52:25 +0100 Subject: [PATCH 190/396] UPSTREAM: bpf: add new prog type for cgroup socket filtering Cherry-pick from commit 0e33661de493db325435d565a4a722120ae4cbf3 This program type is similar to BPF_PROG_TYPE_SOCKET_FILTER, except that it does not allow BPF_LD_[ABS|IND] instructions and hooks up the bpf_skb_load_bytes() helper. Programs of this type will be attached to cgroups for network filtering and accounting. Signed-off-by: Daniel Mack Acked-by: Alexei Starovoitov Signed-off-by: David S. Miller Bug: 30950746 Change-Id: I7b9e063d5d7a91da80917c6d353a60b877133752 --- include/uapi/linux/bpf.h | 9 +++++++++ net/core/filter.c | 23 +++++++++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h index f09c70b97eca..1f3e6f14e7c5 100644 --- a/include/uapi/linux/bpf.h +++ b/include/uapi/linux/bpf.h @@ -96,8 +96,17 @@ enum bpf_prog_type { BPF_PROG_TYPE_TRACEPOINT, BPF_PROG_TYPE_XDP, BPF_PROG_TYPE_PERF_EVENT, + BPF_PROG_TYPE_CGROUP_SKB, }; +enum bpf_attach_type { + BPF_CGROUP_INET_INGRESS, + BPF_CGROUP_INET_EGRESS, + __MAX_BPF_ATTACH_TYPE +}; + +#define MAX_BPF_ATTACH_TYPE __MAX_BPF_ATTACH_TYPE + #define BPF_PSEUDO_MAP_FD 1 /* flags for BPF_MAP_UPDATE_ELEM command */ diff --git a/net/core/filter.c b/net/core/filter.c index b391209838ef..689c83e225d0 100644 --- a/net/core/filter.c +++ b/net/core/filter.c @@ -2628,6 +2628,17 @@ xdp_func_proto(enum bpf_func_id func_id) } } +static const struct bpf_func_proto * +cg_skb_func_proto(enum bpf_func_id func_id) +{ + switch (func_id) { + case BPF_FUNC_skb_load_bytes: + return &bpf_skb_load_bytes_proto; + default: + return sk_filter_func_proto(func_id); + } +} + static bool __is_valid_access(int off, int size, enum bpf_access_type type) { if (off < 0 || off >= sizeof(struct __sk_buff)) @@ -2990,6 +3001,12 @@ static const struct bpf_verifier_ops xdp_ops = { .convert_ctx_access = xdp_convert_ctx_access, }; +static const struct bpf_verifier_ops cg_skb_ops = { + .get_func_proto = cg_skb_func_proto, + .is_valid_access = sk_filter_is_valid_access, + .convert_ctx_access = sk_filter_convert_ctx_access, +}; + static struct bpf_prog_type_list sk_filter_type __read_mostly = { .ops = &sk_filter_ops, .type = BPF_PROG_TYPE_SOCKET_FILTER, @@ -3010,12 +3027,18 @@ static struct bpf_prog_type_list xdp_type __read_mostly = { .type = BPF_PROG_TYPE_XDP, }; +static struct bpf_prog_type_list cg_skb_type __read_mostly = { + .ops = &cg_skb_ops, + .type = BPF_PROG_TYPE_CGROUP_SKB, +}; + static int __init register_sk_filter_ops(void) { bpf_register_prog_type(&sk_filter_type); bpf_register_prog_type(&sched_cls_type); bpf_register_prog_type(&sched_act_type); bpf_register_prog_type(&xdp_type); + bpf_register_prog_type(&cg_skb_type); return 0; } From f791c42b6371b5a6dadd4aa8f3f99b41e3b6fe8e Mon Sep 17 00:00:00 2001 From: Daniel Mack Date: Wed, 23 Nov 2016 16:52:26 +0100 Subject: [PATCH 191/396] UPSTREAM: cgroup: add support for eBPF programs Cherry-pick from commit 3007098494bec614fb55dee7bc0410bb7db5ad18 This patch adds two sets of eBPF program pointers to struct cgroup. One for such that are directly pinned to a cgroup, and one for such that are effective for it. To illustrate the logic behind that, assume the following example cgroup hierarchy. A - B - C \ D - E If only B has a program attached, it will be effective for B, C, D and E. If D then attaches a program itself, that will be effective for both D and E, and the program in B will only affect B and C. Only one program of a given type is effective for a cgroup. Attaching and detaching programs will be done through the bpf(2) syscall. For now, ingress and egress inet socket filtering are the only supported use-cases. Signed-off-by: Daniel Mack Acked-by: Alexei Starovoitov Signed-off-by: David S. Miller Bug: 30950746 Change-Id: I3df35d8d3b1261503f9b5bcd90b18c9358f1ac28 --- include/linux/bpf-cgroup.h | 79 +++++++++++++++++ include/linux/cgroup-defs.h | 4 + init/Kconfig | 12 +++ kernel/bpf/Makefile | 1 + kernel/bpf/cgroup.c | 167 ++++++++++++++++++++++++++++++++++++ kernel/cgroup.c | 18 ++++ 6 files changed, 281 insertions(+) create mode 100644 include/linux/bpf-cgroup.h create mode 100644 kernel/bpf/cgroup.c diff --git a/include/linux/bpf-cgroup.h b/include/linux/bpf-cgroup.h new file mode 100644 index 000000000000..ec80d0c0953e --- /dev/null +++ b/include/linux/bpf-cgroup.h @@ -0,0 +1,79 @@ +#ifndef _BPF_CGROUP_H +#define _BPF_CGROUP_H + +#include +#include +#include + +struct sock; +struct cgroup; +struct sk_buff; + +#ifdef CONFIG_CGROUP_BPF + +extern struct static_key_false cgroup_bpf_enabled_key; +#define cgroup_bpf_enabled static_branch_unlikely(&cgroup_bpf_enabled_key) + +struct cgroup_bpf { + /* + * Store two sets of bpf_prog pointers, one for programs that are + * pinned directly to this cgroup, and one for those that are effective + * when this cgroup is accessed. + */ + struct bpf_prog *prog[MAX_BPF_ATTACH_TYPE]; + struct bpf_prog *effective[MAX_BPF_ATTACH_TYPE]; +}; + +void cgroup_bpf_put(struct cgroup *cgrp); +void cgroup_bpf_inherit(struct cgroup *cgrp, struct cgroup *parent); + +void __cgroup_bpf_update(struct cgroup *cgrp, + struct cgroup *parent, + struct bpf_prog *prog, + enum bpf_attach_type type); + +/* Wrapper for __cgroup_bpf_update() protected by cgroup_mutex */ +void cgroup_bpf_update(struct cgroup *cgrp, + struct bpf_prog *prog, + enum bpf_attach_type type); + +int __cgroup_bpf_run_filter(struct sock *sk, + struct sk_buff *skb, + enum bpf_attach_type type); + +/* Wrappers for __cgroup_bpf_run_filter() guarded by cgroup_bpf_enabled. */ +#define BPF_CGROUP_RUN_PROG_INET_INGRESS(sk,skb) \ +({ \ + int __ret = 0; \ + if (cgroup_bpf_enabled) \ + __ret = __cgroup_bpf_run_filter(sk, skb, \ + BPF_CGROUP_INET_INGRESS); \ + \ + __ret; \ +}) + +#define BPF_CGROUP_RUN_PROG_INET_EGRESS(sk,skb) \ +({ \ + int __ret = 0; \ + if (cgroup_bpf_enabled && sk && sk == skb->sk) { \ + typeof(sk) __sk = sk_to_full_sk(sk); \ + if (sk_fullsock(__sk)) \ + __ret = __cgroup_bpf_run_filter(__sk, skb, \ + BPF_CGROUP_INET_EGRESS); \ + } \ + __ret; \ +}) + +#else + +struct cgroup_bpf {}; +static inline void cgroup_bpf_put(struct cgroup *cgrp) {} +static inline void cgroup_bpf_inherit(struct cgroup *cgrp, + struct cgroup *parent) {} + +#define BPF_CGROUP_RUN_PROG_INET_INGRESS(sk,skb) ({ 0; }) +#define BPF_CGROUP_RUN_PROG_INET_EGRESS(sk,skb) ({ 0; }) + +#endif /* CONFIG_CGROUP_BPF */ + +#endif /* _BPF_CGROUP_H */ diff --git a/include/linux/cgroup-defs.h b/include/linux/cgroup-defs.h index 5b17de62c962..861b4677fc5b 100644 --- a/include/linux/cgroup-defs.h +++ b/include/linux/cgroup-defs.h @@ -16,6 +16,7 @@ #include #include #include +#include #ifdef CONFIG_CGROUPS @@ -300,6 +301,9 @@ struct cgroup { /* used to schedule release agent */ struct work_struct release_agent_work; + /* used to store eBPF programs */ + struct cgroup_bpf bpf; + /* ids of the ancestors at each level including self */ int ancestor_ids[]; }; diff --git a/init/Kconfig b/init/Kconfig index 2e15b932aeea..8d60e294583c 100644 --- a/init/Kconfig +++ b/init/Kconfig @@ -1239,6 +1239,18 @@ config CGROUP_PERF Say N if unsure. +config CGROUP_BPF + bool "Support for eBPF programs attached to cgroups" + depends on BPF_SYSCALL && SOCK_CGROUP_DATA + help + Allow attaching eBPF programs to a cgroup using the bpf(2) + syscall command BPF_PROG_ATTACH. + + In which context these programs are accessed depends on the type + of attachment. For instance, programs that are attached using + BPF_CGROUP_INET_INGRESS will be executed on the ingress path of + inet sockets. + config CGROUP_DEBUG bool "Example controller" default n diff --git a/kernel/bpf/Makefile b/kernel/bpf/Makefile index eed911d091da..b22256b3893d 100644 --- a/kernel/bpf/Makefile +++ b/kernel/bpf/Makefile @@ -5,3 +5,4 @@ obj-$(CONFIG_BPF_SYSCALL) += hashtab.o arraymap.o percpu_freelist.o ifeq ($(CONFIG_PERF_EVENTS),y) obj-$(CONFIG_BPF_SYSCALL) += stackmap.o endif +obj-$(CONFIG_CGROUP_BPF) += cgroup.o diff --git a/kernel/bpf/cgroup.c b/kernel/bpf/cgroup.c new file mode 100644 index 000000000000..a0ab43f264b0 --- /dev/null +++ b/kernel/bpf/cgroup.c @@ -0,0 +1,167 @@ +/* + * Functions to manage eBPF programs attached to cgroups + * + * Copyright (c) 2016 Daniel Mack + * + * This file is subject to the terms and conditions of version 2 of the GNU + * General Public License. See the file COPYING in the main directory of the + * Linux distribution for more details. + */ + +#include +#include +#include +#include +#include +#include +#include + +DEFINE_STATIC_KEY_FALSE(cgroup_bpf_enabled_key); +EXPORT_SYMBOL(cgroup_bpf_enabled_key); + +/** + * cgroup_bpf_put() - put references of all bpf programs + * @cgrp: the cgroup to modify + */ +void cgroup_bpf_put(struct cgroup *cgrp) +{ + unsigned int type; + + for (type = 0; type < ARRAY_SIZE(cgrp->bpf.prog); type++) { + struct bpf_prog *prog = cgrp->bpf.prog[type]; + + if (prog) { + bpf_prog_put(prog); + static_branch_dec(&cgroup_bpf_enabled_key); + } + } +} + +/** + * cgroup_bpf_inherit() - inherit effective programs from parent + * @cgrp: the cgroup to modify + * @parent: the parent to inherit from + */ +void cgroup_bpf_inherit(struct cgroup *cgrp, struct cgroup *parent) +{ + unsigned int type; + + for (type = 0; type < ARRAY_SIZE(cgrp->bpf.effective); type++) { + struct bpf_prog *e; + + e = rcu_dereference_protected(parent->bpf.effective[type], + lockdep_is_held(&cgroup_mutex)); + rcu_assign_pointer(cgrp->bpf.effective[type], e); + } +} + +/** + * __cgroup_bpf_update() - Update the pinned program of a cgroup, and + * propagate the change to descendants + * @cgrp: The cgroup which descendants to traverse + * @parent: The parent of @cgrp, or %NULL if @cgrp is the root + * @prog: A new program to pin + * @type: Type of pinning operation (ingress/egress) + * + * Each cgroup has a set of two pointers for bpf programs; one for eBPF + * programs it owns, and which is effective for execution. + * + * If @prog is %NULL, this function attaches a new program to the cgroup and + * releases the one that is currently attached, if any. @prog is then made + * the effective program of type @type in that cgroup. + * + * If @prog is %NULL, the currently attached program of type @type is released, + * and the effective program of the parent cgroup (if any) is inherited to + * @cgrp. + * + * Then, the descendants of @cgrp are walked and the effective program for + * each of them is set to the effective program of @cgrp unless the + * descendant has its own program attached, in which case the subbranch is + * skipped. This ensures that delegated subcgroups with own programs are left + * untouched. + * + * Must be called with cgroup_mutex held. + */ +void __cgroup_bpf_update(struct cgroup *cgrp, + struct cgroup *parent, + struct bpf_prog *prog, + enum bpf_attach_type type) +{ + struct bpf_prog *old_prog, *effective; + struct cgroup_subsys_state *pos; + + old_prog = xchg(cgrp->bpf.prog + type, prog); + + effective = (!prog && parent) ? + rcu_dereference_protected(parent->bpf.effective[type], + lockdep_is_held(&cgroup_mutex)) : + prog; + + css_for_each_descendant_pre(pos, &cgrp->self) { + struct cgroup *desc = container_of(pos, struct cgroup, self); + + /* skip the subtree if the descendant has its own program */ + if (desc->bpf.prog[type] && desc != cgrp) + pos = css_rightmost_descendant(pos); + else + rcu_assign_pointer(desc->bpf.effective[type], + effective); + } + + if (prog) + static_branch_inc(&cgroup_bpf_enabled_key); + + if (old_prog) { + bpf_prog_put(old_prog); + static_branch_dec(&cgroup_bpf_enabled_key); + } +} + +/** + * __cgroup_bpf_run_filter() - Run a program for packet filtering + * @sk: The socken sending or receiving traffic + * @skb: The skb that is being sent or received + * @type: The type of program to be exectuted + * + * If no socket is passed, or the socket is not of type INET or INET6, + * this function does nothing and returns 0. + * + * The program type passed in via @type must be suitable for network + * filtering. No further check is performed to assert that. + * + * This function will return %-EPERM if any if an attached program was found + * and if it returned != 1 during execution. In all other cases, 0 is returned. + */ +int __cgroup_bpf_run_filter(struct sock *sk, + struct sk_buff *skb, + enum bpf_attach_type type) +{ + struct bpf_prog *prog; + struct cgroup *cgrp; + int ret = 0; + + if (!sk || !sk_fullsock(sk)) + return 0; + + if (sk->sk_family != AF_INET && + sk->sk_family != AF_INET6) + return 0; + + cgrp = sock_cgroup_ptr(&sk->sk_cgrp_data); + + rcu_read_lock(); + + prog = rcu_dereference(cgrp->bpf.effective[type]); + if (prog) { + unsigned int offset = skb->data - skb_network_header(skb); + + __skb_push(skb, offset); + ret = bpf_prog_run_save_cb(prog, skb) == 1 ? 0 : -EPERM; + __skb_pull(skb, offset); + } + + rcu_read_unlock(); + + return ret; +} +EXPORT_SYMBOL(__cgroup_bpf_run_filter); diff --git a/kernel/cgroup.c b/kernel/cgroup.c index 567244cb19a0..70e1f486a0b3 100644 --- a/kernel/cgroup.c +++ b/kernel/cgroup.c @@ -5076,6 +5076,8 @@ static void css_release_work_fn(struct work_struct *work) if (cgrp->kn) RCU_INIT_POINTER(*(void __rcu __force **)&cgrp->kn->priv, NULL); + + cgroup_bpf_put(cgrp); } mutex_unlock(&cgroup_mutex); @@ -5288,6 +5290,9 @@ static struct cgroup *cgroup_create(struct cgroup *parent) if (!cgroup_on_dfl(cgrp)) cgrp->subtree_control = cgroup_control(cgrp); + if (parent) + cgroup_bpf_inherit(cgrp, parent); + cgroup_propagate_control(cgrp); return cgrp; @@ -6494,6 +6499,19 @@ static __init int cgroup_namespaces_init(void) } subsys_initcall(cgroup_namespaces_init); +#ifdef CONFIG_CGROUP_BPF +void cgroup_bpf_update(struct cgroup *cgrp, + struct bpf_prog *prog, + enum bpf_attach_type type) +{ + struct cgroup *parent = cgroup_parent(cgrp); + + mutex_lock(&cgroup_mutex); + __cgroup_bpf_update(cgrp, parent, prog, type); + mutex_unlock(&cgroup_mutex); +} +#endif /* CONFIG_CGROUP_BPF */ + #ifdef CONFIG_CGROUP_DEBUG static struct cgroup_subsys_state * debug_css_alloc(struct cgroup_subsys_state *parent_css) From 00615dfcd2265fee47d857101801bc27c25656b9 Mon Sep 17 00:00:00 2001 From: Daniel Mack Date: Wed, 23 Nov 2016 16:52:27 +0100 Subject: [PATCH 192/396] UPSTREAM: bpf: add BPF_PROG_ATTACH and BPF_PROG_DETACH commands Cherry-pick from commit f4324551489e8781d838f941b7aee4208e52e8bf Extend the bpf(2) syscall by two new commands, BPF_PROG_ATTACH and BPF_PROG_DETACH which allow attaching and detaching eBPF programs to a target. On the API level, the target could be anything that has an fd in userspace, hence the name of the field in union bpf_attr is called 'target_fd'. When called with BPF_ATTACH_TYPE_CGROUP_INET_{E,IN}GRESS, the target is expected to be a valid file descriptor of a cgroup v2 directory which has the bpf controller enabled. These are the only use-cases implemented by this patch at this point, but more can be added. If a program of the given type already exists in the given cgroup, the program is swapped automically, so userspace does not have to drop an existing program first before installing a new one, which would otherwise leave a gap in which no program is attached. For more information on the propagation logic to subcgroups, please refer to the bpf cgroup controller implementation. The API is guarded by CAP_NET_ADMIN. Signed-off-by: Daniel Mack Acked-by: Alexei Starovoitov Signed-off-by: David S. Miller Bug: 30950746 Change-Id: Iab156859332166835d51e1e6f64e5cb8b81870f2 --- include/uapi/linux/bpf.h | 8 ++++ kernel/bpf/syscall.c | 81 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 89 insertions(+) diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h index 1f3e6f14e7c5..f31b655f93cf 100644 --- a/include/uapi/linux/bpf.h +++ b/include/uapi/linux/bpf.h @@ -73,6 +73,8 @@ enum bpf_cmd { BPF_PROG_LOAD, BPF_OBJ_PIN, BPF_OBJ_GET, + BPF_PROG_ATTACH, + BPF_PROG_DETACH, }; enum bpf_map_type { @@ -150,6 +152,12 @@ union bpf_attr { __aligned_u64 pathname; __u32 bpf_fd; }; + + struct { /* anonymous struct used by BPF_PROG_ATTACH/DETACH commands */ + __u32 target_fd; /* container object to attach to */ + __u32 attach_bpf_fd; /* eBPF program to attach */ + __u32 attach_type; + }; } __attribute__((aligned(8))); /* integer value in 'imm' field of BPF_CALL instruction selects which helper diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c index 237f3d6a7ddc..e13157fd4253 100644 --- a/kernel/bpf/syscall.c +++ b/kernel/bpf/syscall.c @@ -824,6 +824,77 @@ static int bpf_obj_get(const union bpf_attr *attr) return bpf_obj_get_user(u64_to_ptr(attr->pathname)); } +#ifdef CONFIG_CGROUP_BPF + +#define BPF_PROG_ATTACH_LAST_FIELD attach_type + +static int bpf_prog_attach(const union bpf_attr *attr) +{ + struct bpf_prog *prog; + struct cgroup *cgrp; + + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + + if (CHECK_ATTR(BPF_PROG_ATTACH)) + return -EINVAL; + + switch (attr->attach_type) { + case BPF_CGROUP_INET_INGRESS: + case BPF_CGROUP_INET_EGRESS: + prog = bpf_prog_get_type(attr->attach_bpf_fd, + BPF_PROG_TYPE_CGROUP_SKB); + if (IS_ERR(prog)) + return PTR_ERR(prog); + + cgrp = cgroup_get_from_fd(attr->target_fd); + if (IS_ERR(cgrp)) { + bpf_prog_put(prog); + return PTR_ERR(cgrp); + } + + cgroup_bpf_update(cgrp, prog, attr->attach_type); + cgroup_put(cgrp); + break; + + default: + return -EINVAL; + } + + return 0; +} + +#define BPF_PROG_DETACH_LAST_FIELD attach_type + +static int bpf_prog_detach(const union bpf_attr *attr) +{ + struct cgroup *cgrp; + + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + + if (CHECK_ATTR(BPF_PROG_DETACH)) + return -EINVAL; + + switch (attr->attach_type) { + case BPF_CGROUP_INET_INGRESS: + case BPF_CGROUP_INET_EGRESS: + cgrp = cgroup_get_from_fd(attr->target_fd); + if (IS_ERR(cgrp)) + return PTR_ERR(cgrp); + + cgroup_bpf_update(cgrp, NULL, attr->attach_type); + cgroup_put(cgrp); + break; + + default: + return -EINVAL; + } + + return 0; +} +#endif /* CONFIG_CGROUP_BPF */ + SYSCALL_DEFINE3(bpf, int, cmd, union bpf_attr __user *, uattr, unsigned int, size) { union bpf_attr attr = {}; @@ -890,6 +961,16 @@ SYSCALL_DEFINE3(bpf, int, cmd, union bpf_attr __user *, uattr, unsigned int, siz case BPF_OBJ_GET: err = bpf_obj_get(&attr); break; + +#ifdef CONFIG_CGROUP_BPF + case BPF_PROG_ATTACH: + err = bpf_prog_attach(&attr); + break; + case BPF_PROG_DETACH: + err = bpf_prog_detach(&attr); + break; +#endif + default: err = -EINVAL; break; From 719a297aa41c89f013425a5a4767e144d87383f8 Mon Sep 17 00:00:00 2001 From: Daniel Mack Date: Wed, 23 Nov 2016 16:52:28 +0100 Subject: [PATCH 193/396] UPSTREAM: net: filter: run cgroup eBPF ingress programs Cherry-pick from commit c11cd3a6ec3a817c6b71b00c559e25d855f7e5b4 If the cgroup associated with the receiving socket has an eBPF programs installed, run them from sk_filter_trim_cap(). eBPF programs used in this context are expected to either return 1 to let the packet pass, or != 1 to drop them. The programs have access to the skb through bpf_skb_load_bytes(), and the payload starts at the network headers (L3). Note that cgroup_bpf_run_filter() is stubbed out as static inline nop for !CONFIG_CGROUP_BPF, and is otherwise guarded by a static key if the feature is unused. Signed-off-by: Daniel Mack Acked-by: Alexei Starovoitov Signed-off-by: David S. Miller Bug: 30950746 Change-Id: I5f1bdb6f0fc5d8dbef4b71855d26d68d39367837 --- net/core/filter.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/net/core/filter.c b/net/core/filter.c index 689c83e225d0..9983c3fb2fa8 100644 --- a/net/core/filter.c +++ b/net/core/filter.c @@ -78,6 +78,10 @@ int sk_filter_trim_cap(struct sock *sk, struct sk_buff *skb, unsigned int cap) if (skb_pfmemalloc(skb) && !sock_flag(sk, SOCK_MEMALLOC)) return -ENOMEM; + err = BPF_CGROUP_RUN_PROG_INET_INGRESS(sk, skb); + if (err) + return err; + err = security_sock_rcv_skb(sk, skb); if (err) return err; From 9290d742365a559adb79b0e3c00e88fa82d858ab Mon Sep 17 00:00:00 2001 From: Daniel Mack Date: Wed, 23 Nov 2016 16:52:29 +0100 Subject: [PATCH 194/396] UPSTREAM: net: ipv4, ipv6: run cgroup eBPF egress programs Cherry-pick from commit 33b486793cb31311f3a91ae4fe4be5926e7677b0 If the cgroup associated with the receiving socket has an eBPF programs installed, run them from ip_output(), ip6_output() and ip_mc_output(). From mentioned functions we have two socket contexts as per 7026b1ddb6b8 ("netfilter: Pass socket pointer down through okfn()."). We explicitly need to use sk instead of skb->sk here, since otherwise the same program would run multiple times on egress when encap devices are involved, which is not desired in our case. eBPF programs used in this context are expected to either return 1 to let the packet pass, or != 1 to drop them. The programs have access to the skb through bpf_skb_load_bytes(), and the payload starts at the network headers (L3). Note that cgroup_bpf_run_filter() is stubbed out as static inline nop for !CONFIG_CGROUP_BPF, and is otherwise guarded by a static key if the feature is unused. Signed-off-by: Daniel Mack Acked-by: Alexei Starovoitov Signed-off-by: David S. Miller Bug: 30950746 Change-Id: Ib6928205f098548b7a69d0e6d878fc8ed0242e8e --- net/ipv4/ip_output.c | 26 ++++++++++++++++++++++++-- net/ipv6/ip6_output.c | 9 +++++++++ 2 files changed, 33 insertions(+), 2 deletions(-) diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c index 0bd3efe1be21..2c18bcf6420f 100644 --- a/net/ipv4/ip_output.c +++ b/net/ipv4/ip_output.c @@ -74,6 +74,7 @@ #include #include #include +#include #include #include #include @@ -287,6 +288,13 @@ static int ip_finish_output_gso(struct net *net, struct sock *sk, static int ip_finish_output(struct net *net, struct sock *sk, struct sk_buff *skb) { unsigned int mtu; + int ret; + + ret = BPF_CGROUP_RUN_PROG_INET_EGRESS(sk, skb); + if (ret) { + kfree_skb(skb); + return ret; + } #if defined(CONFIG_NETFILTER) && defined(CONFIG_XFRM) /* Policy lookup after SNAT yielded a new policy */ @@ -305,6 +313,20 @@ static int ip_finish_output(struct net *net, struct sock *sk, struct sk_buff *sk return ip_finish_output2(net, sk, skb); } +static int ip_mc_finish_output(struct net *net, struct sock *sk, + struct sk_buff *skb) +{ + int ret; + + ret = BPF_CGROUP_RUN_PROG_INET_EGRESS(sk, skb); + if (ret) { + kfree_skb(skb); + return ret; + } + + return dev_loopback_xmit(net, sk, skb); +} + int ip_mc_output(struct net *net, struct sock *sk, struct sk_buff *skb) { struct rtable *rt = skb_rtable(skb); @@ -342,7 +364,7 @@ int ip_mc_output(struct net *net, struct sock *sk, struct sk_buff *skb) if (newskb) NF_HOOK(NFPROTO_IPV4, NF_INET_POST_ROUTING, net, sk, newskb, NULL, newskb->dev, - dev_loopback_xmit); + ip_mc_finish_output); } /* Multicasts with ttl 0 must not go beyond the host */ @@ -358,7 +380,7 @@ int ip_mc_output(struct net *net, struct sock *sk, struct sk_buff *skb) if (newskb) NF_HOOK(NFPROTO_IPV4, NF_INET_POST_ROUTING, net, sk, newskb, NULL, newskb->dev, - dev_loopback_xmit); + ip_mc_finish_output); } return NF_HOOK_COND(NFPROTO_IPV4, NF_INET_POST_ROUTING, diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index e27b8fdba5d2..a2158022e260 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c @@ -39,6 +39,7 @@ #include #include +#include #include #include @@ -131,6 +132,14 @@ static int ip6_finish_output2(struct net *net, struct sock *sk, struct sk_buff * static int ip6_finish_output(struct net *net, struct sock *sk, struct sk_buff *skb) { + int ret; + + ret = BPF_CGROUP_RUN_PROG_INET_EGRESS(sk, skb); + if (ret) { + kfree_skb(skb); + return ret; + } + if ((skb->len > ip6_skb_dst_mtu(skb) && !skb_is_gso(skb)) || dst_allfrag(skb_dst(skb)) || (IP6CB(skb)->frag_max_size && skb->len > IP6CB(skb)->frag_max_size)) From c00662a5879a2cf9413079dfbcbc2ee7f62ea2a8 Mon Sep 17 00:00:00 2001 From: Daniel Mack Date: Wed, 23 Nov 2016 16:52:30 +0100 Subject: [PATCH 195/396] UPSTREAM: samples: bpf: add userspace example for attaching eBPF programs to cgroups Cherry-pick from commit d8c5b17f2bc0de09fbbfa14d90e8168163a579e7 Add a simple userpace program to demonstrate the new API to attach eBPF programs to cgroups. This is what it does: * Create arraymap in kernel with 4 byte keys and 8 byte values * Load eBPF program The eBPF program accesses the map passed in to store two pieces of information. The number of invocations of the program, which maps to the number of packets received, is stored to key 0. Key 1 is incremented on each iteration by the number of bytes stored in the skb. * Detach any eBPF program previously attached to the cgroup * Attach the new program to the cgroup using BPF_PROG_ATTACH * Once a second, read map[0] and map[1] to see how many bytes and packets were seen on any socket of tasks in the given cgroup. The program takes a cgroup path as 1st argument, and either "ingress" or "egress" as 2nd. Optionally, "drop" can be passed as 3rd argument, which will make the generated eBPF program return 0 instead of 1, so the kernel will drop the packet. libbpf gained two new wrappers for the new syscall commands. Signed-off-by: Daniel Mack Acked-by: Alexei Starovoitov Signed-off-by: David S. Miller Bug: 30950746 Change-Id: I011436a755abd62050edd22e47995c166a0bd8a2 --- samples/bpf/Makefile | 2 + samples/bpf/libbpf.c | 21 +++++ samples/bpf/libbpf.h | 3 + samples/bpf/test_cgrp2_attach.c | 147 ++++++++++++++++++++++++++++++++ 4 files changed, 173 insertions(+) create mode 100644 samples/bpf/test_cgrp2_attach.c diff --git a/samples/bpf/Makefile b/samples/bpf/Makefile index 72c58675973e..b2cdced61090 100644 --- a/samples/bpf/Makefile +++ b/samples/bpf/Makefile @@ -22,6 +22,7 @@ hostprogs-y += spintest hostprogs-y += map_perf_test hostprogs-y += test_overhead hostprogs-y += test_cgrp2_array_pin +hostprogs-y += test_cgrp2_attach hostprogs-y += xdp1 hostprogs-y += xdp2 hostprogs-y += test_current_task_under_cgroup @@ -50,6 +51,7 @@ spintest-objs := bpf_load.o libbpf.o spintest_user.o map_perf_test-objs := bpf_load.o libbpf.o map_perf_test_user.o test_overhead-objs := bpf_load.o libbpf.o test_overhead_user.o test_cgrp2_array_pin-objs := libbpf.o test_cgrp2_array_pin.o +test_cgrp2_attach-objs := libbpf.o test_cgrp2_attach.o xdp1-objs := bpf_load.o libbpf.o xdp1_user.o # reuse xdp1 source intentionally xdp2-objs := bpf_load.o libbpf.o xdp1_user.o diff --git a/samples/bpf/libbpf.c b/samples/bpf/libbpf.c index 9969e35550c3..9ce707bf02a7 100644 --- a/samples/bpf/libbpf.c +++ b/samples/bpf/libbpf.c @@ -104,6 +104,27 @@ int bpf_prog_load(enum bpf_prog_type prog_type, return syscall(__NR_bpf, BPF_PROG_LOAD, &attr, sizeof(attr)); } +int bpf_prog_attach(int prog_fd, int target_fd, enum bpf_attach_type type) +{ + union bpf_attr attr = { + .target_fd = target_fd, + .attach_bpf_fd = prog_fd, + .attach_type = type, + }; + + return syscall(__NR_bpf, BPF_PROG_ATTACH, &attr, sizeof(attr)); +} + +int bpf_prog_detach(int target_fd, enum bpf_attach_type type) +{ + union bpf_attr attr = { + .target_fd = target_fd, + .attach_type = type, + }; + + return syscall(__NR_bpf, BPF_PROG_DETACH, &attr, sizeof(attr)); +} + int bpf_obj_pin(int fd, const char *pathname) { union bpf_attr attr = { diff --git a/samples/bpf/libbpf.h b/samples/bpf/libbpf.h index ac6edb61b64a..d0a799a52eaf 100644 --- a/samples/bpf/libbpf.h +++ b/samples/bpf/libbpf.h @@ -15,6 +15,9 @@ int bpf_prog_load(enum bpf_prog_type prog_type, const struct bpf_insn *insns, int insn_len, const char *license, int kern_version); +int bpf_prog_attach(int prog_fd, int attachable_fd, enum bpf_attach_type type); +int bpf_prog_detach(int attachable_fd, enum bpf_attach_type type); + int bpf_obj_pin(int fd, const char *pathname); int bpf_obj_get(const char *pathname); diff --git a/samples/bpf/test_cgrp2_attach.c b/samples/bpf/test_cgrp2_attach.c new file mode 100644 index 000000000000..63ef2083f766 --- /dev/null +++ b/samples/bpf/test_cgrp2_attach.c @@ -0,0 +1,147 @@ +/* eBPF example program: + * + * - Creates arraymap in kernel with 4 bytes keys and 8 byte values + * + * - Loads eBPF program + * + * The eBPF program accesses the map passed in to store two pieces of + * information. The number of invocations of the program, which maps + * to the number of packets received, is stored to key 0. Key 1 is + * incremented on each iteration by the number of bytes stored in + * the skb. + * + * - Detaches any eBPF program previously attached to the cgroup + * + * - Attaches the new program to a cgroup using BPF_PROG_ATTACH + * + * - Every second, reads map[0] and map[1] to see how many bytes and + * packets were seen on any socket of tasks in the given cgroup. + */ + +#define _GNU_SOURCE + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "libbpf.h" + +enum { + MAP_KEY_PACKETS, + MAP_KEY_BYTES, +}; + +static int prog_load(int map_fd, int verdict) +{ + struct bpf_insn prog[] = { + BPF_MOV64_REG(BPF_REG_6, BPF_REG_1), /* save r6 so it's not clobbered by BPF_CALL */ + + /* Count packets */ + BPF_MOV64_IMM(BPF_REG_0, MAP_KEY_PACKETS), /* r0 = 0 */ + BPF_STX_MEM(BPF_W, BPF_REG_10, BPF_REG_0, -4), /* *(u32 *)(fp - 4) = r0 */ + BPF_MOV64_REG(BPF_REG_2, BPF_REG_10), + BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -4), /* r2 = fp - 4 */ + BPF_LD_MAP_FD(BPF_REG_1, map_fd), /* load map fd to r1 */ + BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem), + BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 2), + BPF_MOV64_IMM(BPF_REG_1, 1), /* r1 = 1 */ + BPF_RAW_INSN(BPF_STX | BPF_XADD | BPF_DW, BPF_REG_0, BPF_REG_1, 0, 0), /* xadd r0 += r1 */ + + /* Count bytes */ + BPF_MOV64_IMM(BPF_REG_0, MAP_KEY_BYTES), /* r0 = 1 */ + BPF_STX_MEM(BPF_W, BPF_REG_10, BPF_REG_0, -4), /* *(u32 *)(fp - 4) = r0 */ + BPF_MOV64_REG(BPF_REG_2, BPF_REG_10), + BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -4), /* r2 = fp - 4 */ + BPF_LD_MAP_FD(BPF_REG_1, map_fd), + BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem), + BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 2), + BPF_LDX_MEM(BPF_W, BPF_REG_1, BPF_REG_6, offsetof(struct __sk_buff, len)), /* r1 = skb->len */ + BPF_RAW_INSN(BPF_STX | BPF_XADD | BPF_DW, BPF_REG_0, BPF_REG_1, 0, 0), /* xadd r0 += r1 */ + + BPF_MOV64_IMM(BPF_REG_0, verdict), /* r0 = verdict */ + BPF_EXIT_INSN(), + }; + + return bpf_prog_load(BPF_PROG_TYPE_CGROUP_SKB, + prog, sizeof(prog), "GPL", 0); +} + +static int usage(const char *argv0) +{ + printf("Usage: %s [drop]\n", argv0); + return EXIT_FAILURE; +} + +int main(int argc, char **argv) +{ + int cg_fd, map_fd, prog_fd, key, ret; + long long pkt_cnt, byte_cnt; + enum bpf_attach_type type; + int verdict = 1; + + if (argc < 3) + return usage(argv[0]); + + if (strcmp(argv[2], "ingress") == 0) + type = BPF_CGROUP_INET_INGRESS; + else if (strcmp(argv[2], "egress") == 0) + type = BPF_CGROUP_INET_EGRESS; + else + return usage(argv[0]); + + if (argc > 3 && strcmp(argv[3], "drop") == 0) + verdict = 0; + + cg_fd = open(argv[1], O_DIRECTORY | O_RDONLY); + if (cg_fd < 0) { + printf("Failed to open cgroup path: '%s'\n", strerror(errno)); + return EXIT_FAILURE; + } + + map_fd = bpf_create_map(BPF_MAP_TYPE_ARRAY, + sizeof(key), sizeof(byte_cnt), + 256, 0); + if (map_fd < 0) { + printf("Failed to create map: '%s'\n", strerror(errno)); + return EXIT_FAILURE; + } + + prog_fd = prog_load(map_fd, verdict); + printf("Output from kernel verifier:\n%s\n-------\n", bpf_log_buf); + + if (prog_fd < 0) { + printf("Failed to load prog: '%s'\n", strerror(errno)); + return EXIT_FAILURE; + } + + ret = bpf_prog_detach(cg_fd, type); + printf("bpf_prog_detach() returned '%s' (%d)\n", strerror(errno), errno); + + ret = bpf_prog_attach(prog_fd, cg_fd, type); + if (ret < 0) { + printf("Failed to attach prog to cgroup: '%s'\n", + strerror(errno)); + return EXIT_FAILURE; + } + + while (1) { + key = MAP_KEY_PACKETS; + assert(bpf_lookup_elem(map_fd, &key, &pkt_cnt) == 0); + + key = MAP_KEY_BYTES; + assert(bpf_lookup_elem(map_fd, &key, &byte_cnt) == 0); + + printf("cgroup received %lld packets, %lld bytes\n", + pkt_cnt, byte_cnt); + sleep(1); + } + + return EXIT_SUCCESS; +} From cde30d1a2b30db834f80b6c7812e1ec53fc52ffc Mon Sep 17 00:00:00 2001 From: Andy Lutomirski Date: Fri, 16 Dec 2016 08:33:45 -0800 Subject: [PATCH 196/396] UPSTREAM: cgroup: Fix CGROUP_BPF config Cherry-pick from commit 483c4933ea09b7aa625b9d64af286fc22ec7e419 CGROUP_BPF depended on SOCK_CGROUP_DATA which can't be manually enabled, making it rather challenging to turn CGROUP_BPF on. Signed-off-by: Andy Lutomirski Acked-by: Alexei Starovoitov Signed-off-by: David S. Miller Bug: 30950746 Change-Id: Ib41ef78fba02eb9e592558ddbf06f9ec0aa337b6 --- init/Kconfig | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/init/Kconfig b/init/Kconfig index 8d60e294583c..95270dd0a35c 100644 --- a/init/Kconfig +++ b/init/Kconfig @@ -1241,7 +1241,8 @@ config CGROUP_PERF config CGROUP_BPF bool "Support for eBPF programs attached to cgroups" - depends on BPF_SYSCALL && SOCK_CGROUP_DATA + depends on BPF_SYSCALL + select SOCK_CGROUP_DATA help Allow attaching eBPF programs to a cgroup using the bpf(2) syscall command BPF_PROG_ATTACH. From 0aa0151c730ad95cf6d5d6bcbd21d5f11079e51d Mon Sep 17 00:00:00 2001 From: Chenbo Feng Date: Wed, 3 May 2017 15:22:42 -0700 Subject: [PATCH 197/396] ANDROID: Fix missing uapi headers Update the missing bpf helper function name in bpf_func_id to keep the uapi header consistent with upstream uapi header because we need the new added bpf helper function bpf get_socket_cookie and get_socket_uid. The patch related to those headers are not backetported since they are not related and backport them will bring in extra confilict. Signed-off-by: Chenbo Feng Bug: 30950746 Change-Id: I2b5fd03799ac5f2e3243ab11a1bccb932f06c312 --- include/uapi/linux/bpf.h | 43 ++++++++++++++++++ tools/include/uapi/linux/bpf.h | 81 ++++++++++++++++++++++++++++++++++ 2 files changed, 124 insertions(+) diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h index f31b655f93cf..16b4ae0f3e0b 100644 --- a/include/uapi/linux/bpf.h +++ b/include/uapi/linux/bpf.h @@ -443,6 +443,49 @@ enum bpf_func_id { */ BPF_FUNC_set_hash_invalid, + /** + * int bpf_get_numa_node_id() + * Return: Id of current NUMA node. + */ + BPF_FUNC_get_numa_node_id, + + /** + * int bpf_skb_change_head() + * Grows headroom of skb and adjusts MAC header offset accordingly. + * Will extends/reallocae as required automatically. + * May change skb data pointer and will thus invalidate any check + * performed for direct packet access. + * @skb: pointer to skb + * @len: length of header to be pushed in front + * @flags: Flags (unused for now) + * Return: 0 on success or negative error + */ + BPF_FUNC_skb_change_head, + + /** + * int bpf_xdp_adjust_head(xdp_md, delta) + * Adjust the xdp_md.data by delta + * @xdp_md: pointer to xdp_md + * @delta: An positive/negative integer to be added to xdp_md.data + * Return: 0 on success or negative on error + */ + BPF_FUNC_xdp_adjust_head, + + /** + * int bpf_probe_read_str(void *dst, int size, const void *unsafe_ptr) + * Copy a NUL terminated string from unsafe address. In case the string + * length is smaller than size, the target is not padded with further NUL + * bytes. In case the string length is larger than size, just count-1 + * bytes are copied and the last byte is set to NUL. + * @dst: destination address + * @size: maximum number of bytes to copy, including the trailing NUL + * @unsafe_ptr: unsafe address + * Return: + * > 0 length of the string including the trailing NUL on success + * < 0 error + */ + BPF_FUNC_probe_read_str, + __BPF_FUNC_MAX_ID, }; diff --git a/tools/include/uapi/linux/bpf.h b/tools/include/uapi/linux/bpf.h index 9e5fc168c8a3..034199ba75aa 100644 --- a/tools/include/uapi/linux/bpf.h +++ b/tools/include/uapi/linux/bpf.h @@ -375,6 +375,87 @@ enum bpf_func_id { */ BPF_FUNC_probe_write_user, + /** + * int bpf_skb_change_tail(skb, len, flags) + * The helper will resize the skb to the given new size, to be used f.e. + * with control messages. + * @skb: pointer to skb + * @len: new skb length + * @flags: reserved + * Return: 0 on success or negative error + */ + BPF_FUNC_skb_change_tail, + + /** + * int bpf_skb_pull_data(skb, len) + * The helper will pull in non-linear data in case the skb is non-linear + * and not all of len are part of the linear section. Only needed for + * read/write with direct packet access. + * @skb: pointer to skb + * @len: len to make read/writeable + * Return: 0 on success or negative error + */ + BPF_FUNC_skb_pull_data, + + /** + * s64 bpf_csum_update(skb, csum) + * Adds csum into skb->csum in case of CHECKSUM_COMPLETE. + * @skb: pointer to skb + * @csum: csum to add + * Return: csum on success or negative error + */ + BPF_FUNC_csum_update, + + /** + * void bpf_set_hash_invalid(skb) + * Invalidate current skb->hash. + * @skb: pointer to skb + */ + BPF_FUNC_set_hash_invalid, + + /** + * int bpf_get_numa_node_id() + * Return: Id of current NUMA node. + */ + BPF_FUNC_get_numa_node_id, + + /** + * int bpf_skb_change_head() + * Grows headroom of skb and adjusts MAC header offset accordingly. + * Will extends/reallocae as required automatically. + * May change skb data pointer and will thus invalidate any check + * performed for direct packet access. + * @skb: pointer to skb + * @len: length of header to be pushed in front + * @flags: Flags (unused for now) + * Return: 0 on success or negative error + */ + BPF_FUNC_skb_change_head, + + /** + * int bpf_xdp_adjust_head(xdp_md, delta) + * Adjust the xdp_md.data by delta + * @xdp_md: pointer to xdp_md + * @delta: An positive/negative integer to be added to xdp_md.data + * Return: 0 on success or negative on error + */ + BPF_FUNC_xdp_adjust_head, + + /** + * int bpf_probe_read_str(void *dst, int size, const void *unsafe_ptr) + * Copy a NUL terminated string from unsafe address. In case the string + * length is smaller than size, the target is not padded with further NUL + * bytes. In case the string length is larger than size, just count-1 + * bytes are copied and the last byte is set to NUL. + * @dst: destination address + * @size: maximum number of bytes to copy, including the trailing NUL + * @unsafe_ptr: unsafe address + * Return: + * > 0 length of the string including the trailing NUL on success + * < 0 error + */ + BPF_FUNC_probe_read_str, + __BPF_FUNC_MAX_ID, }; From 093136631262289b5f7d6ad1da267d531f383f8c Mon Sep 17 00:00:00 2001 From: Chenbo Feng Date: Wed, 22 Mar 2017 17:27:34 -0700 Subject: [PATCH 198/396] BACKPORT: UPSTREAM: Add a helper function to get socket cookie in eBPF Cherrypick from commit: 91b8270f2a4d1d9b268de90451cdca63a70052d6 Retrieve the socket cookie generated by sock_gen_cookie() from a sk_buff with a known socket. Generates a new cookie if one was not yet set.If the socket pointer inside sk_buff is NULL, 0 is returned. The helper function coud be useful in monitoring per socket networking traffic statistics and provide a unique socket identifier per namespace. Acked-by: Daniel Borkmann Acked-by: Alexei Starovoitov Acked-by: Willem de Bruijn Signed-off-by: Chenbo Feng Signed-off-by: David S. Miller Bug: 30950746 Change-Id: I95918dcc3ceffb3061495a859d28aee88e3cde3c --- include/linux/sock_diag.h | 1 + include/uapi/linux/bpf.h | 9 +++++++++ net/core/filter.c | 15 +++++++++++++++ net/core/sock_diag.c | 2 +- tools/include/uapi/linux/bpf.h | 10 ++++++++++ 5 files changed, 36 insertions(+), 1 deletion(-) diff --git a/include/linux/sock_diag.h b/include/linux/sock_diag.h index a0596ca0e80a..a2f8109bb215 100644 --- a/include/linux/sock_diag.h +++ b/include/linux/sock_diag.h @@ -24,6 +24,7 @@ void sock_diag_unregister(const struct sock_diag_handler *h); void sock_diag_register_inet_compat(int (*fn)(struct sk_buff *skb, struct nlmsghdr *nlh)); void sock_diag_unregister_inet_compat(int (*fn)(struct sk_buff *skb, struct nlmsghdr *nlh)); +u64 sock_gen_cookie(struct sock *sk); int sock_diag_check_cookie(struct sock *sk, const __u32 *cookie); void sock_diag_save_cookie(struct sock *sk, __u32 *cookie); diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h index 16b4ae0f3e0b..c118c1df881a 100644 --- a/include/uapi/linux/bpf.h +++ b/include/uapi/linux/bpf.h @@ -486,6 +486,15 @@ enum bpf_func_id { */ BPF_FUNC_probe_read_str, + /** + * u64 bpf_bpf_get_socket_cookie(skb) + * Get the cookie for the socket stored inside sk_buff. + * @skb: pointer to skb + * Return: 8 Bytes non-decreasing number on success or 0 if the socket + * field is missing inside sk_buff + */ + BPF_FUNC_get_socket_cookie, + __BPF_FUNC_MAX_ID, }; diff --git a/net/core/filter.c b/net/core/filter.c index 9983c3fb2fa8..1aa3d6f433f4 100644 --- a/net/core/filter.c +++ b/net/core/filter.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -2534,6 +2535,18 @@ static const struct bpf_func_proto bpf_xdp_event_output_proto = { .arg5_type = ARG_CONST_STACK_SIZE, }; +BPF_CALL_1(bpf_get_socket_cookie, struct sk_buff *, skb) +{ + return skb->sk ? sock_gen_cookie(skb->sk) : 0; +} + +static const struct bpf_func_proto bpf_get_socket_cookie_proto = { + .func = bpf_get_socket_cookie, + .gpl_only = false, + .ret_type = RET_INTEGER, + .arg1_type = ARG_PTR_TO_CTX, +}; + static const struct bpf_func_proto * sk_filter_func_proto(enum bpf_func_id func_id) { @@ -2555,6 +2568,8 @@ sk_filter_func_proto(enum bpf_func_id func_id) case BPF_FUNC_trace_printk: if (capable(CAP_SYS_ADMIN)) return bpf_get_trace_printk_proto(); + case BPF_FUNC_get_socket_cookie: + return &bpf_get_socket_cookie_proto; default: return NULL; } diff --git a/net/core/sock_diag.c b/net/core/sock_diag.c index 6b10573cc9fa..acd2a6caba85 100644 --- a/net/core/sock_diag.c +++ b/net/core/sock_diag.c @@ -19,7 +19,7 @@ static int (*inet_rcv_compat)(struct sk_buff *skb, struct nlmsghdr *nlh); static DEFINE_MUTEX(sock_diag_table_mutex); static struct workqueue_struct *broadcast_wq; -static u64 sock_gen_cookie(struct sock *sk) +u64 sock_gen_cookie(struct sock *sk) { while (1) { u64 res = atomic64_read(&sk->sk_cookie); diff --git a/tools/include/uapi/linux/bpf.h b/tools/include/uapi/linux/bpf.h index 034199ba75aa..535792b750ae 100644 --- a/tools/include/uapi/linux/bpf.h +++ b/tools/include/uapi/linux/bpf.h @@ -456,6 +456,16 @@ enum bpf_func_id { */ BPF_FUNC_probe_read_str, + /** + * u64 bpf_get_socket_cookie(skb) + * Get the cookie for the socket stored inside sk_buff. + * @skb: pointer to skb + * Return: 8 Bytes non-decreasing number on success or 0 if + * the socket + * field is missing inside sk_buff + */ + BPF_FUNC_get_socket_cookie, + __BPF_FUNC_MAX_ID, }; From a29c81e91c2defa2ffc0d1db742466ee68f244f6 Mon Sep 17 00:00:00 2001 From: Chenbo Feng Date: Wed, 22 Mar 2017 17:27:35 -0700 Subject: [PATCH 199/396] BACKPORT: UPSTREAM: Add a eBPF helper function to retrieve socket uid Cherry-pick from commit 6acc5c2910689fc6ee181bf63085c5efff6a42bd Returns the owner uid of the socket inside a sk_buff. This is useful to perform per-UID accounting of network traffic or per-UID packet filtering. The socket need to be a fullsock otherwise overflowuid is returned. Signed-off-by: Chenbo Feng Signed-off-by: David S. Miller Bug: 30950746 Change-Id: Idc00947ccfdd4e9f2214ffc4178d701cd9ead0ac --- include/uapi/linux/bpf.h | 9 +++++++++ net/core/filter.c | 20 ++++++++++++++++++++ tools/include/uapi/linux/bpf.h | 8 ++++++++ 3 files changed, 37 insertions(+) diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h index c118c1df881a..14eaf2d5ec13 100644 --- a/include/uapi/linux/bpf.h +++ b/include/uapi/linux/bpf.h @@ -495,6 +495,15 @@ enum bpf_func_id { */ BPF_FUNC_get_socket_cookie, + /** + * u32 bpf_get_socket_uid(skb) + * Get the owner uid of the socket stored inside sk_buff. + * @skb: pointer to skb + * Return: uid of the socket owner on success or 0 if the socket pointer + * inside sk_buff is NULL + */ + BPF_FUNC_get_socket_uid, + __BPF_FUNC_MAX_ID, }; diff --git a/net/core/filter.c b/net/core/filter.c index 1aa3d6f433f4..14ad25bb3eb3 100644 --- a/net/core/filter.c +++ b/net/core/filter.c @@ -2547,6 +2547,24 @@ static const struct bpf_func_proto bpf_get_socket_cookie_proto = { .arg1_type = ARG_PTR_TO_CTX, }; +BPF_CALL_1(bpf_get_socket_uid, struct sk_buff *, skb) +{ + struct sock *sk = sk_to_full_sk(skb->sk); + kuid_t kuid; + + if (!sk || !sk_fullsock(sk)) + return overflowuid; + kuid = sock_net_uid(sock_net(sk), sk); + return from_kuid_munged(sock_net(sk)->user_ns, kuid); +} + +static const struct bpf_func_proto bpf_get_socket_uid_proto = { + .func = bpf_get_socket_uid, + .gpl_only = false, + .ret_type = RET_INTEGER, + .arg1_type = ARG_PTR_TO_CTX, +}; + static const struct bpf_func_proto * sk_filter_func_proto(enum bpf_func_id func_id) { @@ -2570,6 +2588,8 @@ sk_filter_func_proto(enum bpf_func_id func_id) return bpf_get_trace_printk_proto(); case BPF_FUNC_get_socket_cookie: return &bpf_get_socket_cookie_proto; + case BPF_FUNC_get_socket_uid: + return &bpf_get_socket_uid_proto; default: return NULL; } diff --git a/tools/include/uapi/linux/bpf.h b/tools/include/uapi/linux/bpf.h index 535792b750ae..42dfbeb416b7 100644 --- a/tools/include/uapi/linux/bpf.h +++ b/tools/include/uapi/linux/bpf.h @@ -466,6 +466,14 @@ enum bpf_func_id { */ BPF_FUNC_get_socket_cookie, + /** + * u32 bpf_get_socket_uid(skb) + * Get the owner uid of the socket stored inside sk_buff. + * @skb: pointer to skb + * Return: uid of the socket owner on success or overflowuid if failed. + */ + BPF_FUNC_get_socket_uid, + __BPF_FUNC_MAX_ID, }; From 2c1289c999b933214b77c93b63bc84552e85ead5 Mon Sep 17 00:00:00 2001 From: Willem de Bruijn Date: Tue, 11 Apr 2017 14:08:08 -0400 Subject: [PATCH 200/396] BACKPORT: UPSTREAM: bpf: pass sk to helper functions Cherrypick from commit 8f917bba0042f1e3b7693743fbe9782709e936e7 BPF helper functions access socket fields through skb->sk. This is not set in ingress cgroup and socket filters. The association is only made in skb_set_owner_r once the filter has accepted the packet. Sk is available as socket lookup has taken place. Temporarily set skb->sk to sk in these cases. Signed-off-by: Willem de Bruijn Acked-by: Alexei Starovoitov Signed-off-by: David S. Miller Bug: 30950746 Change-Id: Ifcbcbe2ab2882dc79c56f9707be1d6aef08c7fd3 --- kernel/bpf/cgroup.c | 5 ++++- net/core/filter.c | 7 ++++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/kernel/bpf/cgroup.c b/kernel/bpf/cgroup.c index a0ab43f264b0..d05c292290fe 100644 --- a/kernel/bpf/cgroup.c +++ b/kernel/bpf/cgroup.c @@ -119,7 +119,7 @@ void __cgroup_bpf_update(struct cgroup *cgrp, /** * __cgroup_bpf_run_filter() - Run a program for packet filtering - * @sk: The socken sending or receiving traffic + * @sk: The socket sending or receiving traffic * @skb: The skb that is being sent or received * @type: The type of program to be exectuted * @@ -154,10 +154,13 @@ int __cgroup_bpf_run_filter(struct sock *sk, prog = rcu_dereference(cgrp->bpf.effective[type]); if (prog) { unsigned int offset = skb->data - skb_network_header(skb); + struct sock *save_sk = skb->sk; + skb->sk = sk; __skb_push(skb, offset); ret = bpf_prog_run_save_cb(prog, skb) == 1 ? 0 : -EPERM; __skb_pull(skb, offset); + skb->sk = save_sk; } rcu_read_unlock(); diff --git a/net/core/filter.c b/net/core/filter.c index 14ad25bb3eb3..2cb4f0f1da2e 100644 --- a/net/core/filter.c +++ b/net/core/filter.c @@ -90,8 +90,13 @@ int sk_filter_trim_cap(struct sock *sk, struct sk_buff *skb, unsigned int cap) rcu_read_lock(); filter = rcu_dereference(sk->sk_filter); if (filter) { - unsigned int pkt_len = bpf_prog_run_save_cb(filter->prog, skb); + struct sock *save_sk = skb->sk; + unsigned int pkt_len; + + skb->sk = sk; + pkt_len = bpf_prog_run_save_cb(filter->prog, skb); err = pkt_len ? pskb_trim(skb, max(cap, pkt_len)) : -EPERM; + skb->sk = save_sk; } rcu_read_unlock(); From 9e6b5ccfb97a719030962ccee57e55ad39610845 Mon Sep 17 00:00:00 2001 From: Chenbo Feng Date: Fri, 19 May 2017 11:32:13 -0700 Subject: [PATCH 201/396] ANDROID: Add CGROUP_BPF to android base config Add CONFIG_CGROUP_BPF as a default configuration in android base config since it is used to replace XT_QTAGUID in future. Signed-off-by: Chenbo Feng Bug: 30950746 Change-Id: I14f340a12b9def11057bbd0a1d94a5baf558b314 --- kernel/configs/android-base.config | 1 + 1 file changed, 1 insertion(+) diff --git a/kernel/configs/android-base.config b/kernel/configs/android-base.config index b7b997fd58c9..bc615c62810b 100644 --- a/kernel/configs/android-base.config +++ b/kernel/configs/android-base.config @@ -19,6 +19,7 @@ CONFIG_CGROUP_CPUACCT=y CONFIG_CGROUP_DEBUG=y CONFIG_CGROUP_FREEZER=y CONFIG_CGROUP_SCHED=y +CONFIG_CGROUP_BPF=y CONFIG_CP15_BARRIER_EMULATION=y CONFIG_DEFAULT_SECURITY_SELINUX=y CONFIG_EMBEDDED=y From db95048ac894e98fcaa9c390e25f3cb954684702 Mon Sep 17 00:00:00 2001 From: Daniel Rosenberg Date: Mon, 22 May 2017 13:23:56 -0700 Subject: [PATCH 202/396] ANDROID: sdcardfs: Check for NULL in revalidate If the inode is in the process of being evicted, the top value may be NULL. Signed-off-by: Daniel Rosenberg Bug: 38502532 Change-Id: I0b9d04aab621e0398d44d1c5dc53293106aa5f89 --- fs/sdcardfs/dentry.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/fs/sdcardfs/dentry.c b/fs/sdcardfs/dentry.c index a23168179716..e9426a61d04a 100644 --- a/fs/sdcardfs/dentry.c +++ b/fs/sdcardfs/dentry.c @@ -109,14 +109,16 @@ static int sdcardfs_d_revalidate(struct dentry *dentry, unsigned int flags) goto out; /* If our top's inode is gone, we may be out of date */ - inode = d_inode(dentry); + inode = igrab(d_inode(dentry)); if (inode) { data = top_data_get(SDCARDFS_I(inode)); - if (data->abandoned) { + if (!data || data->abandoned) { d_drop(dentry); err = 0; } - data_put(data); + if (data) + data_put(data); + iput(inode); } out: From 941055b401e56e588a8e127a049619750001b670 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Mon, 29 Aug 2016 08:08:29 +0100 Subject: [PATCH 203/396] UPSTREAM: dma-buf: Introduce fence_get_rcu_safe() This variant of fence_get_rcu() takes an RCU protected pointer to a fence and carefully returns a reference to the fence ensuring that it is not reallocated as it does. This is required when mixing fences and SLAB_DESTROY_BY_RCU - although it serves a more pedagogical function atm Signed-off-by: Chris Wilson Cc: Daniel Vetter Cc: Sumit Semwal Cc: linux-media@vger.kernel.org Cc: dri-devel@lists.freedesktop.org Cc: linaro-mm-sig@lists.linaro.org Reviewed-by: Daniel Vetter Signed-off-by: Sumit Semwal Link: http://patchwork.freedesktop.org/patch/msgid/20160829070834.22296-6-chris@chris-wilson.co.uk (cherry picked from commit 4be0542073a33cc063b6a8f8fb367536e234e7aa) Signed-off-by: Marissa Wall Change-Id: I05a97e915fdca3823d31583f650ddd2029f2f8ad --- include/linux/fence.h | 56 +++++++++++++++++++++++++++++++++++++++---- 1 file changed, 51 insertions(+), 5 deletions(-) diff --git a/include/linux/fence.h b/include/linux/fence.h index 8d7265fe049e..fd9b89f96ba3 100644 --- a/include/linux/fence.h +++ b/include/linux/fence.h @@ -184,6 +184,16 @@ void fence_init(struct fence *fence, const struct fence_ops *ops, void fence_release(struct kref *kref); void fence_free(struct fence *fence); +/** + * fence_put - decreases refcount of the fence + * @fence: [in] fence to reduce refcount of + */ +static inline void fence_put(struct fence *fence) +{ + if (fence) + kref_put(&fence->refcount, fence_release); +} + /** * fence_get - increases refcount of the fence * @fence: [in] fence to increase refcount of @@ -212,13 +222,49 @@ static inline struct fence *fence_get_rcu(struct fence *fence) } /** - * fence_put - decreases refcount of the fence - * @fence: [in] fence to reduce refcount of + * fence_get_rcu_safe - acquire a reference to an RCU tracked fence + * @fence: [in] pointer to fence to increase refcount of + * + * Function returns NULL if no refcount could be obtained, or the fence. + * This function handles acquiring a reference to a fence that may be + * reallocated within the RCU grace period (such as with SLAB_DESTROY_BY_RCU), + * so long as the caller is using RCU on the pointer to the fence. + * + * An alternative mechanism is to employ a seqlock to protect a bunch of + * fences, such as used by struct reservation_object. When using a seqlock, + * the seqlock must be taken before and checked after a reference to the + * fence is acquired (as shown here). + * + * The caller is required to hold the RCU read lock. */ -static inline void fence_put(struct fence *fence) +static inline struct fence *fence_get_rcu_safe(struct fence * __rcu *fencep) { - if (fence) - kref_put(&fence->refcount, fence_release); + do { + struct fence *fence; + + fence = rcu_dereference(*fencep); + if (!fence || !fence_get_rcu(fence)) + return NULL; + + /* The atomic_inc_not_zero() inside fence_get_rcu() + * provides a full memory barrier upon success (such as now). + * This is paired with the write barrier from assigning + * to the __rcu protected fence pointer so that if that + * pointer still matches the current fence, we know we + * have successfully acquire a reference to it. If it no + * longer matches, we are holding a reference to some other + * reallocated pointer. This is possible if the allocator + * is using a freelist like SLAB_DESTROY_BY_RCU where the + * fence remains valid for the RCU grace period, but it + * may be reallocated. When using such allocators, we are + * responsible for ensuring the reference we get is to + * the right fence, as below. + */ + if (fence == rcu_access_pointer(*fencep)) + return rcu_pointer_handoff(fence); + + fence_put(fence); + } while (1); } int fence_signal(struct fence *fence); From 2264af0978e98105080a6103688c47f7d71f28bb Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Mon, 29 Aug 2016 08:08:30 +0100 Subject: [PATCH 204/396] UPSTREAM: dma-buf: Restart reservation_object_get_fences_rcu() after writes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In order to be completely generic, we have to double check the read seqlock after acquiring a reference to the fence. If the driver is allocating fences from a SLAB_DESTROY_BY_RCU, or similar freelist, then within an RCU grace period a fence may be freed and reallocated. The RCU read side critical section does not prevent this reallocation, instead we have to inspect the reservation's seqlock to double check if the fences have been reassigned as we were acquiring our reference. Signed-off-by: Chris Wilson Cc: Daniel Vetter Cc: Maarten Lankhorst Cc: Christian König Cc: Alex Deucher Cc: Sumit Semwal Cc: linux-media@vger.kernel.org Cc: dri-devel@lists.freedesktop.org Cc: linaro-mm-sig@lists.linaro.org Reviewed-by: Daniel Vetter Signed-off-by: Sumit Semwal Link: http://patchwork.freedesktop.org/patch/msgid/20160829070834.22296-7-chris@chris-wilson.co.uk (cherry picked from commit fedf54132d2410c3949036e3f611ab8dd9dbe89e) Signed-off-by: Marissa Wall Change-Id: I32dacb1b95a73c49984b88e01e7f7424d069ef07 --- drivers/dma-buf/reservation.c | 71 +++++++++++++++-------------------- 1 file changed, 31 insertions(+), 40 deletions(-) diff --git a/drivers/dma-buf/reservation.c b/drivers/dma-buf/reservation.c index 723d8af988e5..ba3e25dab95b 100644 --- a/drivers/dma-buf/reservation.c +++ b/drivers/dma-buf/reservation.c @@ -280,18 +280,24 @@ int reservation_object_get_fences_rcu(struct reservation_object *obj, unsigned *pshared_count, struct fence ***pshared) { - unsigned shared_count = 0; - unsigned retry = 1; - struct fence **shared = NULL, *fence_excl = NULL; - int ret = 0; + struct fence **shared = NULL; + struct fence *fence_excl; + unsigned int shared_count; + int ret = 1; - while (retry) { + do { struct reservation_object_list *fobj; unsigned seq; + unsigned int i; - seq = read_seqcount_begin(&obj->seq); + shared_count = i = 0; rcu_read_lock(); + seq = read_seqcount_begin(&obj->seq); + + fence_excl = rcu_dereference(obj->fence_excl); + if (fence_excl && !fence_get_rcu(fence_excl)) + goto unlock; fobj = rcu_dereference(obj->fence); if (fobj) { @@ -309,52 +315,37 @@ int reservation_object_get_fences_rcu(struct reservation_object *obj, } ret = -ENOMEM; - shared_count = 0; break; } shared = nshared; - memcpy(shared, fobj->shared, sz); shared_count = fobj->shared_count; - } else - shared_count = 0; - fence_excl = rcu_dereference(obj->fence_excl); - - retry = read_seqcount_retry(&obj->seq, seq); - if (retry) - goto unlock; - - if (!fence_excl || fence_get_rcu(fence_excl)) { - unsigned i; for (i = 0; i < shared_count; ++i) { - if (fence_get_rcu(shared[i])) - continue; - - /* uh oh, refcount failed, abort and retry */ - while (i--) - fence_put(shared[i]); - - if (fence_excl) { - fence_put(fence_excl); - fence_excl = NULL; - } - - retry = 1; - break; + shared[i] = rcu_dereference(fobj->shared[i]); + if (!fence_get_rcu(shared[i])) + break; } - } else - retry = 1; + } + if (i != shared_count || read_seqcount_retry(&obj->seq, seq)) { + while (i--) + fence_put(shared[i]); + fence_put(fence_excl); + goto unlock; + } + + ret = 0; unlock: rcu_read_unlock(); - } - *pshared_count = shared_count; - if (shared_count) - *pshared = shared; - else { - *pshared = NULL; + } while (ret); + + if (!shared_count) { kfree(shared); + shared = NULL; } + + *pshared_count = shared_count; + *pshared = shared; *pfence_excl = fence_excl; return ret; From b0f869d1daa10bc78007cd2c5b0965d781d6aa06 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Mon, 29 Aug 2016 08:08:31 +0100 Subject: [PATCH 205/396] UPSTREAM: dma-buf: Restart reservation_object_wait_timeout_rcu() after writes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In order to be completely generic, we have to double check the read seqlock after acquiring a reference to the fence. If the driver is allocating fences from a SLAB_DESTROY_BY_RCU, or similar freelist, then within an RCU grace period a fence may be freed and reallocated. The RCU read side critical section does not prevent this reallocation, instead we have to inspect the reservation's seqlock to double check if the fences have been reassigned as we were acquiring our reference. Signed-off-by: Chris Wilson Cc: Daniel Vetter Cc: Maarten Lankhorst Cc: Christian König Cc: Alex Deucher Cc: Sumit Semwal Cc: linux-media@vger.kernel.org Cc: dri-devel@lists.freedesktop.org Cc: linaro-mm-sig@lists.linaro.org Reviewed-by: Daniel Vetter Signed-off-by: Sumit Semwal Link: http://patchwork.freedesktop.org/patch/msgid/20160829070834.22296-8-chris@chris-wilson.co.uk (cherry picked from commit 1cec20f0ea0e3bc617aed47e0936f17386c131f9) Signed-off-by: Marissa Wall Change-Id: Ie397f56a605ec1e63de54cc59eb2715e58f6cc09 --- drivers/dma-buf/reservation.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/drivers/dma-buf/reservation.c b/drivers/dma-buf/reservation.c index ba3e25dab95b..648e5d0325f9 100644 --- a/drivers/dma-buf/reservation.c +++ b/drivers/dma-buf/reservation.c @@ -388,9 +388,6 @@ retry: if (fobj) shared_count = fobj->shared_count; - if (read_seqcount_retry(&obj->seq, seq)) - goto unlock_retry; - for (i = 0; i < shared_count; ++i) { struct fence *lfence = rcu_dereference(fobj->shared[i]); @@ -413,9 +410,6 @@ retry: if (!shared_count) { struct fence *fence_excl = rcu_dereference(obj->fence_excl); - if (read_seqcount_retry(&obj->seq, seq)) - goto unlock_retry; - if (fence_excl && !test_bit(FENCE_FLAG_SIGNALED_BIT, &fence_excl->flags)) { if (!fence_get_rcu(fence_excl)) @@ -430,6 +424,11 @@ retry: rcu_read_unlock(); if (fence) { + if (read_seqcount_retry(&obj->seq, seq)) { + fence_put(fence); + goto retry; + } + ret = fence_wait_timeout(fence, intr, ret); fence_put(fence); if (ret > 0 && wait_all && (i + 1 < shared_count)) From 850759508138ed17451874bc372411e539ad5982 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Mon, 29 Aug 2016 08:08:32 +0100 Subject: [PATCH 206/396] UPSTREAM: dma-buf: Restart reservation_object_test_signaled_rcu() after writes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In order to be completely generic, we have to double check the read seqlock after acquiring a reference to the fence. If the driver is allocating fences from a SLAB_DESTROY_BY_RCU, or similar freelist, then within an RCU grace period a fence may be freed and reallocated. The RCU read side critical section does not prevent this reallocation, instead we have to inspect the reservation's seqlock to double check if the fences have been reassigned as we were acquiring our reference. Signed-off-by: Chris Wilson Cc: Daniel Vetter Cc: Maarten Lankhorst Cc: Christian König Cc: Alex Deucher Cc: Sumit Semwal Cc: linux-media@vger.kernel.org Cc: dri-devel@lists.freedesktop.org Cc: linaro-mm-sig@lists.linaro.org Reviewed-by: Daniel Vetter Signed-off-by: Sumit Semwal Link: http://patchwork.freedesktop.org/patch/msgid/20160829070834.22296-9-chris@chris-wilson.co.uk (cherry picked from commit b68d8379c28ddfe74b78be9414082f281332d86c) Signed-off-by: Marissa Wall Change-Id: Icc81d30c1c2b7f3ea3c47bb5e0c7f48ffa90e585 --- drivers/dma-buf/reservation.c | 30 ++++++++++-------------------- 1 file changed, 10 insertions(+), 20 deletions(-) diff --git a/drivers/dma-buf/reservation.c b/drivers/dma-buf/reservation.c index 648e5d0325f9..82de59f7cbbd 100644 --- a/drivers/dma-buf/reservation.c +++ b/drivers/dma-buf/reservation.c @@ -474,12 +474,13 @@ bool reservation_object_test_signaled_rcu(struct reservation_object *obj, bool test_all) { unsigned seq, shared_count; - int ret = true; + int ret; + rcu_read_lock(); retry: + ret = true; shared_count = 0; seq = read_seqcount_begin(&obj->seq); - rcu_read_lock(); if (test_all) { unsigned i; @@ -490,46 +491,35 @@ retry: if (fobj) shared_count = fobj->shared_count; - if (read_seqcount_retry(&obj->seq, seq)) - goto unlock_retry; - for (i = 0; i < shared_count; ++i) { struct fence *fence = rcu_dereference(fobj->shared[i]); ret = reservation_object_test_signaled_single(fence); if (ret < 0) - goto unlock_retry; + goto retry; else if (!ret) break; } - /* - * There could be a read_seqcount_retry here, but nothing cares - * about whether it's the old or newer fence pointers that are - * signaled. That race could still have happened after checking - * read_seqcount_retry. If you care, use ww_mutex_lock. - */ + if (read_seqcount_retry(&obj->seq, seq)) + goto retry; } if (!shared_count) { struct fence *fence_excl = rcu_dereference(obj->fence_excl); - if (read_seqcount_retry(&obj->seq, seq)) - goto unlock_retry; - if (fence_excl) { ret = reservation_object_test_signaled_single( fence_excl); if (ret < 0) - goto unlock_retry; + goto retry; + + if (read_seqcount_retry(&obj->seq, seq)) + goto retry; } } rcu_read_unlock(); return ret; - -unlock_retry: - rcu_read_unlock(); - goto retry; } EXPORT_SYMBOL_GPL(reservation_object_test_signaled_rcu); From 675ed82c41b5248814e5867495a37e94b03bd669 Mon Sep 17 00:00:00 2001 From: Gustavo Padovan Date: Thu, 20 Oct 2016 12:50:03 -0200 Subject: [PATCH 207/396] UPSTREAM: drm/fence: release fence reference when canceling event If the event gets canceled we also need to put away the fence reference it holds. Signed-off-by: Gustavo Padovan Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/1476975005-30441-3-git-send-email-gustavo@padovan.org (cherry picked from commit 838de39fc9516470b1410cc068c7f41daec69265) Signed-off-by: Marissa Wall Change-Id: I421435486b4e40e342564fa5c4327ff3ab62498c --- drivers/gpu/drm/drm_fops.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/gpu/drm/drm_fops.c b/drivers/gpu/drm/drm_fops.c index f5815e1a4390..fe00beaf2f48 100644 --- a/drivers/gpu/drm/drm_fops.c +++ b/drivers/gpu/drm/drm_fops.c @@ -663,6 +663,10 @@ void drm_event_cancel_free(struct drm_device *dev, list_del(&p->pending_link); } spin_unlock_irqrestore(&dev->event_lock, flags); + + if (p->fence) + fence_put(p->fence); + kfree(p); } EXPORT_SYMBOL(drm_event_cancel_free); From 8fba9cde9b815209e8f8fcd2587c85860b17ad06 Mon Sep 17 00:00:00 2001 From: Gustavo Padovan Date: Wed, 19 Oct 2016 15:48:32 -0200 Subject: [PATCH 208/396] UPSTREAM: dma-buf/sync_file: hold reference to fence when creating sync_file fence referencing was out of balance. It was not taking any ref to the fence at creating time, but it was putting a reference when freeing the sync file. This patch fixes the balancing issue by getting a reference for the fence when creating the sync_file. Signed-off-by: Gustavo Padovan Signed-off-by: Sean Paul Link: http://patchwork.freedesktop.org/patch/msgid/1476899313-22241-1-git-send-email-gustavo@padovan.org (cherry picked from commit 30cd85dd6edc86ea8d8589efb813f1fad41ef233) Signed-off-by: Marissa Wall Change-Id: Ia24fb15d88b8b2034c28ac5fe13a7ecdd16f48dd --- drivers/dma-buf/sync_file.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/dma-buf/sync_file.c b/drivers/dma-buf/sync_file.c index b29a9e817320..235f8ac113cc 100644 --- a/drivers/dma-buf/sync_file.c +++ b/drivers/dma-buf/sync_file.c @@ -79,7 +79,7 @@ struct sync_file *sync_file_create(struct fence *fence) if (!sync_file) return NULL; - sync_file->fence = fence; + sync_file->fence = fence_get(fence); snprintf(sync_file->name, sizeof(sync_file->name), "%s-%s%llu-%d", fence->ops->get_driver_name(fence), From ce2a4b627d0cef47695b691fb19071d32a72bc9a Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Mon, 24 Oct 2016 15:57:10 -0400 Subject: [PATCH 209/396] UPSTREAM: dma-buf/fence: add an lockdep_assert_held() Signed-off-by: Rob Clark Reviewed-by: Chris Wilson Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/1477339030-32657-1-git-send-email-robdclark@gmail.com (cherry picked from commit 78010cd9736ec571796f4404524ed575b81238b9) Signed-off-by: Marissa Wall Change-Id: I8fce7abb30f9f54e87deab215556f3679c6afa1e --- drivers/dma-buf/fence.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/dma-buf/fence.c b/drivers/dma-buf/fence.c index 2453e076ee36..88d03a11b27f 100644 --- a/drivers/dma-buf/fence.c +++ b/drivers/dma-buf/fence.c @@ -68,6 +68,8 @@ int fence_signal_locked(struct fence *fence) struct fence_cb *cur, *tmp; int ret = 0; + lockdep_assert_held(fence->lock); + if (WARN_ON(!fence)) return -EINVAL; From a2837749518860904c3fe301d53893eb060d521f Mon Sep 17 00:00:00 2001 From: Gustavo Padovan Date: Wed, 26 Oct 2016 18:59:59 -0200 Subject: [PATCH 210/396] UPSTREAM: dma-buf/sw_sync: put fence reference from the fence creation Once sw_sync_ioctl_create_fence() returns we no longer have the *pt pointer to the fence base object thus we need to put the reference we have from the fence creation to keep a correct reference accounting. Signed-off-by: Gustavo Padovan Reviewed-by: Chris Wilson Signed-off-by: Sumit Semwal Link: http://patchwork.freedesktop.org/patch/msgid/1477515599-7685-1-git-send-email-gustavo@padovan.org (cherry picked from commit 4592bfcd177fe78cf9adc59f2dcddd1fa1f71079) Signed-off-by: Marissa Wall Change-Id: I674fde09fa40446b50c63878e0083c5ee8d509b9 --- drivers/dma-buf/sw_sync.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/dma-buf/sw_sync.c b/drivers/dma-buf/sw_sync.c index 454d3b3df512..0cb8d9d8784a 100644 --- a/drivers/dma-buf/sw_sync.c +++ b/drivers/dma-buf/sw_sync.c @@ -324,8 +324,8 @@ static long sw_sync_ioctl_create_fence(struct sync_timeline *obj, } sync_file = sync_file_create(&pt->base); + fence_put(&pt->base); if (!sync_file) { - fence_put(&pt->base); err = -ENOMEM; goto err; } From 4b85bcea3c7239fbd0e48400adab5d3810236dec Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 7 Nov 2016 16:16:14 -0500 Subject: [PATCH 211/396] BACKPORT: dma-buf/fence: revert "don't wait when specified timeout is zero" (v2) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reverts commit 847b19a39e4c ("dma-buf/fence: don't wait when specified timeout is zero") When we don't call the wait function software signaling might never be activated. This can cause infinite polling loops with unreliable interrupt driven hardware. v2: rebase on drm-next Reviewed-by: Alex Deucher Signed-off-by: Christian König Reviewed-by: Chunming Zhou Reviewed-by: Gustavo Padovan Signed-off-by: Alex Deucher Signed-off-by: Sumit Semwal [sumits: reword commit msg for checkpatch warnings] Link: http://patchwork.freedesktop.org/patch/msgid/1478553376-18575-2-git-send-email-alexander.deucher@amd.com (cherry picked from commit 698c0f7ff21674ec08a4c6e99dd6da62fe5a344d) Signed-off-by: Marissa Wall Change-Id: I6a0d72034ecec3832c90864291bc5674da8a0b5d --- drivers/dma-buf/fence.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/dma-buf/fence.c b/drivers/dma-buf/fence.c index 88d03a11b27f..094548bcb9cf 100644 --- a/drivers/dma-buf/fence.c +++ b/drivers/dma-buf/fence.c @@ -161,9 +161,6 @@ fence_wait_timeout(struct fence *fence, bool intr, signed long timeout) if (WARN_ON(timeout < 0)) return -EINVAL; - if (timeout == 0) - return fence_is_signaled(fence); - trace_fence_wait_start(fence); ret = fence->ops->wait(fence, intr, timeout); trace_fence_wait_end(fence); From dbbeec418b588585179a175172e6cc3ef32387d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Mon, 7 Nov 2016 16:16:16 -0500 Subject: [PATCH 212/396] UPSTREAM: reservation: revert "wait only with non-zero timeout specified (v3)" v2 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reverts commit fb8b7d2b9d80 ("reservation: wait only with non-zero timeout specified (v3)") Otherwise signaling might never be activated on the fences. This can result in infinite waiting with hardware which has unreliable interrupts. v2: still return one when the timeout is zero and we don't have any fences. Reviewed-by: Alex Deucher Signed-off-by: Christian König Reviewed-by: Chunming Zhou (v1) Signed-off-by: Alex Deucher Reviewed-by: Gustavo Padovan Signed-off-by: Sumit Semwal [sumits: fix checkpatch warnings] Link: http://patchwork.freedesktop.org/patch/msgid/1478553376-18575-4-git-send-email-alexander.deucher@amd.com (cherry picked from commit 06a66b5c77ede71f0601f4710284ca1076e673fa) Signed-off-by: Marissa Wall Change-Id: I5cb90c048f38f4b1f46ed15c486cc718f97cf0d5 --- drivers/dma-buf/reservation.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/dma-buf/reservation.c b/drivers/dma-buf/reservation.c index 82de59f7cbbd..82f35a4ab390 100644 --- a/drivers/dma-buf/reservation.c +++ b/drivers/dma-buf/reservation.c @@ -370,10 +370,7 @@ long reservation_object_wait_timeout_rcu(struct reservation_object *obj, { struct fence *fence; unsigned seq, shared_count, i = 0; - long ret = timeout; - - if (!timeout) - return reservation_object_test_signaled_rcu(obj, wait_all); + long ret = timeout ? timeout : 1; retry: fence = NULL; From 733c30d0729a139f77b152dde357584dfa5ca144 Mon Sep 17 00:00:00 2001 From: Gustavo Padovan Date: Fri, 18 Nov 2016 17:26:43 +0900 Subject: [PATCH 213/396] UPSTREAM: Revert "dma-buf/sync-file: Avoid enable fence signaling if poll(.timeout=0)" This reverts commit ecebca79f6976ddaddfd054d699272515869ea28. Do not enable fence callback on poll() when using fence_array causes the fence_array to not signal. For now we will revert the change and enable signaling everytime time poll is called with timeout=0 as well. Cc: Chris Wilson Signed-off-by: Gustavo Padovan Acked-by: Chris Wilson Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/1479457603-30758-1-git-send-email-gustavo@padovan.org (cherry picked from commit 069cad6d02fef7924fb942b37a6c17dd02a79f7f) Signed-off-by: Marissa Wall Change-Id: Id3e3df319fecfa128f3b94fb41a0f3437625a6d5 --- drivers/dma-buf/sync_file.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/dma-buf/sync_file.c b/drivers/dma-buf/sync_file.c index 235f8ac113cc..05a5ed9f16a2 100644 --- a/drivers/dma-buf/sync_file.c +++ b/drivers/dma-buf/sync_file.c @@ -305,10 +305,9 @@ static unsigned int sync_file_poll(struct file *file, poll_table *wait) poll_wait(file, &sync_file->wq, wait); - if (!poll_does_not_wait(wait) && - !test_and_set_bit(POLL_ENABLED, &sync_file->fence->flags)) { + if (!test_and_set_bit(POLL_ENABLED, &sync_file->fence->flags)) { if (fence_add_callback(sync_file->fence, &sync_file->cb, - fence_check_cb_func) < 0) + fence_check_cb_func) < 0) wake_up_all(&sync_file->wq); } From 4baaef801c2926c7332b1ef564f46bd74b0d7e61 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Fri, 9 Dec 2016 19:53:06 +0100 Subject: [PATCH 214/396] UPSTREAM: dma-buf: Update kerneldoc for sync_file_create This was missed when adding a dma_fence_get call. While at it also remove the kerneldoc for the static inline helper - no point documenting internals down to every detail. Fixes: 30cd85dd6edc ("dma-buf/sync_file: hold reference to fence when creating sync_file") Cc: Gustavo Padovan Cc: Sean Paul Cc: linux-doc@vger.kernel.org Cc: Jonathan Corbet Cc: Sumit Semwal Signed-off-by: Daniel Vetter Reviewed-by: Gustavo Padovan Signed-off-by: Sumit Semwal Link: http://patchwork.freedesktop.org/patch/msgid/20161209185309.1682-3-daniel.vetter@ffwll.ch (cherry picked from commit 24a367348a017555f982a9ee137070a7a821fa97) Signed-off-by: Marissa Wall Change-Id: I8a3cff2b2a4d248a0316813105de8f84d95dd1df --- drivers/dma-buf/sync_file.c | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/drivers/dma-buf/sync_file.c b/drivers/dma-buf/sync_file.c index 05a5ed9f16a2..1beebf8beb3e 100644 --- a/drivers/dma-buf/sync_file.c +++ b/drivers/dma-buf/sync_file.c @@ -67,9 +67,10 @@ static void fence_check_cb_func(struct fence *f, struct fence_cb *cb) * sync_file_create() - creates a sync file * @fence: fence to add to the sync_fence * - * Creates a sync_file containg @fence. Once this is called, the sync_file - * takes ownership of @fence. The sync_file can be released with - * fput(sync_file->file). Returns the sync_file or NULL in case of error. + * Creates a sync_file containg @fence. This function acquires and additional + * reference of @fence for the newly-created &sync_file, if it succeeds. The + * sync_file can be released with fput(sync_file->file). Returns the + * sync_file or NULL in case of error. */ struct sync_file *sync_file_create(struct fence *fence) { @@ -90,13 +91,6 @@ struct sync_file *sync_file_create(struct fence *fence) } EXPORT_SYMBOL(sync_file_create); -/** - * sync_file_fdget() - get a sync_file from an fd - * @fd: fd referencing a fence - * - * Ensures @fd references a valid sync_file, increments the refcount of the - * backing file. Returns the sync_file or NULL in case of error. - */ static struct sync_file *sync_file_fdget(int fd) { struct file *file = fget(fd); From 0ed87071d4f1cf442b345d4f78baee8c788203cb Mon Sep 17 00:00:00 2001 From: Gustavo Padovan Date: Mon, 7 Nov 2016 19:03:30 +0900 Subject: [PATCH 215/396] BACKPORT: drm/atomic: add drm_atomic_set_fence_for_plane() This new function should be used by drivers when setting a implicit fence for the plane. It abstracts the fact that the user might have chosen explicit fencing instead. Signed-off-by: Gustavo Padovan Reviewed-by: Daniel Vetter Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/1478513013-3221-1-git-send-email-gustavo@padovan.org (cherry picked from commit 13b55664eec7b85607c4ab9d26a62b4af413a771) Signed-off-by: Marissa Wall Change-Id: If364103f7e85d915e13b84c0cb8ce37202c6f9b9 --- drivers/gpu/drm/drm_atomic.c | 30 ++++++++++++++++++++++++++++++ include/drm/drm_atomic.h | 2 ++ include/drm/drm_plane.h | 2 +- 3 files changed, 33 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c index 4e19bde4bbff..aa1e2b5935fc 100644 --- a/drivers/gpu/drm/drm_atomic.c +++ b/drivers/gpu/drm/drm_atomic.c @@ -1151,6 +1151,36 @@ drm_atomic_set_fb_for_plane(struct drm_plane_state *plane_state, } EXPORT_SYMBOL(drm_atomic_set_fb_for_plane); +/** + * drm_atomic_set_fence_for_plane - set fence for plane + * @plane_state: atomic state object for the plane + * @fence: fence to use for the plane + * + * Helper to setup the plane_state fence in case it is not set yet. + * By using this drivers doesn't need to worry if the user choose + * implicit or explicit fencing. + * + * This function will not set the fence to the state if it was set + * via explicit fencing interfaces on the atomic ioctl. It will + * all drope the reference to the fence as we not storing it + * anywhere. + * + * Otherwise, if plane_state->fence is not set this function we + * just set it with the received implict fence. + */ +void +drm_atomic_set_fence_for_plane(struct drm_plane_state *plane_state, + struct fence *fence) +{ + if (plane_state->fence) { + fence_put(fence); + return; + } + + plane_state->fence = fence; +} +EXPORT_SYMBOL(drm_atomic_set_fence_for_plane); + /** * drm_atomic_set_crtc_for_connector - set crtc for connector * @conn_state: atomic state object for the connector diff --git a/include/drm/drm_atomic.h b/include/drm/drm_atomic.h index 9701f2dfb784..d07a254baaec 100644 --- a/include/drm/drm_atomic.h +++ b/include/drm/drm_atomic.h @@ -316,6 +316,8 @@ drm_atomic_set_crtc_for_plane(struct drm_plane_state *plane_state, struct drm_crtc *crtc); void drm_atomic_set_fb_for_plane(struct drm_plane_state *plane_state, struct drm_framebuffer *fb); +void drm_atomic_set_fence_for_plane(struct drm_plane_state *plane_state, + struct fence *fence); int __must_check drm_atomic_set_crtc_for_connector(struct drm_connector_state *conn_state, struct drm_crtc *crtc); diff --git a/include/drm/drm_plane.h b/include/drm/drm_plane.h index 8b4dc62470ff..952ef84dc046 100644 --- a/include/drm/drm_plane.h +++ b/include/drm/drm_plane.h @@ -65,7 +65,7 @@ struct drm_plane_state { struct drm_crtc *crtc; /* do not write directly, use drm_atomic_set_crtc_for_plane() */ struct drm_framebuffer *fb; /* do not write directly, use drm_atomic_set_fb_for_plane() */ - struct fence *fence; + struct fence *fence; /* do not write directly, use drm_atomic_set_fence_for_plane() */ /* Signed dest location allows it to be partially off screen */ int32_t crtc_x, crtc_y; From cdf014c6a1fecc9b974b0e232a09059b663f5fd1 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Mon, 14 Nov 2016 11:07:31 +0100 Subject: [PATCH 216/396] BACKPORT: drm/fb_cma_helper: Add drm_fb_cma_prepare_fb() helper Add new drm_fb_cma_prepare_fb() helper function extracted from the imx-drm driver. This function checks if the plane has DMABUF attached to it, extracts the exclusive fence from it and attaches it to the plane state for the atomic helper to wait on it. Signed-off-by: Marek Vasut Cc: Daniel Vetter Cc: Lucas Stach Reviewed-by: Lucas Stach Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/20161114100732.3446-1-marex@denx.de (cherry picked from commit 14d7f96f90fb65c2ca0e0ac7df237e06ff001c29) Signed-off-by: Marissa Wall Change-Id: I3b7adb3c3217eed72e45c53c5c749f6218611df0 --- drivers/gpu/drm/drm_fb_cma_helper.c | 35 +++++++++++++++++++++++++++++ include/drm/drm_fb_cma_helper.h | 3 +++ 2 files changed, 38 insertions(+) diff --git a/drivers/gpu/drm/drm_fb_cma_helper.c b/drivers/gpu/drm/drm_fb_cma_helper.c index 1fd6eac1400c..52629b62b002 100644 --- a/drivers/gpu/drm/drm_fb_cma_helper.c +++ b/drivers/gpu/drm/drm_fb_cma_helper.c @@ -18,13 +18,16 @@ */ #include +#include #include #include #include #include #include +#include #include #include +#include #define DEFAULT_FBDEFIO_DELAY_MS 50 @@ -265,6 +268,38 @@ struct drm_gem_cma_object *drm_fb_cma_get_gem_obj(struct drm_framebuffer *fb, } EXPORT_SYMBOL_GPL(drm_fb_cma_get_gem_obj); +/** + * drm_fb_cma_prepare_fb() - Prepare CMA framebuffer + * @plane: Which plane + * @state: Plane state attach fence to + * + * This should be put into prepare_fb hook of struct &drm_plane_helper_funcs . + * + * This function checks if the plane FB has an dma-buf attached, extracts + * the exclusive fence and attaches it to plane state for the atomic helper + * to wait on. + * + * There is no need for cleanup_fb for CMA based framebuffer drivers. + */ +int drm_fb_cma_prepare_fb(struct drm_plane *plane, + struct drm_plane_state *state) +{ + struct dma_buf *dma_buf; + struct fence *fence; + + if ((plane->state->fb == state->fb) || !state->fb) + return 0; + + dma_buf = drm_fb_cma_get_gem_obj(state->fb, 0)->base.dma_buf; + if (dma_buf) { + fence = reservation_object_get_excl_rcu(dma_buf->resv); + drm_atomic_set_fence_for_plane(state, fence); + } + + return 0; +} +EXPORT_SYMBOL_GPL(drm_fb_cma_prepare_fb); + #ifdef CONFIG_DEBUG_FS static void drm_fb_cma_describe(struct drm_framebuffer *fb, struct seq_file *m) { diff --git a/include/drm/drm_fb_cma_helper.h b/include/drm/drm_fb_cma_helper.h index f313211f8ed5..cc82c73b07fc 100644 --- a/include/drm/drm_fb_cma_helper.h +++ b/include/drm/drm_fb_cma_helper.h @@ -41,6 +41,9 @@ struct drm_framebuffer *drm_fb_cma_create(struct drm_device *dev, struct drm_gem_cma_object *drm_fb_cma_get_gem_obj(struct drm_framebuffer *fb, unsigned int plane); +int drm_fb_cma_prepare_fb(struct drm_plane *plane, + struct drm_plane_state *state); + #ifdef CONFIG_DEBUG_FS struct seq_file; From d14cc2bbf09a22b04e0c5d8af86276efdd6c18aa Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Mon, 14 Nov 2016 11:55:40 +0000 Subject: [PATCH 217/396] BACKPORT: dma-buf: Use fence_get_rcu_safe() for retrieving the exclusive fence MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The current code is subject to a race where we may try to acquire a reference on a stale fence: [13703.335118] WARNING: CPU: 1 PID: 14975 at ./include/linux/kref.h:46 i915_gem_object_wait+0x1a3/0x1c0 [13703.335184] Modules linked in: [13703.335202] CPU: 1 PID: 14975 Comm: gem_concurrent_ Not tainted 4.9.0-rc4+ #26 [13703.335216] Hardware name: / , BIOS PYBSWCEL.86A.0027.2015.0507.1758 05/07/2015 [13703.335233] ffffc90002f5bcc8 ffffffff812807de 0000000000000000 0000000000000000 [13703.335257] ffffc90002f5bd08 ffffffff81073811 0000002e80000000 ffff88026bf7c780 [13703.335279] 7fffffffffffffff 0000000000000001 ffff88027045a550 ffff88026bf7c780 [13703.335301] Call Trace: [13703.335316] [] dump_stack+0x4d/0x6f [13703.335331] [] __warn+0xc1/0xe0 [13703.335343] [] warn_slowpath_null+0x18/0x20 [13703.335355] [] i915_gem_object_wait+0x1a3/0x1c0 [13703.335367] [] i915_gem_set_domain_ioctl+0xcc/0x330 [13703.335386] [] drm_ioctl+0x1cb/0x410 [13703.335400] [] ? i915_gem_obj_prepare_shmem_write+0x1d0/0x1d0 [13703.335416] [] ? drm_ioctl+0x2bb/0x410 [13703.335429] [] do_vfs_ioctl+0x8f/0x5c0 [13703.335442] [] SyS_ioctl+0x3c/0x70 [13703.335456] [] entry_SYSCALL_64_fastpath+0x17/0x98 [13703.335558] ---[ end trace fd24176416ba6981 ]--- [13703.382778] general protection fault: 0000 [#1] SMP [13703.382802] Modules linked in: [13703.382816] CPU: 1 PID: 14967 Comm: gem_concurrent_ Tainted: G W 4.9.0-rc4+ #26 [13703.382828] Hardware name: / , BIOS PYBSWCEL.86A.0027.2015.0507.1758 05/07/2015 [13703.382841] task: ffff880275458000 task.stack: ffffc90002f18000 [13703.382849] RIP: 0010:[] [] i915_gem_request_retire+0x2b4/0x320 [13703.382870] RSP: 0018:ffffc90002f1bbc8 EFLAGS: 00010293 [13703.382878] RAX: dead000000000200 RBX: ffff88026bf7dce8 RCX: dead000000000100 [13703.382887] RDX: dead000000000100 RSI: ffff88026bf7c930 RDI: ffff88026bf7dd00 [13703.382897] RBP: ffffc90002f1bbf8 R08: 00000000ffffffff R09: ffff88026b89a000 [13703.382905] R10: 0000000000000001 R11: ffff88026bbe8fe0 R12: ffff88026bf7c000 [13703.382913] R13: ffff880275af8000 R14: ffff88026bf7c180 R15: dead000000000200 [13703.382922] FS: 00007f89e787d740(0000) GS:ffff88027fd00000(0000) knlGS:0000000000000000 [13703.382934] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [13703.382942] CR2: 00007f9053d2e000 CR3: 000000026d414000 CR4: 00000000001006e0 [13703.382951] Stack: [13703.382958] ffff880275413000 ffffc90002f1bde8 ffff880275af8000 ffff880274e8a600 [13703.382976] ffff880276a06000 ffffc90002f1bde8 ffffc90002f1bc38 ffffffff813b48c5 [13703.382995] ffffc90002f1bc00 ffffc90002f1bde8 ffff88026972a440 0000000000000000 [13703.383021] Call Trace: [13703.383032] [] i915_gem_request_alloc+0xa5/0x350 [13703.383043] [] i915_gem_do_execbuffer.isra.41+0x7b3/0x18b0 [13703.383055] [] ? i915_gem_object_get_sg+0x25c/0x2b0 [13703.383065] [] ? i915_gem_object_get_page+0x1d/0x50 [13703.383076] [] ? i915_gem_pwrite_ioctl+0x66c/0x6d0 [13703.383086] [] i915_gem_execbuffer2+0x95/0x1e0 [13703.383096] [] drm_ioctl+0x1cb/0x410 [13703.383105] [] ? i915_gem_execbuffer+0x2d0/0x2d0 [13703.383117] [] ? hrtimer_start_range_ns+0x1a0/0x310 [13703.383128] [] do_vfs_ioctl+0x8f/0x5c0 [13703.383140] [] ? SyS_timer_settime+0x118/0x1a0 [13703.383150] [] SyS_ioctl+0x3c/0x70 [13703.383162] [] entry_SYSCALL_64_fastpath+0x17/0x98 [13703.383172] Code: 49 39 c6 48 8d 70 e8 48 8d 5f e8 75 16 eb 47 48 8d 43 18 48 8b 53 18 48 89 de 49 39 c6 48 8d 5a e8 74 33 48 8b 56 08 48 8b 46 10 <48> 89 42 08 48 89 10 f6 46 38 01 48 89 4e 08 4c 89 7e 10 74 cf [13703.383557] RIP [] i915_gem_request_retire+0x2b4/0x320 [13703.383570] RSP [13703.383586] ---[ end trace fd24176416ba6982 ]--- This is fixed by using the kref_get_unless_zero() as a full memory barrier to validate the fence is still the current exclusive fence before returning it back to the caller. (Note the fix only requires using fence_get_rcu() and correct handling, but we may as well use the helper rather than inline equivalent code.) Note: Issue can only be hit with the i915 driver. Signed-off-by: Chris Wilson Cc: Sumit Semwal . Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/20161114115540.31155-1-chris@chris-wilson.co.uk (cherry picked from commit 6bfec6d94556683c91c937a20576118183af9e1d) Signed-off-by: Marissa Wall Change-Id: I97d60ddd81b27281c326d7afa07e456f9ac7c125 --- include/linux/reservation.h | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/include/linux/reservation.h b/include/linux/reservation.h index b0f305e77b7f..bad7710866af 100644 --- a/include/linux/reservation.h +++ b/include/linux/reservation.h @@ -177,17 +177,14 @@ static inline struct fence * reservation_object_get_excl_rcu(struct reservation_object *obj) { struct fence *fence; - unsigned seq; -retry: - seq = read_seqcount_begin(&obj->seq); + + if (!rcu_access_pointer(obj->fence_excl)) + return NULL; + rcu_read_lock(); - fence = rcu_dereference(obj->fence_excl); - if (read_seqcount_retry(&obj->seq, seq)) { - rcu_read_unlock(); - goto retry; - } - fence = fence_get(fence); + fence = fence_get_rcu_safe(&obj->fence_excl); rcu_read_unlock(); + return fence; } From 96e02f4de5ee300033f2832432d771480db7d124 Mon Sep 17 00:00:00 2001 From: Gustavo Padovan Date: Tue, 15 Nov 2016 22:06:39 +0900 Subject: [PATCH 218/396] BACKPORT: drm/fence: add in-fences support There is now a new property called IN_FENCE_FD attached to every plane state that receives sync_file fds from userspace via the atomic commit IOCTL. The fd is then translated to a fence (that may be a fence_array subclass or just a normal fence) and then used by DRM to fence_wait() for all fences in the sync_file to signal. So it only commits when all framebuffers are ready to scanout. v2: Comments by Daniel Vetter: - remove set state->fence = NULL in destroy phase - accept fence -1 as valid and just return 0 - do not call fence_get() - sync_file_fences_get() already calls it - fence_put() if state->fence is already set, in case userspace set the property more than once. v3: WARN_ON if fence is set but state has no FB v4: Comment from Maarten Lankhorst - allow set fence with no related fb v5: rename FENCE_FD to IN_FENCE_FD v6: Comments by Daniel Vetter: - rename plane_state->in_fence back to "fence" - re-introduce WARN_ON if fence set but no fb - rebase after fence -> dma_fence rename v7: Comments by Brian Starkey - set state->fence to NULL when duplicating the state - fail if IN_FENCE_FD was already set v8: rebase against latest drm-misc Signed-off-by: Gustavo Padovan Reviewed-by: Brian Starkey Reviewed-by: Sean Paul Tested-by: Robert Foss [danvet: Rebase onto extracted drm_mode_config.[hc].] Signed-off-by: Daniel Vetter (cherry picked from commit 9626014258a5957ff120b3987ee72decdbe0c798) Signed-off-by: Marissa Wall Change-Id: I1a4e7395bc7709b457544c5086611122d4602a61 --- drivers/gpu/drm/Kconfig | 1 + drivers/gpu/drm/drm_atomic.c | 14 ++++++++++++++ drivers/gpu/drm/drm_atomic_helper.c | 3 +++ drivers/gpu/drm/drm_crtc.c | 6 ++++++ drivers/gpu/drm/drm_plane.c | 1 + include/drm/drm_crtc.h | 5 +++++ 6 files changed, 30 insertions(+) diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig index 483059a22b1b..43cb33dc8333 100644 --- a/drivers/gpu/drm/Kconfig +++ b/drivers/gpu/drm/Kconfig @@ -12,6 +12,7 @@ menuconfig DRM select I2C select I2C_ALGOBIT select DMA_SHARED_BUFFER + select SYNC_FILE help Kernel-level support for the Direct Rendering Infrastructure (DRI) introduced in XFree86 4.0. If you say Y here, you need to select diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c index aa1e2b5935fc..6c0626bee74e 100644 --- a/drivers/gpu/drm/drm_atomic.c +++ b/drivers/gpu/drm/drm_atomic.c @@ -30,6 +30,7 @@ #include #include #include +#include #include "drm_crtc_internal.h" @@ -693,6 +694,17 @@ int drm_atomic_plane_set_property(struct drm_plane *plane, drm_atomic_set_fb_for_plane(state, fb); if (fb) drm_framebuffer_unreference(fb); + } else if (property == config->prop_in_fence_fd) { + if (state->fence) + return -EINVAL; + + if (U642I64(val) == -1) + return 0; + + state->fence = sync_file_get_fence(val); + if (!state->fence) + return -EINVAL; + } else if (property == config->prop_crtc_id) { struct drm_crtc *crtc = drm_crtc_find(dev, val); return drm_atomic_set_crtc_for_plane(state, crtc); @@ -752,6 +764,8 @@ drm_atomic_plane_get_property(struct drm_plane *plane, if (property == config->prop_fb_id) { *val = (state->fb) ? state->fb->base.id : 0; + } else if (property == config->prop_in_fence_fd) { + *val = -1; } else if (property == config->prop_crtc_id) { *val = (state->crtc) ? state->crtc->base.id : 0; } else if (property == config->prop_crtc_x) { diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index 50acd799babe..f34b4e8455a6 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -3166,6 +3166,9 @@ void __drm_atomic_helper_plane_destroy_state(struct drm_plane_state *state) { if (state->fb) drm_framebuffer_unreference(state->fb); + + if (state->fence) + fence_put(state->fence); } EXPORT_SYMBOL(__drm_atomic_helper_plane_destroy_state); diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index 2d7bedf28647..30f45ebd59dc 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -365,6 +365,12 @@ static int drm_mode_create_standard_properties(struct drm_device *dev) return -ENOMEM; dev->mode_config.prop_fb_id = prop; + prop = drm_property_create_signed_range(dev, DRM_MODE_PROP_ATOMIC, + "IN_FENCE_FD", -1, INT_MAX); + if (!prop) + return -ENOMEM; + dev->mode_config.prop_in_fence_fd = prop; + prop = drm_property_create_object(dev, DRM_MODE_PROP_ATOMIC, "CRTC_ID", DRM_MODE_OBJECT_CRTC); if (!prop) diff --git a/drivers/gpu/drm/drm_plane.c b/drivers/gpu/drm/drm_plane.c index 249c0ae52c6d..3957ef8f026b 100644 --- a/drivers/gpu/drm/drm_plane.c +++ b/drivers/gpu/drm/drm_plane.c @@ -137,6 +137,7 @@ int drm_universal_plane_init(struct drm_device *dev, struct drm_plane *plane, if (drm_core_check_feature(dev, DRIVER_ATOMIC)) { drm_object_attach_property(&plane->base, config->prop_fb_id, 0); + drm_object_attach_property(&plane->base, config->prop_in_fence_fd, -1); drm_object_attach_property(&plane->base, config->prop_crtc_id, 0); drm_object_attach_property(&plane->base, config->prop_crtc_x, 0); drm_object_attach_property(&plane->base, config->prop_crtc_y, 0); diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index 0aa292526567..3851b68fbe11 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h @@ -1159,6 +1159,11 @@ struct drm_mode_config { * &drm_framebuffer. */ struct drm_property *prop_fb_id; + /** + * @prop_in_fence_fd: Sync File fd representing the incoming fences + * for a Plane. + */ + struct drm_property *prop_in_fence_fd; /** * @prop_crtc_id: Default atomic plane property to specify the * &drm_crtc. From 2a38015dd306f16da8e72c427cdba0f239e4b38d Mon Sep 17 00:00:00 2001 From: Gustavo Padovan Date: Tue, 15 Nov 2016 23:37:08 +0900 Subject: [PATCH 219/396] BACKPORT: drm/fence: add fence timeline to drm_crtc MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Create one timeline context for each CRTC to be able to handle out-fences and signal them. It adds a few members to struct drm_crtc: fence_context, where we store the context we get from fence_context_alloc(), the fence seqno and the fence lock, that we pass in fence_init() to be used by the fence. v2: Comment by Daniel Stone: - add BUG_ON() to fence_to_crtc() macro v3: Comment by Ville Syrjälä - Use more meaningful name as crtc timeline name v4: Comments by Brian Starkey - Use even more meaninful name for the crtc timeline - add doc for timeline_name Comment by Daniel Vetter - use in-line style for comments - rebase after fence -> dma_fence rename [removed in backport to Android common kernel 4.9] v5: Comment by Daniel Vetter - Add doc for drm_crtc_fence_ops v6: Comment by Chris Wilson - Move fence_to_crtc to drm_crtc.c - Move export of drm_crtc_fence_ops to drm_crtc_internal.h - rebase against latest drm-misc Signed-off-by: Gustavo Padovan Reviewed-by: Daniel Vetter (v5) Reviewed-by: Sean Paul (v5) Tested-by: Robert Foss (v5) Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/1479220628-10204-1-git-send-email-gustavo@padovan.org (cherry picked from commit 6d6003c4b613c93973e4e870d83f4bed2ad9ac34) Signed-off-by: Marissa Wall Change-Id: Id1722e5611757509ec311b56c70fa985a2d5035a --- drivers/gpu/drm/drm_crtc.c | 38 +++++++++++++++++++++++++++++ drivers/gpu/drm/drm_crtc_internal.h | 2 ++ include/drm/drm_crtc.h | 29 ++++++++++++++++++++++ 3 files changed, 69 insertions(+) diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index 30f45ebd59dc..68c554135db6 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -33,6 +33,7 @@ #include #include #include +#include #include #include #include @@ -141,6 +142,38 @@ static void drm_crtc_unregister_all(struct drm_device *dev) } } +static struct drm_crtc *fence_to_crtc(struct fence *fence) +{ + BUG_ON(fence->ops != &drm_crtc_fence_ops); + return container_of(fence->lock, struct drm_crtc, fence_lock); +} + +static const char *drm_crtc_fence_get_driver_name(struct fence *fence) +{ + struct drm_crtc *crtc = fence_to_crtc(fence); + + return crtc->dev->driver->name; +} + +static const char *drm_crtc_fence_get_timeline_name(struct fence *fence) +{ + struct drm_crtc *crtc = fence_to_crtc(fence); + + return crtc->timeline_name; +} + +static bool drm_crtc_fence_enable_signaling(struct fence *fence) +{ + return true; +} + +const struct fence_ops drm_crtc_fence_ops = { + .get_driver_name = drm_crtc_fence_get_driver_name, + .get_timeline_name = drm_crtc_fence_get_timeline_name, + .enable_signaling = drm_crtc_fence_enable_signaling, + .wait = fence_default_wait, +}; + /** * drm_crtc_init_with_planes - Initialise a new CRTC object with * specified primary and cursor planes. @@ -198,6 +231,11 @@ int drm_crtc_init_with_planes(struct drm_device *dev, struct drm_crtc *crtc, return -ENOMEM; } + crtc->fence_context = fence_context_alloc(1); + spin_lock_init(&crtc->fence_lock); + snprintf(crtc->timeline_name, sizeof(crtc->timeline_name), + "CRTC:%d-%s", crtc->base.id, crtc->name); + crtc->base.properties = &crtc->properties; list_add_tail(&crtc->head, &config->crtc_list); diff --git a/drivers/gpu/drm/drm_crtc_internal.h b/drivers/gpu/drm/drm_crtc_internal.h index c48ba02c5365..c0a8a6f1f496 100644 --- a/drivers/gpu/drm/drm_crtc_internal.h +++ b/drivers/gpu/drm/drm_crtc_internal.h @@ -41,6 +41,8 @@ int drm_crtc_check_viewport(const struct drm_crtc *crtc, const struct drm_display_mode *mode, const struct drm_framebuffer *fb); +extern const struct fence_ops drm_crtc_fence_ops; + void drm_fb_release(struct drm_file *file_priv); /* dumb buffer support IOCTLs */ diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index 3851b68fbe11..8d636c65813e 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h @@ -680,6 +680,35 @@ struct drm_crtc { * context. */ struct drm_modeset_acquire_ctx *acquire_ctx; + + /** + * @fence_context: + * + * timeline context used for fence operations. + */ + unsigned int fence_context; + + /** + * @fence_lock: + * + * spinlock to protect the fences in the fence_context. + */ + + spinlock_t fence_lock; + /** + * @fence_seqno: + * + * Seqno variable used as monotonic counter for the fences + * created on the CRTC's timeline. + */ + unsigned long fence_seqno; + + /** + * @timeline_name: + * + * The name of the CRTC's fence timeline. + */ + char timeline_name[32]; }; /** From 710c1edc0ee8ec4f3b694a8171a691cd266b83f6 Mon Sep 17 00:00:00 2001 From: Gustavo Padovan Date: Wed, 16 Nov 2016 22:00:21 +0900 Subject: [PATCH 220/396] BACKPORT: drm/fence: add out-fences support Support DRM out-fences by creating a sync_file with a fence for each CRTC that sets the OUT_FENCE_PTR property. We use the out_fence pointer received in the OUT_FENCE_PTR prop to send the sync_file fd back to userspace. The sync_file and fd are allocated/created before commit, but the fd_install operation only happens after we know that commit succeed. v2: Comment by Rob Clark: - Squash commit that adds DRM_MODE_ATOMIC_OUT_FENCE flag here. Comment by Daniel Vetter: - Add clean up code for out_fences v3: Comments by Daniel Vetter: - create DRM_MODE_ATOMIC_EVENT_MASK - userspace should fill out_fences_ptr with the crtc_ids for which it wants fences back. v4: Create OUT_FENCE_PTR properties and remove old approach. v5: Comments by Brian Starkey: - Remove extra fence_get() in atomic_ioctl() - Check ret before iterating on the crtc_state - check ret before fd_install - set fence_state to NULL at the beginning - check fence_state->out_fence_ptr before put_user() - change order of fput() and put_unused_fd() on failure - Add access_ok() check to the out_fence_ptr received - Rebase after fence -> dma_fence rename [removed in backport to Android common kernel 4.9] - Store out_fence_ptr in the drm_atomic_state - Split crtc_setup_out_fence() - return -1 as out_fence with TEST_ONLY flag v6: Comments by Daniel Vetter - Add prepare/unprepare_crtc_signaling() - move struct drm_out_fence_state to drm_atomic.c - mark get_crtc_fence() as static Comments by Brian Starkey - proper set fence_ptr fence_state array - isolate fence_idx increment - improve error handling v7: Comments by Daniel Vetter - remove prefix from internal functions - make out_fence_ptr an s64 pointer - degrade DRM_INFO to DRM_DEBUG_ATOMIC when put_user fail - fix doc issues - filter out OUT_FENCE_PTR == NULL and do not fail in this case - add complete_crtc_signalling() - krealloc fence_state on demand Comment by Brian Starkey - remove unused crtc_state arg from get_out_fence() v8: Comment by Brian Starkey - cancel events before check for !fence_state - convert a few lefovers u64 types for out_fence_ptr - fix memleak by assign fence_state earlier after realloc - proper accout num_fences in case of error v9: Comment by Brian Starkey - memset last position of fence_state after krealloc Comments by Sean Paul - pass install_fds in complete_crtc_signaling() instead of ret - put_user(-1, fence_ptr) when decoding props v10: Comment by Brian Starkey - remove unneeded num_fences increment on error path - kfree fence_state after installing fences fd v11: rebase against latest drm-misc v12: rebase again against latest drm-misc Signed-off-by: Gustavo Padovan Reviewed-by: Brian Starkey (v10) Reviewed-by: Sean Paul Tested-by: Robert Foss (v10) [danvet: Appease checkpatch.] Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/1479301221-13056-1-git-send-email-gustavo@padovan.org (cherry picked from commit beaf5af48034c9e2ebb8b2b1fb12dc4d8aeba99e) Signed-off-by: Marissa Wall Change-Id: I5fed59f7358aaf3f3acd7a4ca9c85091f23cdbf5 --- drivers/gpu/drm/drm_atomic.c | 241 ++++++++++++++++++++++++++++------- drivers/gpu/drm/drm_crtc.c | 8 ++ include/drm/drm_atomic.h | 1 + include/drm/drm_crtc.h | 6 + 4 files changed, 211 insertions(+), 45 deletions(-) diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c index 6c0626bee74e..b0d0636db5f1 100644 --- a/drivers/gpu/drm/drm_atomic.c +++ b/drivers/gpu/drm/drm_atomic.c @@ -293,6 +293,23 @@ drm_atomic_get_crtc_state(struct drm_atomic_state *state, } EXPORT_SYMBOL(drm_atomic_get_crtc_state); +static void set_out_fence_for_crtc(struct drm_atomic_state *state, + struct drm_crtc *crtc, s64 __user *fence_ptr) +{ + state->crtcs[drm_crtc_index(crtc)].out_fence_ptr = fence_ptr; +} + +static s64 __user *get_out_fence_for_crtc(struct drm_atomic_state *state, + struct drm_crtc *crtc) +{ + s64 __user *fence_ptr; + + fence_ptr = state->crtcs[drm_crtc_index(crtc)].out_fence_ptr; + state->crtcs[drm_crtc_index(crtc)].out_fence_ptr = NULL; + + return fence_ptr; +} + /** * drm_atomic_set_mode_for_crtc - set mode for CRTC * @state: the CRTC whose incoming state to update @@ -497,6 +514,16 @@ int drm_atomic_crtc_set_property(struct drm_crtc *crtc, &replaced); state->color_mgmt_changed |= replaced; return ret; + } else if (property == config->prop_out_fence_ptr) { + s64 __user *fence_ptr = u64_to_user_ptr(val); + + if (!fence_ptr) + return 0; + + if (put_user(-1, fence_ptr)) + return -EFAULT; + + set_out_fence_for_crtc(state->state, crtc, fence_ptr); } else if (crtc->funcs->atomic_set_property) return crtc->funcs->atomic_set_property(crtc, state, property, val); else @@ -539,6 +566,8 @@ drm_atomic_crtc_get_property(struct drm_crtc *crtc, *val = (state->ctm) ? state->ctm->base.id : 0; else if (property == config->gamma_lut_property) *val = (state->gamma_lut) ? state->gamma_lut->base.id : 0; + else if (property == config->prop_out_fence_ptr) + *val = 0; else if (crtc->funcs->atomic_get_property) return crtc->funcs->atomic_get_property(crtc, state, property, val); else @@ -1511,11 +1540,9 @@ EXPORT_SYMBOL(drm_atomic_nonblocking_commit); */ static struct drm_pending_vblank_event *create_vblank_event( - struct drm_device *dev, struct drm_file *file_priv, - struct fence *fence, uint64_t user_data) + struct drm_device *dev, uint64_t user_data) { struct drm_pending_vblank_event *e = NULL; - int ret; e = kzalloc(sizeof *e, GFP_KERNEL); if (!e) @@ -1525,17 +1552,6 @@ static struct drm_pending_vblank_event *create_vblank_event( e->event.base.length = sizeof(e->event); e->event.user_data = user_data; - if (file_priv) { - ret = drm_event_reserve_init(dev, file_priv, &e->base, - &e->event.base); - if (ret) { - kfree(e); - return NULL; - } - } - - e->base.fence = fence; - return e; } @@ -1640,6 +1656,165 @@ void drm_atomic_clean_old_fb(struct drm_device *dev, } EXPORT_SYMBOL(drm_atomic_clean_old_fb); +static struct fence *get_crtc_fence(struct drm_crtc *crtc) +{ + struct fence *fence; + + fence = kzalloc(sizeof(*fence), GFP_KERNEL); + if (!fence) + return NULL; + + fence_init(fence, &drm_crtc_fence_ops, &crtc->fence_lock, + crtc->fence_context, ++crtc->fence_seqno); + + return fence; +} + +struct drm_out_fence_state { + s64 __user *out_fence_ptr; + struct sync_file *sync_file; + int fd; +}; + +static int setup_out_fence(struct drm_out_fence_state *fence_state, + struct fence *fence) +{ + fence_state->fd = get_unused_fd_flags(O_CLOEXEC); + if (fence_state->fd < 0) + return fence_state->fd; + + if (put_user(fence_state->fd, fence_state->out_fence_ptr)) + return -EFAULT; + + fence_state->sync_file = sync_file_create(fence); + if (!fence_state->sync_file) + return -ENOMEM; + + return 0; +} + +static int prepare_crtc_signaling(struct drm_device *dev, + struct drm_atomic_state *state, + struct drm_mode_atomic *arg, + struct drm_file *file_priv, + struct drm_out_fence_state **fence_state, + unsigned int *num_fences) +{ + struct drm_crtc *crtc; + struct drm_crtc_state *crtc_state; + int i, ret; + + if (arg->flags & DRM_MODE_ATOMIC_TEST_ONLY) + return 0; + + for_each_crtc_in_state(state, crtc, crtc_state, i) { + u64 __user *fence_ptr; + + fence_ptr = get_out_fence_for_crtc(crtc_state->state, crtc); + + if (arg->flags & DRM_MODE_PAGE_FLIP_EVENT || fence_ptr) { + struct drm_pending_vblank_event *e; + + e = create_vblank_event(dev, arg->user_data); + if (!e) + return -ENOMEM; + + crtc_state->event = e; + } + + if (arg->flags & DRM_MODE_PAGE_FLIP_EVENT) { + struct drm_pending_vblank_event *e = crtc_state->event; + + if (!file_priv) + continue; + + ret = drm_event_reserve_init(dev, file_priv, &e->base, + &e->event.base); + if (ret) { + kfree(e); + crtc_state->event = NULL; + return ret; + } + } + + if (fence_ptr) { + struct fence *fence; + struct drm_out_fence_state *f; + + f = krealloc(*fence_state, sizeof(**fence_state) * + (*num_fences + 1), GFP_KERNEL); + if (!f) + return -ENOMEM; + + memset(&f[*num_fences], 0, sizeof(*f)); + + f[*num_fences].out_fence_ptr = fence_ptr; + *fence_state = f; + + fence = get_crtc_fence(crtc); + if (!fence) + return -ENOMEM; + + ret = setup_out_fence(&f[(*num_fences)++], fence); + if (ret) { + fence_put(fence); + return ret; + } + + crtc_state->event->base.fence = fence; + } + } + + return 0; +} + +static void complete_crtc_signaling(struct drm_device *dev, + struct drm_atomic_state *state, + struct drm_out_fence_state *fence_state, + unsigned int num_fences, + bool install_fds) +{ + struct drm_crtc *crtc; + struct drm_crtc_state *crtc_state; + int i; + + if (install_fds) { + for (i = 0; i < num_fences; i++) + fd_install(fence_state[i].fd, + fence_state[i].sync_file->file); + + kfree(fence_state); + return; + } + + for_each_crtc_in_state(state, crtc, crtc_state, i) { + /* + * TEST_ONLY and PAGE_FLIP_EVENT are mutually + * exclusive, if they weren't, this code should be + * called on success for TEST_ONLY too. + */ + if (crtc_state->event) + drm_event_cancel_free(dev, &crtc_state->event->base); + } + + if (!fence_state) + return; + + for (i = 0; i < num_fences; i++) { + if (fence_state[i].sync_file) + fput(fence_state[i].sync_file->file); + if (fence_state[i].fd >= 0) + put_unused_fd(fence_state[i].fd); + + /* If this fails log error to the user */ + if (fence_state[i].out_fence_ptr && + put_user(-1, fence_state[i].out_fence_ptr)) + DRM_DEBUG_ATOMIC("Couldn't clear out_fence_ptr\n"); + } + + kfree(fence_state); +} + int drm_mode_atomic_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv) { @@ -1652,11 +1827,10 @@ int drm_mode_atomic_ioctl(struct drm_device *dev, struct drm_atomic_state *state; struct drm_modeset_acquire_ctx ctx; struct drm_plane *plane; - struct drm_crtc *crtc; - struct drm_crtc_state *crtc_state; + struct drm_out_fence_state *fence_state = NULL; unsigned plane_mask; int ret = 0; - unsigned int i, j; + unsigned int i, j, num_fences = 0; /* disallow for drivers not supporting atomic: */ if (!drm_core_check_feature(dev, DRIVER_ATOMIC)) @@ -1771,20 +1945,10 @@ retry: drm_mode_object_unreference(obj); } - if (arg->flags & DRM_MODE_PAGE_FLIP_EVENT) { - for_each_crtc_in_state(state, crtc, crtc_state, i) { - struct drm_pending_vblank_event *e; - - e = create_vblank_event(dev, file_priv, NULL, - arg->user_data); - if (!e) { - ret = -ENOMEM; - goto out; - } - - crtc_state->event = e; - } - } + ret = prepare_crtc_signaling(dev, state, arg, file_priv, &fence_state, + &num_fences); + if (ret) + goto out; if (arg->flags & DRM_MODE_ATOMIC_TEST_ONLY) { /* @@ -1801,20 +1965,7 @@ retry: out: drm_atomic_clean_old_fb(dev, plane_mask, ret); - if (ret && arg->flags & DRM_MODE_PAGE_FLIP_EVENT) { - /* - * Free the allocated event. drm_atomic_helper_setup_commit - * can allocate an event too, so only free it if it's ours - * to prevent a double free in drm_atomic_state_clear. - */ - for_each_crtc_in_state(state, crtc, crtc_state, i) { - struct drm_pending_vblank_event *event = crtc_state->event; - if (event && (event->base.fence || event->base.file_priv)) { - drm_event_cancel_free(dev, &event->base); - crtc_state->event = NULL; - } - } - } + complete_crtc_signaling(dev, state, fence_state, num_fences, !ret); if (ret == -EDEADLK) { drm_atomic_state_clear(state); diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index 68c554135db6..3c04159f186d 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -251,6 +251,8 @@ int drm_crtc_init_with_planes(struct drm_device *dev, struct drm_crtc *crtc, if (drm_core_check_feature(dev, DRIVER_ATOMIC)) { drm_object_attach_property(&crtc->base, config->prop_active, 0); drm_object_attach_property(&crtc->base, config->prop_mode_id, 0); + drm_object_attach_property(&crtc->base, + config->prop_out_fence_ptr, 0); } return 0; @@ -409,6 +411,12 @@ static int drm_mode_create_standard_properties(struct drm_device *dev) return -ENOMEM; dev->mode_config.prop_in_fence_fd = prop; + prop = drm_property_create_range(dev, DRM_MODE_PROP_ATOMIC, + "OUT_FENCE_PTR", 0, U64_MAX); + if (!prop) + return -ENOMEM; + dev->mode_config.prop_out_fence_ptr = prop; + prop = drm_property_create_object(dev, DRM_MODE_PROP_ATOMIC, "CRTC_ID", DRM_MODE_OBJECT_CRTC); if (!prop) diff --git a/include/drm/drm_atomic.h b/include/drm/drm_atomic.h index d07a254baaec..8eff4cb8199e 100644 --- a/include/drm/drm_atomic.h +++ b/include/drm/drm_atomic.h @@ -144,6 +144,7 @@ struct __drm_crtcs_state { struct drm_crtc *ptr; struct drm_crtc_state *state; struct drm_crtc_commit *commit; + s64 __user *out_fence_ptr; }; struct __drm_connnectors_state { diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index 8d636c65813e..9551bcd00db4 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h @@ -1193,6 +1193,12 @@ struct drm_mode_config { * for a Plane. */ struct drm_property *prop_in_fence_fd; + /** + * @prop_out_fence_ptr: Sync File fd pointer representing the + * outgoing fences for a CRTC. Userspace should provide a pointer to a + * value of type s64, and then cast that pointer to u64. + */ + struct drm_property *prop_out_fence_ptr; /** * @prop_crtc_id: Default atomic plane property to specify the * &drm_crtc. From 4dfd0ed795dc8df66ae49671ec7fa78d9ac2924a Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Tue, 31 Jan 2017 10:25:25 +0100 Subject: [PATCH 221/396] UPSTREAM: drm/atomic: Fix double free in drm_atomic_state_default_clear drm_atomic_helper_page_flip and drm_atomic_ioctl set their own events in crtc_state->event. But when it's set the event is freed in 2 places. Solve this by only freeing the event in the atomic ioctl when it allocated its own event. This has been broken twice. The first time when the code was introduced, but only in the corner case when an event is allocated, but more crtc's were included by atomic check and then failing. This can mostly happen when you do an atomic modeset in i915 and the display clock is changed, which forces all crtc's to be included to the state. This has been broken worse by adding in-fences support, which caused the double free to be done unconditionally. [IGT] kms_rotation_crc: starting subtest primary-rotation-180 ============================================================================= BUG kmalloc-128 (Tainted: G U ): Object already free ----------------------------------------------------------------------------- Disabling lock debugging due to kernel taint INFO: Allocated in drm_atomic_helper_setup_commit+0x285/0x2f0 [drm_kms_helper] age=0 cpu=3 pid=1529 ___slab_alloc+0x308/0x3b0 __slab_alloc+0xd/0x20 kmem_cache_alloc_trace+0x92/0x1c0 drm_atomic_helper_setup_commit+0x285/0x2f0 [drm_kms_helper] intel_atomic_commit+0x35/0x4f0 [i915] drm_atomic_commit+0x46/0x50 [drm] drm_mode_atomic_ioctl+0x7d4/0xab0 [drm] drm_ioctl+0x2b3/0x490 [drm] do_vfs_ioctl+0x69c/0x700 SyS_ioctl+0x4e/0x80 entry_SYSCALL_64_fastpath+0x13/0x94 INFO: Freed in drm_event_cancel_free+0xa3/0xb0 [drm] age=0 cpu=3 pid=1529 __slab_free+0x48/0x2e0 kfree+0x159/0x1a0 drm_event_cancel_free+0xa3/0xb0 [drm] drm_mode_atomic_ioctl+0x86d/0xab0 [drm] drm_ioctl+0x2b3/0x490 [drm] do_vfs_ioctl+0x69c/0x700 SyS_ioctl+0x4e/0x80 entry_SYSCALL_64_fastpath+0x13/0x94 INFO: Slab 0xffffde1f0997b080 objects=17 used=2 fp=0xffff92fb65ec2578 flags=0x200000000008101 INFO: Object 0xffff92fb65ec2578 @offset=1400 fp=0xffff92fb65ec2ae8 Redzone ffff92fb65ec2570: bb bb bb bb bb bb bb bb ........ Object ffff92fb65ec2578: 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b kkkkkkkkkkkkkkkk Object ffff92fb65ec2588: 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b kkkkkkkkkkkkkkkk Object ffff92fb65ec2598: 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b kkkkkkkkkkkkkkkk Object ffff92fb65ec25a8: 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b kkkkkkkkkkkkkkkk Object ffff92fb65ec25b8: 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b kkkkkkkkkkkkkkkk Object ffff92fb65ec25c8: 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b kkkkkkkkkkkkkkkk Object ffff92fb65ec25d8: 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b kkkkkkkkkkkkkkkk Object ffff92fb65ec25e8: 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b a5 kkkkkkkkkkkkkkk. Redzone ffff92fb65ec25f8: bb bb bb bb bb bb bb bb ........ Padding ffff92fb65ec2738: 5a 5a 5a 5a 5a 5a 5a 5a ZZZZZZZZ CPU: 3 PID: 180 Comm: kworker/3:2 Tainted: G BU 4.10.0-rc6-patser+ #5039 Hardware name: /NUC5PPYB, BIOS PYBSWCEL.86A.0031.2015.0601.1712 06/01/2015 Workqueue: events intel_atomic_helper_free_state [i915] Call Trace: dump_stack+0x4d/0x6d print_trailer+0x20c/0x220 free_debug_processing+0x1c6/0x330 ? drm_atomic_state_default_clear+0xf7/0x1c0 [drm] __slab_free+0x48/0x2e0 ? drm_atomic_state_default_clear+0xf7/0x1c0 [drm] kfree+0x159/0x1a0 drm_atomic_state_default_clear+0xf7/0x1c0 [drm] ? drm_atomic_state_clear+0x30/0x30 [drm] intel_atomic_state_clear+0xd/0x20 [i915] drm_atomic_state_clear+0x1a/0x30 [drm] __drm_atomic_state_free+0x13/0x60 [drm] intel_atomic_helper_free_state+0x5d/0x70 [i915] process_one_work+0x260/0x4a0 worker_thread+0x2d1/0x4f0 kthread+0x127/0x130 ? process_one_work+0x4a0/0x4a0 ? kthread_stop+0x120/0x120 ret_from_fork+0x29/0x40 FIX kmalloc-128: Object at 0xffff92fb65ec2578 not freed Fixes: 3b24f7d67581 ("drm/atomic: Add struct drm_crtc_commit to track async updates") Fixes: 9626014258a5 ("drm/fence: add in-fences support") Cc: # v4.8+ Cc: Daniel Vetter Signed-off-by: Maarten Lankhorst Reviewed-by: Daniel Vetter Reviewed-by: Gustavo Padovan Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/1485854725-27640-1-git-send-email-maarten.lankhorst@linux.intel.com (cherry picked from commit 92c715fca907686f5298220ece53423e38ba3aed) Signed-off-by: Marissa Wall Change-Id: Idc052b33ae28e2092ccdbb20a6df726f121acc7c --- drivers/gpu/drm/drm_atomic.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c index b0d0636db5f1..e9c31d350f70 100644 --- a/drivers/gpu/drm/drm_atomic.c +++ b/drivers/gpu/drm/drm_atomic.c @@ -1788,13 +1788,16 @@ static void complete_crtc_signaling(struct drm_device *dev, } for_each_crtc_in_state(state, crtc, crtc_state, i) { + struct drm_pending_vblank_event *event = crtc_state->event; /* - * TEST_ONLY and PAGE_FLIP_EVENT are mutually - * exclusive, if they weren't, this code should be - * called on success for TEST_ONLY too. + * Free the allocated event. drm_atomic_helper_setup_commit + * can allocate an event too, so only free it if it's ours + * to prevent a double free in drm_atomic_state_clear. */ - if (crtc_state->event) - drm_event_cancel_free(dev, &crtc_state->event->base); + if (event && (event->base.fence || event->base.file_priv)) { + drm_event_cancel_free(dev, &event->base); + crtc_state->event = NULL; + } } if (!fence_state) From 50696b306d8007f23ce19e07cfd88c7098fece06 Mon Sep 17 00:00:00 2001 From: Gustavo Padovan Date: Tue, 22 Nov 2016 09:11:28 +0900 Subject: [PATCH 222/396] UPSTREAM: drm/fences: add DOC: for explicit fencing Document IN_FENCE_FD and OUT_FENCE_PTR properties. v2: incorporate comments from Daniel Vetter Signed-off-by: Gustavo Padovan [danvet: s/async/nonblocking/ atomic commits.] Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/1479773488-15048-1-git-send-email-gustavo@padovan.org (cherry picked from commit 9a83a71ac0d57ceffa32cbbb438ded055ab77887) Signed-off-by: Marissa Wall Change-Id: I30f045523988648baf3d219a80c0438b2433822a --- Documentation/gpu/drm-kms.rst | 6 ++++ drivers/gpu/drm/drm_atomic.c | 52 +++++++++++++++++++++++++++++++++++ 2 files changed, 58 insertions(+) diff --git a/Documentation/gpu/drm-kms.rst b/Documentation/gpu/drm-kms.rst index 53b872c105d2..db86cda6fa34 100644 --- a/Documentation/gpu/drm-kms.rst +++ b/Documentation/gpu/drm-kms.rst @@ -308,6 +308,12 @@ Color Management Properties .. kernel-doc:: drivers/gpu/drm/drm_color_mgmt.c :export: +Explicit Fencing Properties +--------------------------- + +.. kernel-doc:: drivers/gpu/drm/drm_atomic.c + :doc: explicit fencing properties + Existing KMS Properties ----------------------- diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c index e9c31d350f70..320b4e7b3541 100644 --- a/drivers/gpu/drm/drm_atomic.c +++ b/drivers/gpu/drm/drm_atomic.c @@ -1656,6 +1656,58 @@ void drm_atomic_clean_old_fb(struct drm_device *dev, } EXPORT_SYMBOL(drm_atomic_clean_old_fb); +/** + * DOC: explicit fencing properties + * + * Explicit fencing allows userspace to control the buffer synchronization + * between devices. A Fence or a group of fences are transfered to/from + * userspace using Sync File fds and there are two DRM properties for that. + * IN_FENCE_FD on each DRM Plane to send fences to the kernel and + * OUT_FENCE_PTR on each DRM CRTC to receive fences from the kernel. + * + * As a contrast, with implicit fencing the kernel keeps track of any + * ongoing rendering, and automatically ensures that the atomic update waits + * for any pending rendering to complete. For shared buffers represented with + * a struct &dma_buf this is tracked in &reservation_object structures. + * Implicit syncing is how Linux traditionally worked (e.g. DRI2/3 on X.org), + * whereas explicit fencing is what Android wants. + * + * "IN_FENCE_FD”: + * Use this property to pass a fence that DRM should wait on before + * proceeding with the Atomic Commit request and show the framebuffer for + * the plane on the screen. The fence can be either a normal fence or a + * merged one, the sync_file framework will handle both cases and use a + * fence_array if a merged fence is received. Passing -1 here means no + * fences to wait on. + * + * If the Atomic Commit request has the DRM_MODE_ATOMIC_TEST_ONLY flag + * it will only check if the Sync File is a valid one. + * + * On the driver side the fence is stored on the @fence parameter of + * struct &drm_plane_state. Drivers which also support implicit fencing + * should set the implicit fence using drm_atomic_set_fence_for_plane(), + * to make sure there's consistent behaviour between drivers in precedence + * of implicit vs. explicit fencing. + * + * "OUT_FENCE_PTR”: + * Use this property to pass a file descriptor pointer to DRM. Once the + * Atomic Commit request call returns OUT_FENCE_PTR will be filled with + * the file descriptor number of a Sync File. This Sync File contains the + * CRTC fence that will be signaled when all framebuffers present on the + * Atomic Commit * request for that given CRTC are scanned out on the + * screen. + * + * The Atomic Commit request fails if a invalid pointer is passed. If the + * Atomic Commit request fails for any other reason the out fence fd + * returned will be -1. On a Atomic Commit with the + * DRM_MODE_ATOMIC_TEST_ONLY flag the out fence will also be set to -1. + * + * Note that out-fences don't have a special interface to drivers and are + * internally represented by a struct &drm_pending_vblank_event in struct + * &drm_crtc_state, which is also used by the nonblocking atomic commit + * helpers and for the DRM event handling for existing userspace. + */ + static struct fence *get_crtc_fence(struct drm_crtc *crtc) { struct fence *fence; From 34e0b7db8cbf3263179bf55bebfa5aaf98df07f7 Mon Sep 17 00:00:00 2001 From: Gustavo Padovan Date: Tue, 6 Dec 2016 15:47:17 -0200 Subject: [PATCH 223/396] BACKPORT: drm/fence: add drm_crtc_create_fence() Instead of dealing with crtc details inside drm_atomic.c we should just export a function that creates a new crtc fence for us and use that. Suggested-by: Chris Wilson Signed-off-by: Gustavo Padovan Reviewed-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/1481046437-18778-1-git-send-email-gustavo@padovan.org (cherry picked from commit 35f8cc3b9a92c661e5331d64fdfdedb518891d5c) Signed-off-by: Marissa Wall Change-Id: Ia127dc391cb0b6e8adb283a12009466f86e9df1b --- drivers/gpu/drm/drm_atomic.c | 16 +--------------- drivers/gpu/drm/drm_crtc.c | 18 +++++++++++++++++- drivers/gpu/drm/drm_crtc_internal.h | 2 +- 3 files changed, 19 insertions(+), 17 deletions(-) diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c index 320b4e7b3541..149c599a39f4 100644 --- a/drivers/gpu/drm/drm_atomic.c +++ b/drivers/gpu/drm/drm_atomic.c @@ -1708,20 +1708,6 @@ EXPORT_SYMBOL(drm_atomic_clean_old_fb); * helpers and for the DRM event handling for existing userspace. */ -static struct fence *get_crtc_fence(struct drm_crtc *crtc) -{ - struct fence *fence; - - fence = kzalloc(sizeof(*fence), GFP_KERNEL); - if (!fence) - return NULL; - - fence_init(fence, &drm_crtc_fence_ops, &crtc->fence_lock, - crtc->fence_context, ++crtc->fence_seqno); - - return fence; -} - struct drm_out_fence_state { s64 __user *out_fence_ptr; struct sync_file *sync_file; @@ -1803,7 +1789,7 @@ static int prepare_crtc_signaling(struct drm_device *dev, f[*num_fences].out_fence_ptr = fence_ptr; *fence_state = f; - fence = get_crtc_fence(crtc); + fence = drm_crtc_create_fence(crtc); if (!fence) return -ENOMEM; diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index 3c04159f186d..79b3d521c388 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -142,6 +142,8 @@ static void drm_crtc_unregister_all(struct drm_device *dev) } } +static const struct fence_ops drm_crtc_fence_ops; + static struct drm_crtc *fence_to_crtc(struct fence *fence) { BUG_ON(fence->ops != &drm_crtc_fence_ops); @@ -167,13 +169,27 @@ static bool drm_crtc_fence_enable_signaling(struct fence *fence) return true; } -const struct fence_ops drm_crtc_fence_ops = { +static const struct fence_ops drm_crtc_fence_ops = { .get_driver_name = drm_crtc_fence_get_driver_name, .get_timeline_name = drm_crtc_fence_get_timeline_name, .enable_signaling = drm_crtc_fence_enable_signaling, .wait = fence_default_wait, }; +struct fence *drm_crtc_create_fence(struct drm_crtc *crtc) +{ + struct fence *fence; + + fence = kzalloc(sizeof(*fence), GFP_KERNEL); + if (!fence) + return NULL; + + fence_init(fence, &drm_crtc_fence_ops, &crtc->fence_lock, + crtc->fence_context, ++crtc->fence_seqno); + + return fence; +} + /** * drm_crtc_init_with_planes - Initialise a new CRTC object with * specified primary and cursor planes. diff --git a/drivers/gpu/drm/drm_crtc_internal.h b/drivers/gpu/drm/drm_crtc_internal.h index c0a8a6f1f496..df2b51a4f75e 100644 --- a/drivers/gpu/drm/drm_crtc_internal.h +++ b/drivers/gpu/drm/drm_crtc_internal.h @@ -41,7 +41,7 @@ int drm_crtc_check_viewport(const struct drm_crtc *crtc, const struct drm_display_mode *mode, const struct drm_framebuffer *fb); -extern const struct fence_ops drm_crtc_fence_ops; +struct fence *drm_crtc_create_fence(struct drm_crtc *crtc); void drm_fb_release(struct drm_file *file_priv); From d6eefcb2d9efb8de133a4b51c3f05ee0f9a6dc05 Mon Sep 17 00:00:00 2001 From: Gustavo Padovan Date: Fri, 13 Jan 2017 12:22:09 -0200 Subject: [PATCH 224/396] BACKPORT: drm/fence: fix memory overwrite when setting out_fence fd Currently if the userspace declares a int variable to store the out_fence fd and pass it to OUT_FENCE_PTR the kernel will overwrite the 32 bits above the int variable on 64 bits systems. Fix this by making the internal storage of out_fence in the kernel a s32 pointer. Reported-by: Chad Versace Signed-off-by: Gustavo Padovan Fixes: beaf5af48034 ("drm/fence: add out-fences support") Cc: Daniel Vetter Cc: Rafael Antognolli Cc: Laurent Pinchart Acked-by: Laurent Pinchart Reviewed-and-Tested-by: Chad Versace Link: http://patchwork.freedesktop.org/patch/msgid/1484317329-9293-1-git-send-email-gustavo@padovan.org (cherry picked from commit 7e9081c5aac73b8a0bc22e0b3e7a12c3e9cf5256) Signed-off-by: Marissa Wall Change-Id: I67a3d3c27c46d454444c6f195407d6aad59f2343 --- drivers/gpu/drm/drm_atomic.c | 12 ++++++------ include/drm/drm_atomic.h | 2 +- include/drm/drm_crtc.h | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c index 149c599a39f4..99011621bb12 100644 --- a/drivers/gpu/drm/drm_atomic.c +++ b/drivers/gpu/drm/drm_atomic.c @@ -294,15 +294,15 @@ drm_atomic_get_crtc_state(struct drm_atomic_state *state, EXPORT_SYMBOL(drm_atomic_get_crtc_state); static void set_out_fence_for_crtc(struct drm_atomic_state *state, - struct drm_crtc *crtc, s64 __user *fence_ptr) + struct drm_crtc *crtc, s32 __user *fence_ptr) { state->crtcs[drm_crtc_index(crtc)].out_fence_ptr = fence_ptr; } -static s64 __user *get_out_fence_for_crtc(struct drm_atomic_state *state, +static s32 __user *get_out_fence_for_crtc(struct drm_atomic_state *state, struct drm_crtc *crtc) { - s64 __user *fence_ptr; + s32 __user *fence_ptr; fence_ptr = state->crtcs[drm_crtc_index(crtc)].out_fence_ptr; state->crtcs[drm_crtc_index(crtc)].out_fence_ptr = NULL; @@ -515,7 +515,7 @@ int drm_atomic_crtc_set_property(struct drm_crtc *crtc, state->color_mgmt_changed |= replaced; return ret; } else if (property == config->prop_out_fence_ptr) { - s64 __user *fence_ptr = u64_to_user_ptr(val); + s32 __user *fence_ptr = u64_to_user_ptr(val); if (!fence_ptr) return 0; @@ -1709,7 +1709,7 @@ EXPORT_SYMBOL(drm_atomic_clean_old_fb); */ struct drm_out_fence_state { - s64 __user *out_fence_ptr; + s32 __user *out_fence_ptr; struct sync_file *sync_file; int fd; }; @@ -1746,7 +1746,7 @@ static int prepare_crtc_signaling(struct drm_device *dev, return 0; for_each_crtc_in_state(state, crtc, crtc_state, i) { - u64 __user *fence_ptr; + s32 __user *fence_ptr; fence_ptr = get_out_fence_for_crtc(crtc_state->state, crtc); diff --git a/include/drm/drm_atomic.h b/include/drm/drm_atomic.h index 8eff4cb8199e..a5696c1806c9 100644 --- a/include/drm/drm_atomic.h +++ b/include/drm/drm_atomic.h @@ -144,7 +144,7 @@ struct __drm_crtcs_state { struct drm_crtc *ptr; struct drm_crtc_state *state; struct drm_crtc_commit *commit; - s64 __user *out_fence_ptr; + s32 __user *out_fence_ptr; }; struct __drm_connnectors_state { diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index 9551bcd00db4..f3d58c7eb97e 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h @@ -1196,7 +1196,7 @@ struct drm_mode_config { /** * @prop_out_fence_ptr: Sync File fd pointer representing the * outgoing fences for a CRTC. Userspace should provide a pointer to a - * value of type s64, and then cast that pointer to u64. + * value of type s32, and then cast that pointer to u64. */ struct drm_property *prop_out_fence_ptr; /** From cd5e19c17d4dd758a53fa2f774e8256d5ebb7cb8 Mon Sep 17 00:00:00 2001 From: Jin Qian Date: Mon, 22 May 2017 12:08:06 -0700 Subject: [PATCH 225/396] ANDROID: uid_sys_stats: defer io stats calulation for dead tasks Store sum of dead task io stats in uid_entry and defer uid io calulation until next uid proc stat change or dumpsys. Bug: 37754877 Change-Id: I970f010a4c841c5ca26d0efc7e027414c3c952e0 Signed-off-by: Jin Qian --- drivers/misc/uid_sys_stats.c | 107 ++++++++++++++--------------------- 1 file changed, 42 insertions(+), 65 deletions(-) diff --git a/drivers/misc/uid_sys_stats.c b/drivers/misc/uid_sys_stats.c index 127a052ed141..871040e17b6b 100644 --- a/drivers/misc/uid_sys_stats.c +++ b/drivers/misc/uid_sys_stats.c @@ -50,7 +50,8 @@ struct io_stats { #define UID_STATE_TOTAL_CURR 2 #define UID_STATE_TOTAL_LAST 3 -#define UID_STATE_SIZE 4 +#define UID_STATE_DEAD_TASKS 4 +#define UID_STATE_SIZE 5 struct uid_entry { uid_t uid; @@ -215,35 +216,44 @@ static u64 compute_write_bytes(struct task_struct *task) return task->ioac.write_bytes - task->ioac.cancelled_write_bytes; } -static void add_uid_io_curr_stats(struct uid_entry *uid_entry, - struct task_struct *task) +static void add_uid_io_stats(struct uid_entry *uid_entry, + struct task_struct *task, int slot) { - struct io_stats *io_curr = &uid_entry->io[UID_STATE_TOTAL_CURR]; + struct io_stats *io_slot = &uid_entry->io[slot]; - io_curr->read_bytes += task->ioac.read_bytes; - io_curr->write_bytes += compute_write_bytes(task); - io_curr->rchar += task->ioac.rchar; - io_curr->wchar += task->ioac.wchar; - io_curr->fsync += task->ioac.syscfs; + io_slot->read_bytes += task->ioac.read_bytes; + io_slot->write_bytes += compute_write_bytes(task); + io_slot->rchar += task->ioac.rchar; + io_slot->wchar += task->ioac.wchar; + io_slot->fsync += task->ioac.syscfs; } -static void clean_uid_io_last_stats(struct uid_entry *uid_entry, - struct task_struct *task) +static void compute_uid_io_bucket_stats(struct io_stats *io_bucket, + struct io_stats *io_curr, + struct io_stats *io_last, + struct io_stats *io_dead) { - struct io_stats *io_last = &uid_entry->io[UID_STATE_TOTAL_LAST]; + io_bucket->read_bytes += io_curr->read_bytes + io_dead->read_bytes - + io_last->read_bytes; + io_bucket->write_bytes += io_curr->write_bytes + io_dead->write_bytes - + io_last->write_bytes; + io_bucket->rchar += io_curr->rchar + io_dead->rchar - io_last->rchar; + io_bucket->wchar += io_curr->wchar + io_dead->wchar - io_last->wchar; + io_bucket->fsync += io_curr->fsync + io_dead->fsync - io_last->fsync; - io_last->read_bytes -= task->ioac.read_bytes; - io_last->write_bytes -= compute_write_bytes(task); - io_last->rchar -= task->ioac.rchar; - io_last->wchar -= task->ioac.wchar; - io_last->fsync -= task->ioac.syscfs; + io_last->read_bytes = io_curr->read_bytes; + io_last->write_bytes = io_curr->write_bytes; + io_last->rchar = io_curr->rchar; + io_last->wchar = io_curr->wchar; + io_last->fsync = io_curr->fsync; + + memset(io_dead, 0, sizeof(struct io_stats)); } static void update_io_stats_all_locked(void) { struct uid_entry *uid_entry; struct task_struct *task, *temp; - struct io_stats *io_bucket, *io_curr, *io_last; struct user_namespace *user_ns = current_user_ns(); unsigned long bkt; uid_t uid; @@ -258,70 +268,38 @@ static void update_io_stats_all_locked(void) uid_entry = find_or_register_uid(uid); if (!uid_entry) continue; - add_uid_io_curr_stats(uid_entry, task); + add_uid_io_stats(uid_entry, task, UID_STATE_TOTAL_CURR); } while_each_thread(temp, task); rcu_read_unlock(); hash_for_each(hash_table, bkt, uid_entry, hash) { - io_bucket = &uid_entry->io[uid_entry->state]; - io_curr = &uid_entry->io[UID_STATE_TOTAL_CURR]; - io_last = &uid_entry->io[UID_STATE_TOTAL_LAST]; - - io_bucket->read_bytes += - io_curr->read_bytes - io_last->read_bytes; - io_bucket->write_bytes += - io_curr->write_bytes - io_last->write_bytes; - io_bucket->rchar += io_curr->rchar - io_last->rchar; - io_bucket->wchar += io_curr->wchar - io_last->wchar; - io_bucket->fsync += io_curr->fsync - io_last->fsync; - - io_last->read_bytes = io_curr->read_bytes; - io_last->write_bytes = io_curr->write_bytes; - io_last->rchar = io_curr->rchar; - io_last->wchar = io_curr->wchar; - io_last->fsync = io_curr->fsync; + compute_uid_io_bucket_stats(&uid_entry->io[uid_entry->state], + &uid_entry->io[UID_STATE_TOTAL_CURR], + &uid_entry->io[UID_STATE_TOTAL_LAST], + &uid_entry->io[UID_STATE_DEAD_TASKS]); } } -static void update_io_stats_uid_locked(uid_t target_uid) +static void update_io_stats_uid_locked(struct uid_entry *uid_entry) { - struct uid_entry *uid_entry; struct task_struct *task, *temp; - struct io_stats *io_bucket, *io_curr, *io_last; struct user_namespace *user_ns = current_user_ns(); - uid_entry = find_or_register_uid(target_uid); - if (!uid_entry) - return; - memset(&uid_entry->io[UID_STATE_TOTAL_CURR], 0, sizeof(struct io_stats)); rcu_read_lock(); do_each_thread(temp, task) { - if (from_kuid_munged(user_ns, task_uid(task)) != target_uid) + if (from_kuid_munged(user_ns, task_uid(task)) != uid_entry->uid) continue; - add_uid_io_curr_stats(uid_entry, task); + add_uid_io_stats(uid_entry, task, UID_STATE_TOTAL_CURR); } while_each_thread(temp, task); rcu_read_unlock(); - io_bucket = &uid_entry->io[uid_entry->state]; - io_curr = &uid_entry->io[UID_STATE_TOTAL_CURR]; - io_last = &uid_entry->io[UID_STATE_TOTAL_LAST]; - - io_bucket->read_bytes += - io_curr->read_bytes - io_last->read_bytes; - io_bucket->write_bytes += - io_curr->write_bytes - io_last->write_bytes; - io_bucket->rchar += io_curr->rchar - io_last->rchar; - io_bucket->wchar += io_curr->wchar - io_last->wchar; - io_bucket->fsync += io_curr->fsync - io_last->fsync; - - io_last->read_bytes = io_curr->read_bytes; - io_last->write_bytes = io_curr->write_bytes; - io_last->rchar = io_curr->rchar; - io_last->wchar = io_curr->wchar; - io_last->fsync = io_curr->fsync; + compute_uid_io_bucket_stats(&uid_entry->io[uid_entry->state], + &uid_entry->io[UID_STATE_TOTAL_CURR], + &uid_entry->io[UID_STATE_TOTAL_LAST], + &uid_entry->io[UID_STATE_DEAD_TASKS]); } static int uid_io_show(struct seq_file *m, void *v) @@ -406,7 +384,7 @@ static ssize_t uid_procstat_write(struct file *file, return count; } - update_io_stats_uid_locked(uid); + update_io_stats_uid_locked(uid_entry); uid_entry->state = state; @@ -444,8 +422,7 @@ static int process_notifier(struct notifier_block *self, uid_entry->utime += utime; uid_entry->stime += stime; - update_io_stats_uid_locked(uid); - clean_uid_io_last_stats(uid_entry, task); + add_uid_io_stats(uid_entry, task, UID_STATE_DEAD_TASKS); exit: rt_mutex_unlock(&uid_lock); From 4b593e607163792ec93f16fe24ab34743df36299 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Tue, 15 Nov 2016 11:55:29 +0100 Subject: [PATCH 226/396] UPSTREAM: drm/fb_cma_helper: Add missing forward declaration MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add missing forward declaration for struct drm_plane and drm_plane_state, which causes the following warning in the VC4 driver (can be replicated by building using bcm2835_defconfig): In file included from drivers/gpu/drm/vc4/vc4_drv.c:18:0: include/drm/drm_fb_cma_helper.h:45:13: warning: ‘struct drm_plane_state’ declared inside parameter list will not be visible outside of this definition or declaration struct drm_plane_state *state); ^~~~~~~~~~~~~~~ include/drm/drm_fb_cma_helper.h:44:34: warning: ‘struct drm_plane’ declared inside parameter list will not be visible outside of this definition or declaration int drm_fb_cma_prepare_fb(struct drm_plane *plane, Change-Id: Ieffc4ce7b13044c323ef8ee0af683c46813eb34a Signed-off-by: Marek Vasut Cc: Daniel Vetter Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/20161115105529.3227-1-marex@denx.de (cherry picked from commit 196594efc2b9) Signed-off-by: Marissa Wall --- include/drm/drm_fb_cma_helper.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/drm/drm_fb_cma_helper.h b/include/drm/drm_fb_cma_helper.h index cc82c73b07fc..3b00f6480b83 100644 --- a/include/drm/drm_fb_cma_helper.h +++ b/include/drm/drm_fb_cma_helper.h @@ -12,6 +12,8 @@ struct drm_fb_helper; struct drm_device; struct drm_file; struct drm_mode_fb_cmd2; +struct drm_plane; +struct drm_plane_state; struct drm_fbdev_cma *drm_fbdev_cma_init_with_funcs(struct drm_device *dev, unsigned int preferred_bpp, unsigned int num_crtc, From 810b7c5599540d4f17c4fbda2a5c03b5e0e39a11 Mon Sep 17 00:00:00 2001 From: Maksim Salau Date: Tue, 25 Apr 2017 22:49:21 +0300 Subject: [PATCH 227/396] usb: misc: legousbtower: Fix buffers on stack commit 942a48730faf149ccbf3e12ac718aee120bb3529 upstream. Allocate buffers on HEAP instead of STACK for local structures that are to be received using usb_control_msg(). Signed-off-by: Maksim Salau Tested-by: Alfredo Rafael Vicente Boix Signed-off-by: Greg Kroah-Hartman --- drivers/usb/misc/legousbtower.c | 37 ++++++++++++++++++++++++--------- 1 file changed, 27 insertions(+), 10 deletions(-) diff --git a/drivers/usb/misc/legousbtower.c b/drivers/usb/misc/legousbtower.c index c8fbe7b739a0..9dd202ba1663 100644 --- a/drivers/usb/misc/legousbtower.c +++ b/drivers/usb/misc/legousbtower.c @@ -317,9 +317,16 @@ static int tower_open (struct inode *inode, struct file *file) int subminor; int retval = 0; struct usb_interface *interface; - struct tower_reset_reply reset_reply; + struct tower_reset_reply *reset_reply; int result; + reset_reply = kmalloc(sizeof(*reset_reply), GFP_KERNEL); + + if (!reset_reply) { + retval = -ENOMEM; + goto exit; + } + nonseekable_open(inode, file); subminor = iminor(inode); @@ -364,8 +371,8 @@ static int tower_open (struct inode *inode, struct file *file) USB_TYPE_VENDOR | USB_DIR_IN | USB_RECIP_DEVICE, 0, 0, - &reset_reply, - sizeof(reset_reply), + reset_reply, + sizeof(*reset_reply), 1000); if (result < 0) { dev_err(&dev->udev->dev, @@ -406,6 +413,7 @@ unlock_exit: mutex_unlock(&dev->lock); exit: + kfree(reset_reply); return retval; } @@ -808,7 +816,7 @@ static int tower_probe (struct usb_interface *interface, const struct usb_device struct lego_usb_tower *dev = NULL; struct usb_host_interface *iface_desc; struct usb_endpoint_descriptor* endpoint; - struct tower_get_version_reply get_version_reply; + struct tower_get_version_reply *get_version_reply = NULL; int i; int retval = -ENOMEM; int result; @@ -886,6 +894,13 @@ static int tower_probe (struct usb_interface *interface, const struct usb_device dev->interrupt_in_interval = interrupt_in_interval ? interrupt_in_interval : dev->interrupt_in_endpoint->bInterval; dev->interrupt_out_interval = interrupt_out_interval ? interrupt_out_interval : dev->interrupt_out_endpoint->bInterval; + get_version_reply = kmalloc(sizeof(*get_version_reply), GFP_KERNEL); + + if (!get_version_reply) { + retval = -ENOMEM; + goto error; + } + /* get the firmware version and log it */ result = usb_control_msg (udev, usb_rcvctrlpipe(udev, 0), @@ -893,18 +908,19 @@ static int tower_probe (struct usb_interface *interface, const struct usb_device USB_TYPE_VENDOR | USB_DIR_IN | USB_RECIP_DEVICE, 0, 0, - &get_version_reply, - sizeof(get_version_reply), + get_version_reply, + sizeof(*get_version_reply), 1000); if (result < 0) { dev_err(idev, "LEGO USB Tower get version control request failed\n"); retval = result; goto error; } - dev_info(&interface->dev, "LEGO USB Tower firmware version is %d.%d " - "build %d\n", get_version_reply.major, - get_version_reply.minor, - le16_to_cpu(get_version_reply.build_no)); + dev_info(&interface->dev, + "LEGO USB Tower firmware version is %d.%d build %d\n", + get_version_reply->major, + get_version_reply->minor, + le16_to_cpu(get_version_reply->build_no)); /* we can register the device now, as it is ready */ usb_set_intfdata (interface, dev); @@ -928,6 +944,7 @@ exit: return retval; error: + kfree(get_version_reply); tower_delete(dev); return retval; } From 7d96e4a404c1eec5a4f941d2af572a252028b462 Mon Sep 17 00:00:00 2001 From: Maksim Salau Date: Sat, 13 May 2017 23:49:26 +0300 Subject: [PATCH 228/396] usb: misc: legousbtower: Fix memory leak commit 0bd193d62b4270a2a7a09da43ad1034c7ca5b3d3 upstream. get_version_reply is not freed if function returns with success. Fixes: 942a48730faf ("usb: misc: legousbtower: Fix buffers on stack") Reported-by: Heikki Krogerus Signed-off-by: Maksim Salau Signed-off-by: Greg Kroah-Hartman --- drivers/usb/misc/legousbtower.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/usb/misc/legousbtower.c b/drivers/usb/misc/legousbtower.c index 9dd202ba1663..c2e2b2ea32d8 100644 --- a/drivers/usb/misc/legousbtower.c +++ b/drivers/usb/misc/legousbtower.c @@ -941,6 +941,7 @@ static int tower_probe (struct usb_interface *interface, const struct usb_device USB_MAJOR, dev->minor); exit: + kfree(get_version_reply); return retval; error: From 6e2078c100929be9e21229c6c6732bd8ff0d88c2 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Tue, 16 May 2017 11:47:29 -0400 Subject: [PATCH 229/396] USB: ene_usb6250: fix DMA to the stack commit 628c2893d44876ddd11602400c70606ade62e129 upstream. The ene_usb6250 sub-driver in usb-storage does USB I/O to buffers on the stack, which doesn't work with vmapped stacks. This patch fixes the problem by allocating a separate 512-byte buffer at probe time and using it for all of the offending I/O operations. Signed-off-by: Alan Stern Reported-and-tested-by: Andreas Hartmann Signed-off-by: Greg Kroah-Hartman --- drivers/usb/storage/ene_ub6250.c | 90 +++++++++++++++++++------------- 1 file changed, 55 insertions(+), 35 deletions(-) diff --git a/drivers/usb/storage/ene_ub6250.c b/drivers/usb/storage/ene_ub6250.c index 02bdaa912164..4340b4925daa 100644 --- a/drivers/usb/storage/ene_ub6250.c +++ b/drivers/usb/storage/ene_ub6250.c @@ -446,6 +446,10 @@ struct ms_lib_ctrl { #define SD_BLOCK_LEN 9 struct ene_ub6250_info { + + /* I/O bounce buffer */ + u8 *bbuf; + /* for 6250 code */ struct SD_STATUS SD_Status; struct MS_STATUS MS_Status; @@ -493,8 +497,11 @@ static int ene_load_bincode(struct us_data *us, unsigned char flag); static void ene_ub6250_info_destructor(void *extra) { + struct ene_ub6250_info *info = (struct ene_ub6250_info *) extra; + if (!extra) return; + kfree(info->bbuf); } static int ene_send_scsi_cmd(struct us_data *us, u8 fDir, void *buf, int use_sg) @@ -860,8 +867,9 @@ static int ms_read_readpage(struct us_data *us, u32 PhyBlockAddr, u8 PageNum, u32 *PageBuf, struct ms_lib_type_extdat *ExtraDat) { struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf; + struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra; + u8 *bbuf = info->bbuf; int result; - u8 ExtBuf[4]; u32 bn = PhyBlockAddr * 0x20 + PageNum; result = ene_load_bincode(us, MS_RW_PATTERN); @@ -901,7 +909,7 @@ static int ms_read_readpage(struct us_data *us, u32 PhyBlockAddr, bcb->CDB[2] = (unsigned char)(PhyBlockAddr>>16); bcb->CDB[6] = 0x01; - result = ene_send_scsi_cmd(us, FDIR_READ, &ExtBuf, 0); + result = ene_send_scsi_cmd(us, FDIR_READ, bbuf, 0); if (result != USB_STOR_XFER_GOOD) return USB_STOR_TRANSPORT_ERROR; @@ -910,9 +918,9 @@ static int ms_read_readpage(struct us_data *us, u32 PhyBlockAddr, ExtraDat->status0 = 0x10; /* Not yet,fireware support */ ExtraDat->status1 = 0x00; /* Not yet,fireware support */ - ExtraDat->ovrflg = ExtBuf[0]; - ExtraDat->mngflg = ExtBuf[1]; - ExtraDat->logadr = memstick_logaddr(ExtBuf[2], ExtBuf[3]); + ExtraDat->ovrflg = bbuf[0]; + ExtraDat->mngflg = bbuf[1]; + ExtraDat->logadr = memstick_logaddr(bbuf[2], bbuf[3]); return USB_STOR_TRANSPORT_GOOD; } @@ -1332,8 +1340,9 @@ static int ms_lib_read_extra(struct us_data *us, u32 PhyBlock, u8 PageNum, struct ms_lib_type_extdat *ExtraDat) { struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf; + struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra; + u8 *bbuf = info->bbuf; int result; - u8 ExtBuf[4]; memset(bcb, 0, sizeof(struct bulk_cb_wrap)); bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN); @@ -1347,7 +1356,7 @@ static int ms_lib_read_extra(struct us_data *us, u32 PhyBlock, bcb->CDB[2] = (unsigned char)(PhyBlock>>16); bcb->CDB[6] = 0x01; - result = ene_send_scsi_cmd(us, FDIR_READ, &ExtBuf, 0); + result = ene_send_scsi_cmd(us, FDIR_READ, bbuf, 0); if (result != USB_STOR_XFER_GOOD) return USB_STOR_TRANSPORT_ERROR; @@ -1355,9 +1364,9 @@ static int ms_lib_read_extra(struct us_data *us, u32 PhyBlock, ExtraDat->intr = 0x80; /* Not yet, waiting for fireware support */ ExtraDat->status0 = 0x10; /* Not yet, waiting for fireware support */ ExtraDat->status1 = 0x00; /* Not yet, waiting for fireware support */ - ExtraDat->ovrflg = ExtBuf[0]; - ExtraDat->mngflg = ExtBuf[1]; - ExtraDat->logadr = memstick_logaddr(ExtBuf[2], ExtBuf[3]); + ExtraDat->ovrflg = bbuf[0]; + ExtraDat->mngflg = bbuf[1]; + ExtraDat->logadr = memstick_logaddr(bbuf[2], bbuf[3]); return USB_STOR_TRANSPORT_GOOD; } @@ -1558,9 +1567,9 @@ static int ms_lib_scan_logicalblocknumber(struct us_data *us, u16 btBlk1st) u16 PhyBlock, newblk, i; u16 LogStart, LogEnde; struct ms_lib_type_extdat extdat; - u8 buf[0x200]; u32 count = 0, index = 0; struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra; + u8 *bbuf = info->bbuf; for (PhyBlock = 0; PhyBlock < info->MS_Lib.NumberOfPhyBlock;) { ms_lib_phy_to_log_range(PhyBlock, &LogStart, &LogEnde); @@ -1574,14 +1583,16 @@ static int ms_lib_scan_logicalblocknumber(struct us_data *us, u16 btBlk1st) } if (count == PhyBlock) { - ms_lib_read_extrablock(us, PhyBlock, 0, 0x80, &buf); + ms_lib_read_extrablock(us, PhyBlock, 0, 0x80, + bbuf); count += 0x80; } index = (PhyBlock % 0x80) * 4; - extdat.ovrflg = buf[index]; - extdat.mngflg = buf[index+1]; - extdat.logadr = memstick_logaddr(buf[index+2], buf[index+3]); + extdat.ovrflg = bbuf[index]; + extdat.mngflg = bbuf[index+1]; + extdat.logadr = memstick_logaddr(bbuf[index+2], + bbuf[index+3]); if ((extdat.ovrflg & MS_REG_OVR_BKST) != MS_REG_OVR_BKST_OK) { ms_lib_setacquired_errorblock(us, PhyBlock); @@ -2064,9 +2075,9 @@ static int ene_ms_init(struct us_data *us) { struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf; int result; - u8 buf[0x200]; u16 MSP_BlockSize, MSP_UserAreaBlocks; struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra; + u8 *bbuf = info->bbuf; printk(KERN_INFO "transport --- ENE_MSInit\n"); @@ -2085,13 +2096,13 @@ static int ene_ms_init(struct us_data *us) bcb->CDB[0] = 0xF1; bcb->CDB[1] = 0x01; - result = ene_send_scsi_cmd(us, FDIR_READ, &buf, 0); + result = ene_send_scsi_cmd(us, FDIR_READ, bbuf, 0); if (result != USB_STOR_XFER_GOOD) { printk(KERN_ERR "Execution MS Init Code Fail !!\n"); return USB_STOR_TRANSPORT_ERROR; } /* the same part to test ENE */ - info->MS_Status = *(struct MS_STATUS *)&buf[0]; + info->MS_Status = *(struct MS_STATUS *) bbuf; if (info->MS_Status.Insert && info->MS_Status.Ready) { printk(KERN_INFO "Insert = %x\n", info->MS_Status.Insert); @@ -2100,15 +2111,15 @@ static int ene_ms_init(struct us_data *us) printk(KERN_INFO "IsMSPHG = %x\n", info->MS_Status.IsMSPHG); printk(KERN_INFO "WtP= %x\n", info->MS_Status.WtP); if (info->MS_Status.IsMSPro) { - MSP_BlockSize = (buf[6] << 8) | buf[7]; - MSP_UserAreaBlocks = (buf[10] << 8) | buf[11]; + MSP_BlockSize = (bbuf[6] << 8) | bbuf[7]; + MSP_UserAreaBlocks = (bbuf[10] << 8) | bbuf[11]; info->MSP_TotalBlock = MSP_BlockSize * MSP_UserAreaBlocks; } else { ms_card_init(us); /* Card is MS (to ms.c)*/ } usb_stor_dbg(us, "MS Init Code OK !!\n"); } else { - usb_stor_dbg(us, "MS Card Not Ready --- %x\n", buf[0]); + usb_stor_dbg(us, "MS Card Not Ready --- %x\n", bbuf[0]); return USB_STOR_TRANSPORT_ERROR; } @@ -2118,9 +2129,9 @@ static int ene_ms_init(struct us_data *us) static int ene_sd_init(struct us_data *us) { int result; - u8 buf[0x200]; struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf; struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra; + u8 *bbuf = info->bbuf; usb_stor_dbg(us, "transport --- ENE_SDInit\n"); /* SD Init Part-1 */ @@ -2154,17 +2165,17 @@ static int ene_sd_init(struct us_data *us) bcb->Flags = US_BULK_FLAG_IN; bcb->CDB[0] = 0xF1; - result = ene_send_scsi_cmd(us, FDIR_READ, &buf, 0); + result = ene_send_scsi_cmd(us, FDIR_READ, bbuf, 0); if (result != USB_STOR_XFER_GOOD) { usb_stor_dbg(us, "Execution SD Init Code Fail !!\n"); return USB_STOR_TRANSPORT_ERROR; } - info->SD_Status = *(struct SD_STATUS *)&buf[0]; + info->SD_Status = *(struct SD_STATUS *) bbuf; if (info->SD_Status.Insert && info->SD_Status.Ready) { struct SD_STATUS *s = &info->SD_Status; - ene_get_card_status(us, (unsigned char *)&buf); + ene_get_card_status(us, bbuf); usb_stor_dbg(us, "Insert = %x\n", s->Insert); usb_stor_dbg(us, "Ready = %x\n", s->Ready); usb_stor_dbg(us, "IsMMC = %x\n", s->IsMMC); @@ -2172,7 +2183,7 @@ static int ene_sd_init(struct us_data *us) usb_stor_dbg(us, "HiSpeed = %x\n", s->HiSpeed); usb_stor_dbg(us, "WtP = %x\n", s->WtP); } else { - usb_stor_dbg(us, "SD Card Not Ready --- %x\n", buf[0]); + usb_stor_dbg(us, "SD Card Not Ready --- %x\n", bbuf[0]); return USB_STOR_TRANSPORT_ERROR; } return USB_STOR_TRANSPORT_GOOD; @@ -2182,13 +2193,15 @@ static int ene_sd_init(struct us_data *us) static int ene_init(struct us_data *us) { int result; - u8 misc_reg03 = 0; + u8 misc_reg03; struct ene_ub6250_info *info = (struct ene_ub6250_info *)(us->extra); + u8 *bbuf = info->bbuf; - result = ene_get_card_type(us, REG_CARD_STATUS, &misc_reg03); + result = ene_get_card_type(us, REG_CARD_STATUS, bbuf); if (result != USB_STOR_XFER_GOOD) return USB_STOR_TRANSPORT_ERROR; + misc_reg03 = bbuf[0]; if (misc_reg03 & 0x01) { if (!info->SD_Status.Ready) { result = ene_sd_init(us); @@ -2305,8 +2318,9 @@ static int ene_ub6250_probe(struct usb_interface *intf, const struct usb_device_id *id) { int result; - u8 misc_reg03 = 0; + u8 misc_reg03; struct us_data *us; + struct ene_ub6250_info *info; result = usb_stor_probe1(&us, intf, id, (id - ene_ub6250_usb_ids) + ene_ub6250_unusual_dev_list, @@ -2315,11 +2329,16 @@ static int ene_ub6250_probe(struct usb_interface *intf, return result; /* FIXME: where should the code alloc extra buf ? */ - if (!us->extra) { - us->extra = kzalloc(sizeof(struct ene_ub6250_info), GFP_KERNEL); - if (!us->extra) - return -ENOMEM; - us->extra_destructor = ene_ub6250_info_destructor; + us->extra = kzalloc(sizeof(struct ene_ub6250_info), GFP_KERNEL); + if (!us->extra) + return -ENOMEM; + us->extra_destructor = ene_ub6250_info_destructor; + + info = (struct ene_ub6250_info *)(us->extra); + info->bbuf = kmalloc(512, GFP_KERNEL); + if (!info->bbuf) { + kfree(us->extra); + return -ENOMEM; } us->transport_name = "ene_ub6250"; @@ -2331,12 +2350,13 @@ static int ene_ub6250_probe(struct usb_interface *intf, return result; /* probe card type */ - result = ene_get_card_type(us, REG_CARD_STATUS, &misc_reg03); + result = ene_get_card_type(us, REG_CARD_STATUS, info->bbuf); if (result != USB_STOR_XFER_GOOD) { usb_stor_disconnect(intf); return USB_STOR_TRANSPORT_ERROR; } + misc_reg03 = info->bbuf[0]; if (!(misc_reg03 & 0x01)) { pr_info("ums_eneub6250: This driver only supports SD/MS cards. " "It does not support SM cards.\n"); From 7a2b8471ab1243437215468b4da6c5ddfd4d80da Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Mon, 13 Mar 2017 13:49:45 +0100 Subject: [PATCH 230/396] watchdog: pcwd_usb: fix NULL-deref at probe commit 46c319b848268dab3f0e7c4a5b6e9146d3bca8a4 upstream. Make sure to check the number of endpoints to avoid dereferencing a NULL-pointer should a malicious device lack endpoints. Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") Signed-off-by: Johan Hovold Reviewed-by: Guenter Roeck Signed-off-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck Signed-off-by: Greg Kroah-Hartman --- drivers/watchdog/pcwd_usb.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/watchdog/pcwd_usb.c b/drivers/watchdog/pcwd_usb.c index 99ebf6ea3de6..5615f4013924 100644 --- a/drivers/watchdog/pcwd_usb.c +++ b/drivers/watchdog/pcwd_usb.c @@ -630,6 +630,9 @@ static int usb_pcwd_probe(struct usb_interface *interface, return -ENODEV; } + if (iface_desc->desc.bNumEndpoints < 1) + return -ENODEV; + /* check out the endpoint: it has to be Interrupt & IN */ endpoint = &iface_desc->endpoint[0].desc; From 5d263d94a870a774a24acb2a2cc1e79ef39c2416 Mon Sep 17 00:00:00 2001 From: Willy Tarreau Date: Tue, 16 May 2017 19:18:55 +0200 Subject: [PATCH 231/396] char: lp: fix possible integer overflow in lp_setup() commit 3e21f4af170bebf47c187c1ff8bf155583c9f3b1 upstream. The lp_setup() code doesn't apply any bounds checking when passing "lp=none", and only in this case, resulting in an overflow of the parport_nr[] array. All versions in Git history are affected. Reported-By: Roee Hay Cc: Ben Hutchings Signed-off-by: Willy Tarreau Signed-off-by: Greg Kroah-Hartman --- drivers/char/lp.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/char/lp.c b/drivers/char/lp.c index c4094c4e22c1..34ef474a3923 100644 --- a/drivers/char/lp.c +++ b/drivers/char/lp.c @@ -859,7 +859,11 @@ static int __init lp_setup (char *str) } else if (!strcmp(str, "auto")) { parport_nr[0] = LP_PARPORT_AUTO; } else if (!strcmp(str, "none")) { - parport_nr[parport_ptr++] = LP_PARPORT_NONE; + if (parport_ptr < LP_NO) + parport_nr[parport_ptr++] = LP_PARPORT_NONE; + else + printk(KERN_INFO "lp: too many ports, %s ignored.\n", + str); } else if (!strcmp(str, "reset")) { reset = 1; } From 3888f62943bbc77496dc919080296c3a954b56a9 Mon Sep 17 00:00:00 2001 From: Vamsi Krishna Samavedam Date: Tue, 16 May 2017 14:38:08 +0200 Subject: [PATCH 232/396] USB: core: replace %p with %pK commit 2f964780c03b73de269b08d12aff96a9618d13f3 upstream. Format specifier %p can leak kernel addresses while not valuing the kptr_restrict system settings. When kptr_restrict is set to (1), kernel pointers printed using the %pK format specifier will be replaced with Zeros. Debugging Note : &pK prints only Zeros as address. If you need actual address information, write 0 to kptr_restrict. echo 0 > /proc/sys/kernel/kptr_restrict [Found by poking around in a random vendor kernel tree, it would be nice if someone would actually send these types of patches upstream - gkh] Signed-off-by: Vamsi Krishna Samavedam Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/devio.c | 14 +++++++------- drivers/usb/core/hcd.c | 4 ++-- drivers/usb/core/urb.c | 2 +- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c index 4016dae7433b..840930b014f6 100644 --- a/drivers/usb/core/devio.c +++ b/drivers/usb/core/devio.c @@ -481,11 +481,11 @@ static void snoop_urb(struct usb_device *udev, if (userurb) { /* Async */ if (when == SUBMIT) - dev_info(&udev->dev, "userurb %p, ep%d %s-%s, " + dev_info(&udev->dev, "userurb %pK, ep%d %s-%s, " "length %u\n", userurb, ep, t, d, length); else - dev_info(&udev->dev, "userurb %p, ep%d %s-%s, " + dev_info(&udev->dev, "userurb %pK, ep%d %s-%s, " "actual_length %u status %d\n", userurb, ep, t, d, length, timeout_or_status); @@ -1905,7 +1905,7 @@ static int proc_reapurb(struct usb_dev_state *ps, void __user *arg) if (as) { int retval; - snoop(&ps->dev->dev, "reap %p\n", as->userurb); + snoop(&ps->dev->dev, "reap %pK\n", as->userurb); retval = processcompl(as, (void __user * __user *)arg); free_async(as); return retval; @@ -1922,7 +1922,7 @@ static int proc_reapurbnonblock(struct usb_dev_state *ps, void __user *arg) as = async_getcompleted(ps); if (as) { - snoop(&ps->dev->dev, "reap %p\n", as->userurb); + snoop(&ps->dev->dev, "reap %pK\n", as->userurb); retval = processcompl(as, (void __user * __user *)arg); free_async(as); } else { @@ -2053,7 +2053,7 @@ static int proc_reapurb_compat(struct usb_dev_state *ps, void __user *arg) if (as) { int retval; - snoop(&ps->dev->dev, "reap %p\n", as->userurb); + snoop(&ps->dev->dev, "reap %pK\n", as->userurb); retval = processcompl_compat(as, (void __user * __user *)arg); free_async(as); return retval; @@ -2070,7 +2070,7 @@ static int proc_reapurbnonblock_compat(struct usb_dev_state *ps, void __user *ar as = async_getcompleted(ps); if (as) { - snoop(&ps->dev->dev, "reap %p\n", as->userurb); + snoop(&ps->dev->dev, "reap %pK\n", as->userurb); retval = processcompl_compat(as, (void __user * __user *)arg); free_async(as); } else { @@ -2499,7 +2499,7 @@ static long usbdev_do_ioctl(struct file *file, unsigned int cmd, #endif case USBDEVFS_DISCARDURB: - snoop(&dev->dev, "%s: DISCARDURB %p\n", __func__, p); + snoop(&dev->dev, "%s: DISCARDURB %pK\n", __func__, p); ret = proc_unlinkurb(ps, p); break; diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index f029aad67183..3b9735abf2e0 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c @@ -1722,7 +1722,7 @@ int usb_hcd_unlink_urb (struct urb *urb, int status) if (retval == 0) retval = -EINPROGRESS; else if (retval != -EIDRM && retval != -EBUSY) - dev_dbg(&udev->dev, "hcd_unlink_urb %p fail %d\n", + dev_dbg(&udev->dev, "hcd_unlink_urb %pK fail %d\n", urb, retval); usb_put_dev(udev); } @@ -1889,7 +1889,7 @@ rescan: /* kick hcd */ unlink1(hcd, urb, -ESHUTDOWN); dev_dbg (hcd->self.controller, - "shutdown urb %p ep%d%s%s\n", + "shutdown urb %pK ep%d%s%s\n", urb, usb_endpoint_num(&ep->desc), is_in ? "in" : "out", ({ char *s; diff --git a/drivers/usb/core/urb.c b/drivers/usb/core/urb.c index a9039696476e..5133ab965229 100644 --- a/drivers/usb/core/urb.c +++ b/drivers/usb/core/urb.c @@ -333,7 +333,7 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags) if (!urb || !urb->complete) return -EINVAL; if (urb->hcpriv) { - WARN_ONCE(1, "URB %p submitted while active\n", urb); + WARN_ONCE(1, "URB %pK submitted while active\n", urb); return -EBUSY; } From 5c1bd0cb49929e84bfafc2c442dfa9b54e26a4a4 Mon Sep 17 00:00:00 2001 From: Alexander Steffen Date: Thu, 16 Feb 2017 15:33:36 +0000 Subject: [PATCH 233/396] tpm_tis_core: Choose appropriate timeout for reading burstcount commit 302a6ad7fc77146191126a1f3e2c5d724fd72416 upstream. TIS v1.3 for TPM 1.2 and PTP for TPM 2.0 disagree about which timeout value applies to reading a valid burstcount. It is TIMEOUT_D according to TIS, but TIMEOUT_A according to PTP, so choose the appropriate value depending on whether we deal with a TPM 1.2 or a TPM 2.0. This is important since according to the PTP TIMEOUT_D is much smaller than TIMEOUT_A. So the previous implementation could run into timeouts with a TPM 2.0, even though the TPM was behaving perfectly fine. During tpm2_probe TIMEOUT_D will be used even with a TPM 2.0, because TPM_CHIP_FLAG_TPM2 is not yet set. This is fine, since the timeout values will only be changed afterwards by tpm_get_timeouts. Until then TIS_TIMEOUT_D_MAX applies, which is large enough. Fixes: aec04cbdf723 ("tpm: TPM 2.0 FIFO Interface") Signed-off-by: Alexander Steffen Signed-off-by: Peter Huewe Reviewed-by: Jarkko Sakkinen Signed-off-by: Jarkko Sakkinen Signed-off-by: Greg Kroah-Hartman --- drivers/char/tpm/tpm_tis_core.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/char/tpm/tpm_tis_core.c b/drivers/char/tpm/tpm_tis_core.c index a1ce0607bf7b..4d24ec3d7cd6 100644 --- a/drivers/char/tpm/tpm_tis_core.c +++ b/drivers/char/tpm/tpm_tis_core.c @@ -160,8 +160,10 @@ static int get_burstcount(struct tpm_chip *chip) u32 value; /* wait for burstcount */ - /* which timeout value, spec has 2 answers (c & d) */ - stop = jiffies + chip->timeout_d; + if (chip->flags & TPM_CHIP_FLAG_TPM2) + stop = jiffies + chip->timeout_a; + else + stop = jiffies + chip->timeout_d; do { rc = tpm_tis_read32(priv, TPM_STS(priv->locality), &value); if (rc < 0) From 0251f6affb1170a3c3364651a1c2757526cbfb88 Mon Sep 17 00:00:00 2001 From: Jeeja KP Date: Wed, 10 May 2017 11:51:58 +0530 Subject: [PATCH 234/396] ALSA: hda: Fix cpu lockup when stopping the cmd dmas commit 960013762df0a214b57f2fce655422fb52bdfd2c upstream. Using jiffies in hdac_wait_for_cmd_dmas() to determine when to time out when interrupts are off (snd_hdac_bus_stop_cmd_io()/spin_lock_irq()) causes hard lockup so unlock while waiting using jiffies. ---<-snip->--- <0>[ 1211.603046] NMI watchdog: Watchdog detected hard LOCKUP on cpu 3 <4>[ 1211.603047] Modules linked in: snd_hda_intel i915 vgem <4>[ 1211.603053] irq event stamp: 13366 <4>[ 1211.603053] hardirqs last enabled at (13365): ... <4>[ 1211.603059] Call Trace: <4>[ 1211.603059] ? delay_tsc+0x3d/0xc0 <4>[ 1211.603059] __delay+0xa/0x10 <4>[ 1211.603060] __const_udelay+0x31/0x40 <4>[ 1211.603060] snd_hdac_bus_stop_cmd_io+0x96/0xe0 [snd_hda_core] <4>[ 1211.603060] ? azx_dev_disconnect+0x20/0x20 [snd_hda_intel] <4>[ 1211.603061] snd_hdac_bus_stop_chip+0xb1/0x100 [snd_hda_core] <4>[ 1211.603061] azx_stop_chip+0x9/0x10 [snd_hda_codec] <4>[ 1211.603061] azx_suspend+0x72/0x220 [snd_hda_intel] <4>[ 1211.603061] pci_pm_suspend+0x71/0x140 <4>[ 1211.603062] dpm_run_callback+0x6f/0x330 <4>[ 1211.603062] ? pci_pm_freeze+0xe0/0xe0 <4>[ 1211.603062] __device_suspend+0xf9/0x370 <4>[ 1211.603062] ? dpm_watchdog_set+0x60/0x60 <4>[ 1211.603063] async_suspend+0x1a/0x90 <4>[ 1211.603063] async_run_entry_fn+0x34/0x160 <4>[ 1211.603063] process_one_work+0x1f4/0x6d0 <4>[ 1211.603063] ? process_one_work+0x16e/0x6d0 <4>[ 1211.603064] worker_thread+0x49/0x4a0 <4>[ 1211.603064] kthread+0x107/0x140 <4>[ 1211.603064] ? process_one_work+0x6d0/0x6d0 <4>[ 1211.603065] ? kthread_create_on_node+0x40/0x40 <4>[ 1211.603065] ret_from_fork+0x2e/0x40 Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=100419 Fixes: 38b19ed7f81ec ("ALSA: hda: fix to wait for RIRB & CORB DMA to set") Reported-by: Marta Lofstedt Suggested-by: Takashi Iwai Signed-off-by: Jeeja KP Acked-by: Vinod Koul Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/hda/hdac_controller.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/sound/hda/hdac_controller.c b/sound/hda/hdac_controller.c index 043065867656..0f41257d339e 100644 --- a/sound/hda/hdac_controller.c +++ b/sound/hda/hdac_controller.c @@ -106,7 +106,11 @@ void snd_hdac_bus_stop_cmd_io(struct hdac_bus *bus) /* disable ringbuffer DMAs */ snd_hdac_chip_writeb(bus, RIRBCTL, 0); snd_hdac_chip_writeb(bus, CORBCTL, 0); + spin_unlock_irq(&bus->reg_lock); + hdac_wait_for_cmd_dmas(bus); + + spin_lock_irq(&bus->reg_lock); /* disable unsolicited responses */ snd_hdac_chip_updatel(bus, GCTL, AZX_GCTL_UNSOL, 0); spin_unlock_irq(&bus->reg_lock); From e8b6d43ce3ea4afd8aecf2ac6a8523b085058db0 Mon Sep 17 00:00:00 2001 From: Marc Dietrich Date: Fri, 9 Dec 2016 10:20:38 +0100 Subject: [PATCH 235/396] ARM: tegra: paz00: Mark panel regulator as enabled on boot commit 0c18927f51f4d390abdcf385bff5f995407ee732 upstream. Current U-Boot enables the display already. Marking the regulator as enabled on boot fixes sporadic panel initialization failures. Signed-off-by: Marc Dietrich Tested-by: Misha Komarovskiy Signed-off-by: Thierry Reding Signed-off-by: Greg Kroah-Hartman --- arch/arm/boot/dts/tegra20-paz00.dts | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/boot/dts/tegra20-paz00.dts b/arch/arm/boot/dts/tegra20-paz00.dts index 4e361a8c167e..b4bfa5586c23 100644 --- a/arch/arm/boot/dts/tegra20-paz00.dts +++ b/arch/arm/boot/dts/tegra20-paz00.dts @@ -569,6 +569,7 @@ regulator-name = "+3VS,vdd_pnl"; regulator-min-microvolt = <3300000>; regulator-max-microvolt = <3300000>; + regulator-boot-on; gpio = <&gpio TEGRA_GPIO(A, 4) GPIO_ACTIVE_HIGH>; enable-active-high; }; From cc0f994c205df817b9ed4a29fd712fa0da82c68b Mon Sep 17 00:00:00 2001 From: Amir Goldstein Date: Tue, 25 Apr 2017 14:29:35 +0300 Subject: [PATCH 236/396] fanotify: don't expose EOPENSTALE to userspace commit 4ff33aafd32e084f5ee7faa54ba06e95f8b1b8af upstream. When delivering an event to userspace for a file on an NFS share, if the file is deleted on server side before user reads the event, user will not get the event. If the event queue contained several events, the stale event is quietly dropped and read() returns to user with events read so far in the buffer. If the event queue contains a single stale event or if the stale event is a permission event, read() returns to user with the kernel internal error code 518 (EOPENSTALE), which is not a POSIX error code. Check the internal return value -EOPENSTALE in fanotify_read(), just the same as it is checked in path_openat() and drop the event in the cases that it is not already dropped. This is a reproducer from Marko Rauhamaa: Just take the example program listed under "man fanotify" ("fantest") and follow these steps: ============================================================== NFS Server NFS Client(1) NFS Client(2) ============================================================== # echo foo >/nfsshare/bar.txt # cat /nfsshare/bar.txt foo # ./fantest /nfsshare Press enter key to terminate. Listening for events. # rm -f /nfsshare/bar.txt # cat /nfsshare/bar.txt read: Unknown error 518 cat: /nfsshare/bar.txt: Operation not permitted ============================================================== where NFS Client (1) and (2) are two terminal sessions on a single NFS Client machine. Reported-by: Marko Rauhamaa Tested-by: Marko Rauhamaa Cc: Signed-off-by: Amir Goldstein Signed-off-by: Jan Kara Signed-off-by: Greg Kroah-Hartman --- fs/notify/fanotify/fanotify_user.c | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/fs/notify/fanotify/fanotify_user.c b/fs/notify/fanotify/fanotify_user.c index 7ebfca6a1427..258e8f635148 100644 --- a/fs/notify/fanotify/fanotify_user.c +++ b/fs/notify/fanotify/fanotify_user.c @@ -294,27 +294,37 @@ static ssize_t fanotify_read(struct file *file, char __user *buf, } ret = copy_event_to_user(group, kevent, buf); + if (unlikely(ret == -EOPENSTALE)) { + /* + * We cannot report events with stale fd so drop it. + * Setting ret to 0 will continue the event loop and + * do the right thing if there are no more events to + * read (i.e. return bytes read, -EAGAIN or wait). + */ + ret = 0; + } + /* * Permission events get queued to wait for response. Other * events can be destroyed now. */ if (!(kevent->mask & FAN_ALL_PERM_EVENTS)) { fsnotify_destroy_event(group, kevent); - if (ret < 0) - break; } else { #ifdef CONFIG_FANOTIFY_ACCESS_PERMISSIONS - if (ret < 0) { + if (ret <= 0) { FANOTIFY_PE(kevent)->response = FAN_DENY; wake_up(&group->fanotify_data.access_waitq); - break; + } else { + spin_lock(&group->notification_lock); + list_add_tail(&kevent->list, + &group->fanotify_data.access_list); + spin_unlock(&group->notification_lock); } - spin_lock(&group->notification_lock); - list_add_tail(&kevent->list, - &group->fanotify_data.access_list); - spin_unlock(&group->notification_lock); #endif } + if (ret < 0) + break; buf += ret; count -= ret; } From aad1e5c81cbb0617ef544f65d2e4b41fed05484f Mon Sep 17 00:00:00 2001 From: Peter Huewe Date: Thu, 2 Mar 2017 13:03:11 +0000 Subject: [PATCH 237/396] tpm_tis_spi: Use single function to transfer data commit f848f2143ae42dc0918400039257a893835254d1 upstream. The algorithm for sending data to the TPM is mostly identical to the algorithm for receiving data from the TPM, so a single function is sufficient to handle both cases. This is a prequisite for all the other fixes, so we don't have to fix everything twice (send/receive) v2: u16 instead of u8 for the length. Fixes: 0edbfea537d1 ("tpm/tpm_tis_spi: Add support for spi phy") Signed-off-by: Alexander Steffen Signed-off-by: Peter Huewe Reviewed-by: Jarkko Sakkinen Tested-by: Benoit Houyere Signed-off-by: Jarkko Sakkinen Signed-off-by: Greg Kroah-Hartman --- drivers/char/tpm/tpm_tis_spi.c | 87 ++++++++++------------------------ 1 file changed, 24 insertions(+), 63 deletions(-) diff --git a/drivers/char/tpm/tpm_tis_spi.c b/drivers/char/tpm/tpm_tis_spi.c index dbaad9c681e3..8341d5f2792c 100644 --- a/drivers/char/tpm/tpm_tis_spi.c +++ b/drivers/char/tpm/tpm_tis_spi.c @@ -48,8 +48,8 @@ struct tpm_tis_spi_phy { struct tpm_tis_data priv; struct spi_device *spi_device; - u8 tx_buf[MAX_SPI_FRAMESIZE + 4]; - u8 rx_buf[MAX_SPI_FRAMESIZE + 4]; + u8 tx_buf[4]; + u8 rx_buf[4]; }; static inline struct tpm_tis_spi_phy *to_tpm_tis_spi_phy(struct tpm_tis_data *data) @@ -57,8 +57,8 @@ static inline struct tpm_tis_spi_phy *to_tpm_tis_spi_phy(struct tpm_tis_data *da return container_of(data, struct tpm_tis_spi_phy, priv); } -static int tpm_tis_spi_read_bytes(struct tpm_tis_data *data, u32 addr, - u16 len, u8 *result) +static int tpm_tis_spi_transfer(struct tpm_tis_data *data, u32 addr, u16 len, + u8 *buffer, u8 direction) { struct tpm_tis_spi_phy *phy = to_tpm_tis_spi_phy(data); int ret, i; @@ -67,17 +67,17 @@ static int tpm_tis_spi_read_bytes(struct tpm_tis_data *data, u32 addr, .tx_buf = phy->tx_buf, .rx_buf = phy->rx_buf, .len = 4, + .cs_change = 1, }; if (len > MAX_SPI_FRAMESIZE) return -ENOMEM; - phy->tx_buf[0] = 0x80 | (len - 1); + phy->tx_buf[0] = direction | (len - 1); phy->tx_buf[1] = 0xd4; - phy->tx_buf[2] = (addr >> 8) & 0xFF; - phy->tx_buf[3] = addr & 0xFF; + phy->tx_buf[2] = addr >> 8; + phy->tx_buf[3] = addr; - spi_xfer.cs_change = 1; spi_message_init(&m); spi_message_add_tail(&spi_xfer, &m); @@ -86,7 +86,7 @@ static int tpm_tis_spi_read_bytes(struct tpm_tis_data *data, u32 addr, if (ret < 0) goto exit; - memset(phy->tx_buf, 0, len); + phy->tx_buf[0] = 0; /* According to TCG PTP specification, if there is no TPM present at * all, then the design has a weak pull-up on MISO. If a TPM is not @@ -104,7 +104,14 @@ static int tpm_tis_spi_read_bytes(struct tpm_tis_data *data, u32 addr, spi_xfer.cs_change = 0; spi_xfer.len = len; - spi_xfer.rx_buf = result; + + if (direction) { + spi_xfer.tx_buf = NULL; + spi_xfer.rx_buf = buffer; + } else { + spi_xfer.tx_buf = buffer; + spi_xfer.rx_buf = NULL; + } spi_message_init(&m); spi_message_add_tail(&spi_xfer, &m); @@ -115,62 +122,16 @@ exit: return ret; } +static int tpm_tis_spi_read_bytes(struct tpm_tis_data *data, u32 addr, + u16 len, u8 *result) +{ + return tpm_tis_spi_transfer(data, addr, len, result, 0x80); +} + static int tpm_tis_spi_write_bytes(struct tpm_tis_data *data, u32 addr, u16 len, u8 *value) { - struct tpm_tis_spi_phy *phy = to_tpm_tis_spi_phy(data); - int ret, i; - struct spi_message m; - struct spi_transfer spi_xfer = { - .tx_buf = phy->tx_buf, - .rx_buf = phy->rx_buf, - .len = 4, - }; - - if (len > MAX_SPI_FRAMESIZE) - return -ENOMEM; - - phy->tx_buf[0] = len - 1; - phy->tx_buf[1] = 0xd4; - phy->tx_buf[2] = (addr >> 8) & 0xFF; - phy->tx_buf[3] = addr & 0xFF; - - spi_xfer.cs_change = 1; - spi_message_init(&m); - spi_message_add_tail(&spi_xfer, &m); - - spi_bus_lock(phy->spi_device->master); - ret = spi_sync_locked(phy->spi_device, &m); - if (ret < 0) - goto exit; - - memset(phy->tx_buf, 0, len); - - /* According to TCG PTP specification, if there is no TPM present at - * all, then the design has a weak pull-up on MISO. If a TPM is not - * present, a pull-up on MISO means that the SB controller sees a 1, - * and will latch in 0xFF on the read. - */ - for (i = 0; (phy->rx_buf[0] & 0x01) == 0 && i < TPM_RETRY; i++) { - spi_xfer.len = 1; - spi_message_init(&m); - spi_message_add_tail(&spi_xfer, &m); - ret = spi_sync_locked(phy->spi_device, &m); - if (ret < 0) - goto exit; - } - - spi_xfer.len = len; - spi_xfer.tx_buf = value; - spi_xfer.cs_change = 0; - spi_xfer.tx_buf = value; - spi_message_init(&m); - spi_message_add_tail(&spi_xfer, &m); - ret = spi_sync_locked(phy->spi_device, &m); - -exit: - spi_bus_unlock(phy->spi_device->master); - return ret; + return tpm_tis_spi_transfer(data, addr, len, value, 0); } static int tpm_tis_spi_read16(struct tpm_tis_data *data, u32 addr, u16 *result) From daa432c1a65a541b413111328f8aea61161ad372 Mon Sep 17 00:00:00 2001 From: Peter Huewe Date: Thu, 2 Mar 2017 13:03:12 +0000 Subject: [PATCH 238/396] tpm_tis_spi: Abort transfer when too many wait states are signaled commit 975094ddc369a32f27210248bdd9bbd153061b00 upstream. Abort the transfer with ETIMEDOUT when the TPM signals more than TPM_RETRY wait states. Continuing with the transfer in this state will only lead to arbitrary failures in other parts of the code. Fixes: 0edbfea537d1 ("tpm/tpm_tis_spi: Add support for spi phy") Signed-off-by: Alexander Steffen Signed-off-by: Peter Huewe Reviewed-by: Jarkko Sakkinen Tested-by: Benoit Houyere Signed-off-by: Jarkko Sakkinen Signed-off-by: Greg Kroah-Hartman --- drivers/char/tpm/tpm_tis_spi.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/char/tpm/tpm_tis_spi.c b/drivers/char/tpm/tpm_tis_spi.c index 8341d5f2792c..b515ce755f12 100644 --- a/drivers/char/tpm/tpm_tis_spi.c +++ b/drivers/char/tpm/tpm_tis_spi.c @@ -102,6 +102,11 @@ static int tpm_tis_spi_transfer(struct tpm_tis_data *data, u32 addr, u16 len, goto exit; } + if (i == TPM_RETRY) { + ret = -ETIMEDOUT; + goto exit; + } + spi_xfer.cs_change = 0; spi_xfer.len = len; From d513cf24e240f8c7a9127b566b915ce9730fd23e Mon Sep 17 00:00:00 2001 From: Peter Huewe Date: Thu, 2 Mar 2017 13:03:13 +0000 Subject: [PATCH 239/396] tpm_tis_spi: Check correct byte for wait state indicator commit e110cc69dc2ad679d6d478df636b99b14e6fbbc9 upstream. Wait states are signaled in the last byte received from the TPM in response to the header, not the first byte. Check rx_buf[3] instead of rx_buf[0]. Fixes: 0edbfea537d1 ("tpm/tpm_tis_spi: Add support for spi phy") Signed-off-by: Alexander Steffen Signed-off-by: Peter Huewe Reviewed-by: Jarkko Sakkinen Tested-by: Benoit Houyere Signed-off-by: Jarkko Sakkinen Signed-off-by: Greg Kroah-Hartman --- drivers/char/tpm/tpm_tis_spi.c | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/drivers/char/tpm/tpm_tis_spi.c b/drivers/char/tpm/tpm_tis_spi.c index b515ce755f12..f0e23011098b 100644 --- a/drivers/char/tpm/tpm_tis_spi.c +++ b/drivers/char/tpm/tpm_tis_spi.c @@ -86,25 +86,25 @@ static int tpm_tis_spi_transfer(struct tpm_tis_data *data, u32 addr, u16 len, if (ret < 0) goto exit; - phy->tx_buf[0] = 0; + if ((phy->rx_buf[3] & 0x01) == 0) { + // handle SPI wait states + phy->tx_buf[0] = 0; - /* According to TCG PTP specification, if there is no TPM present at - * all, then the design has a weak pull-up on MISO. If a TPM is not - * present, a pull-up on MISO means that the SB controller sees a 1, - * and will latch in 0xFF on the read. - */ - for (i = 0; (phy->rx_buf[0] & 0x01) == 0 && i < TPM_RETRY; i++) { - spi_xfer.len = 1; - spi_message_init(&m); - spi_message_add_tail(&spi_xfer, &m); - ret = spi_sync_locked(phy->spi_device, &m); - if (ret < 0) + for (i = 0; i < TPM_RETRY; i++) { + spi_xfer.len = 1; + spi_message_init(&m); + spi_message_add_tail(&spi_xfer, &m); + ret = spi_sync_locked(phy->spi_device, &m); + if (ret < 0) + goto exit; + if (phy->rx_buf[0] & 0x01) + break; + } + + if (i == TPM_RETRY) { + ret = -ETIMEDOUT; goto exit; - } - - if (i == TPM_RETRY) { - ret = -ETIMEDOUT; - goto exit; + } } spi_xfer.cs_change = 0; From c4b3779c978339a5b169ed08d773f9f98e15aa99 Mon Sep 17 00:00:00 2001 From: Peter Huewe Date: Thu, 2 Mar 2017 13:03:14 +0000 Subject: [PATCH 240/396] tpm_tis_spi: Remove limitation of transfers to MAX_SPI_FRAMESIZE bytes commit 591e48c26ced7c455751eef27fb5963e902c2137 upstream. Limiting transfers to MAX_SPI_FRAMESIZE was not expected by the upper layers, as tpm_tis has no such limitation. Add a loop to hide that limitation. v2: Moved scope of spi_message to the top as requested by Jarkko Fixes: 0edbfea537d1 ("tpm/tpm_tis_spi: Add support for spi phy") Signed-off-by: Alexander Steffen Signed-off-by: Peter Huewe Reviewed-by: Jarkko Sakkinen Tested-by: Benoit Houyere Signed-off-by: Jarkko Sakkinen Signed-off-by: Greg Kroah-Hartman --- drivers/char/tpm/tpm_tis_spi.c | 111 ++++++++++++++++++--------------- 1 file changed, 60 insertions(+), 51 deletions(-) diff --git a/drivers/char/tpm/tpm_tis_spi.c b/drivers/char/tpm/tpm_tis_spi.c index f0e23011098b..bc125f9229f0 100644 --- a/drivers/char/tpm/tpm_tis_spi.c +++ b/drivers/char/tpm/tpm_tis_spi.c @@ -61,67 +61,76 @@ static int tpm_tis_spi_transfer(struct tpm_tis_data *data, u32 addr, u16 len, u8 *buffer, u8 direction) { struct tpm_tis_spi_phy *phy = to_tpm_tis_spi_phy(data); - int ret, i; + int ret = 0; + int i; struct spi_message m; - struct spi_transfer spi_xfer = { - .tx_buf = phy->tx_buf, - .rx_buf = phy->rx_buf, - .len = 4, - .cs_change = 1, - }; - - if (len > MAX_SPI_FRAMESIZE) - return -ENOMEM; - - phy->tx_buf[0] = direction | (len - 1); - phy->tx_buf[1] = 0xd4; - phy->tx_buf[2] = addr >> 8; - phy->tx_buf[3] = addr; - - spi_message_init(&m); - spi_message_add_tail(&spi_xfer, &m); + struct spi_transfer spi_xfer; + u8 transfer_len; spi_bus_lock(phy->spi_device->master); - ret = spi_sync_locked(phy->spi_device, &m); - if (ret < 0) - goto exit; - if ((phy->rx_buf[3] & 0x01) == 0) { - // handle SPI wait states - phy->tx_buf[0] = 0; + while (len) { + transfer_len = min_t(u16, len, MAX_SPI_FRAMESIZE); - for (i = 0; i < TPM_RETRY; i++) { - spi_xfer.len = 1; - spi_message_init(&m); - spi_message_add_tail(&spi_xfer, &m); - ret = spi_sync_locked(phy->spi_device, &m); - if (ret < 0) - goto exit; - if (phy->rx_buf[0] & 0x01) - break; - } + phy->tx_buf[0] = direction | (transfer_len - 1); + phy->tx_buf[1] = 0xd4; + phy->tx_buf[2] = addr >> 8; + phy->tx_buf[3] = addr; - if (i == TPM_RETRY) { - ret = -ETIMEDOUT; + memset(&spi_xfer, 0, sizeof(spi_xfer)); + spi_xfer.tx_buf = phy->tx_buf; + spi_xfer.rx_buf = phy->rx_buf; + spi_xfer.len = 4; + spi_xfer.cs_change = 1; + + spi_message_init(&m); + spi_message_add_tail(&spi_xfer, &m); + ret = spi_sync_locked(phy->spi_device, &m); + if (ret < 0) goto exit; + + if ((phy->rx_buf[3] & 0x01) == 0) { + // handle SPI wait states + phy->tx_buf[0] = 0; + + for (i = 0; i < TPM_RETRY; i++) { + spi_xfer.len = 1; + spi_message_init(&m); + spi_message_add_tail(&spi_xfer, &m); + ret = spi_sync_locked(phy->spi_device, &m); + if (ret < 0) + goto exit; + if (phy->rx_buf[0] & 0x01) + break; + } + + if (i == TPM_RETRY) { + ret = -ETIMEDOUT; + goto exit; + } } + + spi_xfer.cs_change = 0; + spi_xfer.len = transfer_len; + + if (direction) { + spi_xfer.tx_buf = NULL; + spi_xfer.rx_buf = buffer; + } else { + spi_xfer.tx_buf = buffer; + spi_xfer.rx_buf = NULL; + } + + spi_message_init(&m); + spi_message_add_tail(&spi_xfer, &m); + ret = spi_sync_locked(phy->spi_device, &m); + if (ret < 0) + goto exit; + + len -= transfer_len; + buffer += transfer_len; } - spi_xfer.cs_change = 0; - spi_xfer.len = len; - - if (direction) { - spi_xfer.tx_buf = NULL; - spi_xfer.rx_buf = buffer; - } else { - spi_xfer.tx_buf = buffer; - spi_xfer.rx_buf = NULL; - } - - spi_message_init(&m); - spi_message_add_tail(&spi_xfer, &m); - ret = spi_sync_locked(phy->spi_device, &m); - exit: spi_bus_unlock(phy->spi_device->master); return ret; From 568ea0dcc27ed8855361a204cd0cdb7c38189268 Mon Sep 17 00:00:00 2001 From: Peter Huewe Date: Thu, 2 Mar 2017 13:03:15 +0000 Subject: [PATCH 241/396] tpm_tis_spi: Add small delay after last transfer commit 5cc0101d1f88500f8901d01b035af743215d4c3a upstream. Testing the implementation with a Raspberry Pi 2 showed that under some circumstances its SPI master erroneously releases the CS line before the transfer is complete, i.e. before the end of the last clock. In this case the TPM ignores the transfer and misses for example the GO command. The driver is unable to detect this communication problem and will wait for a command response that is never going to arrive, timing out eventually. As a workaround, the small delay ensures that the CS line is held long enough, even with a faulty SPI master. Other SPI masters are not affected, except for a negligible performance penalty. Fixes: 0edbfea537d1 ("tpm/tpm_tis_spi: Add support for spi phy") Signed-off-by: Alexander Steffen Signed-off-by: Peter Huewe Reviewed-by: Jarkko Sakkinen Tested-by: Benoit Houyere Signed-off-by: Jarkko Sakkinen Signed-off-by: Greg Kroah-Hartman --- drivers/char/tpm/tpm_tis_spi.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/char/tpm/tpm_tis_spi.c b/drivers/char/tpm/tpm_tis_spi.c index bc125f9229f0..3b97b14c3417 100644 --- a/drivers/char/tpm/tpm_tis_spi.c +++ b/drivers/char/tpm/tpm_tis_spi.c @@ -112,6 +112,7 @@ static int tpm_tis_spi_transfer(struct tpm_tis_data *data, u32 addr, u16 len, spi_xfer.cs_change = 0; spi_xfer.len = transfer_len; + spi_xfer.delay_usecs = 5; if (direction) { spi_xfer.tx_buf = NULL; From 40ca1fd38e110d26a7d4f268425550aceb453471 Mon Sep 17 00:00:00 2001 From: Nayna Jain Date: Fri, 10 Mar 2017 13:45:53 -0500 Subject: [PATCH 242/396] tpm: msleep() delays - replace with usleep_range() in i2c nuvoton driver commit a233a0289cf9a96ef9b42c730a7621ccbf9a6f98 upstream. Commit 500462a9de65 "timers: Switch to a non-cascading wheel" replaced the 'classic' timer wheel, which aimed for near 'exact' expiry of the timers. Their analysis was that the vast majority of timeout timers are used as safeguards, not as real timers, and are cancelled or rearmed before expiration. The only exception noted to this were networking timers with a small expiry time. Not included in the analysis was the TPM polling timer, which resulted in a longer normal delay and, every so often, a very long delay. The non-cascading wheel delay is based on CONFIG_HZ. For a description of the different rings and their delays, refer to the comments in kernel/time/timer.c. Below are the delays given for rings 0 - 2, which explains the longer "normal" delays and the very, long delays as seen on systems with CONFIG_HZ 250. * HZ 1000 steps * Level Offset Granularity Range * 0 0 1 ms 0 ms - 63 ms * 1 64 8 ms 64 ms - 511 ms * 2 128 64 ms 512 ms - 4095 ms (512ms - ~4s) * HZ 250 * Level Offset Granularity Range * 0 0 4 ms 0 ms - 255 ms * 1 64 32 ms 256 ms - 2047 ms (256ms - ~2s) * 2 128 256 ms 2048 ms - 16383 ms (~2s - ~16s) Below is a comparison of extending the TPM with 1000 measurements, using msleep() vs. usleep_delay() when configured for 1000 hz vs. 250 hz, before and after commit 500462a9de65. linux-4.7 | msleep() usleep_range() 1000 hz: 0m44.628s | 1m34.497s 29.243s 250 hz: 1m28.510s | 4m49.269s 32.386s linux-4.7 | min-max (msleep) min-max (usleep_range) 1000 hz: 0:017 - 2:760s | 0:015 - 3:967s 0:014 - 0:418s 250 hz: 0:028 - 1:954s | 0:040 - 4:096s 0:016 - 0:816s This patch replaces the msleep() with usleep_range() calls in the i2c nuvoton driver with a consistent max range value. Signed-of-by: Mimi Zohar Signed-off-by: Nayna Jain Reviewed-by: Jarkko Sakkinen Signed-off-by: Jarkko Sakkinen Signed-off-by: Greg Kroah-Hartman --- drivers/char/tpm/tpm_i2c_nuvoton.c | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/drivers/char/tpm/tpm_i2c_nuvoton.c b/drivers/char/tpm/tpm_i2c_nuvoton.c index e3a9155ee671..0c98c424d792 100644 --- a/drivers/char/tpm/tpm_i2c_nuvoton.c +++ b/drivers/char/tpm/tpm_i2c_nuvoton.c @@ -49,9 +49,10 @@ */ #define TPM_I2C_MAX_BUF_SIZE 32 #define TPM_I2C_RETRY_COUNT 32 -#define TPM_I2C_BUS_DELAY 1 /* msec */ -#define TPM_I2C_RETRY_DELAY_SHORT 2 /* msec */ -#define TPM_I2C_RETRY_DELAY_LONG 10 /* msec */ +#define TPM_I2C_BUS_DELAY 1000 /* usec */ +#define TPM_I2C_RETRY_DELAY_SHORT (2 * 1000) /* usec */ +#define TPM_I2C_RETRY_DELAY_LONG (10 * 1000) /* usec */ +#define TPM_I2C_DELAY_RANGE 300 /* usec */ #define OF_IS_TPM2 ((void *)1) #define I2C_IS_TPM2 1 @@ -123,7 +124,8 @@ static s32 i2c_nuvoton_write_status(struct i2c_client *client, u8 data) /* this causes the current command to be aborted */ for (i = 0, status = -1; i < TPM_I2C_RETRY_COUNT && status < 0; i++) { status = i2c_nuvoton_write_buf(client, TPM_STS, 1, &data); - msleep(TPM_I2C_BUS_DELAY); + usleep_range(TPM_I2C_BUS_DELAY, TPM_I2C_BUS_DELAY + + TPM_I2C_DELAY_RANGE); } return status; } @@ -160,7 +162,8 @@ static int i2c_nuvoton_get_burstcount(struct i2c_client *client, burst_count = min_t(u8, TPM_I2C_MAX_BUF_SIZE, data); break; } - msleep(TPM_I2C_BUS_DELAY); + usleep_range(TPM_I2C_BUS_DELAY, TPM_I2C_BUS_DELAY + + TPM_I2C_DELAY_RANGE); } while (time_before(jiffies, stop)); return burst_count; @@ -203,13 +206,17 @@ static int i2c_nuvoton_wait_for_stat(struct tpm_chip *chip, u8 mask, u8 value, return 0; /* use polling to wait for the event */ - ten_msec = jiffies + msecs_to_jiffies(TPM_I2C_RETRY_DELAY_LONG); + ten_msec = jiffies + usecs_to_jiffies(TPM_I2C_RETRY_DELAY_LONG); stop = jiffies + timeout; do { if (time_before(jiffies, ten_msec)) - msleep(TPM_I2C_RETRY_DELAY_SHORT); + usleep_range(TPM_I2C_RETRY_DELAY_SHORT, + TPM_I2C_RETRY_DELAY_SHORT + + TPM_I2C_DELAY_RANGE); else - msleep(TPM_I2C_RETRY_DELAY_LONG); + usleep_range(TPM_I2C_RETRY_DELAY_LONG, + TPM_I2C_RETRY_DELAY_LONG + + TPM_I2C_DELAY_RANGE); status_valid = i2c_nuvoton_check_status(chip, mask, value); if (status_valid) From 0c150305212b7afc3c8f90d3fe165ba902cc28f9 Mon Sep 17 00:00:00 2001 From: Nayna Jain Date: Fri, 10 Mar 2017 13:45:54 -0500 Subject: [PATCH 243/396] tpm: add sleep only for retry in i2c_nuvoton_write_status() commit 0afb7118ae021e80ecf70f5a3336e0935505518a upstream. Currently, there is an unnecessary 1 msec delay added in i2c_nuvoton_write_status() for the successful case. This function is called multiple times during send() and recv(), which implies adding multiple extra delays for every TPM operation. This patch calls usleep_range() only if retry is to be done. Signed-off-by: Nayna Jain Reviewed-by: Mimi Zohar Reviewed-by: Jarkko Sakkinen Signed-off-by: Jarkko Sakkinen Signed-off-by: Greg Kroah-Hartman --- drivers/char/tpm/tpm_i2c_nuvoton.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/char/tpm/tpm_i2c_nuvoton.c b/drivers/char/tpm/tpm_i2c_nuvoton.c index 0c98c424d792..c6428771841f 100644 --- a/drivers/char/tpm/tpm_i2c_nuvoton.c +++ b/drivers/char/tpm/tpm_i2c_nuvoton.c @@ -124,8 +124,9 @@ static s32 i2c_nuvoton_write_status(struct i2c_client *client, u8 data) /* this causes the current command to be aborted */ for (i = 0, status = -1; i < TPM_I2C_RETRY_COUNT && status < 0; i++) { status = i2c_nuvoton_write_buf(client, TPM_STS, 1, &data); - usleep_range(TPM_I2C_BUS_DELAY, TPM_I2C_BUS_DELAY - + TPM_I2C_DELAY_RANGE); + if (status < 0) + usleep_range(TPM_I2C_BUS_DELAY, TPM_I2C_BUS_DELAY + + TPM_I2C_DELAY_RANGE); } return status; } From cc15d340ec6a63aec4b0f68465f79b79add847eb Mon Sep 17 00:00:00 2001 From: Jerry Snitselaar Date: Fri, 10 Mar 2017 17:46:04 -0700 Subject: [PATCH 244/396] tpm_crb: check for bad response size commit 8569defde8057258835c51ce01a33de82e14b148 upstream. Make sure size of response buffer is at least 6 bytes, or we will underflow and pass large size_t to memcpy_fromio(). This was encountered while testing earlier version of locality patchset. Fixes: 30fc8d138e912 ("tpm: TPM 2.0 CRB Interface") Signed-off-by: Jerry Snitselaar Reviewed-by: Jarkko Sakkinen Signed-off-by: Jarkko Sakkinen Signed-off-by: Greg Kroah-Hartman --- drivers/char/tpm/tpm_crb.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/char/tpm/tpm_crb.c b/drivers/char/tpm/tpm_crb.c index a7c870af916c..fa0f66809503 100644 --- a/drivers/char/tpm/tpm_crb.c +++ b/drivers/char/tpm/tpm_crb.c @@ -111,8 +111,7 @@ static int crb_recv(struct tpm_chip *chip, u8 *buf, size_t count) memcpy_fromio(buf, priv->rsp, 6); expected = be32_to_cpup((__be32 *) &buf[2]); - - if (expected > count) + if (expected > count || expected < 6) return -EIO; memcpy_fromio(&buf[6], &priv->rsp[6], expected - 6); From ece453e8b0ca45e1b36317042c8aa7f3ef59e440 Mon Sep 17 00:00:00 2001 From: Alexander Sverdlin Date: Sat, 29 Apr 2017 12:19:33 +0200 Subject: [PATCH 245/396] ASoC: cs4271: configure reset GPIO as output commit 49b2e27ab9f66b0a22c21980ad8118a4038324ae upstream. During reset "refactoring" the output configuration was lost. This commit repairs sound on EDB93XX boards. Fixes: 9a397f4 ("ASoC: cs4271: add regulator consumer support") Signed-off-by: Alexander Sverdlin Signed-off-by: Mark Brown Signed-off-by: Greg Kroah-Hartman --- sound/soc/codecs/cs4271.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/cs4271.c b/sound/soc/codecs/cs4271.c index 8c0f3b89b5bc..e78b5f055f25 100644 --- a/sound/soc/codecs/cs4271.c +++ b/sound/soc/codecs/cs4271.c @@ -498,7 +498,7 @@ static int cs4271_reset(struct snd_soc_codec *codec) struct cs4271_private *cs4271 = snd_soc_codec_get_drvdata(codec); if (gpio_is_valid(cs4271->gpio_nreset)) { - gpio_set_value(cs4271->gpio_nreset, 0); + gpio_direction_output(cs4271->gpio_nreset, 0); mdelay(1); gpio_set_value(cs4271->gpio_nreset, 1); mdelay(1); From cb5cf8aaba2ede15fd13b52029bf4e5915e6096f Mon Sep 17 00:00:00 2001 From: Sagi Grimberg Date: Sun, 23 Apr 2017 14:31:42 +0300 Subject: [PATCH 246/396] mlx5: Fix mlx5_ib_map_mr_sg mr length commit 0a49f2c31c3efbeb0de3e4b5598764887f629be2 upstream. In case we got an initial sg_offset, we need to account for it in the mr length. Fixes: ff2ba9936591 ("IB/core: Add passing an offset into the SG to ib_map_mr_sg") Signed-off-by: Sagi Grimberg Tested-by: Israel Rukshin Signed-off-by: Doug Ledford Signed-off-by: Greg Kroah-Hartman --- drivers/infiniband/hw/mlx5/mr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/infiniband/hw/mlx5/mr.c b/drivers/infiniband/hw/mlx5/mr.c index be2d02b6a6aa..1fb31a47966d 100644 --- a/drivers/infiniband/hw/mlx5/mr.c +++ b/drivers/infiniband/hw/mlx5/mr.c @@ -1828,7 +1828,7 @@ mlx5_ib_sg_to_klms(struct mlx5_ib_mr *mr, klms[i].va = cpu_to_be64(sg_dma_address(sg) + sg_offset); klms[i].bcount = cpu_to_be32(sg_dma_len(sg) - sg_offset); klms[i].key = cpu_to_be32(lkey); - mr->ibmr.length += sg_dma_len(sg); + mr->ibmr.length += sg_dma_len(sg) - sg_offset; sg_offset = 0; } From 5db8f42b62daab43666a358d03c98f7a7310a5d6 Mon Sep 17 00:00:00 2001 From: Paolo Abeni Date: Fri, 28 Apr 2017 11:20:01 +0200 Subject: [PATCH 247/396] infiniband: call ipv6 route lookup via the stub interface commit eea40b8f624f25cbc02d55f2d93203f60cee9341 upstream. The infiniband address handle can be triggered to resolve an ipv6 address in response to MAD packets, regardless of the ipv6 module being disabled via the kernel command line argument. That will cause a call into the ipv6 routing code, which is not initialized, and a conseguent oops. This commit addresses the above issue replacing the direct lookup call with an indirect one via the ipv6 stub, which is properly initialized according to the ipv6 status (e.g. if ipv6 is disabled, the routing lookup fails gracefully) Signed-off-by: Paolo Abeni Signed-off-by: Doug Ledford Signed-off-by: Greg Kroah-Hartman --- drivers/infiniband/core/addr.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/infiniband/core/addr.c b/drivers/infiniband/core/addr.c index 0f58f46dbad7..8fd108d89527 100644 --- a/drivers/infiniband/core/addr.c +++ b/drivers/infiniband/core/addr.c @@ -444,8 +444,8 @@ static int addr6_resolve(struct sockaddr_in6 *src_in, fl6.saddr = src_in->sin6_addr; fl6.flowi6_oif = addr->bound_dev_if; - dst = ip6_route_output(addr->net, NULL, &fl6); - if ((ret = dst->error)) + ret = ipv6_stub->ipv6_dst_lookup(addr->net, NULL, &dst, &fl6); + if (ret < 0) goto put; rt = (struct rt6_info *)dst; From 4de8eceefbeabbf367b143cd29108a5ddcfab0e8 Mon Sep 17 00:00:00 2001 From: Vinothkumar Raja Date: Thu, 6 Apr 2017 22:09:38 -0400 Subject: [PATCH 248/396] dm btree: fix for dm_btree_find_lowest_key() commit 7d1fedb6e96a960aa91e4ff70714c3fb09195a5a upstream. dm_btree_find_lowest_key() is giving incorrect results. find_key() traverses the btree correctly for finding the highest key, but there is an error in the way it traverses the btree for retrieving the lowest key. dm_btree_find_lowest_key() fetches the first key of the rightmost block of the btree instead of fetching the first key from the leftmost block. Fix this by conditionally passing the correct parameter to value64() based on the @find_highest flag. Signed-off-by: Erez Zadok Signed-off-by: Vinothkumar Raja Signed-off-by: Nidhi Panpalia Signed-off-by: Mike Snitzer Signed-off-by: Greg Kroah-Hartman --- drivers/md/persistent-data/dm-btree.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/md/persistent-data/dm-btree.c b/drivers/md/persistent-data/dm-btree.c index 20a40329d84a..7a75b5010f73 100644 --- a/drivers/md/persistent-data/dm-btree.c +++ b/drivers/md/persistent-data/dm-btree.c @@ -897,8 +897,12 @@ static int find_key(struct ro_spine *s, dm_block_t block, bool find_highest, else *result_key = le64_to_cpu(ro_node(s)->keys[0]); - if (next_block || flags & INTERNAL_NODE) - block = value64(ro_node(s), i); + if (next_block || flags & INTERNAL_NODE) { + if (find_highest) + block = value64(ro_node(s), i); + else + block = value64(ro_node(s), 0); + } } while (flags & INTERNAL_NODE); From c5066c4c1b7ee20538eebd48e79a93cd4963b72c Mon Sep 17 00:00:00 2001 From: Mikulas Patocka Date: Tue, 28 Mar 2017 12:53:39 -0400 Subject: [PATCH 249/396] dm raid: select the Kconfig option CONFIG_MD_RAID0 commit 7b81ef8b14f80033e4a4168d199a0f5fd79b9426 upstream. Since the commit 0cf4503174c1 ("dm raid: add support for the MD RAID0 personality"), the dm-raid subsystem can activate a RAID-0 array. Therefore, add MD_RAID0 to the dependencies of DM_RAID, so that MD_RAID0 will be selected when DM_RAID is selected. Fixes: 0cf4503174c1 ("dm raid: add support for the MD RAID0 personality") Signed-off-by: Mikulas Patocka Signed-off-by: Mike Snitzer Signed-off-by: Greg Kroah-Hartman --- drivers/md/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/md/Kconfig b/drivers/md/Kconfig index 02a5345a44a6..197e29d1c2e6 100644 --- a/drivers/md/Kconfig +++ b/drivers/md/Kconfig @@ -357,6 +357,7 @@ config DM_LOG_USERSPACE config DM_RAID tristate "RAID 1/4/5/6/10 target" depends on BLK_DEV_DM + select MD_RAID0 select MD_RAID1 select MD_RAID10 select MD_RAID456 From 98e7b9d45bf443b02a7b8aacb2e502042ea88441 Mon Sep 17 00:00:00 2001 From: Mikulas Patocka Date: Sun, 30 Apr 2017 17:33:26 -0400 Subject: [PATCH 250/396] dm bufio: avoid a possible ABBA deadlock commit 1b0fb5a5b2dc0dddcfa575060441a7176ba7ac37 upstream. __get_memory_limit() tests if dm_bufio_cache_size changed and calls __cache_size_refresh() if it did. It takes dm_bufio_clients_lock while it already holds the client lock. However, lock ordering is violated because in cleanup_old_buffers() dm_bufio_clients_lock is taken before the client lock. This results in a possible deadlock and lockdep engine warning. Fix this deadlock by changing mutex_lock() to mutex_trylock(). If the lock can't be taken, it will be re-checked next time when a new buffer is allocated. Also add "unlikely" to the if condition, so that the optimizer assumes that the condition is false. Signed-off-by: Mikulas Patocka Signed-off-by: Mike Snitzer Signed-off-by: Greg Kroah-Hartman --- drivers/md/dm-bufio.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/md/dm-bufio.c b/drivers/md/dm-bufio.c index 125aedc3875f..d0745965f8ec 100644 --- a/drivers/md/dm-bufio.c +++ b/drivers/md/dm-bufio.c @@ -923,10 +923,11 @@ static void __get_memory_limit(struct dm_bufio_client *c, { unsigned long buffers; - if (ACCESS_ONCE(dm_bufio_cache_size) != dm_bufio_cache_size_latch) { - mutex_lock(&dm_bufio_clients_lock); - __cache_size_refresh(); - mutex_unlock(&dm_bufio_clients_lock); + if (unlikely(ACCESS_ONCE(dm_bufio_cache_size) != dm_bufio_cache_size_latch)) { + if (mutex_trylock(&dm_bufio_clients_lock)) { + __cache_size_refresh(); + mutex_unlock(&dm_bufio_clients_lock); + } } buffers = dm_bufio_cache_size_per_client >> From e08047c90c8aa2c0bb2403c30b0692c7f147f200 Mon Sep 17 00:00:00 2001 From: Mikulas Patocka Date: Sun, 30 Apr 2017 17:34:53 -0400 Subject: [PATCH 251/396] dm bufio: check new buffer allocation watermark every 30 seconds commit 390020ad2af9ca04844c4f3b1f299ad8746d84c8 upstream. dm-bufio checks a watermark when it allocates a new buffer in __bufio_new(). However, it doesn't check the watermark when the user changes /sys/module/dm_bufio/parameters/max_cache_size_bytes. This may result in a problem - if the watermark is high enough so that all possible buffers are allocated and if the user lowers the value of "max_cache_size_bytes", the watermark will never be checked against the new value because no new buffer would be allocated. To fix this, change __evict_old_buffers() so that it checks the watermark. __evict_old_buffers() is called every 30 seconds, so if the user reduces "max_cache_size_bytes", dm-bufio will react to this change within 30 seconds and decrease memory consumption. Depends-on: 1b0fb5a5b2 ("dm bufio: avoid a possible ABBA deadlock") Signed-off-by: Mikulas Patocka Signed-off-by: Mike Snitzer Signed-off-by: Greg Kroah-Hartman --- drivers/md/dm-bufio.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/md/dm-bufio.c b/drivers/md/dm-bufio.c index d0745965f8ec..c805fd9184bf 100644 --- a/drivers/md/dm-bufio.c +++ b/drivers/md/dm-bufio.c @@ -1782,9 +1782,17 @@ static void __evict_old_buffers(struct dm_bufio_client *c, unsigned long age_hz) struct dm_buffer *b, *tmp; unsigned retain_target = get_retain_buffers(c); unsigned count; + LIST_HEAD(write_list); dm_bufio_lock(c); + __check_watermark(c, &write_list); + if (unlikely(!list_empty(&write_list))) { + dm_bufio_unlock(c); + __flush_write_list(&write_list); + dm_bufio_lock(c); + } + count = c->n_buffers[LIST_CLEAN] + c->n_buffers[LIST_DIRTY]; list_for_each_entry_safe_reverse(b, tmp, &c->lru[LIST_CLEAN], lru_list) { if (count <= retain_target) @@ -1809,6 +1817,8 @@ static void cleanup_old_buffers(void) mutex_lock(&dm_bufio_clients_lock); + __cache_size_refresh(); + list_for_each_entry(c, &dm_bufio_all_clients, client_list) __evict_old_buffers(c, max_age_hz); From 042d8dbf69c6ca0d542eaf41480d9303c36c56a9 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Thu, 27 Apr 2017 10:11:14 -0700 Subject: [PATCH 252/396] dm mpath: split and rename activate_path() to prepare for its expanded use commit 89bfce763e43fa4897e0d3af6b29ed909df64cfd upstream. activate_path() is renamed to activate_path_work() which now calls activate_or_offline_path(). activate_or_offline_path() will be used by the next commit. Signed-off-by: Bart Van Assche Cc: Hannes Reinecke Cc: Christoph Hellwig Signed-off-by: Mike Snitzer Signed-off-by: Greg Kroah-Hartman --- drivers/md/dm-mpath.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/drivers/md/dm-mpath.c b/drivers/md/dm-mpath.c index e477af8596e2..ac8235bda61b 100644 --- a/drivers/md/dm-mpath.c +++ b/drivers/md/dm-mpath.c @@ -119,7 +119,8 @@ static struct kmem_cache *_mpio_cache; static struct workqueue_struct *kmultipathd, *kmpath_handlerd; static void trigger_event(struct work_struct *work); -static void activate_path(struct work_struct *work); +static void activate_or_offline_path(struct pgpath *pgpath); +static void activate_path_work(struct work_struct *work); static void process_queued_bios(struct work_struct *work); /*----------------------------------------------- @@ -144,7 +145,7 @@ static struct pgpath *alloc_pgpath(void) if (pgpath) { pgpath->is_active = true; - INIT_DELAYED_WORK(&pgpath->activate_path, activate_path); + INIT_DELAYED_WORK(&pgpath->activate_path, activate_path_work); } return pgpath; @@ -1515,10 +1516,8 @@ out: spin_unlock_irqrestore(&m->lock, flags); } -static void activate_path(struct work_struct *work) +static void activate_or_offline_path(struct pgpath *pgpath) { - struct pgpath *pgpath = - container_of(work, struct pgpath, activate_path.work); struct request_queue *q = bdev_get_queue(pgpath->path.dev->bdev); if (pgpath->is_active && !blk_queue_dying(q)) @@ -1527,6 +1526,14 @@ static void activate_path(struct work_struct *work) pg_init_done(pgpath, SCSI_DH_DEV_OFFLINED); } +static void activate_path_work(struct work_struct *work) +{ + struct pgpath *pgpath = + container_of(work, struct pgpath, activate_path.work); + + activate_or_offline_path(pgpath); +} + static int noretry_error(int error) { switch (error) { From e69242436b6b086a6f342f715c68389596a9a7ac Mon Sep 17 00:00:00 2001 From: Mike Snitzer Date: Fri, 5 May 2017 14:40:13 -0400 Subject: [PATCH 253/396] dm cache metadata: fail operations if fail_io mode has been established commit 10add84e276432d9dd8044679a1028dd4084117e upstream. Otherwise it is possible to trigger crashes due to the metadata being inaccessible yet these methods don't safely account for that possibility without these checks. Reported-by: Mikulas Patocka Signed-off-by: Mike Snitzer Signed-off-by: Greg Kroah-Hartman --- drivers/md/dm-cache-metadata.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/drivers/md/dm-cache-metadata.c b/drivers/md/dm-cache-metadata.c index 695577812cf6..6937ca42be8c 100644 --- a/drivers/md/dm-cache-metadata.c +++ b/drivers/md/dm-cache-metadata.c @@ -1383,17 +1383,19 @@ void dm_cache_metadata_set_stats(struct dm_cache_metadata *cmd, int dm_cache_commit(struct dm_cache_metadata *cmd, bool clean_shutdown) { - int r; + int r = -EINVAL; flags_mutator mutator = (clean_shutdown ? set_clean_shutdown : clear_clean_shutdown); WRITE_LOCK(cmd); + if (cmd->fail_io) + goto out; + r = __commit_transaction(cmd, mutator); if (r) goto out; r = __begin_transaction(cmd); - out: WRITE_UNLOCK(cmd); return r; @@ -1405,7 +1407,8 @@ int dm_cache_get_free_metadata_block_count(struct dm_cache_metadata *cmd, int r = -EINVAL; READ_LOCK(cmd); - r = dm_sm_get_nr_free(cmd->metadata_sm, result); + if (!cmd->fail_io) + r = dm_sm_get_nr_free(cmd->metadata_sm, result); READ_UNLOCK(cmd); return r; @@ -1417,7 +1420,8 @@ int dm_cache_get_metadata_dev_size(struct dm_cache_metadata *cmd, int r = -EINVAL; READ_LOCK(cmd); - r = dm_sm_get_nr_blocks(cmd->metadata_sm, result); + if (!cmd->fail_io) + r = dm_sm_get_nr_blocks(cmd->metadata_sm, result); READ_UNLOCK(cmd); return r; From eeaf13394d32763d75d3314ca47264e5078076cd Mon Sep 17 00:00:00 2001 From: Mikulas Patocka Date: Sun, 30 Apr 2017 17:32:28 -0400 Subject: [PATCH 254/396] dm bufio: make the parameter "retain_bytes" unsigned long commit 13840d38016203f0095cd547b90352812d24b787 upstream. Change the type of the parameter "retain_bytes" from unsigned to unsigned long, so that on 64-bit machines the user can set more than 4GiB of data to be retained. Also, change the type of the variable "count" in the function "__evict_old_buffers" to unsigned long. The assignment "count = c->n_buffers[LIST_CLEAN] + c->n_buffers[LIST_DIRTY];" could result in unsigned long to unsigned overflow and that could result in buffers not being freed when they should. While at it, avoid division in get_retain_buffers(). Division is slow, we can change it to shift because we have precalculated the log2 of block size. Signed-off-by: Mikulas Patocka Signed-off-by: Mike Snitzer Signed-off-by: Greg Kroah-Hartman --- drivers/md/dm-bufio.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/md/dm-bufio.c b/drivers/md/dm-bufio.c index c805fd9184bf..8bf9667ff46b 100644 --- a/drivers/md/dm-bufio.c +++ b/drivers/md/dm-bufio.c @@ -215,7 +215,7 @@ static DEFINE_SPINLOCK(param_spinlock); * Buffers are freed after this timeout */ static unsigned dm_bufio_max_age = DM_BUFIO_DEFAULT_AGE_SECS; -static unsigned dm_bufio_retain_bytes = DM_BUFIO_DEFAULT_RETAIN_BYTES; +static unsigned long dm_bufio_retain_bytes = DM_BUFIO_DEFAULT_RETAIN_BYTES; static unsigned long dm_bufio_peak_allocated; static unsigned long dm_bufio_allocated_kmem_cache; @@ -1541,10 +1541,10 @@ static bool __try_evict_buffer(struct dm_buffer *b, gfp_t gfp) return true; } -static unsigned get_retain_buffers(struct dm_bufio_client *c) +static unsigned long get_retain_buffers(struct dm_bufio_client *c) { - unsigned retain_bytes = ACCESS_ONCE(dm_bufio_retain_bytes); - return retain_bytes / c->block_size; + unsigned long retain_bytes = ACCESS_ONCE(dm_bufio_retain_bytes); + return retain_bytes >> (c->sectors_per_block_bits + SECTOR_SHIFT); } static unsigned long __scan(struct dm_bufio_client *c, unsigned long nr_to_scan, @@ -1554,7 +1554,7 @@ static unsigned long __scan(struct dm_bufio_client *c, unsigned long nr_to_scan, struct dm_buffer *b, *tmp; unsigned long freed = 0; unsigned long count = nr_to_scan; - unsigned retain_target = get_retain_buffers(c); + unsigned long retain_target = get_retain_buffers(c); for (l = 0; l < LIST_SIZE; l++) { list_for_each_entry_safe_reverse(b, tmp, &c->lru[l], lru_list) { @@ -1780,8 +1780,8 @@ static bool older_than(struct dm_buffer *b, unsigned long age_hz) static void __evict_old_buffers(struct dm_bufio_client *c, unsigned long age_hz) { struct dm_buffer *b, *tmp; - unsigned retain_target = get_retain_buffers(c); - unsigned count; + unsigned long retain_target = get_retain_buffers(c); + unsigned long count; LIST_HEAD(write_list); dm_bufio_lock(c); @@ -1941,7 +1941,7 @@ MODULE_PARM_DESC(max_cache_size_bytes, "Size of metadata cache"); module_param_named(max_age_seconds, dm_bufio_max_age, uint, S_IRUGO | S_IWUSR); MODULE_PARM_DESC(max_age_seconds, "Max age of a buffer in seconds"); -module_param_named(retain_bytes, dm_bufio_retain_bytes, uint, S_IRUGO | S_IWUSR); +module_param_named(retain_bytes, dm_bufio_retain_bytes, ulong, S_IRUGO | S_IWUSR); MODULE_PARM_DESC(retain_bytes, "Try to keep at least this many bytes cached in memory"); module_param_named(peak_allocated_bytes, dm_bufio_peak_allocated, ulong, S_IRUGO | S_IWUSR); From cc681811a92cd7cae589b5026b3d9d3bb1850365 Mon Sep 17 00:00:00 2001 From: Joe Thornber Date: Mon, 15 May 2017 09:43:05 -0400 Subject: [PATCH 255/396] dm thin metadata: call precommit before saving the roots commit 91bcdb92d39711d1adb40c26b653b7978d93eb98 upstream. These calls were the wrong way round in __write_initial_superblock. Signed-off-by: Joe Thornber Signed-off-by: Mike Snitzer Signed-off-by: Greg Kroah-Hartman --- drivers/md/dm-thin-metadata.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/md/dm-thin-metadata.c b/drivers/md/dm-thin-metadata.c index a15091a0d40c..4477bf930cf4 100644 --- a/drivers/md/dm-thin-metadata.c +++ b/drivers/md/dm-thin-metadata.c @@ -485,11 +485,11 @@ static int __write_initial_superblock(struct dm_pool_metadata *pmd) if (r < 0) return r; - r = save_sm_roots(pmd); + r = dm_tm_pre_commit(pmd->tm); if (r < 0) return r; - r = dm_tm_pre_commit(pmd->tm); + r = save_sm_roots(pmd); if (r < 0) return r; From f2bb8bcbc09dfe32138efc44105be9a58fad5cef Mon Sep 17 00:00:00 2001 From: Joe Thornber Date: Mon, 15 May 2017 09:45:40 -0400 Subject: [PATCH 256/396] dm space map disk: fix some book keeping in the disk space map commit 0377a07c7a035e0d033cd8b29f0cb15244c0916a upstream. When decrementing the reference count for a block, the free count wasn't being updated if the reference count went to zero. Signed-off-by: Joe Thornber Signed-off-by: Mike Snitzer Signed-off-by: Greg Kroah-Hartman --- drivers/md/persistent-data/dm-space-map-disk.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/drivers/md/persistent-data/dm-space-map-disk.c b/drivers/md/persistent-data/dm-space-map-disk.c index ebb280a14325..32adf6b4a9c7 100644 --- a/drivers/md/persistent-data/dm-space-map-disk.c +++ b/drivers/md/persistent-data/dm-space-map-disk.c @@ -142,10 +142,23 @@ static int sm_disk_inc_block(struct dm_space_map *sm, dm_block_t b) static int sm_disk_dec_block(struct dm_space_map *sm, dm_block_t b) { + int r; + uint32_t old_count; enum allocation_event ev; struct sm_disk *smd = container_of(sm, struct sm_disk, sm); - return sm_ll_dec(&smd->ll, b, &ev); + r = sm_ll_dec(&smd->ll, b, &ev); + if (!r && (ev == SM_FREE)) { + /* + * It's only free if it's also free in the last + * transaction. + */ + r = sm_ll_lookup(&smd->old_ll, b, &old_count); + if (!r && !old_count) + smd->nr_allocated_this_transaction--; + } + + return r; } static int sm_disk_new_block(struct dm_space_map *sm, dm_block_t *b) From fa9a4a9c6d6ffb21c220418384ed9d89f8c18e35 Mon Sep 17 00:00:00 2001 From: Dennis Yang Date: Wed, 29 Mar 2017 15:46:13 +0800 Subject: [PATCH 257/396] md: update slab_cache before releasing new stripes when stripes resizing commit 583da48e388f472e8818d9bb60ef6a1d40ee9f9d upstream. When growing raid5 device on machine with small memory, there is chance that mdadm will be killed and the following bug report can be observed. The same bug could also be reproduced in linux-4.10.6. [57600.075774] BUG: unable to handle kernel NULL pointer dereference at (null) [57600.083796] IP: [] _raw_spin_lock+0x7/0x20 [57600.110378] PGD 421cf067 PUD 4442d067 PMD 0 [57600.114678] Oops: 0002 [#1] SMP [57600.180799] CPU: 1 PID: 25990 Comm: mdadm Tainted: P O 4.2.8 #1 [57600.187849] Hardware name: To be filled by O.E.M. To be filled by O.E.M./MAHOBAY, BIOS QV05AR66 03/06/2013 [57600.197490] task: ffff880044e47240 ti: ffff880043070000 task.ti: ffff880043070000 [57600.204963] RIP: 0010:[] [] _raw_spin_lock+0x7/0x20 [57600.213057] RSP: 0018:ffff880043073810 EFLAGS: 00010046 [57600.218359] RAX: 0000000000000000 RBX: 000000000000000c RCX: ffff88011e296dd0 [57600.225486] RDX: 0000000000000001 RSI: ffffe8ffffcb46c0 RDI: 0000000000000000 [57600.232613] RBP: ffff880043073878 R08: ffff88011e5f8170 R09: 0000000000000282 [57600.239739] R10: 0000000000000005 R11: 28f5c28f5c28f5c3 R12: ffff880043073838 [57600.246872] R13: ffffe8ffffcb46c0 R14: 0000000000000000 R15: ffff8800b9706a00 [57600.253999] FS: 00007f576106c700(0000) GS:ffff88011e280000(0000) knlGS:0000000000000000 [57600.262078] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [57600.267817] CR2: 0000000000000000 CR3: 00000000428fe000 CR4: 00000000001406e0 [57600.274942] Stack: [57600.276949] ffffffff8114ee35 ffff880043073868 0000000000000282 000000000000eb3f [57600.284383] ffffffff81119043 ffff880043073838 ffff880043073838 ffff88003e197b98 [57600.291820] ffffe8ffffcb46c0 ffff88003e197360 0000000000000286 ffff880043073968 [57600.299254] Call Trace: [57600.301698] [] ? cache_flusharray+0x35/0xe0 [57600.307523] [] ? __page_cache_release+0x23/0x110 [57600.313779] [] kmem_cache_free+0x63/0xc0 [57600.319344] [] drop_one_stripe+0x62/0x90 [57600.324915] [] raid5_cache_scan+0x8b/0xb0 [57600.330563] [] shrink_slab.part.36+0x19a/0x250 [57600.336650] [] shrink_zone+0x23c/0x250 [57600.342039] [] do_try_to_free_pages+0x153/0x420 [57600.348210] [] try_to_free_pages+0x91/0xa0 [57600.353959] [] __alloc_pages_nodemask+0x4d1/0x8b0 [57600.360303] [] check_reshape+0x62b/0x770 [57600.365866] [] raid5_check_reshape+0x55/0xa0 [57600.371778] [] update_raid_disks+0xc7/0x110 [57600.377604] [] md_ioctl+0xd83/0x1b10 [57600.382827] [] blkdev_ioctl+0x170/0x690 [57600.388307] [] block_ioctl+0x38/0x40 [57600.393525] [] do_vfs_ioctl+0x2b5/0x480 [57600.399010] [] ? vfs_write+0x14b/0x1f0 [57600.404400] [] SyS_ioctl+0x3c/0x70 [57600.409447] [] entry_SYSCALL_64_fastpath+0x12/0x6a [57600.415875] Code: 00 00 00 00 55 48 89 e5 8b 07 85 c0 74 04 31 c0 5d c3 ba 01 00 00 00 f0 0f b1 17 85 c0 75 ef b0 01 5d c3 90 31 c0 ba 01 00 00 00 0f b1 17 85 c0 75 01 c3 55 89 c6 48 89 e5 e8 85 d1 63 ff 5d [57600.435460] RIP [] _raw_spin_lock+0x7/0x20 [57600.441208] RSP [57600.444690] CR2: 0000000000000000 [57600.448000] ---[ end trace cbc6b5cc4bf9831d ]--- The problem is that resize_stripes() releases new stripe_heads before assigning new slab cache to conf->slab_cache. If the shrinker function raid5_cache_scan() gets called after resize_stripes() starting releasing new stripes but right before new slab cache being assigned, it is possible that these new stripe_heads will be freed with the old slab_cache which was already been destoryed and that triggers this bug. Signed-off-by: Dennis Yang Fixes: edbe83ab4c27 ("md/raid5: allow the stripe_cache to grow and shrink.") Reviewed-by: NeilBrown Signed-off-by: Shaohua Li Signed-off-by: Greg Kroah-Hartman --- drivers/md/raid5.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index cce6057b9aca..f34ad2be66a1 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c @@ -2253,6 +2253,10 @@ static int resize_stripes(struct r5conf *conf, int newsize) err = -ENOMEM; mutex_unlock(&conf->cache_size_mutex); + + conf->slab_cache = sc; + conf->active_name = 1-conf->active_name; + /* Step 4, return new stripes to service */ while(!list_empty(&newstripes)) { nsh = list_entry(newstripes.next, struct stripe_head, lru); @@ -2270,8 +2274,6 @@ static int resize_stripes(struct r5conf *conf, int newsize) } /* critical section pass, GFP_NOIO no longer needed */ - conf->slab_cache = sc; - conf->active_name = 1-conf->active_name; if (!err) conf->pool_size = newsize; return err; From 7e789787878321fc2b1b7869963fa5eeede7402e Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Thu, 6 Apr 2017 11:16:33 +0800 Subject: [PATCH 258/396] md: MD_CLOSING needs to be cleared after called md_set_readonly or do_md_stop commit 065e519e71b2c1f41936cce75b46b5ab34adb588 upstream. if called md_set_readonly and set MD_CLOSING bit, the mddev cannot be opened any more due to the MD_CLOING bit wasn't cleared. Thus it needs to be cleared in md_ioctl after any call to md_set_readonly() or do_md_stop(). Signed-off-by: NeilBrown Fixes: af8d8e6f0315 ("md: changes for MD_STILL_CLOSED flag") Signed-off-by: Zhilong Liu Signed-off-by: Shaohua Li Signed-off-by: Greg Kroah-Hartman --- drivers/md/md.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/md/md.c b/drivers/md/md.c index 24925f2aa235..eddd360624a1 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -6752,6 +6752,7 @@ static int md_ioctl(struct block_device *bdev, fmode_t mode, void __user *argp = (void __user *)arg; struct mddev *mddev = NULL; int ro; + bool did_set_md_closing = false; if (!md_ioctl_valid(cmd)) return -ENOTTY; @@ -6841,7 +6842,9 @@ static int md_ioctl(struct block_device *bdev, fmode_t mode, err = -EBUSY; goto out; } + WARN_ON_ONCE(test_bit(MD_CLOSING, &mddev->flags)); set_bit(MD_CLOSING, &mddev->flags); + did_set_md_closing = true; mutex_unlock(&mddev->open_mutex); sync_blockdev(bdev); } @@ -7041,6 +7044,8 @@ unlock: mddev->hold_active = 0; mddev_unlock(mddev); out: + if(did_set_md_closing) + clear_bit(MD_CLOSING, &mddev->flags); return err; } #ifdef CONFIG_COMPAT From 444df795edf433aa75f10fc62ae171996dbd833c Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Sun, 16 Apr 2017 19:32:07 -0500 Subject: [PATCH 259/396] rtlwifi: rtl8821ae: setup 8812ae RFE according to device type commit 46cfa2148e7371c537efff1a1c693e58f523089d upstream. Current channel switch implementation sets 8812ae RFE reg value assuming that device always has type 2. Extend possible RFE types set and write corresponding reg values. Source for new code is http://dlcdnet.asus.com/pub/ASUS/wireless/PCE-AC51/DR_PCE_AC51_20232801152016.zip Signed-off-by: Maxim Samoylov Signed-off-by: Larry Finger Cc: Yan-Hsuan Chuang Cc: Pkshih Cc: Birming Chiu Cc: Shaofu Cc: Steven Ting Signed-off-by: Kalle Valo Signed-off-by: Greg Kroah-Hartman --- .../wireless/realtek/rtlwifi/rtl8821ae/phy.c | 122 +++++++++++++++--- .../wireless/realtek/rtlwifi/rtl8821ae/reg.h | 1 + 2 files changed, 107 insertions(+), 16 deletions(-) diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/phy.c b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/phy.c index 5dad402171c2..a74fad6e53c1 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/phy.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/phy.c @@ -359,6 +359,107 @@ bool rtl8821ae_phy_rf_config(struct ieee80211_hw *hw) return rtl8821ae_phy_rf6052_config(hw); } +static void _rtl8812ae_phy_set_rfe_reg_24g(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + u8 tmp; + + switch (rtlhal->rfe_type) { + case 3: + rtl_set_bbreg(hw, RA_RFE_PINMUX, BMASKDWORD, 0x54337770); + rtl_set_bbreg(hw, RB_RFE_PINMUX, BMASKDWORD, 0x54337770); + rtl_set_bbreg(hw, RA_RFE_INV, BMASKRFEINV, 0x010); + rtl_set_bbreg(hw, RB_RFE_INV, BMASKRFEINV, 0x010); + rtl_set_bbreg(hw, 0x900, 0x00000303, 0x1); + break; + case 4: + rtl_set_bbreg(hw, RA_RFE_PINMUX, BMASKDWORD, 0x77777777); + rtl_set_bbreg(hw, RB_RFE_PINMUX, BMASKDWORD, 0x77777777); + rtl_set_bbreg(hw, RA_RFE_INV, BMASKRFEINV, 0x001); + rtl_set_bbreg(hw, RB_RFE_INV, BMASKRFEINV, 0x001); + break; + case 5: + rtl_write_byte(rtlpriv, RA_RFE_PINMUX + 2, 0x77); + rtl_set_bbreg(hw, RB_RFE_PINMUX, BMASKDWORD, 0x77777777); + tmp = rtl_read_byte(rtlpriv, RA_RFE_INV + 3); + rtl_write_byte(rtlpriv, RA_RFE_INV + 3, tmp & ~0x1); + rtl_set_bbreg(hw, RB_RFE_INV, BMASKRFEINV, 0x000); + break; + case 1: + if (rtlpriv->btcoexist.bt_coexistence) { + rtl_set_bbreg(hw, RA_RFE_PINMUX, 0xffffff, 0x777777); + rtl_set_bbreg(hw, RB_RFE_PINMUX, BMASKDWORD, + 0x77777777); + rtl_set_bbreg(hw, RA_RFE_INV, 0x33f00000, 0x000); + rtl_set_bbreg(hw, RB_RFE_INV, BMASKRFEINV, 0x000); + break; + } + case 0: + case 2: + default: + rtl_set_bbreg(hw, RA_RFE_PINMUX, BMASKDWORD, 0x77777777); + rtl_set_bbreg(hw, RB_RFE_PINMUX, BMASKDWORD, 0x77777777); + rtl_set_bbreg(hw, RA_RFE_INV, BMASKRFEINV, 0x000); + rtl_set_bbreg(hw, RB_RFE_INV, BMASKRFEINV, 0x000); + break; + } +} + +static void _rtl8812ae_phy_set_rfe_reg_5g(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + u8 tmp; + + switch (rtlhal->rfe_type) { + case 0: + rtl_set_bbreg(hw, RA_RFE_PINMUX, BMASKDWORD, 0x77337717); + rtl_set_bbreg(hw, RB_RFE_PINMUX, BMASKDWORD, 0x77337717); + rtl_set_bbreg(hw, RA_RFE_INV, BMASKRFEINV, 0x010); + rtl_set_bbreg(hw, RB_RFE_INV, BMASKRFEINV, 0x010); + break; + case 1: + if (rtlpriv->btcoexist.bt_coexistence) { + rtl_set_bbreg(hw, RA_RFE_PINMUX, 0xffffff, 0x337717); + rtl_set_bbreg(hw, RB_RFE_PINMUX, BMASKDWORD, + 0x77337717); + rtl_set_bbreg(hw, RA_RFE_INV, 0x33f00000, 0x000); + rtl_set_bbreg(hw, RB_RFE_INV, BMASKRFEINV, 0x000); + } else { + rtl_set_bbreg(hw, RA_RFE_PINMUX, BMASKDWORD, + 0x77337717); + rtl_set_bbreg(hw, RB_RFE_PINMUX, BMASKDWORD, + 0x77337717); + rtl_set_bbreg(hw, RA_RFE_INV, BMASKRFEINV, 0x000); + rtl_set_bbreg(hw, RB_RFE_INV, BMASKRFEINV, 0x000); + } + break; + case 3: + rtl_set_bbreg(hw, RA_RFE_PINMUX, BMASKDWORD, 0x54337717); + rtl_set_bbreg(hw, RB_RFE_PINMUX, BMASKDWORD, 0x54337717); + rtl_set_bbreg(hw, RA_RFE_INV, BMASKRFEINV, 0x010); + rtl_set_bbreg(hw, RB_RFE_INV, BMASKRFEINV, 0x010); + rtl_set_bbreg(hw, 0x900, 0x00000303, 0x1); + break; + case 5: + rtl_write_byte(rtlpriv, RA_RFE_PINMUX + 2, 0x33); + rtl_set_bbreg(hw, RB_RFE_PINMUX, BMASKDWORD, 0x77337777); + tmp = rtl_read_byte(rtlpriv, RA_RFE_INV + 3); + rtl_write_byte(rtlpriv, RA_RFE_INV + 3, tmp | 0x1); + rtl_set_bbreg(hw, RB_RFE_INV, BMASKRFEINV, 0x010); + break; + case 2: + case 4: + default: + rtl_set_bbreg(hw, RA_RFE_PINMUX, BMASKDWORD, 0x77337777); + rtl_set_bbreg(hw, RB_RFE_PINMUX, BMASKDWORD, 0x77337777); + rtl_set_bbreg(hw, RA_RFE_INV, BMASKRFEINV, 0x010); + rtl_set_bbreg(hw, RB_RFE_INV, BMASKRFEINV, 0x010); + break; + } +} + u32 phy_get_tx_swing_8812A(struct ieee80211_hw *hw, u8 band, u8 rf_path) { @@ -553,14 +654,9 @@ void rtl8821ae_phy_switch_wirelessband(struct ieee80211_hw *hw, u8 band) /* 0x82C[1:0] = 2b'00 */ rtl_set_bbreg(hw, 0x82c, 0x3, 0); } - if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE) { - rtl_set_bbreg(hw, RA_RFE_PINMUX, BMASKDWORD, - 0x77777777); - rtl_set_bbreg(hw, RB_RFE_PINMUX, BMASKDWORD, - 0x77777777); - rtl_set_bbreg(hw, RA_RFE_INV, 0x3ff00000, 0x000); - rtl_set_bbreg(hw, RB_RFE_INV, 0x3ff00000, 0x000); - } + + if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE) + _rtl8812ae_phy_set_rfe_reg_24g(hw); rtl_set_bbreg(hw, RTXPATH, 0xf0, 0x1); rtl_set_bbreg(hw, RCCK_RX, 0x0f000000, 0x1); @@ -615,14 +711,8 @@ void rtl8821ae_phy_switch_wirelessband(struct ieee80211_hw *hw, u8 band) /* 0x82C[1:0] = 2'b00 */ rtl_set_bbreg(hw, 0x82c, 0x3, 1); - if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE) { - rtl_set_bbreg(hw, RA_RFE_PINMUX, BMASKDWORD, - 0x77337777); - rtl_set_bbreg(hw, RB_RFE_PINMUX, BMASKDWORD, - 0x77337777); - rtl_set_bbreg(hw, RA_RFE_INV, 0x3ff00000, 0x010); - rtl_set_bbreg(hw, RB_RFE_INV, 0x3ff00000, 0x010); - } + if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE) + _rtl8812ae_phy_set_rfe_reg_5g(hw); rtl_set_bbreg(hw, RTXPATH, 0xf0, 0); rtl_set_bbreg(hw, RCCK_RX, 0x0f000000, 0xf); diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/reg.h b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/reg.h index 1d6110f9c1fb..ed69dbe178ff 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/reg.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/reg.h @@ -2424,6 +2424,7 @@ #define BMASKH4BITS 0xf0000000 #define BMASKOFDM_D 0xffc00000 #define BMASKCCK 0x3f3f3f3f +#define BMASKRFEINV 0x3ff00000 #define BRFREGOFFSETMASK 0xfffff From 385eb9b33e1d67704c66f2ac2632ebf723e87892 Mon Sep 17 00:00:00 2001 From: Brian Norris Date: Wed, 5 Apr 2017 15:26:40 -0700 Subject: [PATCH 260/396] mwifiex: MAC randomization should not be persistent commit 7e2f18f06408ff56d7f75e68de8064777137b319 upstream. nl80211 provides the NL80211_SCAN_FLAG_RANDOM_ADDR for every scan request that should be randomized; the absence of such a flag means we should not randomize. However, mwifiex was stashing the latest randomization request and *always* using it for future scans, even those that didn't set the flag. Let's zero out the randomization info whenever we get a scan request without NL80211_SCAN_FLAG_RANDOM_ADDR. I'd prefer to remove priv->random_mac entirely (and plumb the randomization MAC properly through the call sequence), but the spaghetti is a little difficult to unravel here for me. Fixes: c2a8f0ff9c6c ("mwifiex: support random MAC address for scanning") Signed-off-by: Brian Norris Signed-off-by: Kalle Valo Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/marvell/mwifiex/cfg80211.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/marvell/mwifiex/cfg80211.c b/drivers/net/wireless/marvell/mwifiex/cfg80211.c index 16241d21727b..afdbbf59a278 100644 --- a/drivers/net/wireless/marvell/mwifiex/cfg80211.c +++ b/drivers/net/wireless/marvell/mwifiex/cfg80211.c @@ -2512,9 +2512,11 @@ mwifiex_cfg80211_scan(struct wiphy *wiphy, priv->random_mac[i] |= get_random_int() & ~(request->mac_addr_mask[i]); } + ether_addr_copy(user_scan_cfg->random_mac, priv->random_mac); + } else { + eth_zero_addr(priv->random_mac); } - ether_addr_copy(user_scan_cfg->random_mac, priv->random_mac); user_scan_cfg->num_ssids = request->n_ssids; user_scan_cfg->ssid_list = request->ssids; From ce7146cf9bdf490b9380af2a5d60bc65c68dbcb9 Mon Sep 17 00:00:00 2001 From: Brian Norris Date: Fri, 14 Apr 2017 14:51:17 -0700 Subject: [PATCH 261/396] mwifiex: pcie: fix cmd_buf use-after-free in remove/reset commit 3c8cb9ad032d737b874e402c59eb51e3c991a144 upstream. Command buffers (skb's) are allocated by the main driver, and freed upon the last use. That last use is often in mwifiex_free_cmd_buffer(). In the meantime, if the command buffer gets used by the PCI driver, we map it as DMA-able, and store the mapping information in the 'cb' memory. However, if a command was in-flight when resetting the device (and therefore was still mapped), we don't get a chance to unmap this memory until after the core has cleaned up its command handling. Let's keep a refcount within the PCI driver, so we ensure the memory only gets freed after we've finished unmapping it. Noticed by KASAN when forcing a reset via: echo 1 > /sys/bus/pci/.../reset The same code path can presumably be exercised in remove() and shutdown(). [ 205.390377] mwifiex_pcie 0000:01:00.0: info: shutdown mwifiex... [ 205.400393] ================================================================== [ 205.407719] BUG: KASAN: use-after-free in mwifiex_unmap_pci_memory.isra.14+0x4c/0x100 [mwifiex_pcie] at addr ffffffc0ad471b28 [ 205.419040] Read of size 16 by task bash/1913 [ 205.423421] ============================================================================= [ 205.431625] BUG skbuff_head_cache (Tainted: G B ): kasan: bad access detected [ 205.439815] ----------------------------------------------------------------------------- [ 205.439815] [ 205.449534] INFO: Allocated in __build_skb+0x48/0x114 age=1311 cpu=4 pid=1913 [ 205.456709] alloc_debug_processing+0x124/0x178 [ 205.461282] ___slab_alloc.constprop.58+0x528/0x608 [ 205.466196] __slab_alloc.isra.54.constprop.57+0x44/0x54 [ 205.471542] kmem_cache_alloc+0xcc/0x278 [ 205.475497] __build_skb+0x48/0x114 [ 205.479019] __netdev_alloc_skb+0xe0/0x170 [ 205.483244] mwifiex_alloc_cmd_buffer+0x68/0xdc [mwifiex] [ 205.488759] mwifiex_init_fw+0x40/0x6cc [mwifiex] [ 205.493584] _mwifiex_fw_dpc+0x158/0x520 [mwifiex] [ 205.498491] mwifiex_reinit_sw+0x2c4/0x398 [mwifiex] [ 205.503510] mwifiex_pcie_reset_notify+0x114/0x15c [mwifiex_pcie] [ 205.509643] pci_reset_notify+0x5c/0x6c [ 205.513519] pci_reset_function+0x6c/0x7c [ 205.517567] reset_store+0x68/0x98 [ 205.521003] dev_attr_store+0x54/0x60 [ 205.524705] sysfs_kf_write+0x9c/0xb0 [ 205.528413] INFO: Freed in __kfree_skb+0xb0/0xbc age=131 cpu=4 pid=1913 [ 205.535064] free_debug_processing+0x264/0x370 [ 205.539550] __slab_free+0x84/0x40c [ 205.543075] kmem_cache_free+0x1c8/0x2a0 [ 205.547030] __kfree_skb+0xb0/0xbc [ 205.550465] consume_skb+0x164/0x178 [ 205.554079] __dev_kfree_skb_any+0x58/0x64 [ 205.558304] mwifiex_free_cmd_buffer+0xa0/0x158 [mwifiex] [ 205.563817] mwifiex_shutdown_drv+0x578/0x5c4 [mwifiex] [ 205.569164] mwifiex_shutdown_sw+0x178/0x310 [mwifiex] [ 205.574353] mwifiex_pcie_reset_notify+0xd4/0x15c [mwifiex_pcie] [ 205.580398] pci_reset_notify+0x5c/0x6c [ 205.584274] pci_dev_save_and_disable+0x24/0x6c [ 205.588837] pci_reset_function+0x30/0x7c [ 205.592885] reset_store+0x68/0x98 [ 205.596324] dev_attr_store+0x54/0x60 [ 205.600017] sysfs_kf_write+0x9c/0xb0 ... [ 205.800488] Call trace: [ 205.802980] [] dump_backtrace+0x0/0x190 [ 205.808415] [] show_stack+0x20/0x28 [ 205.813506] [] dump_stack+0xa4/0xcc [ 205.818598] [] print_trailer+0x158/0x168 [ 205.824120] [] object_err+0x4c/0x5c [ 205.829210] [] kasan_report+0x334/0x500 [ 205.834641] [] check_memory_region+0x20/0x14c [ 205.840593] [] __asan_loadN+0x14/0x1c [ 205.845879] [] mwifiex_unmap_pci_memory.isra.14+0x4c/0x100 [mwifiex_pcie] [ 205.854282] [] mwifiex_pcie_delete_cmdrsp_buf+0x94/0xa8 [mwifiex_pcie] [ 205.862421] [] mwifiex_pcie_free_buffers+0x11c/0x158 [mwifiex_pcie] [ 205.870302] [] mwifiex_pcie_down_dev+0x70/0x80 [mwifiex_pcie] [ 205.877736] [] mwifiex_shutdown_sw+0x190/0x310 [mwifiex] [ 205.884658] [] mwifiex_pcie_reset_notify+0xd4/0x15c [mwifiex_pcie] [ 205.892446] [] pci_reset_notify+0x5c/0x6c [ 205.898048] [] pci_dev_save_and_disable+0x24/0x6c [ 205.904350] [] pci_reset_function+0x30/0x7c [ 205.910134] [] reset_store+0x68/0x98 [ 205.915312] [] dev_attr_store+0x54/0x60 [ 205.920750] [] sysfs_kf_write+0x9c/0xb0 [ 205.926182] [] kernfs_fop_write+0x184/0x1f8 [ 205.931963] [] __vfs_write+0x6c/0x17c [ 205.937221] [] vfs_write+0xf0/0x1c4 [ 205.942310] [] SyS_write+0x78/0xd8 [ 205.947312] [] el0_svc_naked+0x24/0x28 ... [ 205.998268] ================================================================== This bug has been around in different forms for a while. It was sort of noticed in commit 955ab095c51a ("mwifiex: Do not kfree cmd buf while unregistering PCIe"), but it just fixed the double-free, without acknowledging the potential for use-after-free. Fixes: fc3314609047 ("mwifiex: use pci_alloc/free_consistent APIs for PCIe") Signed-off-by: Brian Norris Signed-off-by: Kalle Valo Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/marvell/mwifiex/pcie.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/net/wireless/marvell/mwifiex/pcie.c b/drivers/net/wireless/marvell/mwifiex/pcie.c index 7a310c491ea5..1fdb86cd4734 100644 --- a/drivers/net/wireless/marvell/mwifiex/pcie.c +++ b/drivers/net/wireless/marvell/mwifiex/pcie.c @@ -995,6 +995,7 @@ static int mwifiex_pcie_delete_cmdrsp_buf(struct mwifiex_adapter *adapter) if (card && card->cmd_buf) { mwifiex_unmap_pci_memory(adapter, card->cmd_buf, PCI_DMA_TODEVICE); + dev_kfree_skb_any(card->cmd_buf); } return 0; } @@ -1561,6 +1562,11 @@ mwifiex_pcie_send_cmd(struct mwifiex_adapter *adapter, struct sk_buff *skb) return -1; card->cmd_buf = skb; + /* + * Need to keep a reference, since core driver might free up this + * buffer before we've unmapped it. + */ + skb_get(skb); /* To send a command, the driver will: 1. Write the 64bit physical address of the data buffer to @@ -1658,6 +1664,7 @@ static int mwifiex_pcie_process_cmd_complete(struct mwifiex_adapter *adapter) if (card->cmd_buf) { mwifiex_unmap_pci_memory(adapter, card->cmd_buf, PCI_DMA_TODEVICE); + dev_kfree_skb_any(card->cmd_buf); card->cmd_buf = NULL; } From 91034255e42f6026bafb8e8e2b707eb937104bc8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Gl=C3=B6ckner?= Date: Fri, 24 Feb 2017 15:05:14 +0100 Subject: [PATCH 262/396] ima: accept previously set IMA_NEW_FILE MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 1ac202e978e18f045006d75bd549612620c6ec3a upstream. Modifying the attributes of a file makes ima_inode_post_setattr reset the IMA cache flags. So if the file, which has just been created, is opened a second time before the first file descriptor is closed, verification fails since the security.ima xattr has not been written yet. We therefore have to look at the IMA_NEW_FILE even if the file already existed. With this patch there should no longer be an error when cat tries to open testfile: $ rm -f testfile $ ( echo test >&3 ; touch testfile ; cat testfile ) 3>testfile A file being new is no reason to accept that it is missing a digital signature demanded by the policy. Signed-off-by: Daniel Glöckner Signed-off-by: Mimi Zohar Signed-off-by: Greg Kroah-Hartman --- security/integrity/ima/ima_appraise.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/security/integrity/ima/ima_appraise.c b/security/integrity/ima/ima_appraise.c index 389325ac6067..097459830454 100644 --- a/security/integrity/ima/ima_appraise.c +++ b/security/integrity/ima/ima_appraise.c @@ -204,10 +204,11 @@ int ima_appraise_measurement(enum ima_hooks func, cause = "missing-hash"; status = INTEGRITY_NOLABEL; - if (opened & FILE_CREATED) { + if (opened & FILE_CREATED) iint->flags |= IMA_NEW_FILE; + if ((iint->flags & IMA_NEW_FILE) && + !(iint->flags & IMA_DIGSIG_REQUIRED)) status = INTEGRITY_PASS; - } goto out; } From b64ecb25b1d5e13f02a5ec8ce3dc031e53bcfdaf Mon Sep 17 00:00:00 2001 From: Wanpeng Li Date: Thu, 11 May 2017 02:58:55 -0700 Subject: [PATCH 263/396] KVM: x86: Fix load damaged SSEx MXCSR register MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit a575813bfe4bc15aba511a5e91e61d242bff8b9d upstream. Reported by syzkaller: BUG: unable to handle kernel paging request at ffffffffc07f6a2e IP: report_bug+0x94/0x120 PGD 348e12067 P4D 348e12067 PUD 348e14067 PMD 3cbd84067 PTE 80000003f7e87161 Oops: 0003 [#1] SMP CPU: 2 PID: 7091 Comm: kvm_load_guest_ Tainted: G OE 4.11.0+ #8 task: ffff92fdfb525400 task.stack: ffffbda6c3d04000 RIP: 0010:report_bug+0x94/0x120 RSP: 0018:ffffbda6c3d07b20 EFLAGS: 00010202 do_trap+0x156/0x170 do_error_trap+0xa3/0x170 ? kvm_load_guest_fpu.part.175+0x12a/0x170 [kvm] ? mark_held_locks+0x79/0xa0 ? retint_kernel+0x10/0x10 ? trace_hardirqs_off_thunk+0x1a/0x1c do_invalid_op+0x20/0x30 invalid_op+0x1e/0x30 RIP: 0010:kvm_load_guest_fpu.part.175+0x12a/0x170 [kvm] ? kvm_load_guest_fpu.part.175+0x1c/0x170 [kvm] kvm_arch_vcpu_ioctl_run+0xed6/0x1b70 [kvm] kvm_vcpu_ioctl+0x384/0x780 [kvm] ? kvm_vcpu_ioctl+0x384/0x780 [kvm] ? sched_clock+0x13/0x20 ? __do_page_fault+0x2a0/0x550 do_vfs_ioctl+0xa4/0x700 ? up_read+0x1f/0x40 ? __do_page_fault+0x2a0/0x550 SyS_ioctl+0x79/0x90 entry_SYSCALL_64_fastpath+0x23/0xc2 SDM mentioned that "The MXCSR has several reserved bits, and attempting to write a 1 to any of these bits will cause a general-protection exception(#GP) to be generated". The syzkaller forks' testcase overrides xsave area w/ random values and steps on the reserved bits of MXCSR register. The damaged MXCSR register values of guest will be restored to SSEx MXCSR register before vmentry. This patch fixes it by catching userspace override MXCSR register reserved bits w/ random values and bails out immediately. Reported-by: Andrey Konovalov Reviewed-by: Paolo Bonzini Cc: Paolo Bonzini Cc: Radim Krčmář Signed-off-by: Wanpeng Li Signed-off-by: Radim Krčmář Signed-off-by: Greg Kroah-Hartman --- arch/x86/kernel/fpu/init.c | 1 + arch/x86/kvm/x86.c | 9 +++++++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/arch/x86/kernel/fpu/init.c b/arch/x86/kernel/fpu/init.c index 2f2b8c7ccb85..6f0ab305dd5e 100644 --- a/arch/x86/kernel/fpu/init.c +++ b/arch/x86/kernel/fpu/init.c @@ -101,6 +101,7 @@ static void fpu__init_system_early_generic(struct cpuinfo_x86 *c) * Boot time FPU feature detection code: */ unsigned int mxcsr_feature_mask __read_mostly = 0xffffffffu; +EXPORT_SYMBOL_GPL(mxcsr_feature_mask); static void __init fpu__init_system_mxcsr(void) { diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 43c152853969..2d683f8b9287 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -3231,11 +3231,14 @@ static void kvm_vcpu_ioctl_x86_get_xsave(struct kvm_vcpu *vcpu, } } +#define XSAVE_MXCSR_OFFSET 24 + static int kvm_vcpu_ioctl_x86_set_xsave(struct kvm_vcpu *vcpu, struct kvm_xsave *guest_xsave) { u64 xstate_bv = *(u64 *)&guest_xsave->region[XSAVE_HDR_OFFSET / sizeof(u32)]; + u32 mxcsr = *(u32 *)&guest_xsave->region[XSAVE_MXCSR_OFFSET / sizeof(u32)]; if (boot_cpu_has(X86_FEATURE_XSAVE)) { /* @@ -3243,11 +3246,13 @@ static int kvm_vcpu_ioctl_x86_set_xsave(struct kvm_vcpu *vcpu, * CPUID leaf 0xD, index 0, EDX:EAX. This is for compatibility * with old userspace. */ - if (xstate_bv & ~kvm_supported_xcr0()) + if (xstate_bv & ~kvm_supported_xcr0() || + mxcsr & ~mxcsr_feature_mask) return -EINVAL; load_xsave(vcpu, (u8 *)guest_xsave->region); } else { - if (xstate_bv & ~XFEATURE_MASK_FPSSE) + if (xstate_bv & ~XFEATURE_MASK_FPSSE || + mxcsr & ~mxcsr_feature_mask) return -EINVAL; memcpy(&vcpu->arch.guest_fpu.state.fxsave, guest_xsave->region, sizeof(struct fxregs_state)); From c996ad7568c0ed3be135a5369078a4db30398a6d Mon Sep 17 00:00:00 2001 From: Wanpeng Li Date: Thu, 11 May 2017 18:12:05 -0700 Subject: [PATCH 264/396] KVM: x86: Fix potential preemption when get the current kvmclock timestamp MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit e2c2206a18993bc9f62393d49c7b2066c3845b25 upstream. BUG: using __this_cpu_read() in preemptible [00000000] code: qemu-system-x86/2809 caller is __this_cpu_preempt_check+0x13/0x20 CPU: 2 PID: 2809 Comm: qemu-system-x86 Not tainted 4.11.0+ #13 Call Trace: dump_stack+0x99/0xce check_preemption_disabled+0xf5/0x100 __this_cpu_preempt_check+0x13/0x20 get_kvmclock_ns+0x6f/0x110 [kvm] get_time_ref_counter+0x5d/0x80 [kvm] kvm_hv_process_stimers+0x2a1/0x8a0 [kvm] ? kvm_hv_process_stimers+0x2a1/0x8a0 [kvm] ? kvm_arch_vcpu_ioctl_run+0xac9/0x1ce0 [kvm] kvm_arch_vcpu_ioctl_run+0x5bf/0x1ce0 [kvm] kvm_vcpu_ioctl+0x384/0x7b0 [kvm] ? kvm_vcpu_ioctl+0x384/0x7b0 [kvm] ? __fget+0xf3/0x210 do_vfs_ioctl+0xa4/0x700 ? __fget+0x114/0x210 SyS_ioctl+0x79/0x90 entry_SYSCALL_64_fastpath+0x23/0xc2 RIP: 0033:0x7f9d164ed357 ? __this_cpu_preempt_check+0x13/0x20 This can be reproduced by run kvm-unit-tests/hyperv_stimer.flat w/ CONFIG_PREEMPT and CONFIG_DEBUG_PREEMPT enabled. Safe access to per-CPU data requires a couple of constraints, though: the thread working with the data cannot be preempted and it cannot be migrated while it manipulates per-CPU variables. If the thread is preempted, the thread that replaces it could try to work with the same variables; migration to another CPU could also cause confusion. However there is no preemption disable when reads host per-CPU tsc rate to calculate the current kvmclock timestamp. This patch fixes it by utilizing get_cpu/put_cpu pair to guarantee both __this_cpu_read() and rdtsc() are not preempted. Cc: Paolo Bonzini Cc: Radim Krčmář Signed-off-by: Wanpeng Li Reviewed-by: Paolo Bonzini Signed-off-by: Radim Krčmář Signed-off-by: Greg Kroah-Hartman --- arch/x86/kvm/x86.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 2d683f8b9287..42065164d38a 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -1735,6 +1735,7 @@ static u64 __get_kvmclock_ns(struct kvm *kvm) { struct kvm_arch *ka = &kvm->arch; struct pvclock_vcpu_time_info hv_clock; + u64 ret; spin_lock(&ka->pvclock_gtod_sync_lock); if (!ka->use_master_clock) { @@ -1746,10 +1747,17 @@ static u64 __get_kvmclock_ns(struct kvm *kvm) hv_clock.system_time = ka->master_kernel_ns + ka->kvmclock_offset; spin_unlock(&ka->pvclock_gtod_sync_lock); + /* both __this_cpu_read() and rdtsc() should be on the same cpu */ + get_cpu(); + kvm_get_time_scale(NSEC_PER_SEC, __this_cpu_read(cpu_tsc_khz) * 1000LL, &hv_clock.tsc_shift, &hv_clock.tsc_to_system_mul); - return __pvclock_read_cycles(&hv_clock, rdtsc()); + ret = __pvclock_read_cycles(&hv_clock, rdtsc()); + + put_cpu(); + + return ret; } u64 get_kvmclock_ns(struct kvm *kvm) From 54e385430e127634cc959955588fa5ee01488494 Mon Sep 17 00:00:00 2001 From: Wanpeng Li Date: Fri, 19 May 2017 02:46:56 -0700 Subject: [PATCH 265/396] KVM: X86: Fix read out-of-bounds vulnerability in kvm pio emulation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit cbfc6c9184ce71b52df4b1d82af5afc81a709178 upstream. Huawei folks reported a read out-of-bounds vulnerability in kvm pio emulation. - "inb" instruction to access PIT Mod/Command register (ioport 0x43, write only, a read should be ignored) in guest can get a random number. - "rep insb" instruction to access PIT register port 0x43 can control memcpy() in emulator_pio_in_emulated() to copy max 0x400 bytes but only read 1 bytes, which will disclose the unimportant kernel memory in host but no crash. The similar test program below can reproduce the read out-of-bounds vulnerability: void hexdump(void *mem, unsigned int len) { unsigned int i, j; for(i = 0; i < len + ((len % HEXDUMP_COLS) ? (HEXDUMP_COLS - len % HEXDUMP_COLS) : 0); i++) { /* print offset */ if(i % HEXDUMP_COLS == 0) { printf("0x%06x: ", i); } /* print hex data */ if(i < len) { printf("%02x ", 0xFF & ((char*)mem)[i]); } else /* end of block, just aligning for ASCII dump */ { printf(" "); } /* print ASCII dump */ if(i % HEXDUMP_COLS == (HEXDUMP_COLS - 1)) { for(j = i - (HEXDUMP_COLS - 1); j <= i; j++) { if(j >= len) /* end of block, not really printing */ { putchar(' '); } else if(isprint(((char*)mem)[j])) /* printable char */ { putchar(0xFF & ((char*)mem)[j]); } else /* other char */ { putchar('.'); } } putchar('\n'); } } } int main(void) { int i; if (iopl(3)) { err(1, "set iopl unsuccessfully\n"); return -1; } static char buf[0x40]; /* test ioport 0x40,0x41,0x42,0x43,0x44,0x45 */ memset(buf, 0xab, sizeof(buf)); asm volatile("push %rdi;"); asm volatile("mov %0, %%rdi;"::"q"(buf)); asm volatile ("mov $0x40, %rdx;"); asm volatile ("in %dx,%al;"); asm volatile ("stosb;"); asm volatile ("mov $0x41, %rdx;"); asm volatile ("in %dx,%al;"); asm volatile ("stosb;"); asm volatile ("mov $0x42, %rdx;"); asm volatile ("in %dx,%al;"); asm volatile ("stosb;"); asm volatile ("mov $0x43, %rdx;"); asm volatile ("in %dx,%al;"); asm volatile ("stosb;"); asm volatile ("mov $0x44, %rdx;"); asm volatile ("in %dx,%al;"); asm volatile ("stosb;"); asm volatile ("mov $0x45, %rdx;"); asm volatile ("in %dx,%al;"); asm volatile ("stosb;"); asm volatile ("pop %rdi;"); hexdump(buf, 0x40); printf("\n"); /* ins port 0x40 */ memset(buf, 0xab, sizeof(buf)); asm volatile("push %rdi;"); asm volatile("mov %0, %%rdi;"::"q"(buf)); asm volatile ("mov $0x20, %rcx;"); asm volatile ("mov $0x40, %rdx;"); asm volatile ("rep insb;"); asm volatile ("pop %rdi;"); hexdump(buf, 0x40); printf("\n"); /* ins port 0x43 */ memset(buf, 0xab, sizeof(buf)); asm volatile("push %rdi;"); asm volatile("mov %0, %%rdi;"::"q"(buf)); asm volatile ("mov $0x20, %rcx;"); asm volatile ("mov $0x43, %rdx;"); asm volatile ("rep insb;"); asm volatile ("pop %rdi;"); hexdump(buf, 0x40); printf("\n"); return 0; } The vcpu->arch.pio_data buffer is used by both in/out instrutions emulation w/o clear after using which results in some random datas are left over in the buffer. Guest reads port 0x43 will be ignored since it is write only, however, the function kernel_pio() can't distigush this ignore from successfully reads data from device's ioport. There is no new data fill the buffer from port 0x43, however, emulator_pio_in_emulated() will copy the stale data in the buffer to the guest unconditionally. This patch fixes it by clearing the buffer before in instruction emulation to avoid to grant guest the stale data in the buffer. In addition, string I/O is not supported for in kernel device. So there is no iteration to read ioport %RCX times for string I/O. The function kernel_pio() just reads one round, and then copy the io size * %RCX to the guest unconditionally, actually it copies the one round ioport data w/ other random datas which are left over in the vcpu->arch.pio_data buffer to the guest. This patch fixes it by introducing the string I/O support for in kernel device in order to grant the right ioport datas to the guest. Before the patch: 0x000000: fe 38 93 93 ff ff ab ab .8...... 0x000008: ab ab ab ab ab ab ab ab ........ 0x000010: ab ab ab ab ab ab ab ab ........ 0x000018: ab ab ab ab ab ab ab ab ........ 0x000020: ab ab ab ab ab ab ab ab ........ 0x000028: ab ab ab ab ab ab ab ab ........ 0x000030: ab ab ab ab ab ab ab ab ........ 0x000038: ab ab ab ab ab ab ab ab ........ 0x000000: f6 00 00 00 00 00 00 00 ........ 0x000008: 00 00 00 00 00 00 00 00 ........ 0x000010: 00 00 00 00 4d 51 30 30 ....MQ00 0x000018: 30 30 20 33 20 20 20 20 00 3 0x000020: ab ab ab ab ab ab ab ab ........ 0x000028: ab ab ab ab ab ab ab ab ........ 0x000030: ab ab ab ab ab ab ab ab ........ 0x000038: ab ab ab ab ab ab ab ab ........ 0x000000: f6 00 00 00 00 00 00 00 ........ 0x000008: 00 00 00 00 00 00 00 00 ........ 0x000010: 00 00 00 00 4d 51 30 30 ....MQ00 0x000018: 30 30 20 33 20 20 20 20 00 3 0x000020: ab ab ab ab ab ab ab ab ........ 0x000028: ab ab ab ab ab ab ab ab ........ 0x000030: ab ab ab ab ab ab ab ab ........ 0x000038: ab ab ab ab ab ab ab ab ........ After the patch: 0x000000: 1e 02 f8 00 ff ff ab ab ........ 0x000008: ab ab ab ab ab ab ab ab ........ 0x000010: ab ab ab ab ab ab ab ab ........ 0x000018: ab ab ab ab ab ab ab ab ........ 0x000020: ab ab ab ab ab ab ab ab ........ 0x000028: ab ab ab ab ab ab ab ab ........ 0x000030: ab ab ab ab ab ab ab ab ........ 0x000038: ab ab ab ab ab ab ab ab ........ 0x000000: d2 e2 d2 df d2 db d2 d7 ........ 0x000008: d2 d3 d2 cf d2 cb d2 c7 ........ 0x000010: d2 c4 d2 c0 d2 bc d2 b8 ........ 0x000018: d2 b4 d2 b0 d2 ac d2 a8 ........ 0x000020: ab ab ab ab ab ab ab ab ........ 0x000028: ab ab ab ab ab ab ab ab ........ 0x000030: ab ab ab ab ab ab ab ab ........ 0x000038: ab ab ab ab ab ab ab ab ........ 0x000000: 00 00 00 00 00 00 00 00 ........ 0x000008: 00 00 00 00 00 00 00 00 ........ 0x000010: 00 00 00 00 00 00 00 00 ........ 0x000018: 00 00 00 00 00 00 00 00 ........ 0x000020: ab ab ab ab ab ab ab ab ........ 0x000028: ab ab ab ab ab ab ab ab ........ 0x000030: ab ab ab ab ab ab ab ab ........ 0x000038: ab ab ab ab ab ab ab ab ........ Reported-by: Moguofang Cc: Paolo Bonzini Cc: Radim Krčmář Cc: Moguofang Signed-off-by: Wanpeng Li Signed-off-by: Radim Krčmář Signed-off-by: Greg Kroah-Hartman --- arch/x86/kvm/x86.c | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 42065164d38a..81bba3c2137d 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -4763,16 +4763,20 @@ emul_write: static int kernel_pio(struct kvm_vcpu *vcpu, void *pd) { - /* TODO: String I/O for in kernel device */ - int r; + int r = 0, i; - if (vcpu->arch.pio.in) - r = kvm_io_bus_read(vcpu, KVM_PIO_BUS, vcpu->arch.pio.port, - vcpu->arch.pio.size, pd); - else - r = kvm_io_bus_write(vcpu, KVM_PIO_BUS, - vcpu->arch.pio.port, vcpu->arch.pio.size, - pd); + for (i = 0; i < vcpu->arch.pio.count; i++) { + if (vcpu->arch.pio.in) + r = kvm_io_bus_read(vcpu, KVM_PIO_BUS, vcpu->arch.pio.port, + vcpu->arch.pio.size, pd); + else + r = kvm_io_bus_write(vcpu, KVM_PIO_BUS, + vcpu->arch.pio.port, vcpu->arch.pio.size, + pd); + if (r) + break; + pd += vcpu->arch.pio.size; + } return r; } @@ -4810,6 +4814,8 @@ static int emulator_pio_in_emulated(struct x86_emulate_ctxt *ctxt, if (vcpu->arch.pio.count) goto data_avail; + memset(vcpu->arch.pio_data, 0, size * count); + ret = emulator_pio_in_out(vcpu, size, port, val, count, true); if (ret) { data_avail: From ae382caa96f7fecea180b5879e133605a07ef88a Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Sun, 21 May 2017 18:26:54 -0700 Subject: [PATCH 266/396] x86: fix 32-bit case of __get_user_asm_u64() commit 33c9e9729033387ef0521324c62e7eba529294af upstream. The code to fetch a 64-bit value from user space was entirely buggered, and has been since the code was merged in early 2016 in commit b2f680380ddf ("x86/mm/32: Add support for 64-bit __get_user() on 32-bit kernels"). Happily the buggered routine is almost certainly entirely unused, since the normal way to access user space memory is just with the non-inlined "get_user()", and the inlined version didn't even historically exist. The normal "get_user()" case is handled by external hand-written asm in arch/x86/lib/getuser.S that doesn't have either of these issues. There were two independent bugs in __get_user_asm_u64(): - it still did the STAC/CLAC user space access marking, even though that is now done by the wrapper macros, see commit 11f1a4b9755f ("x86: reorganize SMAP handling in user space accesses"). This didn't result in a semantic error, it just means that the inlined optimized version was hugely less efficient than the allegedly slower standard version, since the CLAC/STAC overhead is quite high on modern Intel CPU's. - the double register %eax/%edx was marked as an output, but the %eax part of it was touched early in the asm, and could thus clobber other inputs to the asm that gcc didn't expect it to touch. In particular, that meant that the generated code could look like this: mov (%eax),%eax mov 0x4(%eax),%edx where the load of %edx obviously was _supposed_ to be from the 32-bit word that followed the source of %eax, but because %eax was overwritten by the first instruction, the source of %edx was basically random garbage. The fixes are trivial: remove the extraneous STAC/CLAC entries, and mark the 64-bit output as early-clobber to let gcc know that no inputs should alias with the output register. Cc: Al Viro Cc: Benjamin LaHaise Cc: Ingo Molnar Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- arch/x86/include/asm/uaccess.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/x86/include/asm/uaccess.h b/arch/x86/include/asm/uaccess.h index faf3687f1035..a300aa10ebc5 100644 --- a/arch/x86/include/asm/uaccess.h +++ b/arch/x86/include/asm/uaccess.h @@ -315,10 +315,10 @@ do { \ #define __get_user_asm_u64(x, ptr, retval, errret) \ ({ \ __typeof__(ptr) __ptr = (ptr); \ - asm volatile(ASM_STAC "\n" \ + asm volatile("\n" \ "1: movl %2,%%eax\n" \ "2: movl %3,%%edx\n" \ - "3: " ASM_CLAC "\n" \ + "3:\n" \ ".section .fixup,\"ax\"\n" \ "4: mov %4,%0\n" \ " xorl %%eax,%%eax\n" \ @@ -327,7 +327,7 @@ do { \ ".previous\n" \ _ASM_EXTABLE(1b, 4b) \ _ASM_EXTABLE(2b, 4b) \ - : "=r" (retval), "=A"(x) \ + : "=r" (retval), "=&A"(x) \ : "m" (__m(__ptr)), "m" __m(((u32 *)(__ptr)) + 1), \ "i" (errret), "0" (retval)); \ }) From 5b00d6c85a92076076da408b50cc4ddb323fc59c Mon Sep 17 00:00:00 2001 From: Wadim Egorov Date: Wed, 22 Mar 2017 16:50:50 +0100 Subject: [PATCH 267/396] regulator: rk808: Fix RK818 LDO2 commit 75f88115391156b3f0fecbbae76bf870c89bcab8 upstream. Set the correct voltage select register for LDO2. Signed-off-by: Wadim Egorov Signed-off-by: Mark Brown Signed-off-by: Greg Kroah-Hartman --- drivers/regulator/rk808-regulator.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/regulator/rk808-regulator.c b/drivers/regulator/rk808-regulator.c index 3314bf299a51..dfa8d50a5d74 100644 --- a/drivers/regulator/rk808-regulator.c +++ b/drivers/regulator/rk808-regulator.c @@ -520,7 +520,7 @@ static const struct regulator_desc rk818_reg[] = { RK818_LDO1_ON_VSEL_REG, RK818_LDO_VSEL_MASK, RK818_LDO_EN_REG, BIT(0), 400), RK8XX_DESC(RK818_ID_LDO2, "LDO_REG2", "vcc6", 1800, 3400, 100, - RK818_LDO1_ON_VSEL_REG, RK818_LDO_VSEL_MASK, RK818_LDO_EN_REG, + RK818_LDO2_ON_VSEL_REG, RK818_LDO_VSEL_MASK, RK818_LDO_EN_REG, BIT(1), 400), { .name = "LDO_REG3", From c849b4fa8e106f91cfb2750ddd13fa1e399f8234 Mon Sep 17 00:00:00 2001 From: Richard Cochran Date: Mon, 17 Apr 2017 10:23:36 +0200 Subject: [PATCH 268/396] regulator: tps65023: Fix inverted core enable logic. commit c90722b54a4f5e21ac59301ed9a6dbaa439bdb16 upstream. Commit 43530b69d758328d3ffe6ab98fd640463e8e3667 ("regulator: Use regmap_read/write(), regmap_update_bits functions directly") intended to replace working inline helper functions with standard regmap calls. However, it also inverted the set/clear logic of the "CORE ADJ Allowed" bit. That patch was clearly never tested, since without that bit cleared, the core VDCDC1 voltage output does not react to I2C configuration changes. This patch fixes the issue by clearing the bit as in the original, correct implementation. Note for stable back porting that, due to subsequent driver churn, this patch will not apply on every kernel version. Fixes: 43530b69d758 ("regulator: Use regmap_read/write(), regmap_update_bits functions directly") Signed-off-by: Richard Cochran Signed-off-by: Mark Brown Signed-off-by: Greg Kroah-Hartman --- drivers/regulator/tps65023-regulator.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/regulator/tps65023-regulator.c b/drivers/regulator/tps65023-regulator.c index d2c3d7cc35f5..5ca6d2130593 100644 --- a/drivers/regulator/tps65023-regulator.c +++ b/drivers/regulator/tps65023-regulator.c @@ -311,8 +311,7 @@ static int tps_65023_probe(struct i2c_client *client, /* Enable setting output voltage by I2C */ regmap_update_bits(tps->regmap, TPS65023_REG_CON_CTRL2, - TPS65023_REG_CTRL2_CORE_ADJ, - TPS65023_REG_CTRL2_CORE_ADJ); + TPS65023_REG_CTRL2_CORE_ADJ, 0); return 0; } From 8c5157c1967e58e1cb83c7d3178284afa98502d4 Mon Sep 17 00:00:00 2001 From: Michael Holzheu Date: Thu, 23 Mar 2017 21:02:54 +0100 Subject: [PATCH 269/396] s390/kdump: Add final note commit dcc00b79fc3d076832f7240de8870f492629b171 upstream. Since linux v3.14 with commit 38dfac843cb6d7be1 ("vmcore: prevent PT_NOTE p_memsz overflow during header update") on s390 we get the following message in the kdump kernel: Warning: Exceeded p_memsz, dropping PT_NOTE entry n_namesz=0x6b6b6b6b, n_descsz=0x6b6b6b6b The reason for this is that we don't create a final zero note in the ELF header which the proc/vmcore code uses to find out the end of the notes section (see also kernel/kexec_core.c:final_note()). It still worked on s390 by chance because we (most of the time?) have the byte pattern 0x6b6b6b6b after the notes section which also makes the notes parsing code stop in update_note_header_size_elf64() because 0x6b6b6b6b is interpreded as note size: if ((real_sz + sz) > max_sz) { pr_warn("Warning: Exceeded p_memsz, dropping P ...); break; } So fix this and add the missing final note to the ELF header. We don't have to adjust the memory size for ELF header ("alloc_size") because the new ELF note still fits into the 0x1000 base memory. Signed-off-by: Michael Holzheu Signed-off-by: Martin Schwidefsky Signed-off-by: Greg Kroah-Hartman --- arch/s390/kernel/crash_dump.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/arch/s390/kernel/crash_dump.c b/arch/s390/kernel/crash_dump.c index 408b4f4fda0f..598254461fb7 100644 --- a/arch/s390/kernel/crash_dump.c +++ b/arch/s390/kernel/crash_dump.c @@ -426,6 +426,20 @@ static void *nt_vmcoreinfo(void *ptr) return nt_init_name(ptr, 0, vmcoreinfo, size, "VMCOREINFO"); } +/* + * Initialize final note (needed for /proc/vmcore code) + */ +static void *nt_final(void *ptr) +{ + Elf64_Nhdr *note; + + note = (Elf64_Nhdr *) ptr; + note->n_namesz = 0; + note->n_descsz = 0; + note->n_type = 0; + return PTR_ADD(ptr, sizeof(Elf64_Nhdr)); +} + /* * Initialize ELF header (new kernel) */ @@ -513,6 +527,7 @@ static void *notes_init(Elf64_Phdr *phdr, void *ptr, u64 notes_offset) if (sa->prefix != 0) ptr = fill_cpu_elf_notes(ptr, cpu++, sa); ptr = nt_vmcoreinfo(ptr); + ptr = nt_final(ptr); memset(phdr, 0, sizeof(*phdr)); phdr->p_type = PT_NOTE; phdr->p_offset = notes_offset; From 768ae64b2ab2201cf3d13ecbdc0948e2601f6fd2 Mon Sep 17 00:00:00 2001 From: Martin Schwidefsky Date: Tue, 2 May 2017 13:36:00 +0200 Subject: [PATCH 270/396] s390/cputime: fix incorrect system time commit 07a63cbe8bcb6ba72fb989dcab1ec55ec6c36c7e upstream. git commit c5328901aa1db134 "[S390] entry[64].S improvements" removed the update of the exit_timer lowcore field from the critical section cleanup of the .Lsysc_restore/.Lsysc_done and .Lio_restore/.Lio_done blocks. If the PSW is updated by the critical section cleanup to point to user space again, the interrupt entry code will do a vtime calculation after the cleanup completed with an exit_timer value which has *not* been updated. Due to this incorrect system time deltas are calculated. If an interrupt occured with an old PSW between .Lsysc_restore/.Lsysc_done or .Lio_restore/.Lio_done update __LC_EXIT_TIMER with the system entry time of the interrupt. Tested-by: Christian Borntraeger Signed-off-by: Martin Schwidefsky Signed-off-by: Greg Kroah-Hartman --- arch/s390/kernel/entry.S | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S index 49a30737adde..c43816886839 100644 --- a/arch/s390/kernel/entry.S +++ b/arch/s390/kernel/entry.S @@ -321,6 +321,7 @@ ENTRY(system_call) lg %r14,__LC_VDSO_PER_CPU lmg %r0,%r10,__PT_R0(%r11) mvc __LC_RETURN_PSW(16),__PT_PSW(%r11) +.Lsysc_exit_timer: stpt __LC_EXIT_TIMER mvc __VDSO_ECTG_BASE(16,%r14),__LC_EXIT_TIMER lmg %r11,%r15,__PT_R11(%r11) @@ -606,6 +607,7 @@ ENTRY(io_int_handler) lg %r14,__LC_VDSO_PER_CPU lmg %r0,%r10,__PT_R0(%r11) mvc __LC_RETURN_PSW(16),__PT_PSW(%r11) +.Lio_exit_timer: stpt __LC_EXIT_TIMER mvc __VDSO_ECTG_BASE(16,%r14),__LC_EXIT_TIMER lmg %r11,%r15,__PT_R11(%r11) @@ -1135,15 +1137,23 @@ cleanup_critical: br %r14 .Lcleanup_sysc_restore: + # check if stpt has been executed clg %r9,BASED(.Lcleanup_sysc_restore_insn) + jh 0f + mvc __LC_EXIT_TIMER(8),__LC_ASYNC_ENTER_TIMER + cghi %r11,__LC_SAVE_AREA_ASYNC je 0f + mvc __LC_EXIT_TIMER(8),__LC_MCCK_ENTER_TIMER +0: clg %r9,BASED(.Lcleanup_sysc_restore_insn+8) + je 1f lg %r9,24(%r11) # get saved pointer to pt_regs mvc __LC_RETURN_PSW(16),__PT_PSW(%r9) mvc 0(64,%r11),__PT_R8(%r9) lmg %r0,%r7,__PT_R0(%r9) -0: lmg %r8,%r9,__LC_RETURN_PSW +1: lmg %r8,%r9,__LC_RETURN_PSW br %r14 .Lcleanup_sysc_restore_insn: + .quad .Lsysc_exit_timer .quad .Lsysc_done - 4 .Lcleanup_io_tif: @@ -1151,15 +1161,20 @@ cleanup_critical: br %r14 .Lcleanup_io_restore: + # check if stpt has been executed clg %r9,BASED(.Lcleanup_io_restore_insn) - je 0f + jh 0f + mvc __LC_EXIT_TIMER(8),__LC_MCCK_ENTER_TIMER +0: clg %r9,BASED(.Lcleanup_io_restore_insn+8) + je 1f lg %r9,24(%r11) # get saved r11 pointer to pt_regs mvc __LC_RETURN_PSW(16),__PT_PSW(%r9) mvc 0(64,%r11),__PT_R8(%r9) lmg %r0,%r7,__PT_R0(%r9) -0: lmg %r8,%r9,__LC_RETURN_PSW +1: lmg %r8,%r9,__LC_RETURN_PSW br %r14 .Lcleanup_io_restore_insn: + .quad .Lio_exit_timer .quad .Lio_done - 4 .Lcleanup_idle: From c39bafb9ee7a2aaaf71cdcac7bd583ee741b3da2 Mon Sep 17 00:00:00 2001 From: Dmitry Tunin Date: Wed, 8 Mar 2017 13:52:07 +0200 Subject: [PATCH 271/396] ath9k_htc: Add support of AirTies 1eda:2315 AR9271 device commit 16ff1fb0e32f76a5d285a6f23b82d21aa52813c6 upstream. T: Bus=01 Lev=02 Prnt=02 Port=02 Cnt=01 Dev#= 7 Spd=480 MxCh= 0 D: Ver= 2.00 Cls=ff(vend.) Sub=ff Prot=ff MxPS=64 #Cfgs= 1 P: Vendor=1eda ProdID=2315 Rev=01.08 S: Manufacturer=ATHEROS S: Product=USB2.0 WLAN S: SerialNumber=12345 C: #Ifs= 1 Cfg#= 1 Atr=80 MxPwr=500mA I: If#= 0 Alt= 0 #EPs= 6 Cls=ff(vend.) Sub=00 Prot=00 Driver=(none) Signed-off-by: Dmitry Tunin Signed-off-by: Kalle Valo Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/ath/ath9k/hif_usb.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.c b/drivers/net/wireless/ath/ath9k/hif_usb.c index e1c338cb9cb5..a9b15186df34 100644 --- a/drivers/net/wireless/ath/ath9k/hif_usb.c +++ b/drivers/net/wireless/ath/ath9k/hif_usb.c @@ -37,6 +37,7 @@ static struct usb_device_id ath9k_hif_usb_ids[] = { { USB_DEVICE(0x0cf3, 0xb002) }, /* Ubiquiti WifiStation */ { USB_DEVICE(0x057c, 0x8403) }, /* AVM FRITZ!WLAN 11N v2 USB */ { USB_DEVICE(0x0471, 0x209e) }, /* Philips (or NXP) PTA01 */ + { USB_DEVICE(0x1eda, 0x2315) }, /* AirTies */ { USB_DEVICE(0x0cf3, 0x7015), .driver_info = AR9287_USB }, /* Atheros */ From adc6647c4f0f6f7f3d838d1ccd7398695b6b0702 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Mon, 13 Mar 2017 13:44:20 +0100 Subject: [PATCH 272/396] ath9k_htc: fix NULL-deref at probe commit ebeb36670ecac36c179b5fb5d5c88ff03ba191ec upstream. Make sure to check the number of endpoints to avoid dereferencing a NULL-pointer or accessing memory beyond the endpoint array should a malicious device lack the expected endpoints. Fixes: 36bcce430657 ("ath9k_htc: Handle storage devices") Signed-off-by: Johan Hovold Signed-off-by: Kalle Valo Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/ath/ath9k/hif_usb.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.c b/drivers/net/wireless/ath/ath9k/hif_usb.c index a9b15186df34..f15589c70284 100644 --- a/drivers/net/wireless/ath/ath9k/hif_usb.c +++ b/drivers/net/wireless/ath/ath9k/hif_usb.c @@ -1219,6 +1219,9 @@ static int send_eject_command(struct usb_interface *interface) u8 bulk_out_ep; int r; + if (iface_desc->desc.bNumEndpoints < 2) + return -ENODEV; + /* Find bulk out endpoint */ for (r = 1; r >= 0; r--) { endpoint = &iface_desc->endpoint[r].desc; From ebf3cf5b9a67c694070ba93d8c31469aeb793266 Mon Sep 17 00:00:00 2001 From: Mario Kleiner Date: Wed, 29 Mar 2017 22:09:11 +0200 Subject: [PATCH 273/396] drm/amdgpu: Make display watermark calculations more accurate commit d63c277dc672e0c568481af043359420fa9d4736 upstream. Avoid big roundoff errors in scanline/hactive durations for high pixel clocks, especially for >= 500 Mhz, and thereby program more accurate display fifo watermarks. Implemented here for DCE 6,8,10,11. Successfully tested on DCE 10 with AMD R9 380 Tonga. Reviewed-by: Alex Deucher Signed-off-by: Mario Kleiner Signed-off-by: Alex Deucher Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/amd/amdgpu/dce_v10_0.c | 10 +++++----- drivers/gpu/drm/amd/amdgpu/dce_v11_0.c | 10 +++++----- drivers/gpu/drm/amd/amdgpu/dce_v6_0.c | 10 +++++----- drivers/gpu/drm/amd/amdgpu/dce_v8_0.c | 10 +++++----- 4 files changed, 20 insertions(+), 20 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c index 882404cefbc2..eda2d56d2f2f 100644 --- a/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c +++ b/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c @@ -1297,14 +1297,14 @@ static void dce_v10_0_program_watermarks(struct amdgpu_device *adev, { struct drm_display_mode *mode = &amdgpu_crtc->base.mode; struct dce10_wm_params wm_low, wm_high; - u32 pixel_period; + u32 active_time; u32 line_time = 0; u32 latency_watermark_a = 0, latency_watermark_b = 0; u32 tmp, wm_mask, lb_vblank_lead_lines = 0; if (amdgpu_crtc->base.enabled && num_heads && mode) { - pixel_period = 1000000 / (u32)mode->clock; - line_time = min((u32)mode->crtc_htotal * pixel_period, (u32)65535); + active_time = 1000000UL * (u32)mode->crtc_hdisplay / (u32)mode->clock; + line_time = min((u32) (1000000UL * (u32)mode->crtc_htotal / (u32)mode->clock), (u32)65535); /* watermark for high clocks */ if (adev->pm.dpm_enabled) { @@ -1319,7 +1319,7 @@ static void dce_v10_0_program_watermarks(struct amdgpu_device *adev, wm_high.disp_clk = mode->clock; wm_high.src_width = mode->crtc_hdisplay; - wm_high.active_time = mode->crtc_hdisplay * pixel_period; + wm_high.active_time = active_time; wm_high.blank_time = line_time - wm_high.active_time; wm_high.interlaced = false; if (mode->flags & DRM_MODE_FLAG_INTERLACE) @@ -1358,7 +1358,7 @@ static void dce_v10_0_program_watermarks(struct amdgpu_device *adev, wm_low.disp_clk = mode->clock; wm_low.src_width = mode->crtc_hdisplay; - wm_low.active_time = mode->crtc_hdisplay * pixel_period; + wm_low.active_time = active_time; wm_low.blank_time = line_time - wm_low.active_time; wm_low.interlaced = false; if (mode->flags & DRM_MODE_FLAG_INTERLACE) diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c index 64a1df62cc65..3b610fb405b6 100644 --- a/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c +++ b/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c @@ -1264,14 +1264,14 @@ static void dce_v11_0_program_watermarks(struct amdgpu_device *adev, { struct drm_display_mode *mode = &amdgpu_crtc->base.mode; struct dce10_wm_params wm_low, wm_high; - u32 pixel_period; + u32 active_time; u32 line_time = 0; u32 latency_watermark_a = 0, latency_watermark_b = 0; u32 tmp, wm_mask, lb_vblank_lead_lines = 0; if (amdgpu_crtc->base.enabled && num_heads && mode) { - pixel_period = 1000000 / (u32)mode->clock; - line_time = min((u32)mode->crtc_htotal * pixel_period, (u32)65535); + active_time = 1000000UL * (u32)mode->crtc_hdisplay / (u32)mode->clock; + line_time = min((u32) (1000000UL * (u32)mode->crtc_htotal / (u32)mode->clock), (u32)65535); /* watermark for high clocks */ if (adev->pm.dpm_enabled) { @@ -1286,7 +1286,7 @@ static void dce_v11_0_program_watermarks(struct amdgpu_device *adev, wm_high.disp_clk = mode->clock; wm_high.src_width = mode->crtc_hdisplay; - wm_high.active_time = mode->crtc_hdisplay * pixel_period; + wm_high.active_time = active_time; wm_high.blank_time = line_time - wm_high.active_time; wm_high.interlaced = false; if (mode->flags & DRM_MODE_FLAG_INTERLACE) @@ -1325,7 +1325,7 @@ static void dce_v11_0_program_watermarks(struct amdgpu_device *adev, wm_low.disp_clk = mode->clock; wm_low.src_width = mode->crtc_hdisplay; - wm_low.active_time = mode->crtc_hdisplay * pixel_period; + wm_low.active_time = active_time; wm_low.blank_time = line_time - wm_low.active_time; wm_low.interlaced = false; if (mode->flags & DRM_MODE_FLAG_INTERLACE) diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c index fde6ee1f6f2b..06fc40083151 100644 --- a/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c +++ b/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c @@ -1057,7 +1057,7 @@ static void dce_v6_0_program_watermarks(struct amdgpu_device *adev, struct drm_display_mode *mode = &amdgpu_crtc->base.mode; struct dce6_wm_params wm_low, wm_high; u32 dram_channels; - u32 pixel_period; + u32 active_time; u32 line_time = 0; u32 latency_watermark_a = 0, latency_watermark_b = 0; u32 priority_a_mark = 0, priority_b_mark = 0; @@ -1067,8 +1067,8 @@ static void dce_v6_0_program_watermarks(struct amdgpu_device *adev, fixed20_12 a, b, c; if (amdgpu_crtc->base.enabled && num_heads && mode) { - pixel_period = 1000000 / (u32)mode->clock; - line_time = min((u32)mode->crtc_htotal * pixel_period, (u32)65535); + active_time = 1000000UL * (u32)mode->crtc_hdisplay / (u32)mode->clock; + line_time = min((u32) (1000000UL * (u32)mode->crtc_htotal / (u32)mode->clock), (u32)65535); priority_a_cnt = 0; priority_b_cnt = 0; @@ -1087,7 +1087,7 @@ static void dce_v6_0_program_watermarks(struct amdgpu_device *adev, wm_high.disp_clk = mode->clock; wm_high.src_width = mode->crtc_hdisplay; - wm_high.active_time = mode->crtc_hdisplay * pixel_period; + wm_high.active_time = active_time; wm_high.blank_time = line_time - wm_high.active_time; wm_high.interlaced = false; if (mode->flags & DRM_MODE_FLAG_INTERLACE) @@ -1114,7 +1114,7 @@ static void dce_v6_0_program_watermarks(struct amdgpu_device *adev, wm_low.disp_clk = mode->clock; wm_low.src_width = mode->crtc_hdisplay; - wm_low.active_time = mode->crtc_hdisplay * pixel_period; + wm_low.active_time = active_time; wm_low.blank_time = line_time - wm_low.active_time; wm_low.interlaced = false; if (mode->flags & DRM_MODE_FLAG_INTERLACE) diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c index 7d9ffde0a628..ac88c589be32 100644 --- a/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c +++ b/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c @@ -1218,14 +1218,14 @@ static void dce_v8_0_program_watermarks(struct amdgpu_device *adev, { struct drm_display_mode *mode = &amdgpu_crtc->base.mode; struct dce8_wm_params wm_low, wm_high; - u32 pixel_period; + u32 active_time; u32 line_time = 0; u32 latency_watermark_a = 0, latency_watermark_b = 0; u32 tmp, wm_mask, lb_vblank_lead_lines = 0; if (amdgpu_crtc->base.enabled && num_heads && mode) { - pixel_period = 1000000 / (u32)mode->clock; - line_time = min((u32)mode->crtc_htotal * pixel_period, (u32)65535); + active_time = 1000000UL * (u32)mode->crtc_hdisplay / (u32)mode->clock; + line_time = min((u32) (1000000UL * (u32)mode->crtc_htotal / (u32)mode->clock), (u32)65535); /* watermark for high clocks */ if (adev->pm.dpm_enabled) { @@ -1240,7 +1240,7 @@ static void dce_v8_0_program_watermarks(struct amdgpu_device *adev, wm_high.disp_clk = mode->clock; wm_high.src_width = mode->crtc_hdisplay; - wm_high.active_time = mode->crtc_hdisplay * pixel_period; + wm_high.active_time = active_time; wm_high.blank_time = line_time - wm_high.active_time; wm_high.interlaced = false; if (mode->flags & DRM_MODE_FLAG_INTERLACE) @@ -1279,7 +1279,7 @@ static void dce_v8_0_program_watermarks(struct amdgpu_device *adev, wm_low.disp_clk = mode->clock; wm_low.src_width = mode->crtc_hdisplay; - wm_low.active_time = mode->crtc_hdisplay * pixel_period; + wm_low.active_time = active_time; wm_low.blank_time = line_time - wm_low.active_time; wm_low.interlaced = false; if (mode->flags & DRM_MODE_FLAG_INTERLACE) From b334b3492888068a4ae8373f4e813cf7364d4a61 Mon Sep 17 00:00:00 2001 From: Mario Kleiner Date: Wed, 29 Mar 2017 22:09:12 +0200 Subject: [PATCH 274/396] drm/amdgpu: Avoid overflows/divide-by-zero in latency_watermark calculations. commit e190ed1ea7458e446230de4113cc5d53b8dc4ec8 upstream. At dot clocks > approx. 250 Mhz, some of these calcs will overflow and cause miscalculation of latency watermarks, and for some overflows also divide-by-zero driver crash ("divide error: 0000 [#1] PREEMPT SMP" in "dce_v10_0_latency_watermark+0x12d/0x190"). This zero-divide happened, e.g., on AMD Tonga Pro under DCE-10, on a Displayport panel when trying to set a video mode of 2560x1440 at 165 Hz vrefresh with a dot clock of 635.540 Mhz. Refine calculations to avoid the overflows. Tested for DCE-10 with R9 380 Tonga + ASUS ROG PG279 panel. Reviewed-by: Alex Deucher Signed-off-by: Mario Kleiner Signed-off-by: Alex Deucher Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/amd/amdgpu/dce_v10_0.c | 19 +++---------------- drivers/gpu/drm/amd/amdgpu/dce_v11_0.c | 19 +++---------------- drivers/gpu/drm/amd/amdgpu/dce_v6_0.c | 19 +++---------------- drivers/gpu/drm/amd/amdgpu/dce_v8_0.c | 19 +++---------------- 4 files changed, 12 insertions(+), 64 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c index eda2d56d2f2f..42448c7c5ff5 100644 --- a/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c +++ b/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c @@ -1173,23 +1173,10 @@ static u32 dce_v10_0_latency_watermark(struct dce10_wm_params *wm) a.full = dfixed_const(available_bandwidth); b.full = dfixed_const(wm->num_heads); a.full = dfixed_div(a, b); + tmp = div_u64((u64) dmif_size * (u64) wm->disp_clk, mc_latency + 512); + tmp = min(dfixed_trunc(a), tmp); - b.full = dfixed_const(mc_latency + 512); - c.full = dfixed_const(wm->disp_clk); - b.full = dfixed_div(b, c); - - c.full = dfixed_const(dmif_size); - b.full = dfixed_div(c, b); - - tmp = min(dfixed_trunc(a), dfixed_trunc(b)); - - b.full = dfixed_const(1000); - c.full = dfixed_const(wm->disp_clk); - b.full = dfixed_div(c, b); - c.full = dfixed_const(wm->bytes_per_pixel); - b.full = dfixed_mul(b, c); - - lb_fill_bw = min(tmp, dfixed_trunc(b)); + lb_fill_bw = min(tmp, wm->disp_clk * wm->bytes_per_pixel / 1000); a.full = dfixed_const(max_src_lines_per_dst_line * wm->src_width * wm->bytes_per_pixel); b.full = dfixed_const(1000); diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c index 3b610fb405b6..904dabdc3a1e 100644 --- a/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c +++ b/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c @@ -1140,23 +1140,10 @@ static u32 dce_v11_0_latency_watermark(struct dce10_wm_params *wm) a.full = dfixed_const(available_bandwidth); b.full = dfixed_const(wm->num_heads); a.full = dfixed_div(a, b); + tmp = div_u64((u64) dmif_size * (u64) wm->disp_clk, mc_latency + 512); + tmp = min(dfixed_trunc(a), tmp); - b.full = dfixed_const(mc_latency + 512); - c.full = dfixed_const(wm->disp_clk); - b.full = dfixed_div(b, c); - - c.full = dfixed_const(dmif_size); - b.full = dfixed_div(c, b); - - tmp = min(dfixed_trunc(a), dfixed_trunc(b)); - - b.full = dfixed_const(1000); - c.full = dfixed_const(wm->disp_clk); - b.full = dfixed_div(c, b); - c.full = dfixed_const(wm->bytes_per_pixel); - b.full = dfixed_mul(b, c); - - lb_fill_bw = min(tmp, dfixed_trunc(b)); + lb_fill_bw = min(tmp, wm->disp_clk * wm->bytes_per_pixel / 1000); a.full = dfixed_const(max_src_lines_per_dst_line * wm->src_width * wm->bytes_per_pixel); b.full = dfixed_const(1000); diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c index 06fc40083151..4056318c558d 100644 --- a/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c +++ b/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c @@ -932,23 +932,10 @@ static u32 dce_v6_0_latency_watermark(struct dce6_wm_params *wm) a.full = dfixed_const(available_bandwidth); b.full = dfixed_const(wm->num_heads); a.full = dfixed_div(a, b); + tmp = div_u64((u64) dmif_size * (u64) wm->disp_clk, mc_latency + 512); + tmp = min(dfixed_trunc(a), tmp); - b.full = dfixed_const(mc_latency + 512); - c.full = dfixed_const(wm->disp_clk); - b.full = dfixed_div(b, c); - - c.full = dfixed_const(dmif_size); - b.full = dfixed_div(c, b); - - tmp = min(dfixed_trunc(a), dfixed_trunc(b)); - - b.full = dfixed_const(1000); - c.full = dfixed_const(wm->disp_clk); - b.full = dfixed_div(c, b); - c.full = dfixed_const(wm->bytes_per_pixel); - b.full = dfixed_mul(b, c); - - lb_fill_bw = min(tmp, dfixed_trunc(b)); + lb_fill_bw = min(tmp, wm->disp_clk * wm->bytes_per_pixel / 1000); a.full = dfixed_const(max_src_lines_per_dst_line * wm->src_width * wm->bytes_per_pixel); b.full = dfixed_const(1000); diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c index ac88c589be32..b1fb60107cfa 100644 --- a/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c +++ b/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c @@ -1094,23 +1094,10 @@ static u32 dce_v8_0_latency_watermark(struct dce8_wm_params *wm) a.full = dfixed_const(available_bandwidth); b.full = dfixed_const(wm->num_heads); a.full = dfixed_div(a, b); + tmp = div_u64((u64) dmif_size * (u64) wm->disp_clk, mc_latency + 512); + tmp = min(dfixed_trunc(a), tmp); - b.full = dfixed_const(mc_latency + 512); - c.full = dfixed_const(wm->disp_clk); - b.full = dfixed_div(b, c); - - c.full = dfixed_const(dmif_size); - b.full = dfixed_div(c, b); - - tmp = min(dfixed_trunc(a), dfixed_trunc(b)); - - b.full = dfixed_const(1000); - c.full = dfixed_const(wm->disp_clk); - b.full = dfixed_div(c, b); - c.full = dfixed_const(wm->bytes_per_pixel); - b.full = dfixed_mul(b, c); - - lb_fill_bw = min(tmp, dfixed_trunc(b)); + lb_fill_bw = min(tmp, wm->disp_clk * wm->bytes_per_pixel / 1000); a.full = dfixed_const(max_src_lines_per_dst_line * wm->src_width * wm->bytes_per_pixel); b.full = dfixed_const(1000); From d1f006efde1fa224a52a93a0d21eb389bdea851d Mon Sep 17 00:00:00 2001 From: Mario Kleiner Date: Mon, 24 Apr 2017 01:02:46 +0200 Subject: [PATCH 275/396] drm/amdgpu: Add missing lb_vblank_lead_lines setup to DCE-6 path. commit effaf848b957fbf72a3b6a1ad87f5e031eda0b75 upstream. This apparently got lost when implementing the new DCE-6 support and would cause failures in pageflip scheduling and timestamping. Signed-off-by: Mario Kleiner Cc: Alex Deucher Signed-off-by: Alex Deucher Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/amd/amdgpu/dce_v6_0.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c index 4056318c558d..6d02bdb25d98 100644 --- a/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c +++ b/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c @@ -1050,7 +1050,7 @@ static void dce_v6_0_program_watermarks(struct amdgpu_device *adev, u32 priority_a_mark = 0, priority_b_mark = 0; u32 priority_a_cnt = PRIORITY_OFF; u32 priority_b_cnt = PRIORITY_OFF; - u32 tmp, arb_control3; + u32 tmp, arb_control3, lb_vblank_lead_lines = 0; fixed20_12 a, b, c; if (amdgpu_crtc->base.enabled && num_heads && mode) { @@ -1162,6 +1162,8 @@ static void dce_v6_0_program_watermarks(struct amdgpu_device *adev, c.full = dfixed_div(c, a); priority_b_mark = dfixed_trunc(c); priority_b_cnt |= priority_b_mark & PRIORITY_MARK_MASK; + + lb_vblank_lead_lines = DIV_ROUND_UP(lb_size, mode->crtc_hdisplay); } /* select wm A */ @@ -1191,6 +1193,9 @@ static void dce_v6_0_program_watermarks(struct amdgpu_device *adev, /* save values for DPM */ amdgpu_crtc->line_time = line_time; amdgpu_crtc->wm_high = latency_watermark_a; + + /* Save number of lines the linebuffer leads before the scanout */ + amdgpu_crtc->lb_vblank_lead_lines = lb_vblank_lead_lines; } /* watermark setup */ From e8ee630591963610dd1b5ed9fdfb730c791bd52b Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Thu, 11 May 2017 17:33:39 +1000 Subject: [PATCH 276/396] drm/nouveau/therm: remove ineffective workarounds for alarm bugs commit e4311ee51d1e2676001b2d8fcefd92bdd79aad85 upstream. These were ineffective due to touching the list without the alarm lock, but should no longer be required. Signed-off-by: Ben Skeggs Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/nouveau/nvkm/subdev/therm/base.c | 2 +- drivers/gpu/drm/nouveau/nvkm/subdev/therm/fan.c | 2 +- drivers/gpu/drm/nouveau/nvkm/subdev/therm/fantog.c | 2 +- drivers/gpu/drm/nouveau/nvkm/subdev/therm/temp.c | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/therm/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/therm/base.c index 8894fee30cbc..cbacbb673e54 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/therm/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/therm/base.c @@ -130,7 +130,7 @@ nvkm_therm_update(struct nvkm_therm *therm, int mode) poll = false; } - if (list_empty(&therm->alarm.head) && poll) + if (poll) nvkm_timer_alarm(tmr, 1000000000ULL, &therm->alarm); spin_unlock_irqrestore(&therm->lock, flags); diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/therm/fan.c b/drivers/gpu/drm/nouveau/nvkm/subdev/therm/fan.c index 91198d79393a..e2feccec25f5 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/therm/fan.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/therm/fan.c @@ -83,7 +83,7 @@ nvkm_fan_update(struct nvkm_fan *fan, bool immediate, int target) spin_unlock_irqrestore(&fan->lock, flags); /* schedule next fan update, if not at target speed already */ - if (list_empty(&fan->alarm.head) && target != duty) { + if (target != duty) { u16 bump_period = fan->bios.bump_period; u16 slow_down_period = fan->bios.slow_down_period; u64 delay; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/therm/fantog.c b/drivers/gpu/drm/nouveau/nvkm/subdev/therm/fantog.c index 59701b7a6597..ff9fbe7950e5 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/therm/fantog.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/therm/fantog.c @@ -53,7 +53,7 @@ nvkm_fantog_update(struct nvkm_fantog *fan, int percent) duty = !nvkm_gpio_get(gpio, 0, DCB_GPIO_FAN, 0xff); nvkm_gpio_set(gpio, 0, DCB_GPIO_FAN, 0xff, duty); - if (list_empty(&fan->alarm.head) && percent != (duty * 100)) { + if (percent != (duty * 100)) { u64 next_change = (percent * fan->period_us) / 100; if (!duty) next_change = fan->period_us - next_change; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/therm/temp.c b/drivers/gpu/drm/nouveau/nvkm/subdev/therm/temp.c index b9703c02d8ca..9a79e91fdfdc 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/therm/temp.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/therm/temp.c @@ -185,7 +185,7 @@ alarm_timer_callback(struct nvkm_alarm *alarm) spin_unlock_irqrestore(&therm->sensor.alarm_program_lock, flags); /* schedule the next poll in one second */ - if (therm->func->temp_get(therm) >= 0 && list_empty(&alarm->head)) + if (therm->func->temp_get(therm) >= 0) nvkm_timer_alarm(tmr, 1000000000ULL, alarm); } From 16e10490d260493cec30c5e7adacf99ba304d8b9 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Thu, 11 May 2017 16:53:42 +1000 Subject: [PATCH 277/396] drm/nouveau/tmr: ack interrupt before processing alarms commit 3733bd8b407211739e72d051e5f30ad82a52c4bc upstream. Fixes a race where we can miss an alarm that triggers while we're already processing previous alarms. Signed-off-by: Ben Skeggs Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/nouveau/nvkm/subdev/timer/nv04.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/timer/nv04.c b/drivers/gpu/drm/nouveau/nvkm/subdev/timer/nv04.c index 7b9ce87f0617..7f48249f41de 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/timer/nv04.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/timer/nv04.c @@ -76,8 +76,8 @@ nv04_timer_intr(struct nvkm_timer *tmr) u32 stat = nvkm_rd32(device, NV04_PTIMER_INTR_0); if (stat & 0x00000001) { - nvkm_timer_alarm_trigger(tmr); nvkm_wr32(device, NV04_PTIMER_INTR_0, 0x00000001); + nvkm_timer_alarm_trigger(tmr); stat &= ~0x00000001; } From 6445a49a8c592f891ea38fa307d2617e15b2d524 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Thu, 11 May 2017 17:03:05 +1000 Subject: [PATCH 278/396] drm/nouveau/tmr: fix corruption of the pending list when rescheduling an alarm commit 9fc64667ee48c9a25e7dca1a6bcb6906fec5bcc5 upstream. At least therm/fantog "attempts" to work around this issue, which could lead to corruption of the pending alarm list. Fix it properly by not updating the timestamp without the lock held, or trying to add an already pending alarm to the pending alarm list.... Signed-off-by: Ben Skeggs Signed-off-by: Greg Kroah-Hartman --- .../gpu/drm/nouveau/nvkm/subdev/timer/base.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/timer/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/timer/base.c index 07dc82bfe346..182f27c73aeb 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/timer/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/timer/base.c @@ -65,14 +65,17 @@ nvkm_timer_alarm(struct nvkm_timer *tmr, u32 nsec, struct nvkm_alarm *alarm) struct nvkm_alarm *list; unsigned long flags; - alarm->timestamp = nvkm_timer_read(tmr) + nsec; - - /* append new alarm to list, in soonest-alarm-first order */ + /* Remove alarm from pending list. + * + * This both protects against the corruption of the list, + * and implements alarm rescheduling/cancellation. + */ spin_lock_irqsave(&tmr->lock, flags); - if (!nsec) { - if (!list_empty(&alarm->head)) - list_del(&alarm->head); - } else { + list_del_init(&alarm->head); + + if (nsec) { + /* Insert into pending list, ordered earliest to latest. */ + alarm->timestamp = nvkm_timer_read(tmr) + nsec; list_for_each_entry(list, &tmr->alarms, head) { if (list->timestamp > alarm->timestamp) break; From 1ec3c712e231468ac1b1024b9747882c444d4b19 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Thu, 11 May 2017 17:13:29 +1000 Subject: [PATCH 279/396] drm/nouveau/tmr: avoid processing completed alarms when adding a new one commit 330bdf62fe6a6c5b99a647f7bf7157107c9348b3 upstream. The idea here was to avoid having to "manually" program the HW if there's a new earliest alarm. This was lazy and bad, as it leads to loads of fun races between inter-related callers (ie. therm). Turns out, it's not so difficult after all. Go figure ;) Signed-off-by: Ben Skeggs Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/nouveau/nvkm/subdev/timer/base.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/timer/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/timer/base.c index 182f27c73aeb..934a98819b43 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/timer/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/timer/base.c @@ -80,12 +80,22 @@ nvkm_timer_alarm(struct nvkm_timer *tmr, u32 nsec, struct nvkm_alarm *alarm) if (list->timestamp > alarm->timestamp) break; } + list_add_tail(&alarm->head, &list->head); + + /* Update HW if this is now the earliest alarm. */ + list = list_first_entry(&tmr->alarms, typeof(*list), head); + if (list == alarm) { + tmr->func->alarm_init(tmr, alarm->timestamp); + /* This shouldn't happen if callers aren't stupid. + * + * Worst case scenario is that it'll take roughly + * 4 seconds for the next alarm to trigger. + */ + WARN_ON(alarm->timestamp <= nvkm_timer_read(tmr)); + } } spin_unlock_irqrestore(&tmr->lock, flags); - - /* process pending alarms */ - nvkm_timer_alarm_trigger(tmr); } void From b77adf29b85687fd593d4dc294fb5cb946b3c0e2 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Thu, 11 May 2017 17:19:48 +1000 Subject: [PATCH 280/396] drm/nouveau/tmr: handle races with hw when updating the next alarm time commit 1b0f84380b10ee97f7d2dd191294de9017e94d1d upstream. If the time to the next alarm is short enough, we could race with HW and end up with an ~4 second delay until it triggers. Fix this by checking again after we update HW. Signed-off-by: Ben Skeggs Signed-off-by: Greg Kroah-Hartman --- .../gpu/drm/nouveau/nvkm/subdev/timer/base.c | 26 ++++++++++++------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/timer/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/timer/base.c index 934a98819b43..f2a86eae0a0d 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/timer/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/timer/base.c @@ -36,23 +36,29 @@ nvkm_timer_alarm_trigger(struct nvkm_timer *tmr) unsigned long flags; LIST_HEAD(exec); - /* move any due alarms off the pending list */ + /* Process pending alarms. */ spin_lock_irqsave(&tmr->lock, flags); list_for_each_entry_safe(alarm, atemp, &tmr->alarms, head) { - if (alarm->timestamp <= nvkm_timer_read(tmr)) - list_move_tail(&alarm->head, &exec); + /* Have we hit the earliest alarm that hasn't gone off? */ + if (alarm->timestamp > nvkm_timer_read(tmr)) { + /* Schedule it. If we didn't race, we're done. */ + tmr->func->alarm_init(tmr, alarm->timestamp); + if (alarm->timestamp > nvkm_timer_read(tmr)) + break; + } + + /* Move to completed list. We'll drop the lock before + * executing the callback so it can reschedule itself. + */ + list_move_tail(&alarm->head, &exec); } - /* reschedule interrupt for next alarm time */ - if (!list_empty(&tmr->alarms)) { - alarm = list_first_entry(&tmr->alarms, typeof(*alarm), head); - tmr->func->alarm_init(tmr, alarm->timestamp); - } else { + /* Shut down interrupt if no more pending alarms. */ + if (list_empty(&tmr->alarms)) tmr->func->alarm_fini(tmr); - } spin_unlock_irqrestore(&tmr->lock, flags); - /* execute any pending alarm handlers */ + /* Execute completed callbacks. */ list_for_each_entry_safe(alarm, atemp, &exec, head) { list_del_init(&alarm->head); alarm->func(alarm); From 198ab4031873b5511d6ef9b4777cabc4eebcaf18 Mon Sep 17 00:00:00 2001 From: David Rivshin Date: Mon, 24 Apr 2017 18:56:50 -0400 Subject: [PATCH 281/396] gpio: omap: return error if requested debounce time is not possible commit 83977443938122baeed28dc9f078db3da9855f7c upstream. omap_gpio_debounce() does not validate that the requested debounce is within a range it can handle. Instead it lets the register value wrap silently, and always returns success. This can lead to all sorts of unexpected behavior, such as gpio_keys asking for a too-long debounce, but getting a very short debounce in practice. Fix this by returning -EINVAL if the requested value does not fit into the register field. If there is no debounce clock available at all, return -ENOTSUPP. Fixes: e85ec6c3047b ("gpio: omap: fix omap2_set_gpio_debounce") Signed-off-by: David Rivshin Acked-by: Grygorii Strashko Signed-off-by: Linus Walleij Signed-off-by: Greg Kroah-Hartman --- drivers/gpio/gpio-omap.c | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c index b98ede78c9d8..6f9c9ac6ee70 100644 --- a/drivers/gpio/gpio-omap.c +++ b/drivers/gpio/gpio-omap.c @@ -208,9 +208,11 @@ static inline void omap_gpio_dbck_disable(struct gpio_bank *bank) * OMAP's debounce time is in 31us steps * = (GPIO_DEBOUNCINGTIME[7:0].DEBOUNCETIME + 1) x 31 * so we need to convert and round up to the closest unit. + * + * Return: 0 on success, negative error otherwise. */ -static void omap2_set_gpio_debounce(struct gpio_bank *bank, unsigned offset, - unsigned debounce) +static int omap2_set_gpio_debounce(struct gpio_bank *bank, unsigned offset, + unsigned debounce) { void __iomem *reg; u32 val; @@ -218,11 +220,12 @@ static void omap2_set_gpio_debounce(struct gpio_bank *bank, unsigned offset, bool enable = !!debounce; if (!bank->dbck_flag) - return; + return -ENOTSUPP; if (enable) { debounce = DIV_ROUND_UP(debounce, 31) - 1; - debounce &= OMAP4_GPIO_DEBOUNCINGTIME_MASK; + if ((debounce & OMAP4_GPIO_DEBOUNCINGTIME_MASK) != debounce) + return -EINVAL; } l = BIT(offset); @@ -255,6 +258,8 @@ static void omap2_set_gpio_debounce(struct gpio_bank *bank, unsigned offset, bank->context.debounce = debounce; bank->context.debounce_en = val; } + + return 0; } /** @@ -964,14 +969,20 @@ static int omap_gpio_debounce(struct gpio_chip *chip, unsigned offset, { struct gpio_bank *bank; unsigned long flags; + int ret; bank = gpiochip_get_data(chip); raw_spin_lock_irqsave(&bank->lock, flags); - omap2_set_gpio_debounce(bank, offset, debounce); + ret = omap2_set_gpio_debounce(bank, offset, debounce); raw_spin_unlock_irqrestore(&bank->lock, flags); - return 0; + if (ret) + dev_info(chip->parent, + "Could not set line %u debounce to %u microseconds (%d)", + offset, debounce, ret); + + return ret; } static void omap_gpio_set(struct gpio_chip *chip, unsigned offset, int value) From 809ae061d998359783c1bb0c52bba14f4a6397c4 Mon Sep 17 00:00:00 2001 From: Tobias Herzog Date: Thu, 30 Mar 2017 22:15:10 +0200 Subject: [PATCH 282/396] cdc-acm: fix possible invalid access when processing notification commit 1bb9914e1730417d530de9ed37e59efdc647146b upstream. Notifications may only be 8 bytes long. Accessing the 9th and 10th byte of unimplemented/unknown notifications may be insecure. Also check the length of known notifications before accessing anything behind the 8th byte. Signed-off-by: Tobias Herzog Acked-by: Oliver Neukum Signed-off-by: Greg Kroah-Hartman --- drivers/usb/class/cdc-acm.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index c5ff13f22b24..a876d47246dc 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -311,6 +311,12 @@ static void acm_ctrl_irq(struct urb *urb) break; case USB_CDC_NOTIFY_SERIAL_STATE: + if (le16_to_cpu(dr->wLength) != 2) { + dev_dbg(&acm->control->dev, + "%s - malformed serial state\n", __func__); + break; + } + newctrl = get_unaligned_le16(data); if (!acm->clocal && (acm->ctrlin & ~newctrl & ACM_CTRL_DCD)) { @@ -347,11 +353,10 @@ static void acm_ctrl_irq(struct urb *urb) default: dev_dbg(&acm->control->dev, - "%s - unknown notification %d received: index %d " - "len %d data0 %d data1 %d\n", + "%s - unknown notification %d received: index %d len %d\n", __func__, - dr->bNotificationType, dr->wIndex, - dr->wLength, data[0], data[1]); + dr->bNotificationType, dr->wIndex, dr->wLength); + break; } exit: From fc6b678ab1d47085ee0ab3fae4d5289959b45552 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Mon, 20 Mar 2017 09:11:49 +0100 Subject: [PATCH 283/396] ohci-pci: add qemu quirk commit 21a60f6e65181cad64fd66ccc8080d413721ba27 upstream. On a loaded virtualization host (dozen guests booting at the same time) it may happen that the ohci controller emulation doesn't manage to do timely frame processing, with the result that the io watchdog fires and considers the controller being dead, even though it's only the emulation being unusual slow due to the load peak. So, add a quirk for qemu and don't use the watchdog in case we figure we are running on emulated ohci. The virtual ohci controller masquerades as apple ohci controller, but we can identify it by subsystem id. Signed-off-by: Gerd Hoffmann Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ohci-hcd.c | 3 ++- drivers/usb/host/ohci-pci.c | 16 ++++++++++++++++ drivers/usb/host/ohci.h | 1 + 3 files changed, 19 insertions(+), 1 deletion(-) diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c index 86612ac3fda2..f6c7a2744e5c 100644 --- a/drivers/usb/host/ohci-hcd.c +++ b/drivers/usb/host/ohci-hcd.c @@ -231,7 +231,8 @@ static int ohci_urb_enqueue ( /* Start up the I/O watchdog timer, if it's not running */ if (!timer_pending(&ohci->io_watchdog) && - list_empty(&ohci->eds_in_use)) { + list_empty(&ohci->eds_in_use) && + !(ohci->flags & OHCI_QUIRK_QEMU)) { ohci->prev_frame_no = ohci_frame_no(ohci); mod_timer(&ohci->io_watchdog, jiffies + IO_WATCHDOG_DELAY); diff --git a/drivers/usb/host/ohci-pci.c b/drivers/usb/host/ohci-pci.c index bb1509675727..a84aebe9b0a9 100644 --- a/drivers/usb/host/ohci-pci.c +++ b/drivers/usb/host/ohci-pci.c @@ -164,6 +164,15 @@ static int ohci_quirk_amd700(struct usb_hcd *hcd) return 0; } +static int ohci_quirk_qemu(struct usb_hcd *hcd) +{ + struct ohci_hcd *ohci = hcd_to_ohci(hcd); + + ohci->flags |= OHCI_QUIRK_QEMU; + ohci_dbg(ohci, "enabled qemu quirk\n"); + return 0; +} + /* List of quirks for OHCI */ static const struct pci_device_id ohci_pci_quirks[] = { { @@ -214,6 +223,13 @@ static const struct pci_device_id ohci_pci_quirks[] = { PCI_DEVICE(PCI_VENDOR_ID_ATI, 0x4399), .driver_data = (unsigned long)ohci_quirk_amd700, }, + { + .vendor = PCI_VENDOR_ID_APPLE, + .device = 0x003f, + .subvendor = PCI_SUBVENDOR_ID_REDHAT_QUMRANET, + .subdevice = PCI_SUBDEVICE_ID_QEMU, + .driver_data = (unsigned long)ohci_quirk_qemu, + }, /* FIXME for some of the early AMD 760 southbridges, OHCI * won't work at all. blacklist them. diff --git a/drivers/usb/host/ohci.h b/drivers/usb/host/ohci.h index 37f1725e7a46..a51b189bdbd8 100644 --- a/drivers/usb/host/ohci.h +++ b/drivers/usb/host/ohci.h @@ -418,6 +418,7 @@ struct ohci_hcd { #define OHCI_QUIRK_AMD_PLL 0x200 /* AMD PLL quirk*/ #define OHCI_QUIRK_AMD_PREFETCH 0x400 /* pre-fetch for ISO transfer */ #define OHCI_QUIRK_GLOBAL_SUSPEND 0x800 /* must suspend ports */ +#define OHCI_QUIRK_QEMU 0x1000 /* relax timing expectations */ // there are also chip quirks/bugs in init logic From 3935312995473ce0abc40582d5cda31da3594294 Mon Sep 17 00:00:00 2001 From: Vaibhav Jain Date: Thu, 27 Apr 2017 10:53:25 +0530 Subject: [PATCH 284/396] cxl: Force context lock during EEH flow commit ea9a26d117cf0637c71d3e0076f4a124bf5859df upstream. During an eeh event when the cxl card is fenced and card sysfs attr perst_reloads_same_image is set following warning message is seen in the kernel logs: Adapter context unlocked with 0 active contexts ------------[ cut here ]------------ WARNING: CPU: 12 PID: 627 at ../drivers/misc/cxl/main.c:325 cxl_adapter_context_unlock+0x60/0x80 [cxl] Even though this warning is harmless, it clutters the kernel log during an eeh event. This warning is triggered as the EEH callback cxl_pci_error_detected doesn't obtain a context-lock before forcibly detaching all active context and when context-lock is released during call to cxl_configure_adapter from cxl_pci_slot_reset, a warning in cxl_adapter_context_unlock is triggered. To fix this warning, we acquire the adapter context-lock via cxl_adapter_context_lock() in the eeh callback cxl_pci_error_detected() once all the virtual AFU PHBs are notified and their contexts detached. The context-lock is released in cxl_pci_slot_reset() after the adapter is successfully reconfigured and before the we call the slot_reset callback on slice attached device-drivers. Fixes: 70b565bbdb91 ("cxl: Prevent adapter reset if an active context exists") Reported-by: Andrew Donnellan Signed-off-by: Vaibhav Jain Acked-by: Frederic Barrat Reviewed-by: Matthew R. Ochs Tested-by: Uma Krishnan Signed-off-by: Michael Ellerman Signed-off-by: Greg Kroah-Hartman --- drivers/misc/cxl/pci.c | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/drivers/misc/cxl/pci.c b/drivers/misc/cxl/pci.c index dd99b06e121a..80b1a7e87888 100644 --- a/drivers/misc/cxl/pci.c +++ b/drivers/misc/cxl/pci.c @@ -1496,8 +1496,6 @@ static int cxl_configure_adapter(struct cxl *adapter, struct pci_dev *dev) if ((rc = cxl_native_register_psl_err_irq(adapter))) goto err; - /* Release the context lock as adapter is configured */ - cxl_adapter_context_unlock(adapter); return 0; err: @@ -1596,6 +1594,9 @@ static struct cxl *cxl_pci_init_adapter(struct pci_dev *dev) if ((rc = cxl_sysfs_adapter_add(adapter))) goto err_put1; + /* Release the context lock as adapter is configured */ + cxl_adapter_context_unlock(adapter); + return adapter; err_put1: @@ -1893,6 +1894,13 @@ static pci_ers_result_t cxl_pci_error_detected(struct pci_dev *pdev, cxl_ops->afu_deactivate_mode(afu, afu->current_mode); pci_deconfigure_afu(afu); } + + /* should take the context lock here */ + if (cxl_adapter_context_lock(adapter) != 0) + dev_warn(&adapter->dev, + "Couldn't take context lock with %d active-contexts\n", + atomic_read(&adapter->contexts_num)); + cxl_deconfigure_adapter(adapter); return result; @@ -1911,6 +1919,13 @@ static pci_ers_result_t cxl_pci_slot_reset(struct pci_dev *pdev) if (cxl_configure_adapter(adapter, pdev)) goto err; + /* + * Unlock context activation for the adapter. Ideally this should be + * done in cxl_pci_resume but cxlflash module tries to activate the + * master context as part of slot_reset callback. + */ + cxl_adapter_context_unlock(adapter); + for (i = 0; i < adapter->slices; i++) { afu = adapter->afu[i]; From 168b2bfaa235e91c2f7a76ac693435e530f486b3 Mon Sep 17 00:00:00 2001 From: Vaibhav Jain Date: Thu, 27 Apr 2017 10:58:22 +0530 Subject: [PATCH 285/396] cxl: Route eeh events to all drivers in cxl_pci_error_detected() commit 4f58f0bf155e87dda31a3088b1e107fa9dd79f0e upstream. Fix a boundary condition where in some cases an eeh event that results in card reset isn't passed on to a driver attached to the virtual PCI device associated with a slice. This will happen in case when a slice attached device driver returns a value other than PCI_ERS_RESULT_NEED_RESET from the eeh error_detected() callback. This would result in an early return from cxl_pci_error_detected() and other drivers attached to other AFUs on the card wont be notified. The patch fixes this by making sure that all slice attached device-drivers are notified and the return values from error_detected() callback are aggregated in a scheme where request for 'disconnect' trumps all and 'none' trumps 'need_reset'. Fixes: 9e8df8a21963 ("cxl: EEH support") Signed-off-by: Vaibhav Jain Reviewed-by: Andrew Donnellan Acked-by: Frederic Barrat Signed-off-by: Michael Ellerman Signed-off-by: Greg Kroah-Hartman --- drivers/misc/cxl/pci.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/drivers/misc/cxl/pci.c b/drivers/misc/cxl/pci.c index 80b1a7e87888..fa4fe02cfef4 100644 --- a/drivers/misc/cxl/pci.c +++ b/drivers/misc/cxl/pci.c @@ -1779,7 +1779,7 @@ static pci_ers_result_t cxl_pci_error_detected(struct pci_dev *pdev, { struct cxl *adapter = pci_get_drvdata(pdev); struct cxl_afu *afu; - pci_ers_result_t result = PCI_ERS_RESULT_NEED_RESET; + pci_ers_result_t result = PCI_ERS_RESULT_NEED_RESET, afu_result; int i; /* At this point, we could still have an interrupt pending. @@ -1884,15 +1884,18 @@ static pci_ers_result_t cxl_pci_error_detected(struct pci_dev *pdev, for (i = 0; i < adapter->slices; i++) { afu = adapter->afu[i]; - result = cxl_vphb_error_detected(afu, state); - - /* Only continue if everyone agrees on NEED_RESET */ - if (result != PCI_ERS_RESULT_NEED_RESET) - return result; + afu_result = cxl_vphb_error_detected(afu, state); cxl_context_detach_all(afu); cxl_ops->afu_deactivate_mode(afu, afu->current_mode); pci_deconfigure_afu(afu); + + /* Disconnect trumps all, NONE trumps NEED_RESET */ + if (afu_result == PCI_ERS_RESULT_DISCONNECT) + result = PCI_ERS_RESULT_DISCONNECT; + else if ((afu_result == PCI_ERS_RESULT_NONE) && + (result == PCI_ERS_RESULT_NEED_RESET)) + result = PCI_ERS_RESULT_NONE; } /* should take the context lock here */ From d10b21d6e56261f5d815b8783f944cae8c6369c1 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 28 Apr 2017 15:00:15 +0200 Subject: [PATCH 286/396] proc: Fix unbalanced hard link numbers commit d66bb1607e2d8d384e53f3d93db5c18483c8c4f7 upstream. proc_create_mount_point() forgot to increase the parent's nlink, and it resulted in unbalanced hard link numbers, e.g. /proc/fs shows one less than expected. Fixes: eb6d38d5427b ("proc: Allow creating permanently empty directories...") Reported-by: Tristan Ye Signed-off-by: Takashi Iwai Signed-off-by: Eric W. Biederman Signed-off-by: Greg Kroah-Hartman --- fs/proc/generic.c | 1 + 1 file changed, 1 insertion(+) diff --git a/fs/proc/generic.c b/fs/proc/generic.c index 5f2dc2032c79..6047471575bb 100644 --- a/fs/proc/generic.c +++ b/fs/proc/generic.c @@ -471,6 +471,7 @@ struct proc_dir_entry *proc_create_mount_point(const char *name) ent->data = NULL; ent->proc_fops = NULL; ent->proc_iops = NULL; + parent->nlink++; if (proc_register(parent, ent) < 0) { kfree(ent); parent->nlink--; From ae5074ba9ef8043e17a13c32402e7a80ef7aafb4 Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Thu, 4 May 2017 12:34:30 -0500 Subject: [PATCH 287/396] of: fix sparse warning in of_pci_range_parser_one commit eb3100365791b06242b8bb5c3c2854ba41dabfbc upstream. sparse gives the following warning for 'pci_space': ../drivers/of/address.c:266:26: warning: incorrect type in assignment (different base types) ../drivers/of/address.c:266:26: expected unsigned int [unsigned] [usertype] pci_space ../drivers/of/address.c:266:26: got restricted __be32 const [usertype] It appears that pci_space is only ever accessed on powerpc, so the endian swap is often not needed. Signed-off-by: Rob Herring Signed-off-by: Greg Kroah-Hartman --- drivers/of/address.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/of/address.c b/drivers/of/address.c index 02b2903fe9d2..72914cdfce2a 100644 --- a/drivers/of/address.c +++ b/drivers/of/address.c @@ -263,7 +263,7 @@ struct of_pci_range *of_pci_range_parser_one(struct of_pci_range_parser *parser, if (!parser->range || parser->range + parser->np > parser->end) return NULL; - range->pci_space = parser->range[0]; + range->pci_space = be32_to_cpup(parser->range); range->flags = of_bus_pci_get_flags(parser->range); range->pci_addr = of_read_number(parser->range + 1, ns); range->cpu_addr = of_translate_address(parser->node, From 80cdf2065bf0e10862b400715672555ef3e49a3e Mon Sep 17 00:00:00 2001 From: Tyrel Datwyler Date: Mon, 17 Apr 2017 20:29:17 -0400 Subject: [PATCH 288/396] of: fix "/cpus" reference leak in of_numa_parse_cpu_nodes() commit b8475cbee5ab2eac05f9cd5dbcc94c453d3cbf10 upstream. The call to of_find_node_by_path("/cpus") returns the cpus device_node with its reference count incremented. There is no matching of_node_put() call in of_numa_parse_cpu_nodes() which results in a leaked reference to the "/cpus" node. This patch adds an of_node_put() to release the reference. fixes: 298535c00a2c ("of, numa: Add NUMA of binding implementation.") Signed-off-by: Tyrel Datwyler Acked-by: David Daney Signed-off-by: Rob Herring Signed-off-by: Greg Kroah-Hartman --- drivers/of/of_numa.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/of/of_numa.c b/drivers/of/of_numa.c index a53982a330ea..2db1f7a04baf 100644 --- a/drivers/of/of_numa.c +++ b/drivers/of/of_numa.c @@ -57,6 +57,8 @@ static void __init of_numa_parse_cpu_nodes(void) else node_set(nid, numa_nodes_parsed); } + + of_node_put(cpus); } static int __init of_numa_parse_memory_nodes(void) From 9907c838fc0700de8a614587cc58490c54fd4551 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 17 May 2017 17:29:09 +0200 Subject: [PATCH 289/396] of: fdt: add missing allocation-failure check commit 49e67dd17649b60b4d54966e18ec9c80198227f0 upstream. The memory allocator passed to __unflatten_device_tree() (e.g. a wrapped kzalloc) can fail so add the missing sanity check to avoid dereferencing a NULL pointer. Fixes: fe14042358fa ("of/flattree: Refactor unflatten_device_tree and add fdt_unflatten_tree") Signed-off-by: Johan Hovold Signed-off-by: Rob Herring Signed-off-by: Greg Kroah-Hartman --- drivers/of/fdt.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c index c89d5d231a0e..6a43fd3d0576 100644 --- a/drivers/of/fdt.c +++ b/drivers/of/fdt.c @@ -505,6 +505,9 @@ static void *__unflatten_device_tree(const void *blob, /* Allocate memory for the expanded device tree */ mem = dt_alloc(size + 4, __alignof__(struct device_node)); + if (!mem) + return NULL; + memset(mem, 0, size); *(__be32 *)(mem + size) = cpu_to_be32(0xdeadbeef); From 05a36277a195264427d5af5718e444bafd75cb44 Mon Sep 17 00:00:00 2001 From: "Bryant G. Ly" Date: Fri, 5 May 2017 14:17:15 -0500 Subject: [PATCH 290/396] ibmvscsis: Do not send aborted task response commit 25e78531268e9240fc594ce76587601b873d37c9 upstream. The driver is sending a response to the actual scsi op that was aborted by an abort task TM, while LIO is sending a response to the abort task TM. ibmvscsis_tgt does not send the response to the client until release_cmd time. The reason for this was because if we did it at queue_status time, then the client would be free to reuse the tag for that command, but we're still using the tag until the command is released at release_cmd time, so we chose to delay sending the response until then. That then caused this issue, because release_cmd is always called, even if queue_status is not. SCSI spec says that the initiator that sends the abort task TM NEVER gets a response to the aborted op and with the current code it will send a response. Thus this fix will remove that response if the CMD_T_ABORTED && !CMD_T_TAS. Another case with a small timing window is the case where if LIO sends a TMR_DOES_NOT_EXIST, and the release_cmd callback is called for the TMR Abort cmd before the release_cmd for the (attemped) aborted cmd, then we need to ensure that we send the response for the (attempted) abort cmd to the client before we send the response for the TMR Abort cmd. Signed-off-by: Bryant G. Ly Signed-off-by: Michael Cyr Signed-off-by: Nicholas Bellinger Signed-off-by: Greg Kroah-Hartman --- drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c | 114 ++++++++++++++++++----- drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.h | 2 + 2 files changed, 91 insertions(+), 25 deletions(-) diff --git a/drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c b/drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c index c4fe95a25621..904422f5b62f 100644 --- a/drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c +++ b/drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c @@ -1169,6 +1169,7 @@ static struct ibmvscsis_cmd *ibmvscsis_get_free_cmd(struct scsi_info *vscsi) cmd = list_first_entry_or_null(&vscsi->free_cmd, struct ibmvscsis_cmd, list); if (cmd) { + cmd->flags &= ~(DELAY_SEND); list_del(&cmd->list); cmd->iue = iue; cmd->type = UNSET_TYPE; @@ -1748,45 +1749,79 @@ static void srp_snd_msg_failed(struct scsi_info *vscsi, long rc) static void ibmvscsis_send_messages(struct scsi_info *vscsi) { u64 msg_hi = 0; - /* note do not attmempt to access the IU_data_ptr with this pointer + /* note do not attempt to access the IU_data_ptr with this pointer * it is not valid */ struct viosrp_crq *crq = (struct viosrp_crq *)&msg_hi; struct ibmvscsis_cmd *cmd, *nxt; struct iu_entry *iue; long rc = ADAPT_SUCCESS; + bool retry = false; if (!(vscsi->flags & RESPONSE_Q_DOWN)) { - list_for_each_entry_safe(cmd, nxt, &vscsi->waiting_rsp, list) { - iue = cmd->iue; + do { + retry = false; + list_for_each_entry_safe(cmd, nxt, &vscsi->waiting_rsp, + list) { + /* + * Check to make sure abort cmd gets processed + * prior to the abort tmr cmd + */ + if (cmd->flags & DELAY_SEND) + continue; - crq->valid = VALID_CMD_RESP_EL; - crq->format = cmd->rsp.format; + if (cmd->abort_cmd) { + retry = true; + cmd->abort_cmd->flags &= ~(DELAY_SEND); + } - if (cmd->flags & CMD_FAST_FAIL) - crq->status = VIOSRP_ADAPTER_FAIL; + /* + * If CMD_T_ABORTED w/o CMD_T_TAS scenarios and + * the case where LIO issued a + * ABORT_TASK: Sending TMR_TASK_DOES_NOT_EXIST + * case then we dont send a response, since it + * was already done. + */ + if (cmd->se_cmd.transport_state & CMD_T_ABORTED && + !(cmd->se_cmd.transport_state & CMD_T_TAS)) { + list_del(&cmd->list); + ibmvscsis_free_cmd_resources(vscsi, + cmd); + } else { + iue = cmd->iue; - crq->IU_length = cpu_to_be16(cmd->rsp.len); + crq->valid = VALID_CMD_RESP_EL; + crq->format = cmd->rsp.format; - rc = h_send_crq(vscsi->dma_dev->unit_address, - be64_to_cpu(msg_hi), - be64_to_cpu(cmd->rsp.tag)); + if (cmd->flags & CMD_FAST_FAIL) + crq->status = VIOSRP_ADAPTER_FAIL; - pr_debug("send_messages: cmd %p, tag 0x%llx, rc %ld\n", - cmd, be64_to_cpu(cmd->rsp.tag), rc); + crq->IU_length = cpu_to_be16(cmd->rsp.len); - /* if all ok free up the command element resources */ - if (rc == H_SUCCESS) { - /* some movement has occurred */ - vscsi->rsp_q_timer.timer_pops = 0; - list_del(&cmd->list); + rc = h_send_crq(vscsi->dma_dev->unit_address, + be64_to_cpu(msg_hi), + be64_to_cpu(cmd->rsp.tag)); - ibmvscsis_free_cmd_resources(vscsi, cmd); - } else { - srp_snd_msg_failed(vscsi, rc); - break; + pr_debug("send_messages: cmd %p, tag 0x%llx, rc %ld\n", + cmd, be64_to_cpu(cmd->rsp.tag), rc); + + /* if all ok free up the command + * element resources + */ + if (rc == H_SUCCESS) { + /* some movement has occurred */ + vscsi->rsp_q_timer.timer_pops = 0; + list_del(&cmd->list); + + ibmvscsis_free_cmd_resources(vscsi, + cmd); + } else { + srp_snd_msg_failed(vscsi, rc); + break; + } + } } - } + } while (retry); if (!rc) { /* @@ -2707,6 +2742,7 @@ static int ibmvscsis_alloc_cmds(struct scsi_info *vscsi, int num) for (i = 0, cmd = (struct ibmvscsis_cmd *)vscsi->cmd_pool; i < num; i++, cmd++) { + cmd->abort_cmd = NULL; cmd->adapter = vscsi; INIT_WORK(&cmd->work, ibmvscsis_scheduler); list_add_tail(&cmd->list, &vscsi->free_cmd); @@ -3578,9 +3614,20 @@ static int ibmvscsis_write_pending(struct se_cmd *se_cmd) { struct ibmvscsis_cmd *cmd = container_of(se_cmd, struct ibmvscsis_cmd, se_cmd); + struct scsi_info *vscsi = cmd->adapter; struct iu_entry *iue = cmd->iue; int rc; + /* + * If CLIENT_FAILED OR RESPONSE_Q_DOWN, then just return success + * since LIO can't do anything about it, and we dont want to + * attempt an srp_transfer_data. + */ + if ((vscsi->flags & (CLIENT_FAILED | RESPONSE_Q_DOWN))) { + pr_err("write_pending failed since: %d\n", vscsi->flags); + return 0; + } + rc = srp_transfer_data(cmd, &vio_iu(iue)->srp.cmd, ibmvscsis_rdma, 1, 1); if (rc) { @@ -3659,11 +3706,28 @@ static void ibmvscsis_queue_tm_rsp(struct se_cmd *se_cmd) struct ibmvscsis_cmd *cmd = container_of(se_cmd, struct ibmvscsis_cmd, se_cmd); struct scsi_info *vscsi = cmd->adapter; + struct ibmvscsis_cmd *cmd_itr; + struct iu_entry *iue = iue = cmd->iue; + struct srp_tsk_mgmt *srp_tsk = &vio_iu(iue)->srp.tsk_mgmt; + u64 tag_to_abort = be64_to_cpu(srp_tsk->task_tag); uint len; pr_debug("queue_tm_rsp %p, status %d\n", se_cmd, (int)se_cmd->se_tmr_req->response); + if (srp_tsk->tsk_mgmt_func == SRP_TSK_ABORT_TASK && + cmd->se_cmd.se_tmr_req->response == TMR_TASK_DOES_NOT_EXIST) { + spin_lock_bh(&vscsi->intr_lock); + list_for_each_entry(cmd_itr, &vscsi->active_q, list) { + if (tag_to_abort == cmd_itr->se_cmd.tag) { + cmd_itr->abort_cmd = cmd; + cmd->flags |= DELAY_SEND; + break; + } + } + spin_unlock_bh(&vscsi->intr_lock); + } + srp_build_response(vscsi, cmd, &len); cmd->rsp.format = SRP_FORMAT; cmd->rsp.len = len; @@ -3671,8 +3735,8 @@ static void ibmvscsis_queue_tm_rsp(struct se_cmd *se_cmd) static void ibmvscsis_aborted_task(struct se_cmd *se_cmd) { - /* TBD: What (if anything) should we do here? */ - pr_debug("ibmvscsis_aborted_task %p\n", se_cmd); + pr_debug("ibmvscsis_aborted_task %p task_tag: %llu\n", + se_cmd, se_cmd->tag); } static struct se_wwn *ibmvscsis_make_tport(struct target_fabric_configfs *tf, diff --git a/drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.h b/drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.h index 98b0ca79a5c5..f5683affeff3 100644 --- a/drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.h +++ b/drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.h @@ -167,10 +167,12 @@ struct ibmvscsis_cmd { struct iu_rsp rsp; struct work_struct work; struct scsi_info *adapter; + struct ibmvscsis_cmd *abort_cmd; /* Sense buffer that will be mapped into outgoing status */ unsigned char sense_buf[TRANSPORT_SENSE_BUFFER]; u64 init_time; #define CMD_FAST_FAIL BIT(0) +#define DELAY_SEND BIT(1) u32 flags; char type; }; From a03176f92a02f0e1d1965c32b95d65a8bdbd6ac4 Mon Sep 17 00:00:00 2001 From: Pavel Roskin Date: Thu, 13 Apr 2017 14:54:23 -0700 Subject: [PATCH 291/396] iio: dac: ad7303: fix channel description commit ce420fd4251809b4c3119b3b20c8b13bd8eba150 upstream. realbits, storagebits and shift should be numbers, not ASCII characters. Signed-off-by: Pavel Roskin Reviewed-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron Signed-off-by: Greg Kroah-Hartman --- drivers/iio/dac/ad7303.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/iio/dac/ad7303.c b/drivers/iio/dac/ad7303.c index e690dd11e99f..4b0f942b8914 100644 --- a/drivers/iio/dac/ad7303.c +++ b/drivers/iio/dac/ad7303.c @@ -184,9 +184,9 @@ static const struct iio_chan_spec_ext_info ad7303_ext_info[] = { .address = (chan), \ .scan_type = { \ .sign = 'u', \ - .realbits = '8', \ - .storagebits = '8', \ - .shift = '0', \ + .realbits = 8, \ + .storagebits = 8, \ + .shift = 0, \ }, \ .ext_info = ad7303_ext_info, \ } From dfb450b2b66e4271c63c10f72c17e2a9967e511c Mon Sep 17 00:00:00 2001 From: Andreas Klinger Date: Mon, 10 Apr 2017 19:00:01 +0200 Subject: [PATCH 292/396] IIO: bmp280-core.c: fix error in humidity calculation commit ed3730c435f1a9f9559ed7762035d22d8a95adfe upstream. While calculating the compensation of the humidity there are negative values interpreted as unsigned because of unsigned variables used. These values as well as the constants need to be casted to signed as indicated by the documentation of the sensor. Signed-off-by: Andreas Klinger Acked-by: Linus Walleij Reviewed-by: Matt Ranostay Signed-off-by: Jonathan Cameron Signed-off-by: Greg Kroah-Hartman --- drivers/iio/pressure/bmp280-core.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/drivers/iio/pressure/bmp280-core.c b/drivers/iio/pressure/bmp280-core.c index e5a533cbd53f..f762eb8b174a 100644 --- a/drivers/iio/pressure/bmp280-core.c +++ b/drivers/iio/pressure/bmp280-core.c @@ -175,11 +175,12 @@ static u32 bmp280_compensate_humidity(struct bmp280_data *data, } H6 = sign_extend32(tmp, 7); - var = ((s32)data->t_fine) - 76800; - var = ((((adc_humidity << 14) - (H4 << 20) - (H5 * var)) + 16384) >> 15) - * (((((((var * H6) >> 10) * (((var * H3) >> 11) + 32768)) >> 10) - + 2097152) * H2 + 8192) >> 14); - var -= ((((var >> 15) * (var >> 15)) >> 7) * H1) >> 4; + var = ((s32)data->t_fine) - (s32)76800; + var = ((((adc_humidity << 14) - (H4 << 20) - (H5 * var)) + + (s32)16384) >> 15) * (((((((var * H6) >> 10) + * (((var * (s32)H3) >> 11) + (s32)32768)) >> 10) + + (s32)2097152) * H2 + 8192) >> 14); + var -= ((((var >> 15) * (var >> 15)) >> 7) * (s32)H1) >> 4; return var >> 12; }; From b894ea8263caee43d90c2f956361f280bc32990d Mon Sep 17 00:00:00 2001 From: "Michael J. Ruhl" Date: Thu, 4 May 2017 05:14:28 -0700 Subject: [PATCH 293/396] IB/hfi1: Return an error on memory allocation failure commit 94679061dcdddbafcf24e3bfb526e54dedcc2f2f upstream. If the eager buffer allocation fails, it is necessary to return an error code. Reviewed-by: Mike Marciniszyn Signed-off-by: Michael J. Ruhl Signed-off-by: Dennis Dalessandro Signed-off-by: Doug Ledford Signed-off-by: Greg Kroah-Hartman --- drivers/infiniband/hw/hfi1/init.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/infiniband/hw/hfi1/init.c b/drivers/infiniband/hw/hfi1/init.c index e3b5bc93bc70..34cfd341b6d6 100644 --- a/drivers/infiniband/hw/hfi1/init.c +++ b/drivers/infiniband/hw/hfi1/init.c @@ -1757,6 +1757,7 @@ int hfi1_setup_eagerbufs(struct hfi1_ctxtdata *rcd) !HFI1_CAP_KGET_MASK(rcd->flags, MULTI_PKT_EGR)) { dd_dev_err(dd, "ctxt%u: Failed to allocate eager buffers\n", rcd->ctxt); + ret = -ENOMEM; goto bail_rcvegrbuf_phys; } From 5e40ac3fbd0d733bf32447b44f50ca32efb05e20 Mon Sep 17 00:00:00 2001 From: "Michael J. Ruhl" Date: Thu, 4 May 2017 05:14:34 -0700 Subject: [PATCH 294/396] IB/hfi1: Fix a subcontext memory leak commit 224d71f910102c966cdcd782c97e096d5e26e4da upstream. The only context that frees user_exp_rcv data structures is the last context closed (from a sub-context set). This leaks the allocations from the other sub-contexts. Separate the common frees from the specific frees and call them at the appropriate time. Using KEDR to check for memory leaks we get: Before test: [leak_check] Possible leaks: 25 After test: [leak_check] Possible leaks: 31 (6 leaked data structures) After patch applied (before and after test have the same value) [leak_check] Possible leaks: 25 Each leak is 192 + 13440 + 6720 = 20352 bytes per sub-context. Reviewed-by: Mike Marciniszyn Signed-off-by: Michael J. Ruhl Signed-off-by: Dennis Dalessandro Signed-off-by: Doug Ledford Signed-off-by: Greg Kroah-Hartman --- drivers/infiniband/hw/hfi1/file_ops.c | 5 +++- drivers/infiniband/hw/hfi1/user_exp_rcv.c | 32 +++++++++++++---------- drivers/infiniband/hw/hfi1/user_exp_rcv.h | 1 + 3 files changed, 23 insertions(+), 15 deletions(-) diff --git a/drivers/infiniband/hw/hfi1/file_ops.c b/drivers/infiniband/hw/hfi1/file_ops.c index bd786b7bd30b..bb729764a799 100644 --- a/drivers/infiniband/hw/hfi1/file_ops.c +++ b/drivers/infiniband/hw/hfi1/file_ops.c @@ -751,6 +751,9 @@ static int hfi1_file_close(struct inode *inode, struct file *fp) /* release the cpu */ hfi1_put_proc_affinity(fdata->rec_cpu_num); + /* clean up rcv side */ + hfi1_user_exp_rcv_free(fdata); + /* * Clear any left over, unhandled events so the next process that * gets this context doesn't get confused. @@ -790,7 +793,7 @@ static int hfi1_file_close(struct inode *inode, struct file *fp) dd->rcd[uctxt->ctxt] = NULL; - hfi1_user_exp_rcv_free(fdata); + hfi1_user_exp_rcv_grp_free(uctxt); hfi1_clear_ctxt_pkey(dd, uctxt->ctxt); uctxt->rcvwait_to = 0; diff --git a/drivers/infiniband/hw/hfi1/user_exp_rcv.c b/drivers/infiniband/hw/hfi1/user_exp_rcv.c index 64d26525435a..db0f140e2116 100644 --- a/drivers/infiniband/hw/hfi1/user_exp_rcv.c +++ b/drivers/infiniband/hw/hfi1/user_exp_rcv.c @@ -250,36 +250,40 @@ done: return ret; } +void hfi1_user_exp_rcv_grp_free(struct hfi1_ctxtdata *uctxt) +{ + struct tid_group *grp, *gptr; + + list_for_each_entry_safe(grp, gptr, &uctxt->tid_group_list.list, + list) { + list_del_init(&grp->list); + kfree(grp); + } + hfi1_clear_tids(uctxt); +} + int hfi1_user_exp_rcv_free(struct hfi1_filedata *fd) { struct hfi1_ctxtdata *uctxt = fd->uctxt; - struct tid_group *grp, *gptr; - if (!test_bit(HFI1_CTXT_SETUP_DONE, &uctxt->event_flags)) - return 0; /* * The notifier would have been removed when the process'es mm * was freed. */ - if (fd->handler) + if (fd->handler) { hfi1_mmu_rb_unregister(fd->handler); - - kfree(fd->invalid_tids); - - if (!uctxt->cnt) { + } else { if (!EXP_TID_SET_EMPTY(uctxt->tid_full_list)) unlock_exp_tids(uctxt, &uctxt->tid_full_list, fd); if (!EXP_TID_SET_EMPTY(uctxt->tid_used_list)) unlock_exp_tids(uctxt, &uctxt->tid_used_list, fd); - list_for_each_entry_safe(grp, gptr, &uctxt->tid_group_list.list, - list) { - list_del_init(&grp->list); - kfree(grp); - } - hfi1_clear_tids(uctxt); } + kfree(fd->invalid_tids); + fd->invalid_tids = NULL; + kfree(fd->entry_to_rb); + fd->entry_to_rb = NULL; return 0; } diff --git a/drivers/infiniband/hw/hfi1/user_exp_rcv.h b/drivers/infiniband/hw/hfi1/user_exp_rcv.h index 9bc8d9fba87e..d1d7d3d3bd44 100644 --- a/drivers/infiniband/hw/hfi1/user_exp_rcv.h +++ b/drivers/infiniband/hw/hfi1/user_exp_rcv.h @@ -70,6 +70,7 @@ (tid) |= EXP_TID_SET(field, (value)); \ } while (0) +void hfi1_user_exp_rcv_grp_free(struct hfi1_ctxtdata *uctxt); int hfi1_user_exp_rcv_init(struct file *); int hfi1_user_exp_rcv_free(struct hfi1_filedata *); int hfi1_user_exp_rcv_setup(struct file *, struct hfi1_tid_info *); From 6dc6a2700b6a0dd755027654b85bd614d8d3d52b Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Thu, 11 May 2017 18:21:01 -0500 Subject: [PATCH 295/396] pid_ns: Sleep in TASK_INTERRUPTIBLE in zap_pid_ns_processes commit b9a985db98961ae1ba0be169f19df1c567e4ffe0 upstream. The code can potentially sleep for an indefinite amount of time in zap_pid_ns_processes triggering the hung task timeout, and increasing the system average. This is undesirable. Sleep with a task state of TASK_INTERRUPTIBLE instead of TASK_UNINTERRUPTIBLE to remove these undesirable side effects. Apparently under heavy load this has been allowing Chrome to trigger the hung time task timeout error and cause ChromeOS to reboot. Reported-by: Vovo Yang Reported-by: Guenter Roeck Tested-by: Guenter Roeck Fixes: 6347e9009104 ("pidns: guarantee that the pidns init will be the last pidns process reaped") Signed-off-by: "Eric W. Biederman" Signed-off-by: Greg Kroah-Hartman --- kernel/pid_namespace.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/pid_namespace.c b/kernel/pid_namespace.c index eef2ce968636..3976dd57db78 100644 --- a/kernel/pid_namespace.c +++ b/kernel/pid_namespace.c @@ -274,7 +274,7 @@ void zap_pid_ns_processes(struct pid_namespace *pid_ns) * if reparented. */ for (;;) { - set_current_state(TASK_UNINTERRUPTIBLE); + set_current_state(TASK_INTERRUPTIBLE); if (pid_ns->nr_hashed == init_pids) break; schedule(); From 2ea2f891fa85a6b8fd2fd6991e16844be39da888 Mon Sep 17 00:00:00 2001 From: Kirill Tkhai Date: Fri, 12 May 2017 19:11:31 +0300 Subject: [PATCH 296/396] pid_ns: Fix race between setns'ed fork() and zap_pid_ns_processes() commit 3fd37226216620c1a468afa999739d5016fbc349 upstream. Imagine we have a pid namespace and a task from its parent's pid_ns, which made setns() to the pid namespace. The task is doing fork(), while the pid namespace's child reaper is dying. We have the race between them: Task from parent pid_ns Child reaper copy_process() .. alloc_pid() .. .. zap_pid_ns_processes() .. disable_pid_allocation() .. read_lock(&tasklist_lock) .. iterate over pids in pid_ns .. kill tasks linked to pids .. read_unlock(&tasklist_lock) write_lock_irq(&tasklist_lock); .. attach_pid(p, PIDTYPE_PID); .. .. .. So, just created task p won't receive SIGKILL signal, and the pid namespace will be in contradictory state. Only manual kill will help there, but does the userspace care about this? I suppose, the most users just inject a task into a pid namespace and wait a SIGCHLD from it. The patch fixes the problem. It simply checks for (pid_ns->nr_hashed & PIDNS_HASH_ADDING) in copy_process(). We do it under the tasklist_lock, and can't skip PIDNS_HASH_ADDING as noted by Oleg: "zap_pid_ns_processes() does disable_pid_allocation() and then takes tasklist_lock to kill the whole namespace. Given that copy_process() checks PIDNS_HASH_ADDING under write_lock(tasklist) they can't race; if copy_process() takes this lock first, the new child will be killed, otherwise copy_process() can't miss the change in ->nr_hashed." If allocation is disabled, we just return -ENOMEM like it's made for such cases in alloc_pid(). v2: Do not move disable_pid_allocation(), do not introduce a new variable in copy_process() and simplify the patch as suggested by Oleg Nesterov. Account the problem with double irq enabling found by Eric W. Biederman. Fixes: c876ad768215 ("pidns: Stop pid allocation when init dies") Signed-off-by: Kirill Tkhai CC: Andrew Morton CC: Ingo Molnar CC: Peter Zijlstra CC: Oleg Nesterov CC: Mike Rapoport CC: Michal Hocko CC: Andy Lutomirski CC: "Eric W. Biederman" CC: Andrei Vagin CC: Cyrill Gorcunov CC: Serge Hallyn Acked-by: Oleg Nesterov Signed-off-by: Eric W. Biederman Signed-off-by: Greg Kroah-Hartman --- kernel/fork.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/kernel/fork.c b/kernel/fork.c index ba8a01564985..c994a30f107d 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -1773,11 +1773,13 @@ static __latent_entropy struct task_struct *copy_process( */ recalc_sigpending(); if (signal_pending(current)) { - spin_unlock(¤t->sighand->siglock); - write_unlock_irq(&tasklist_lock); retval = -ERESTARTNOINTR; goto bad_fork_cancel_cgroup; } + if (unlikely(!(ns_of_pid(pid)->nr_hashed & PIDNS_HASH_ADDING))) { + retval = -ENOMEM; + goto bad_fork_cancel_cgroup; + } if (likely(p->pid)) { ptrace_init_task(p, (clone_flags & CLONE_PTRACE) || trace); @@ -1828,6 +1830,8 @@ static __latent_entropy struct task_struct *copy_process( return p; bad_fork_cancel_cgroup: + spin_unlock(¤t->sighand->siglock); + write_unlock_irq(&tasklist_lock); cgroup_cancel_fork(p); bad_fork_free_pid: threadgroup_change_end(current); From 038ccaa5d50e7b338fd6c4b1293d1e2aa0b3d8da Mon Sep 17 00:00:00 2001 From: Anthony Mallet Date: Fri, 5 May 2017 17:30:16 +0200 Subject: [PATCH 297/396] USB: serial: ftdi_sio: fix setting latency for unprivileged users commit bb246681b3ed0967489a7401ad528c1aaa1a4c2e upstream. Commit 557aaa7ffab6 ("ft232: support the ASYNC_LOW_LATENCY flag") enables unprivileged users to set the FTDI latency timer, but there was a logic flaw that skipped sending the corresponding USB control message to the device. Specifically, the device latency timer would not be updated until next open, something which was later also inadvertently broken by commit c19db4c9e49a ("USB: ftdi_sio: set device latency timeout at port probe"). A recent commit c6dce2626606 ("USB: serial: ftdi_sio: fix extreme low-latency setting") disabled the low-latency mode by default so we now need this fix to allow unprivileged users to again enable it. Signed-off-by: Anthony Mallet [johan: amend commit message] Fixes: 557aaa7ffab6 ("ft232: support the ASYNC_LOW_LATENCY flag") Fixes: c19db4c9e49a ("USB: ftdi_sio: set device latency timeout at port probe"). Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/ftdi_sio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index 1dc75db16cbd..9db58daa340e 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -1508,9 +1508,9 @@ static int set_serial_info(struct tty_struct *tty, (new_serial.flags & ASYNC_FLAGS)); priv->custom_divisor = new_serial.custom_divisor; +check_and_exit: write_latency_timer(port); -check_and_exit: if ((old_priv.flags & ASYNC_SPD_MASK) != (priv->flags & ASYNC_SPD_MASK)) { if ((priv->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI) From 545a3171d37fdb5b9390a0852093309dd03ba2a5 Mon Sep 17 00:00:00 2001 From: Andrey Korolyov Date: Tue, 16 May 2017 23:54:41 +0300 Subject: [PATCH 298/396] USB: serial: ftdi_sio: add Olimex ARM-USB-TINY(H) PIDs commit 5f63424ab7daac840df2b12dd5bcc5b38d50f779 upstream. This patch adds support for recognition of ARM-USB-TINY(H) devices which are almost identical to ARM-USB-OCD(H) but lacking separate barrel jack and serial console. By suggestion from Johan Hovold it is possible to replace ftdi_jtag_quirk with a bit more generic construction. Since all Olimex-ARM debuggers has exactly two ports, we could safely always use only second port within the debugger family. Signed-off-by: Andrey Korolyov Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/ftdi_sio.c | 8 ++++---- drivers/usb/serial/ftdi_sio_ids.h | 2 ++ 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index 9db58daa340e..19394963f675 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -809,10 +809,10 @@ static const struct usb_device_id id_table_combined[] = { { USB_DEVICE(FTDI_VID, FTDI_PROPOX_ISPCABLEIII_PID) }, { USB_DEVICE(FTDI_VID, CYBER_CORTEX_AV_PID), .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, - { USB_DEVICE(OLIMEX_VID, OLIMEX_ARM_USB_OCD_PID), - .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, - { USB_DEVICE(OLIMEX_VID, OLIMEX_ARM_USB_OCD_H_PID), - .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, + { USB_DEVICE_INTERFACE_NUMBER(OLIMEX_VID, OLIMEX_ARM_USB_OCD_PID, 1) }, + { USB_DEVICE_INTERFACE_NUMBER(OLIMEX_VID, OLIMEX_ARM_USB_OCD_H_PID, 1) }, + { USB_DEVICE_INTERFACE_NUMBER(OLIMEX_VID, OLIMEX_ARM_USB_TINY_PID, 1) }, + { USB_DEVICE_INTERFACE_NUMBER(OLIMEX_VID, OLIMEX_ARM_USB_TINY_H_PID, 1) }, { USB_DEVICE(FIC_VID, FIC_NEO1973_DEBUG_PID), .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, { USB_DEVICE(FTDI_VID, FTDI_OOCDLINK_PID), diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h index 71fb9e59db71..4fcf1cecb6d7 100644 --- a/drivers/usb/serial/ftdi_sio_ids.h +++ b/drivers/usb/serial/ftdi_sio_ids.h @@ -882,6 +882,8 @@ /* Olimex */ #define OLIMEX_VID 0x15BA #define OLIMEX_ARM_USB_OCD_PID 0x0003 +#define OLIMEX_ARM_USB_TINY_PID 0x0004 +#define OLIMEX_ARM_USB_TINY_H_PID 0x002a #define OLIMEX_ARM_USB_OCD_H_PID 0x002b /* From b9c0da6219e19901c5bea6e5c19514929dae9e18 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 11 May 2017 11:36:01 +0200 Subject: [PATCH 299/396] USB: chaoskey: fix Alea quirk on big-endian hosts commit 63afd5cc78775018ea2dec4004428dafa5283e93 upstream. Add missing endianness conversion when applying the Alea timeout quirk. Found using sparse: warning: restricted __le16 degrades to integer Fixes: e4a886e811cd ("hwrng: chaoskey - Fix URB warning due to timeout on Alea") Cc: Bob Ham Cc: Herbert Xu Cc: Keith Packard Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/misc/chaoskey.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/misc/chaoskey.c b/drivers/usb/misc/chaoskey.c index 6ddd08a32777..efecb87428b1 100644 --- a/drivers/usb/misc/chaoskey.c +++ b/drivers/usb/misc/chaoskey.c @@ -194,7 +194,7 @@ static int chaoskey_probe(struct usb_interface *interface, dev->in_ep = in_ep; - if (udev->descriptor.idVendor != ALEA_VENDOR_ID) + if (le16_to_cpu(udev->descriptor.idVendor) != ALEA_VENDOR_ID) dev->reads_started = 1; dev->size = size; From 8daed21dbce1d28fd082ef6f2faf8990ccebfd6f Mon Sep 17 00:00:00 2001 From: Jaegeuk Kim Date: Mon, 24 Apr 2017 10:00:08 -0700 Subject: [PATCH 300/396] f2fs: check entire encrypted bigname when finding a dentry commit 6332cd32c8290a80e929fc044dc5bdba77396e33 upstream. If user has no key under an encrypted dir, fscrypt gives digested dentries. Previously, when looking up a dentry, f2fs only checks its hash value with first 4 bytes of the digested dentry, which didn't handle hash collisions fully. This patch enhances to check entire dentry bytes likewise ext4. Eric reported how to reproduce this issue by: # seq -f "edir/abcdefghijklmnopqrstuvwxyz012345%.0f" 100000 | xargs touch # find edir -type f | xargs stat -c %i | sort | uniq | wc -l 100000 # sync # echo 3 > /proc/sys/vm/drop_caches # keyctl new_session # find edir -type f | xargs stat -c %i | sort | uniq | wc -l 99999 Cc: Reported-by: Eric Biggers Signed-off-by: Jaegeuk Kim (fixed f2fs_dentry_hash() to work even when the hash is 0) Signed-off-by: Eric Biggers Signed-off-by: Theodore Ts'o Signed-off-by: Greg Kroah-Hartman --- fs/f2fs/dir.c | 37 +++++++++++++++++++++---------------- fs/f2fs/f2fs.h | 3 ++- fs/f2fs/hash.c | 7 ++++++- fs/f2fs/inline.c | 4 ++-- 4 files changed, 31 insertions(+), 20 deletions(-) diff --git a/fs/f2fs/dir.c b/fs/f2fs/dir.c index ebdc90fc71b7..e32d82b011a9 100644 --- a/fs/f2fs/dir.c +++ b/fs/f2fs/dir.c @@ -130,19 +130,29 @@ struct f2fs_dir_entry *find_target_dentry(struct fscrypt_name *fname, continue; } - /* encrypted case */ + if (de->hash_code != namehash) + goto not_match; + de_name.name = d->filename[bit_pos]; de_name.len = le16_to_cpu(de->name_len); - /* show encrypted name */ - if (fname->hash) { - if (de->hash_code == fname->hash) - goto found; - } else if (de_name.len == name->len && - de->hash_code == namehash && - !memcmp(de_name.name, name->name, name->len)) +#ifdef CONFIG_F2FS_FS_ENCRYPTION + if (unlikely(!name->name)) { + if (fname->usr_fname->name[0] == '_') { + if (de_name.len >= 16 && + !memcmp(de_name.name + de_name.len - 16, + fname->crypto_buf.name + 8, 16)) + goto found; + goto not_match; + } + name->name = fname->crypto_buf.name; + name->len = fname->crypto_buf.len; + } +#endif + if (de_name.len == name->len && + !memcmp(de_name.name, name->name, name->len)) goto found; - +not_match: if (max_slots && max_len > *max_slots) *max_slots = max_len; max_len = 0; @@ -170,12 +180,7 @@ static struct f2fs_dir_entry *find_in_level(struct inode *dir, struct f2fs_dir_entry *de = NULL; bool room = false; int max_slots; - f2fs_hash_t namehash; - - if(fname->hash) - namehash = cpu_to_le32(fname->hash); - else - namehash = f2fs_dentry_hash(&name); + f2fs_hash_t namehash = f2fs_dentry_hash(&name, fname); nbucket = dir_buckets(level, F2FS_I(dir)->i_dir_level); nblock = bucket_blocks(level); @@ -539,7 +544,7 @@ int f2fs_add_regular_entry(struct inode *dir, const struct qstr *new_name, level = 0; slots = GET_DENTRY_SLOTS(new_name->len); - dentry_hash = f2fs_dentry_hash(new_name); + dentry_hash = f2fs_dentry_hash(new_name, NULL); current_depth = F2FS_I(dir)->i_current_depth; if (F2FS_I(dir)->chash == dentry_hash) { diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index 3a1640be7ffc..c12f695923b6 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h @@ -2016,7 +2016,8 @@ int sanity_check_ckpt(struct f2fs_sb_info *sbi); /* * hash.c */ -f2fs_hash_t f2fs_dentry_hash(const struct qstr *); +f2fs_hash_t f2fs_dentry_hash(const struct qstr *name_info, + struct fscrypt_name *fname); /* * node.c diff --git a/fs/f2fs/hash.c b/fs/f2fs/hash.c index 71b7206c431e..eb2e031ea887 100644 --- a/fs/f2fs/hash.c +++ b/fs/f2fs/hash.c @@ -70,7 +70,8 @@ static void str2hashbuf(const unsigned char *msg, size_t len, *buf++ = pad; } -f2fs_hash_t f2fs_dentry_hash(const struct qstr *name_info) +f2fs_hash_t f2fs_dentry_hash(const struct qstr *name_info, + struct fscrypt_name *fname) { __u32 hash; f2fs_hash_t f2fs_hash; @@ -79,6 +80,10 @@ f2fs_hash_t f2fs_dentry_hash(const struct qstr *name_info) const unsigned char *name = name_info->name; size_t len = name_info->len; + /* encrypted bigname case */ + if (fname && !fname->disk_name.name) + return cpu_to_le32(fname->hash); + if (is_dot_dotdot(name_info)) return 0; diff --git a/fs/f2fs/inline.c b/fs/f2fs/inline.c index 5f1a67f756af..a21faa1c6817 100644 --- a/fs/f2fs/inline.c +++ b/fs/f2fs/inline.c @@ -294,7 +294,7 @@ struct f2fs_dir_entry *find_in_inline_dir(struct inode *dir, return NULL; } - namehash = f2fs_dentry_hash(&name); + namehash = f2fs_dentry_hash(&name, fname); inline_dentry = inline_data_addr(ipage); @@ -531,7 +531,7 @@ int f2fs_add_inline_entry(struct inode *dir, const struct qstr *new_name, f2fs_wait_on_page_writeback(ipage, NODE, true); - name_hash = f2fs_dentry_hash(new_name); + name_hash = f2fs_dentry_hash(new_name, NULL); make_dentry_ptr(NULL, &d, (void *)dentry_blk, 2); f2fs_update_dentry(ino, mode, &d, new_name, name_hash, bit_pos); From af9bd521885569799475fefcf3333a9ace5ce51f Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Mon, 24 Apr 2017 10:00:09 -0700 Subject: [PATCH 301/396] fscrypt: avoid collisions when presenting long encrypted filenames commit 6b06cdee81d68a8a829ad8e8d0f31d6836744af9 upstream. When accessing an encrypted directory without the key, userspace must operate on filenames derived from the ciphertext names, which contain arbitrary bytes. Since we must support filenames as long as NAME_MAX, we can't always just base64-encode the ciphertext, since that may make it too long. Currently, this is solved by presenting long names in an abbreviated form containing any needed filesystem-specific hashes (e.g. to identify a directory block), then the last 16 bytes of ciphertext. This needs to be sufficient to identify the actual name on lookup. However, there is a bug. It seems to have been assumed that due to the use of a CBC (ciphertext block chaining)-based encryption mode, the last 16 bytes (i.e. the AES block size) of ciphertext would depend on the full plaintext, preventing collisions. However, we actually use CBC with ciphertext stealing (CTS), which handles the last two blocks specially, causing them to appear "flipped". Thus, it's actually the second-to-last block which depends on the full plaintext. This caused long filenames that differ only near the end of their plaintexts to, when observed without the key, point to the wrong inode and be undeletable. For example, with ext4: # echo pass | e4crypt add_key -p 16 edir/ # seq -f "edir/abcdefghijklmnopqrstuvwxyz012345%.0f" 100000 | xargs touch # find edir/ -type f | xargs stat -c %i | sort | uniq | wc -l 100000 # sync # echo 3 > /proc/sys/vm/drop_caches # keyctl new_session # find edir/ -type f | xargs stat -c %i | sort | uniq | wc -l 2004 # rm -rf edir/ rm: cannot remove 'edir/_A7nNFi3rhkEQlJ6P,hdzluhODKOeWx5V': Structure needs cleaning ... To fix this, when presenting long encrypted filenames, encode the second-to-last block of ciphertext rather than the last 16 bytes. Although it would be nice to solve this without depending on a specific encryption mode, that would mean doing a cryptographic hash like SHA-256 which would be much less efficient. This way is sufficient for now, and it's still compatible with encryption modes like HEH which are strong pseudorandom permutations. Also, changing the presented names is still allowed at any time because they are only provided to allow applications to do things like delete encrypted directories. They're not designed to be used to persistently identify files --- which would be hard to do anyway, given that they're encrypted after all. For ease of backports, this patch only makes the minimal fix to both ext4 and f2fs. It leaves ubifs as-is, since ubifs doesn't compare the ciphertext block yet. Follow-on patches will clean things up properly and make the filesystems use a shared helper function. Fixes: 5de0b4d0cd15 ("ext4 crypto: simplify and speed up filename encryption") Reported-by: Gwendal Grignou Signed-off-by: Eric Biggers Signed-off-by: Theodore Ts'o Signed-off-by: Greg Kroah-Hartman --- fs/crypto/fname.c | 2 +- fs/ext4/namei.c | 4 ++-- fs/f2fs/dir.c | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/fs/crypto/fname.c b/fs/crypto/fname.c index 80bb956e14e5..d1bbdc9dda76 100644 --- a/fs/crypto/fname.c +++ b/fs/crypto/fname.c @@ -300,7 +300,7 @@ int fscrypt_fname_disk_to_usr(struct inode *inode, } else { memset(buf, 0, 8); } - memcpy(buf + 8, iname->name + iname->len - 16, 16); + memcpy(buf + 8, iname->name + ((iname->len - 17) & ~15), 16); oname->name[0] = '_'; oname->len = 1 + digest_encode(buf, 24, oname->name + 1); return 0; diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c index c4a389a6027b..423a21cd077c 100644 --- a/fs/ext4/namei.c +++ b/fs/ext4/namei.c @@ -1255,9 +1255,9 @@ static inline int ext4_match(struct ext4_filename *fname, if (unlikely(!name)) { if (fname->usr_fname->name[0] == '_') { int ret; - if (de->name_len < 16) + if (de->name_len <= 32) return 0; - ret = memcmp(de->name + de->name_len - 16, + ret = memcmp(de->name + ((de->name_len - 17) & ~15), fname->crypto_buf.name + 8, 16); return (ret == 0) ? 1 : 0; } diff --git a/fs/f2fs/dir.c b/fs/f2fs/dir.c index e32d82b011a9..11f3717ce481 100644 --- a/fs/f2fs/dir.c +++ b/fs/f2fs/dir.c @@ -139,8 +139,8 @@ struct f2fs_dir_entry *find_target_dentry(struct fscrypt_name *fname, #ifdef CONFIG_F2FS_FS_ENCRYPTION if (unlikely(!name->name)) { if (fname->usr_fname->name[0] == '_') { - if (de_name.len >= 16 && - !memcmp(de_name.name + de_name.len - 16, + if (de_name.len > 32 && + !memcmp(de_name.name + ((de_name.len - 17) & ~15), fname->crypto_buf.name + 8, 16)) goto found; goto not_match; From fa313fd6673e498b6d0b2c87bb3bfedab556c122 Mon Sep 17 00:00:00 2001 From: Toshi Kani Date: Thu, 27 Apr 2017 16:57:05 -0600 Subject: [PATCH 302/396] libnvdimm: fix clear length of nvdimm_forget_poison() commit 8d13c0290655b883df9083a2a0af0d782bc38aef upstream. ND_CMD_CLEAR_ERROR command returns 'clear_err.cleared', the length of error actually cleared, which may be smaller than its requested 'len'. Change nvdimm_clear_poison() to call nvdimm_forget_poison() with 'clear_err.cleared' when this value is valid. Fixes: e046114af5fc ("libnvdimm: clear the internal poison_list when clearing badblocks") Cc: Dave Jiang Cc: Vishal Verma Signed-off-by: Toshi Kani Signed-off-by: Dan Williams Signed-off-by: Greg Kroah-Hartman --- drivers/nvdimm/bus.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/nvdimm/bus.c b/drivers/nvdimm/bus.c index 351bac8f6503..0392eb8a0dea 100644 --- a/drivers/nvdimm/bus.c +++ b/drivers/nvdimm/bus.c @@ -218,7 +218,10 @@ long nvdimm_clear_poison(struct device *dev, phys_addr_t phys, if (cmd_rc < 0) return cmd_rc; - nvdimm_clear_from_poison_list(nvdimm_bus, phys, len); + if (clear_err.cleared > 0) + nvdimm_clear_from_poison_list(nvdimm_bus, phys, + clear_err.cleared); + return clear_err.cleared; } EXPORT_SYMBOL_GPL(nvdimm_clear_poison); From 374a3fb5c3b0934cfda09bcf6362058249e7869b Mon Sep 17 00:00:00 2001 From: Matthias Lange Date: Wed, 17 May 2017 18:32:04 +0300 Subject: [PATCH 303/396] xhci: remove GFP_DMA flag from allocation commit 5db851cf20857c5504b146046e97cb7781f2a743 upstream. There is no reason to restrict allocations to the first 16MB ISA DMA addresses. It is causing problems in a virtualization setup with enabled IOMMU (x86_64). The result is that USB is not working in the VM. Signed-off-by: Matthias Lange Signed-off-by: Mathias Nyman Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/xhci-mem.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index 709b52841c87..8afb62693857 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c @@ -56,7 +56,7 @@ static struct xhci_segment *xhci_segment_alloc(struct xhci_hcd *xhci, } if (max_packet) { - seg->bounce_buf = kzalloc(max_packet, flags | GFP_DMA); + seg->bounce_buf = kzalloc(max_packet, flags); if (!seg->bounce_buf) { dma_pool_free(xhci->segment_pool, seg->trbs, dma); kfree(seg); From 1a926919364fc1840ad3e47b3d900f62483f424b Mon Sep 17 00:00:00 2001 From: Thomas Petazzoni Date: Wed, 17 May 2017 18:32:06 +0300 Subject: [PATCH 304/396] usb: host: xhci-plat: propagate return value of platform_get_irq() commit 4b148d5144d64ee135b8924350cb0b3a7fd21150 upstream. platform_get_irq() returns an error code, but the xhci-plat driver ignores it and always returns -ENODEV. This is not correct, and prevents -EPROBE_DEFER from being propagated properly. Signed-off-by: Thomas Petazzoni Signed-off-by: Mathias Nyman Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/xhci-plat.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/host/xhci-plat.c b/drivers/usb/host/xhci-plat.c index be1572331a64..ca8b0b1ae37d 100644 --- a/drivers/usb/host/xhci-plat.c +++ b/drivers/usb/host/xhci-plat.c @@ -153,7 +153,7 @@ static int xhci_plat_probe(struct platform_device *pdev) irq = platform_get_irq(pdev, 0); if (irq < 0) - return -ENODEV; + return irq; /* Try to set 64-bit DMA first */ if (WARN_ON(!pdev->dev.dma_mask)) From 219628bb0c052b95523dfc526aa0027ff0de3a9d Mon Sep 17 00:00:00 2001 From: Mathias Nyman Date: Wed, 17 May 2017 18:32:00 +0300 Subject: [PATCH 305/396] xhci: apply PME_STUCK_QUIRK and MISSING_CAS quirk for Denverton commit a0c16630d35a874e82bdf2088f58ecaca1024315 upstream. Intel Denverton microserver is Atom based and need the PME and CAS quirks as well. Signed-off-by: Mathias Nyman Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/xhci-pci.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c index 93f566cb968b..e7d6752eff32 100644 --- a/drivers/usb/host/xhci-pci.c +++ b/drivers/usb/host/xhci-pci.c @@ -52,6 +52,7 @@ #define PCI_DEVICE_ID_INTEL_BROXTON_M_XHCI 0x0aa8 #define PCI_DEVICE_ID_INTEL_BROXTON_B_XHCI 0x1aa8 #define PCI_DEVICE_ID_INTEL_APL_XHCI 0x5aa8 +#define PCI_DEVICE_ID_INTEL_DNV_XHCI 0x19d0 static const char hcd_name[] = "xhci_hcd"; @@ -166,7 +167,8 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci) pdev->device == PCI_DEVICE_ID_INTEL_CHERRYVIEW_XHCI || pdev->device == PCI_DEVICE_ID_INTEL_BROXTON_M_XHCI || pdev->device == PCI_DEVICE_ID_INTEL_BROXTON_B_XHCI || - pdev->device == PCI_DEVICE_ID_INTEL_APL_XHCI)) { + pdev->device == PCI_DEVICE_ID_INTEL_APL_XHCI || + pdev->device == PCI_DEVICE_ID_INTEL_DNV_XHCI)) { xhci->quirks |= XHCI_PME_STUCK_QUIRK; } if (pdev->vendor == PCI_VENDOR_ID_INTEL && @@ -175,7 +177,8 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci) } if (pdev->vendor == PCI_VENDOR_ID_INTEL && (pdev->device == PCI_DEVICE_ID_INTEL_CHERRYVIEW_XHCI || - pdev->device == PCI_DEVICE_ID_INTEL_APL_XHCI)) + pdev->device == PCI_DEVICE_ID_INTEL_APL_XHCI || + pdev->device == PCI_DEVICE_ID_INTEL_DNV_XHCI)) xhci->quirks |= XHCI_MISSING_CAS; if (pdev->vendor == PCI_VENDOR_ID_ETRON && From 1046d6a51f570cba480077aa9f22b5fe6efe6cc6 Mon Sep 17 00:00:00 2001 From: Peter Chen Date: Wed, 17 May 2017 18:32:01 +0300 Subject: [PATCH 306/396] usb: host: xhci-mem: allocate zeroed Scratchpad Buffer commit 7480d912d549f414e0ce39331870899e89a5598c upstream. According to xHCI ch4.20 Scratchpad Buffers, the Scratchpad Buffer needs to be zeroed. ... The following operations take place to allocate Scratchpad Buffers to the xHC: ... b. Software clears the Scratchpad Buffer to '0' Signed-off-by: Peter Chen Signed-off-by: Mathias Nyman Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/xhci-mem.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index 8afb62693857..8c6eafe8966c 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c @@ -1721,7 +1721,7 @@ static int scratchpad_alloc(struct xhci_hcd *xhci, gfp_t flags) xhci->dcbaa->dev_context_ptrs[0] = cpu_to_le64(xhci->scratchpad->sp_dma); for (i = 0; i < num_sp; i++) { dma_addr_t dma; - void *buf = dma_alloc_coherent(dev, xhci->page_size, &dma, + void *buf = dma_zalloc_coherent(dev, xhci->page_size, &dma, flags); if (!buf) goto fail_sp5; From a3adb4721ae2af534b1adf74dfb7f54329fa448c Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Fri, 12 May 2017 12:11:13 +0200 Subject: [PATCH 307/396] net: irda: irda-usb: fix firmware name on big-endian hosts commit 75cf067953d5ee543b3bda90bbfcbee5e1f94ae8 upstream. Add missing endianness conversion when using the USB device-descriptor bcdDevice field to construct a firmware file name. Fixes: 8ef80aef118e ("[IRDA]: irda-usb.c: STIR421x cleanups") Cc: Nick Fedchik Signed-off-by: Johan Hovold Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/irda/irda-usb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/irda/irda-usb.c b/drivers/net/irda/irda-usb.c index 8716b8c07feb..6f3c805f7211 100644 --- a/drivers/net/irda/irda-usb.c +++ b/drivers/net/irda/irda-usb.c @@ -1077,7 +1077,7 @@ static int stir421x_patch_device(struct irda_usb_cb *self) * are "42101001.sb" or "42101002.sb" */ sprintf(stir421x_fw_name, "4210%4X.sb", - self->usbdev->descriptor.bcdDevice); + le16_to_cpu(self->usbdev->descriptor.bcdDevice)); ret = request_firmware(&fw, stir421x_fw_name, &self->usbdev->dev); if (ret < 0) return ret; From 736f41a47442c164e3cdc8d2a980d3155130163f Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Mon, 13 Mar 2017 09:53:55 -0300 Subject: [PATCH 308/396] usbvision: fix NULL-deref at probe commit eacb975b48272f54532b62f515a3cf7eefa35123 upstream. Make sure to check the number of endpoints to avoid dereferencing a NULL-pointer or accessing memory beyond the endpoint array should a malicious device lack the expected endpoints. Fixes: 2a9f8b5d25be ("V4L/DVB (5206): Usbvision: set alternate interface modification") Cc: Thierry MERLE Signed-off-by: Johan Hovold Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Greg Kroah-Hartman --- drivers/media/usb/usbvision/usbvision-video.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/media/usb/usbvision/usbvision-video.c b/drivers/media/usb/usbvision/usbvision-video.c index c8b4eb2ee7a2..bfdf72355332 100644 --- a/drivers/media/usb/usbvision/usbvision-video.c +++ b/drivers/media/usb/usbvision/usbvision-video.c @@ -1506,7 +1506,14 @@ static int usbvision_probe(struct usb_interface *intf, } for (i = 0; i < usbvision->num_alt; i++) { - u16 tmp = le16_to_cpu(uif->altsetting[i].endpoint[1].desc. + u16 tmp; + + if (uif->altsetting[i].desc.bNumEndpoints < 2) { + ret = -ENODEV; + goto err_pkt; + } + + tmp = le16_to_cpu(uif->altsetting[i].endpoint[1].desc. wMaxPacketSize); usbvision->alt_max_pkt_size[i] = (tmp & 0x07ff) * (((tmp & 0x1800) >> 11) + 1); From c71b5040632f90131e62ecdc83063179cc2ae7af Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 7 Mar 2017 15:14:13 -0300 Subject: [PATCH 309/396] mceusb: fix NULL-deref at probe commit 03eb2a557ed552e920a0942b774aaf931596eec1 upstream. Make sure to check for the required out endpoint to avoid dereferencing a NULL-pointer in mce_request_packet should a malicious device lack such an endpoint. Note that this path is hit during probe. Fixes: 66e89522aff7 ("V4L/DVB: IR: add mceusb IR receiver driver") Signed-off-by: Johan Hovold Signed-off-by: Sean Young Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Greg Kroah-Hartman --- drivers/media/rc/mceusb.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/media/rc/mceusb.c b/drivers/media/rc/mceusb.c index 4f8c7effdcee..db525cdfac88 100644 --- a/drivers/media/rc/mceusb.c +++ b/drivers/media/rc/mceusb.c @@ -1332,8 +1332,8 @@ static int mceusb_dev_probe(struct usb_interface *intf, } } } - if (ep_in == NULL) { - dev_dbg(&intf->dev, "inbound and/or endpoint not found"); + if (!ep_in || !ep_out) { + dev_dbg(&intf->dev, "required endpoints not found\n"); return -ENODEV; } From 4f93054d9b45857cc68bb7f5e8010e086be656ce Mon Sep 17 00:00:00 2001 From: Alyssa Milburn Date: Sat, 1 Apr 2017 14:34:32 -0300 Subject: [PATCH 310/396] ttusb2: limit messages to buffer size commit a12b8ab8c5ff7ccd7b107a564743507c850a441d upstream. Otherwise ttusb2_i2c_xfer can read or write beyond the end of static and heap buffers. Signed-off-by: Alyssa Milburn Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Greg Kroah-Hartman --- drivers/media/usb/dvb-usb/ttusb2.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/drivers/media/usb/dvb-usb/ttusb2.c b/drivers/media/usb/dvb-usb/ttusb2.c index ecc207fbaf3c..9e0d6a4166d2 100644 --- a/drivers/media/usb/dvb-usb/ttusb2.c +++ b/drivers/media/usb/dvb-usb/ttusb2.c @@ -78,6 +78,9 @@ static int ttusb2_msg(struct dvb_usb_device *d, u8 cmd, u8 *s, *r = NULL; int ret = 0; + if (4 + rlen > 64) + return -EIO; + s = kzalloc(wlen+4, GFP_KERNEL); if (!s) return -ENOMEM; @@ -381,6 +384,22 @@ static int ttusb2_i2c_xfer(struct i2c_adapter *adap,struct i2c_msg msg[],int num write_read = i+1 < num && (msg[i+1].flags & I2C_M_RD); read = msg[i].flags & I2C_M_RD; + if (3 + msg[i].len > sizeof(obuf)) { + err("i2c wr len=%d too high", msg[i].len); + break; + } + if (write_read) { + if (3 + msg[i+1].len > sizeof(ibuf)) { + err("i2c rd len=%d too high", msg[i+1].len); + break; + } + } else if (read) { + if (3 + msg[i].len > sizeof(ibuf)) { + err("i2c rd len=%d too high", msg[i].len); + break; + } + } + obuf[0] = (msg[i].addr << 1) | (write_read | read); if (read) obuf[1] = 0; From 653cd31a2ca536915dd7e4f68e37d36069f9627a Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Fri, 17 Feb 2017 22:30:51 -0200 Subject: [PATCH 311/396] dvb-usb-dibusb-mc-common: Add MODULE_LICENSE commit bf05b65a9fe5f6a6dd3e72cab2aacd8b5b96e41d upstream. dvb-usb-dibusb-mc-common is licensed under GPLv2, and if we don't say so then it won't even load since it needs a GPL-only symbol. Fixes: e91455a1495a ("[media] dvb-usb: split out common parts of dibusb") Reported-by: Dominique Dumont Signed-off-by: Ben Hutchings Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Greg Kroah-Hartman --- drivers/media/usb/dvb-usb/dibusb-mc-common.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/media/usb/dvb-usb/dibusb-mc-common.c b/drivers/media/usb/dvb-usb/dibusb-mc-common.c index d66f56cc46a5..1f7bce64777f 100644 --- a/drivers/media/usb/dvb-usb/dibusb-mc-common.c +++ b/drivers/media/usb/dvb-usb/dibusb-mc-common.c @@ -12,6 +12,8 @@ #include #include "dibusb.h" +MODULE_LICENSE("GPL"); + /* 3000MC/P stuff */ // Config Adjacent channels Perf -cal22 static struct dibx000_agc_config dib3000p_mt2060_agc_config = { From ff9177b158c3cf1420846d1114aec4e2b1cb76e5 Mon Sep 17 00:00:00 2001 From: Thinh Nguyen Date: Thu, 11 May 2017 17:26:47 -0700 Subject: [PATCH 312/396] usb: dwc3: gadget: Prevent losing events in event cache commit d325a1de49d61ee11aca58a529571c91ecea7879 upstream. The dwc3 driver can overwite its previous events if its top-half IRQ handler (TH) gets invoked again before processing the events in the cache. We see this as a hang in the file transfer and the host will attempt to reset the device. TH gets the event count and deasserts the interrupt line by writing DWC3_GEVNTSIZ_INTMASK to DWC3_GEVNTSIZ. If there's a new event coming between reading the event count and interrupt deassertion, dwc3 will lose previous pending events. More generally, we will see 0 event count, which should not affect anything. This shouldn't be possible in the current dwc3 implementation. However, through testing and reading the PCIe trace, the TH occasionally still gets invoked one more time after HW interrupt deassertion. (With PCIe legacy interrupts, TH is called repeatedly as long as the interrupt line is asserted). We suspect that there is a small detection delay in the SW. To avoid this issue, Check DWC3_EVENT_PENDING flag to determine if the events are processed in the bottom-half IRQ handler. If not, return IRQ_HANDLED and don't process new event. Signed-off-by: Thinh Nguyen Signed-off-by: Felipe Balbi Signed-off-by: Greg Kroah-Hartman --- drivers/usb/dwc3/gadget.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index ce603dcbd493..a7e28095026d 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -2856,6 +2856,15 @@ static irqreturn_t dwc3_check_event_buf(struct dwc3_event_buffer *evt) return IRQ_HANDLED; } + /* + * With PCIe legacy interrupt, test shows that top-half irq handler can + * be called again after HW interrupt deassertion. Check if bottom-half + * irq event handler completes before caching new event to prevent + * losing events. + */ + if (evt->flags & DWC3_EVENT_PENDING) + return IRQ_HANDLED; + count = dwc3_readl(dwc->regs, DWC3_GEVNTCOUNT(0)); count &= DWC3_GEVNTCOUNT_MASK; if (!count) From 08c735a15d5b420879cd096b6c417837e1dbe8fa Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Wed, 17 May 2017 11:23:11 -0500 Subject: [PATCH 313/396] usb: musb: tusb6010_omap: Do not reset the other direction's packet size commit 6df2b42f7c040d57d9ecb67244e04e905ab87ac6 upstream. We have one register for each EP to set the maximum packet size for both TX and RX. If for example an RX programming would happen before the previous TX transfer finishes we would reset the TX packet side. To fix this issue, only modify the TX or RX part of the register. Fixes: 550a7375fe72 ("USB: Add MUSB and TUSB support") Signed-off-by: Peter Ujfalusi Tested-by: Tony Lindgren Signed-off-by: Bin Liu Signed-off-by: Greg Kroah-Hartman --- drivers/usb/musb/tusb6010_omap.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/drivers/usb/musb/tusb6010_omap.c b/drivers/usb/musb/tusb6010_omap.c index e6959ccb4453..404742672658 100644 --- a/drivers/usb/musb/tusb6010_omap.c +++ b/drivers/usb/musb/tusb6010_omap.c @@ -220,6 +220,7 @@ static int tusb_omap_dma_program(struct dma_channel *channel, u16 packet_sz, u32 dma_remaining; int src_burst, dst_burst; u16 csr; + u32 psize; int ch; s8 dmareq; s8 sync_dev; @@ -391,15 +392,19 @@ static int tusb_omap_dma_program(struct dma_channel *channel, u16 packet_sz, if (chdat->tx) { /* Send transfer_packet_sz packets at a time */ - musb_writel(ep_conf, TUSB_EP_MAX_PACKET_SIZE_OFFSET, - chdat->transfer_packet_sz); + psize = musb_readl(ep_conf, TUSB_EP_MAX_PACKET_SIZE_OFFSET); + psize &= ~0x7ff; + psize |= chdat->transfer_packet_sz; + musb_writel(ep_conf, TUSB_EP_MAX_PACKET_SIZE_OFFSET, psize); musb_writel(ep_conf, TUSB_EP_TX_OFFSET, TUSB_EP_CONFIG_XFR_SIZE(chdat->transfer_len)); } else { /* Receive transfer_packet_sz packets at a time */ - musb_writel(ep_conf, TUSB_EP_MAX_PACKET_SIZE_OFFSET, - chdat->transfer_packet_sz << 16); + psize = musb_readl(ep_conf, TUSB_EP_MAX_PACKET_SIZE_OFFSET); + psize &= ~(0x7ff << 16); + psize |= (chdat->transfer_packet_sz << 16); + musb_writel(ep_conf, TUSB_EP_MAX_PACKET_SIZE_OFFSET, psize); musb_writel(ep_conf, TUSB_EP_RX_OFFSET, TUSB_EP_CONFIG_XFR_SIZE(chdat->transfer_len)); From dbb127332abf38e6df266b9cabee7d73ef6ea6da Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Wed, 17 May 2017 11:23:10 -0500 Subject: [PATCH 314/396] usb: musb: Fix trying to suspend while active for OTG configurations commit 3c50ffef25855a9d9e4b07b02d756a8cdd653069 upstream. Commit d8e5f0eca1e8 ("usb: musb: Fix hardirq-safe hardirq-unsafe lock order error") caused a regression where musb keeps trying to enable host mode with no cable connected. This seems to be caused by the fact that now phy is enabled earlier, and we are wrongly trying to force USB host mode on an OTG port. The errors we are getting are "trying to suspend as a_idle while active". For ports configured as OTG, we should not need to do anything to try to force USB host mode on it's OTG port. Trying to force host mode in this case just seems to completely confuse the musb state machine. Let's fix the issue by making musb_host_setup() attempt to force the mode only if port_mode is configured for host mode. Fixes: d8e5f0eca1e8 ("usb: musb: Fix hardirq-safe hardirq-unsafe lock order error") Cc: Johan Hovold Reported-by: Laurent Pinchart Reported-by: Peter Ujfalusi Tested-by: Peter Ujfalusi Signed-off-by: Tony Lindgren Signed-off-by: Bin Liu Signed-off-by: Greg Kroah-Hartman --- drivers/usb/musb/musb_host.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c index 806451418cfe..99beda9e241d 100644 --- a/drivers/usb/musb/musb_host.c +++ b/drivers/usb/musb/musb_host.c @@ -2780,10 +2780,11 @@ int musb_host_setup(struct musb *musb, int power_budget) int ret; struct usb_hcd *hcd = musb->hcd; - MUSB_HST_MODE(musb); - musb->xceiv->otg->default_a = 1; - musb->xceiv->otg->state = OTG_STATE_A_IDLE; - + if (musb->port_mode == MUSB_PORT_MODE_HOST) { + MUSB_HST_MODE(musb); + musb->xceiv->otg->default_a = 1; + musb->xceiv->otg->state = OTG_STATE_A_IDLE; + } otg_set_host(musb->xceiv->otg, &hcd->self); hcd->self.otg_port = 1; musb->xceiv->otg->host = &hcd->self; From ee0f3a89842ea7adab3f42d08d98f77f13fa0357 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 11 May 2017 11:36:02 +0200 Subject: [PATCH 315/396] USB: iowarrior: fix info ioctl on big-endian hosts commit dd5ca753fa92fb736b1395db892bd29f78e6d408 upstream. Drop erroneous le16_to_cpu when returning the USB device speed which is already in host byte order. Found using sparse: warning: cast to restricted __le16 Fixes: 946b960d13c1 ("USB: add driver for iowarrior devices.") Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/misc/iowarrior.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/misc/iowarrior.c b/drivers/usb/misc/iowarrior.c index 37c63cb39714..0ef29d202263 100644 --- a/drivers/usb/misc/iowarrior.c +++ b/drivers/usb/misc/iowarrior.c @@ -554,7 +554,7 @@ static long iowarrior_ioctl(struct file *file, unsigned int cmd, info.revision = le16_to_cpu(dev->udev->descriptor.bcdDevice); /* 0==UNKNOWN, 1==LOW(usb1.1) ,2=FULL(usb1.1), 3=HIGH(usb2.0) */ - info.speed = le16_to_cpu(dev->udev->speed); + info.speed = dev->udev->speed; info.if_num = dev->interface->cur_altsetting->desc.bInterfaceNumber; info.report_size = dev->report_size; From 7e5407600663fd7612a46a787063e09c99fc5be6 Mon Sep 17 00:00:00 2001 From: Daniele Palmas Date: Wed, 3 May 2017 10:28:54 +0200 Subject: [PATCH 316/396] usb: serial: option: add Telit ME910 support commit 40dd46048c155b8f0683f468c950a1c107f77a7c upstream. This patch adds support for Telit ME910 PID 0x1100. Signed-off-by: Daniele Palmas Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/option.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index af67a0de6b5d..3bf61acfc26b 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -281,6 +281,7 @@ static void option_instat_callback(struct urb *urb); #define TELIT_PRODUCT_LE922_USBCFG0 0x1042 #define TELIT_PRODUCT_LE922_USBCFG3 0x1043 #define TELIT_PRODUCT_LE922_USBCFG5 0x1045 +#define TELIT_PRODUCT_ME910 0x1100 #define TELIT_PRODUCT_LE920 0x1200 #define TELIT_PRODUCT_LE910 0x1201 #define TELIT_PRODUCT_LE910_USBCFG4 0x1206 @@ -640,6 +641,11 @@ static const struct option_blacklist_info simcom_sim7100e_blacklist = { .reserved = BIT(5) | BIT(6), }; +static const struct option_blacklist_info telit_me910_blacklist = { + .sendsetup = BIT(0), + .reserved = BIT(1) | BIT(3), +}; + static const struct option_blacklist_info telit_le910_blacklist = { .sendsetup = BIT(0), .reserved = BIT(1) | BIT(2), @@ -1235,6 +1241,8 @@ static const struct usb_device_id option_ids[] = { .driver_info = (kernel_ulong_t)&telit_le922_blacklist_usbcfg3 }, { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, TELIT_PRODUCT_LE922_USBCFG5, 0xff), .driver_info = (kernel_ulong_t)&telit_le922_blacklist_usbcfg0 }, + { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_ME910), + .driver_info = (kernel_ulong_t)&telit_me910_blacklist }, { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_LE910), .driver_info = (kernel_ulong_t)&telit_le910_blacklist }, { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_LE910_USBCFG4), From d8fc44d6748862d70d716c2cadd294660563e74e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Mork?= Date: Wed, 17 May 2017 16:30:50 +0200 Subject: [PATCH 317/396] USB: serial: qcserial: add more Lenovo EM74xx device IDs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 8d7a10dd323993cc40bd37bce8bc570133b0c396 upstream. In their infinite wisdom, and never ending quest for end user frustration, Lenovo has decided to use new USB device IDs for the wwan modules in their 2017 laptops. The actual hardware is still the Sierra Wireless EM7455 or EM7430, depending on region. Signed-off-by: Bjørn Mork Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/qcserial.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/usb/serial/qcserial.c b/drivers/usb/serial/qcserial.c index 38b3f0d8cd58..fd509ed6cf70 100644 --- a/drivers/usb/serial/qcserial.c +++ b/drivers/usb/serial/qcserial.c @@ -162,6 +162,8 @@ static const struct usb_device_id id_table[] = { {DEVICE_SWI(0x1199, 0x9071)}, /* Sierra Wireless MC74xx */ {DEVICE_SWI(0x1199, 0x9078)}, /* Sierra Wireless EM74xx */ {DEVICE_SWI(0x1199, 0x9079)}, /* Sierra Wireless EM74xx */ + {DEVICE_SWI(0x1199, 0x907a)}, /* Sierra Wireless EM74xx QDL */ + {DEVICE_SWI(0x1199, 0x907b)}, /* Sierra Wireless EM74xx */ {DEVICE_SWI(0x413c, 0x81a2)}, /* Dell Wireless 5806 Gobi(TM) 4G LTE Mobile Broadband Card */ {DEVICE_SWI(0x413c, 0x81a3)}, /* Dell Wireless 5570 HSPA+ (42Mbps) Mobile Broadband Card */ {DEVICE_SWI(0x413c, 0x81a4)}, /* Dell Wireless 5570e HSPA+ (42Mbps) Mobile Broadband Card */ From c3e024ff91806856059c2fad64ad535bf6bf37eb Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 11 May 2017 11:41:20 +0200 Subject: [PATCH 318/396] USB: serial: mct_u232: fix big-endian baud-rate handling commit 26cede343656c0bc2c33cdc783771282405c7fb2 upstream. Drop erroneous cpu_to_le32 when setting the baud rate, something which corrupted the divisor on big-endian hosts. Found using sparse: warning: incorrect type in argument 1 (different base types) expected unsigned int [unsigned] [usertype] val got restricted __le32 [usertype] Fixes: af2ac1a091bc ("USB: serial mct_usb232: move DMA buffers to heap") Reviewed-by: Greg Kroah-Hartman Acked-By: Pete Zaitcev Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/mct_u232.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/serial/mct_u232.c b/drivers/usb/serial/mct_u232.c index edbc81f205c2..70f346f1aa86 100644 --- a/drivers/usb/serial/mct_u232.c +++ b/drivers/usb/serial/mct_u232.c @@ -189,7 +189,7 @@ static int mct_u232_set_baud_rate(struct tty_struct *tty, return -ENOMEM; divisor = mct_u232_calculate_baud_rate(serial, value, &speed); - put_unaligned_le32(cpu_to_le32(divisor), buf); + put_unaligned_le32(divisor, buf); rc = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), MCT_U232_SET_BAUD_RATE_REQUEST, MCT_U232_SET_REQUEST_TYPE, From f9cd79e0ad1fa620ff34715d24ae1b671c97bc91 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 11 May 2017 11:41:21 +0200 Subject: [PATCH 319/396] USB: serial: io_ti: fix div-by-zero in set_termios commit 6aeb75e6adfaed16e58780309613a578fe1ee90b upstream. Fix a division-by-zero in set_termios when debugging is enabled and a high-enough speed has been requested so that the divisor value becomes zero. Instead of just fixing the offending debug statement, cap the baud rate at the base as a zero divisor value also appears to crash the firmware. Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") Reviewed-by: Greg Kroah-Hartman Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/io_ti.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/usb/serial/io_ti.c b/drivers/usb/serial/io_ti.c index f1a8fdcd8674..e98532feb0cc 100644 --- a/drivers/usb/serial/io_ti.c +++ b/drivers/usb/serial/io_ti.c @@ -2349,8 +2349,11 @@ static void change_port_settings(struct tty_struct *tty, if (!baud) { /* pick a default, any default... */ baud = 9600; - } else + } else { + /* Avoid a zero divisor. */ + baud = min(baud, 461550); tty_encode_baud_rate(tty, baud, baud); + } edge_port->baud_rate = baud; config->wBaudRate = (__u16)((461550L + baud/2) / baud); From 3e4a4e68df087008be9686a9d5cefd90d5341587 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 10 May 2017 18:18:27 +0200 Subject: [PATCH 320/396] USB: hub: fix SS hub-descriptor handling commit 2c25a2c818023df64463aac3288a9f969491e507 upstream. A SuperSpeed hub descriptor does not have any variable-length fields so bail out when reading a short descriptor. This avoids parsing and leaking two bytes of uninitialised slab data through sysfs removable-attributes. Fixes: dbe79bbe9dcb ("USB 3.0 Hub Changes") Cc: John Youn Acked-by: Alan Stern Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/hub.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 579900640faa..8c59bc857a4b 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -378,8 +378,12 @@ static int get_hub_descriptor(struct usb_device *hdev, void *data) USB_REQ_GET_DESCRIPTOR, USB_DIR_IN | USB_RT_HUB, dtype << 8, 0, data, size, USB_CTRL_GET_TIMEOUT); - if (ret >= (USB_DT_HUB_NONVAR_SIZE + 2)) + if (hub_is_superspeed(hdev)) { + if (ret == size) + return ret; + } else if (ret >= (USB_DT_HUB_NONVAR_SIZE + 2)) { return ret; + } } return -EINVAL; } @@ -1319,7 +1323,7 @@ static int hub_configure(struct usb_hub *hub, /* Request the entire hub descriptor. * hub->descriptor can handle USB_MAXCHILDREN ports, - * but the hub can/will return fewer bytes here. + * but a (non-SS) hub can/will return fewer bytes here. */ ret = get_hub_descriptor(hdev, hub->descriptor); if (ret < 0) { From c67e87a22dd8b39ea1c9864336f7c17175053744 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 10 May 2017 18:18:28 +0200 Subject: [PATCH 321/396] USB: hub: fix non-SS hub-descriptor handling commit bec444cd1c94c48df409a35ad4e5b143c245c3f7 upstream. Add missing sanity check on the non-SuperSpeed hub-descriptor length in order to avoid parsing and leaking two bytes of uninitialised slab data through sysfs removable-attributes (or a compound-device debug statement). Note that we only make sure that the DeviceRemovable field is always present (and specifically ignore the unused PortPwrCtrlMask field) in order to continue support any hubs with non-compliant descriptors. As a further safeguard, the descriptor buffer is also cleared. Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") Signed-off-by: Johan Hovold Acked-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/hub.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 8c59bc857a4b..8714b352e57f 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -360,7 +360,8 @@ static void usb_set_lpm_parameters(struct usb_device *udev) } /* USB 2.0 spec Section 11.24.4.5 */ -static int get_hub_descriptor(struct usb_device *hdev, void *data) +static int get_hub_descriptor(struct usb_device *hdev, + struct usb_hub_descriptor *desc) { int i, ret, size; unsigned dtype; @@ -376,12 +377,16 @@ static int get_hub_descriptor(struct usb_device *hdev, void *data) for (i = 0; i < 3; i++) { ret = usb_control_msg(hdev, usb_rcvctrlpipe(hdev, 0), USB_REQ_GET_DESCRIPTOR, USB_DIR_IN | USB_RT_HUB, - dtype << 8, 0, data, size, + dtype << 8, 0, desc, size, USB_CTRL_GET_TIMEOUT); if (hub_is_superspeed(hdev)) { if (ret == size) return ret; - } else if (ret >= (USB_DT_HUB_NONVAR_SIZE + 2)) { + } else if (ret >= USB_DT_HUB_NONVAR_SIZE + 2) { + /* Make sure we have the DeviceRemovable field. */ + size = USB_DT_HUB_NONVAR_SIZE + desc->bNbrPorts / 8 + 1; + if (ret < size) + return -EMSGSIZE; return ret; } } @@ -1315,7 +1320,7 @@ static int hub_configure(struct usb_hub *hub, } mutex_init(&hub->status_mutex); - hub->descriptor = kmalloc(sizeof(*hub->descriptor), GFP_KERNEL); + hub->descriptor = kzalloc(sizeof(*hub->descriptor), GFP_KERNEL); if (!hub->descriptor) { ret = -ENOMEM; goto fail; From 820adccd0e3be9bdd2384ca8fc4712108cfdf28b Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Tue, 2 May 2017 13:58:53 +0300 Subject: [PATCH 322/396] ipx: call ipxitf_put() in ioctl error path MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit ee0d8d8482345ff97a75a7d747efc309f13b0d80 upstream. We should call ipxitf_put() if the copy_to_user() fails. Reported-by: 李强 Signed-off-by: Dan Carpenter Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/ipx/af_ipx.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/net/ipx/af_ipx.c b/net/ipx/af_ipx.c index 48d0dc89b58d..e735f781e4f3 100644 --- a/net/ipx/af_ipx.c +++ b/net/ipx/af_ipx.c @@ -1168,11 +1168,10 @@ static int ipxitf_ioctl(unsigned int cmd, void __user *arg) sipx->sipx_network = ipxif->if_netnum; memcpy(sipx->sipx_node, ipxif->if_node, sizeof(sipx->sipx_node)); - rc = -EFAULT; - if (copy_to_user(arg, &ifr, sizeof(ifr))) - break; - ipxitf_put(ipxif); rc = 0; + if (copy_to_user(arg, &ifr, sizeof(ifr))) + rc = -EFAULT; + ipxitf_put(ipxif); break; } case SIOCAIPXITFCRT: From a99462b13dff9de2aa7941aaad8b4ed10edbb629 Mon Sep 17 00:00:00 2001 From: Matt Ranostay Date: Thu, 13 Apr 2017 23:21:56 -0700 Subject: [PATCH 323/396] iio: proximity: as3935: fix as3935_write commit 84ca8e364acb26aba3292bc113ca8ed4335380fd upstream. AS3935_WRITE_DATA macro bit is incorrect and the actual write sequence is two leading zeros. Cc: George McCollister Signed-off-by: Matt Ranostay Signed-off-by: Jonathan Cameron Signed-off-by: Greg Kroah-Hartman --- drivers/iio/proximity/as3935.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/iio/proximity/as3935.c b/drivers/iio/proximity/as3935.c index 5656deb17261..020459513384 100644 --- a/drivers/iio/proximity/as3935.c +++ b/drivers/iio/proximity/as3935.c @@ -50,7 +50,6 @@ #define AS3935_TUNE_CAP 0x08 #define AS3935_CALIBRATE 0x3D -#define AS3935_WRITE_DATA BIT(15) #define AS3935_READ_DATA BIT(14) #define AS3935_ADDRESS(x) ((x) << 8) @@ -105,7 +104,7 @@ static int as3935_write(struct as3935_state *st, { u8 *buf = st->buf; - buf[0] = (AS3935_WRITE_DATA | AS3935_ADDRESS(reg)) >> 8; + buf[0] = AS3935_ADDRESS(reg) >> 8; buf[1] = val; return spi_write(st->spi, buf, 2); From 6bee0b1fe4eda64055cbf48a556fd77211f63078 Mon Sep 17 00:00:00 2001 From: Srinivas Pandruvada Date: Fri, 7 Apr 2017 17:13:17 -0700 Subject: [PATCH 324/396] iio: hid-sensor: Store restore poll and hysteresis on S3 commit 5d9854eaea776441b38a9a45b4e6879524c4f48c upstream. This change undo the change done by 'commit 3bec24747446 ("iio: hid-sensor-trigger: Change get poll value function order to avoid sensor properties losing after resume from S3")' as this breaks some USB/i2c sensor hubs. Instead of relying on HW for restoring poll and hysteresis, driver stores and restores on resume (S3). In this way user space modified settings are not lost for any kind of sensor hub behavior. In this change, whenever user space modifies sampling frequency or hysteresis driver will get the feature value from the hub and store in the per device hid_sensor_common data structure. On resume callback from S3, system will set the feature to sensor hub, if user space ever modified the feature value. Fixes: 3bec24747446 ("iio: hid-sensor-trigger: Change get poll value function order to avoid sensor properties losing after resume from S3") Reported-by: Ritesh Raj Sarraf Tested-by: Ritesh Raj Sarraf Tested-by: Song, Hongyan Signed-off-by: Srinivas Pandruvada Signed-off-by: Jonathan Cameron Signed-off-by: Greg Kroah-Hartman --- .../hid-sensors/hid-sensor-attributes.c | 26 +++++++++++++++++-- .../common/hid-sensors/hid-sensor-trigger.c | 20 +++++++++++--- include/linux/hid-sensor-hub.h | 2 ++ 3 files changed, 43 insertions(+), 5 deletions(-) diff --git a/drivers/iio/common/hid-sensors/hid-sensor-attributes.c b/drivers/iio/common/hid-sensors/hid-sensor-attributes.c index b5beea53d6f6..ab646a90e3da 100644 --- a/drivers/iio/common/hid-sensors/hid-sensor-attributes.c +++ b/drivers/iio/common/hid-sensors/hid-sensor-attributes.c @@ -217,7 +217,15 @@ int hid_sensor_write_samp_freq_value(struct hid_sensor_common *st, if (ret < 0 || value < 0) ret = -EINVAL; - return ret; + ret = sensor_hub_get_feature(st->hsdev, + st->poll.report_id, + st->poll.index, sizeof(value), &value); + if (ret < 0 || value < 0) + return -EINVAL; + + st->poll_interval = value; + + return 0; } EXPORT_SYMBOL(hid_sensor_write_samp_freq_value); @@ -259,7 +267,16 @@ int hid_sensor_write_raw_hyst_value(struct hid_sensor_common *st, if (ret < 0 || value < 0) ret = -EINVAL; - return ret; + ret = sensor_hub_get_feature(st->hsdev, + st->sensitivity.report_id, + st->sensitivity.index, sizeof(value), + &value); + if (ret < 0 || value < 0) + return -EINVAL; + + st->raw_hystersis = value; + + return 0; } EXPORT_SYMBOL(hid_sensor_write_raw_hyst_value); @@ -355,6 +372,9 @@ int hid_sensor_get_reporting_interval(struct hid_sensor_hub_device *hsdev, /* Default unit of measure is milliseconds */ if (st->poll.units == 0) st->poll.units = HID_USAGE_SENSOR_UNITS_MILLISECOND; + + st->poll_interval = -1; + return 0; } @@ -377,6 +397,8 @@ int hid_sensor_parse_common_attributes(struct hid_sensor_hub_device *hsdev, HID_USAGE_SENSOR_PROY_POWER_STATE, &st->power_state); + st->raw_hystersis = -1; + sensor_hub_input_get_attribute_info(hsdev, HID_FEATURE_REPORT, usage_id, HID_USAGE_SENSOR_PROP_SENSITIVITY_ABS, diff --git a/drivers/iio/common/hid-sensors/hid-sensor-trigger.c b/drivers/iio/common/hid-sensors/hid-sensor-trigger.c index ecf592d69043..60829340a82e 100644 --- a/drivers/iio/common/hid-sensors/hid-sensor-trigger.c +++ b/drivers/iio/common/hid-sensors/hid-sensor-trigger.c @@ -51,6 +51,8 @@ static int _hid_sensor_power_state(struct hid_sensor_common *st, bool state) st->report_state.report_id, st->report_state.index, HID_USAGE_SENSOR_PROP_REPORTING_STATE_ALL_EVENTS_ENUM); + + poll_value = hid_sensor_read_poll_value(st); } else { int val; @@ -87,9 +89,7 @@ static int _hid_sensor_power_state(struct hid_sensor_common *st, bool state) sensor_hub_get_feature(st->hsdev, st->power_state.report_id, st->power_state.index, sizeof(state_val), &state_val); - if (state) - poll_value = hid_sensor_read_poll_value(st); - if (poll_value > 0) + if (state && poll_value) msleep_interruptible(poll_value * 2); return 0; @@ -127,6 +127,20 @@ static void hid_sensor_set_power_work(struct work_struct *work) struct hid_sensor_common *attrb = container_of(work, struct hid_sensor_common, work); + + if (attrb->poll_interval >= 0) + sensor_hub_set_feature(attrb->hsdev, attrb->poll.report_id, + attrb->poll.index, + sizeof(attrb->poll_interval), + &attrb->poll_interval); + + if (attrb->raw_hystersis >= 0) + sensor_hub_set_feature(attrb->hsdev, + attrb->sensitivity.report_id, + attrb->sensitivity.index, + sizeof(attrb->raw_hystersis), + &attrb->raw_hystersis); + _hid_sensor_power_state(attrb, true); } diff --git a/include/linux/hid-sensor-hub.h b/include/linux/hid-sensor-hub.h index dd85f3503410..039e6ababb67 100644 --- a/include/linux/hid-sensor-hub.h +++ b/include/linux/hid-sensor-hub.h @@ -231,6 +231,8 @@ struct hid_sensor_common { unsigned usage_id; atomic_t data_ready; atomic_t user_requested_state; + int poll_interval; + int raw_hystersis; struct iio_trigger *trigger; struct hid_sensor_hub_attribute_info poll; struct hid_sensor_hub_attribute_info report_state; From e2f95f88106f32b1e82898d0a2a757366e2cbc5f Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Thu, 23 Feb 2017 08:43:27 -0300 Subject: [PATCH 325/396] s5p-mfc: Fix race between interrupt routine and device functions commit 0c32b8ec02832df167e16ad659cb11dc148f2ddf upstream. Interrupt routine must wake process waiting for given interrupt AFTER updating driver's internal structures and contexts. Doing it in-between is a serious bug. This patch moves all calls to the wake() function to the end of the interrupt processing block to avoid potential and real races, especially on multi-core platforms. This also fixes following issue reported from clock core (clocks were disabled in interrupt after being unprepared from the other place in the driver, the stack trace however points to the different place than s5p_mfc driver because of the race): WARNING: CPU: 1 PID: 18 at drivers/clk/clk.c:544 clk_core_unprepare+0xc8/0x108 Modules linked in: CPU: 1 PID: 18 Comm: kworker/1:0 Not tainted 4.10.0-next-20170223-00070-g04e18bc99ab9-dirty #2154 Hardware name: SAMSUNG EXYNOS (Flattened Device Tree) Workqueue: pm pm_runtime_work [] (unwind_backtrace) from [] (show_stack+0x10/0x14) [] (show_stack) from [] (dump_stack+0x74/0x94) [] (dump_stack) from [] (__warn+0xd4/0x100) [] (__warn) from [] (warn_slowpath_null+0x20/0x28) [] (warn_slowpath_null) from [] (clk_core_unprepare+0xc8/0x108) [] (clk_core_unprepare) from [] (clk_unprepare+0x24/0x2c) [] (clk_unprepare) from [] (exynos_sysmmu_suspend+0x48/0x60) [] (exynos_sysmmu_suspend) from [] (pm_generic_runtime_suspend+0x2c/0x38) [] (pm_generic_runtime_suspend) from [] (genpd_runtime_suspend+0x94/0x220) [] (genpd_runtime_suspend) from [] (__rpm_callback+0x134/0x208) [] (__rpm_callback) from [] (rpm_callback+0x20/0x80) [] (rpm_callback) from [] (rpm_suspend+0xdc/0x458) [] (rpm_suspend) from [] (pm_runtime_work+0x80/0x90) [] (pm_runtime_work) from [] (process_one_work+0x120/0x318) [] (process_one_work) from [] (worker_thread+0x2c/0x4ac) [] (worker_thread) from [] (kthread+0xfc/0x134) [] (kthread) from [] (ret_from_fork+0x14/0x3c) ---[ end trace 1ead49a7bb83f0d8 ]--- Fixes: af93574678108 ("[media] MFC: Add MFC 5.1 V4L2 driver") Signed-off-by: Marek Szyprowski Reviewed-by: Javier Martinez Canillas Signed-off-by: Sylwester Nawrocki Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Greg Kroah-Hartman --- drivers/media/platform/s5p-mfc/s5p_mfc.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc.c b/drivers/media/platform/s5p-mfc/s5p_mfc.c index 27e7cf65c2a7..d566b918c600 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc.c @@ -663,9 +663,9 @@ static irqreturn_t s5p_mfc_irq(int irq, void *priv) break; } s5p_mfc_hw_call(dev->mfc_ops, clear_int_flags, dev); - wake_up_ctx(ctx, reason, err); WARN_ON(test_and_clear_bit(0, &dev->hw_lock) == 0); s5p_mfc_clock_off(); + wake_up_ctx(ctx, reason, err); s5p_mfc_hw_call(dev->mfc_ops, try_run, dev); } else { s5p_mfc_handle_frame(ctx, reason, err); @@ -679,15 +679,11 @@ static irqreturn_t s5p_mfc_irq(int irq, void *priv) case S5P_MFC_R2H_CMD_OPEN_INSTANCE_RET: ctx->inst_no = s5p_mfc_hw_call(dev->mfc_ops, get_inst_no, dev); ctx->state = MFCINST_GOT_INST; - clear_work_bit(ctx); - wake_up(&ctx->queue); goto irq_cleanup_hw; case S5P_MFC_R2H_CMD_CLOSE_INSTANCE_RET: - clear_work_bit(ctx); ctx->inst_no = MFC_NO_INSTANCE_SET; ctx->state = MFCINST_FREE; - wake_up(&ctx->queue); goto irq_cleanup_hw; case S5P_MFC_R2H_CMD_SYS_INIT_RET: @@ -697,9 +693,9 @@ static irqreturn_t s5p_mfc_irq(int irq, void *priv) if (ctx) clear_work_bit(ctx); s5p_mfc_hw_call(dev->mfc_ops, clear_int_flags, dev); - wake_up_dev(dev, reason, err); clear_bit(0, &dev->hw_lock); clear_bit(0, &dev->enter_suspend); + wake_up_dev(dev, reason, err); break; case S5P_MFC_R2H_CMD_INIT_BUFFERS_RET: @@ -714,9 +710,7 @@ static irqreturn_t s5p_mfc_irq(int irq, void *priv) break; case S5P_MFC_R2H_CMD_DPB_FLUSH_RET: - clear_work_bit(ctx); ctx->state = MFCINST_RUNNING; - wake_up(&ctx->queue); goto irq_cleanup_hw; default: @@ -735,6 +729,8 @@ irq_cleanup_hw: mfc_err("Failed to unlock hw\n"); s5p_mfc_clock_off(); + clear_work_bit(ctx); + wake_up(&ctx->queue); s5p_mfc_hw_call(dev->mfc_ops, try_run, dev); spin_unlock(&dev->irqlock); From 4a9c54250492a1a8c5fa62885c7f3dcd3eefb76b Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Mon, 13 Mar 2017 09:53:59 -0300 Subject: [PATCH 326/396] gspca: konica: add missing endpoint sanity check commit aa58fedb8c7b6cf2f05941d238495f9e2f29655c upstream. Make sure to check the number of endpoints to avoid accessing memory beyond the endpoint array should a device lack the expected endpoints. Note that, as far as I can tell, the gspca framework has already made sure there is at least one endpoint in the current alternate setting so there should be no risk for a NULL-pointer dereference here. Fixes: b517af722860 ("V4L/DVB: gspca_konica: New gspca subdriver for konica chipset using cams") Cc: Hans de Goede Signed-off-by: Johan Hovold Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Greg Kroah-Hartman --- drivers/media/usb/gspca/konica.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/media/usb/gspca/konica.c b/drivers/media/usb/gspca/konica.c index 40aaaa9c5f30..78542fff403f 100644 --- a/drivers/media/usb/gspca/konica.c +++ b/drivers/media/usb/gspca/konica.c @@ -188,6 +188,9 @@ static int sd_start(struct gspca_dev *gspca_dev) return -EIO; } + if (alt->desc.bNumEndpoints < 2) + return -ENODEV; + packet_size = le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize); n = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv; From 074912daab5584e79e3e8d8291f4cc33b14ac9d3 Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Wed, 22 Mar 2017 04:53:57 -0300 Subject: [PATCH 327/396] s5p-mfc: Fix unbalanced call to clock management commit a5cb00eb4223458250b55daf03ac7ea5f424d601 upstream. Clock should be turned off after calling s5p_mfc_init_hw() from the watchdog worker, like it is already done in the s5p_mfc_open() which also calls this function. Fixes: af93574678108 ("[media] MFC: Add MFC 5.1 V4L2 driver") Signed-off-by: Marek Szyprowski Signed-off-by: Sylwester Nawrocki Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Greg Kroah-Hartman --- drivers/media/platform/s5p-mfc/s5p_mfc.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc.c b/drivers/media/platform/s5p-mfc/s5p_mfc.c index d566b918c600..7c24da51626c 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc.c @@ -206,6 +206,7 @@ static void s5p_mfc_watchdog_worker(struct work_struct *work) } s5p_mfc_clock_on(); ret = s5p_mfc_init_hw(dev); + s5p_mfc_clock_off(); if (ret) mfc_err("Failed to reinit FW\n"); } From 466b45af50fd27754dff2982c65396c5ca9d461c Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Mon, 13 Mar 2017 09:53:54 -0300 Subject: [PATCH 328/396] dib0700: fix NULL-deref at probe commit d5823511c0f8719a39e72ede1bce65411ac653b7 upstream. Make sure to check the number of endpoints to avoid dereferencing a NULL-pointer should a malicious device lack endpoints. Fixes: c4018fa2e4c0 ("[media] dib0700: fix RC support on Hauppauge Nova-TD") Cc: Mauro Carvalho Chehab Signed-off-by: Johan Hovold Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Greg Kroah-Hartman --- drivers/media/usb/dvb-usb/dib0700_core.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/media/usb/dvb-usb/dib0700_core.c b/drivers/media/usb/dvb-usb/dib0700_core.c index 47ce9d5de4c6..563f690cd978 100644 --- a/drivers/media/usb/dvb-usb/dib0700_core.c +++ b/drivers/media/usb/dvb-usb/dib0700_core.c @@ -812,6 +812,9 @@ int dib0700_rc_setup(struct dvb_usb_device *d, struct usb_interface *intf) /* Starting in firmware 1.20, the RC info is provided on a bulk pipe */ + if (intf->altsetting[0].desc.bNumEndpoints < rc_ep + 1) + return -ENODEV; + purb = usb_alloc_urb(0, GFP_KERNEL); if (purb == NULL) return -ENOMEM; From 64579fcc57fd00e1e9f021eba90d01d3371dc6b7 Mon Sep 17 00:00:00 2001 From: Alyssa Milburn Date: Sat, 1 Apr 2017 14:34:08 -0300 Subject: [PATCH 329/396] zr364xx: enforce minimum size when reading header commit ee0fe833d96793853335844b6d99fb76bd12cbeb upstream. This code copies actual_length-128 bytes from the header, which will underflow if the received buffer is too small. Signed-off-by: Alyssa Milburn Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Greg Kroah-Hartman --- drivers/media/usb/zr364xx/zr364xx.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/media/usb/zr364xx/zr364xx.c b/drivers/media/usb/zr364xx/zr364xx.c index cc128db85723..e3735bfcc02f 100644 --- a/drivers/media/usb/zr364xx/zr364xx.c +++ b/drivers/media/usb/zr364xx/zr364xx.c @@ -604,6 +604,14 @@ static int zr364xx_read_video_callback(struct zr364xx_camera *cam, ptr = pdest = frm->lpvbits; if (frm->ulState == ZR364XX_READ_IDLE) { + if (purb->actual_length < 128) { + /* header incomplete */ + dev_info(&cam->udev->dev, + "%s: buffer (%d bytes) too small to hold jpeg header. Discarding.\n", + __func__, purb->actual_length); + return -EINVAL; + } + frm->ulState = ZR364XX_READ_FRAME; frm->cur_size = 0; From 28590f1bb601862c663c1e95158ffcc452593ff9 Mon Sep 17 00:00:00 2001 From: Daniel Scheller Date: Sun, 19 Mar 2017 12:26:39 -0300 Subject: [PATCH 330/396] dvb-frontends/cxd2841er: define symbol_rate_min/max in T/C fe-ops commit 158f0328af86a99d64073851967a02694bff987d upstream. Fixes "w_scan -f c" complaining with This dvb driver is *buggy*: the symbol rate limits are undefined - please report to linuxtv.org) Signed-off-by: Daniel Scheller Acked-by: Abylay Ospan Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Greg Kroah-Hartman --- drivers/media/dvb-frontends/cxd2841er.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/media/dvb-frontends/cxd2841er.c b/drivers/media/dvb-frontends/cxd2841er.c index 5afb9c508f65..fd0f25ee251f 100644 --- a/drivers/media/dvb-frontends/cxd2841er.c +++ b/drivers/media/dvb-frontends/cxd2841er.c @@ -3852,7 +3852,9 @@ static struct dvb_frontend_ops cxd2841er_t_c_ops = { FE_CAN_MUTE_TS | FE_CAN_2G_MODULATION, .frequency_min = 42000000, - .frequency_max = 1002000000 + .frequency_max = 1002000000, + .symbol_rate_min = 870000, + .symbol_rate_max = 11700000 }, .init = cxd2841er_init_tc, .sleep = cxd2841er_sleep_tc, From e42a6715d26bc777b545018d585333ee91cdbbe9 Mon Sep 17 00:00:00 2001 From: Alyssa Milburn Date: Sat, 1 Apr 2017 14:33:42 -0300 Subject: [PATCH 331/396] digitv: limit messages to buffer size commit 821117dc21083a99dd99174c10848d70ff43de29 upstream. Return an error rather than memcpy()ing beyond the end of the buffer. Internal callers use appropriate sizes, but digitv_i2c_xfer may not. Signed-off-by: Alyssa Milburn Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Greg Kroah-Hartman --- drivers/media/usb/dvb-usb/digitv.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/media/usb/dvb-usb/digitv.c b/drivers/media/usb/dvb-usb/digitv.c index 4284f6984dc1..475a3c0cdee7 100644 --- a/drivers/media/usb/dvb-usb/digitv.c +++ b/drivers/media/usb/dvb-usb/digitv.c @@ -33,6 +33,9 @@ static int digitv_ctrl_msg(struct dvb_usb_device *d, wo = (rbuf == NULL || rlen == 0); /* write-only */ + if (wlen > 4 || rlen > 4) + return -EIO; + memset(st->sndbuf, 0, 7); memset(st->rcvbuf, 0, 7); From 40616929f87e1bb236f5daa0dffa3a95553ac76a Mon Sep 17 00:00:00 2001 From: Alyssa Milburn Date: Sat, 1 Apr 2017 14:34:49 -0300 Subject: [PATCH 332/396] dw2102: limit messages to buffer size commit 950e252cb469f323740d78e4907843acef89eedb upstream. Otherwise the i2c transfer functions can read or write beyond the end of stack or heap buffers. Signed-off-by: Alyssa Milburn Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Greg Kroah-Hartman --- drivers/media/usb/dvb-usb/dw2102.c | 54 ++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/drivers/media/usb/dvb-usb/dw2102.c b/drivers/media/usb/dvb-usb/dw2102.c index c3e67347a977..4a0cc54870c7 100644 --- a/drivers/media/usb/dvb-usb/dw2102.c +++ b/drivers/media/usb/dvb-usb/dw2102.c @@ -205,6 +205,20 @@ static int dw2102_serit_i2c_transfer(struct i2c_adapter *adap, switch (num) { case 2: + if (msg[0].len != 1) { + warn("i2c rd: len=%d is not 1!\n", + msg[0].len); + num = -EOPNOTSUPP; + break; + } + + if (2 + msg[1].len > sizeof(buf6)) { + warn("i2c rd: len=%d is too big!\n", + msg[1].len); + num = -EOPNOTSUPP; + break; + } + /* read si2109 register by number */ buf6[0] = msg[0].addr << 1; buf6[1] = msg[0].len; @@ -220,6 +234,13 @@ static int dw2102_serit_i2c_transfer(struct i2c_adapter *adap, case 1: switch (msg[0].addr) { case 0x68: + if (2 + msg[0].len > sizeof(buf6)) { + warn("i2c wr: len=%d is too big!\n", + msg[0].len); + num = -EOPNOTSUPP; + break; + } + /* write to si2109 register */ buf6[0] = msg[0].addr << 1; buf6[1] = msg[0].len; @@ -263,6 +284,13 @@ static int dw2102_earda_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg ms /* first write first register number */ u8 ibuf[MAX_XFER_SIZE], obuf[3]; + if (2 + msg[0].len != sizeof(obuf)) { + warn("i2c rd: len=%d is not 1!\n", + msg[0].len); + ret = -EOPNOTSUPP; + goto unlock; + } + if (2 + msg[1].len > sizeof(ibuf)) { warn("i2c rd: len=%d is too big!\n", msg[1].len); @@ -463,6 +491,12 @@ static int dw3101_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[], /* first write first register number */ u8 ibuf[MAX_XFER_SIZE], obuf[3]; + if (2 + msg[0].len != sizeof(obuf)) { + warn("i2c rd: len=%d is not 1!\n", + msg[0].len); + ret = -EOPNOTSUPP; + goto unlock; + } if (2 + msg[1].len > sizeof(ibuf)) { warn("i2c rd: len=%d is too big!\n", msg[1].len); @@ -697,6 +731,13 @@ static int su3000_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[], msg[0].buf[0] = state->data[1]; break; default: + if (3 + msg[0].len > sizeof(state->data)) { + warn("i2c wr: len=%d is too big!\n", + msg[0].len); + num = -EOPNOTSUPP; + break; + } + /* always i2c write*/ state->data[0] = 0x08; state->data[1] = msg[0].addr; @@ -712,6 +753,19 @@ static int su3000_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[], break; case 2: /* always i2c read */ + if (4 + msg[0].len > sizeof(state->data)) { + warn("i2c rd: len=%d is too big!\n", + msg[0].len); + num = -EOPNOTSUPP; + break; + } + if (1 + msg[1].len > sizeof(state->data)) { + warn("i2c rd: len=%d is too big!\n", + msg[1].len); + num = -EOPNOTSUPP; + break; + } + state->data[0] = 0x09; state->data[1] = msg[0].len; state->data[2] = msg[1].len; From 1b24b8c070230d4a539063ca3291233fa0cd80a6 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Mon, 13 Mar 2017 09:53:57 -0300 Subject: [PATCH 333/396] cx231xx-audio: fix init error path commit fff1abc4d54e469140a699612b4db8d6397bfcba upstream. Make sure to release the snd_card also on a late allocation error. Fixes: e0d3bafd0258 ("V4L/DVB (10954): Add cx231xx USB driver") Cc: Sri Deevi Signed-off-by: Johan Hovold Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Greg Kroah-Hartman --- drivers/media/usb/cx231xx/cx231xx-audio.c | 25 +++++++++++++---------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/drivers/media/usb/cx231xx/cx231xx-audio.c b/drivers/media/usb/cx231xx/cx231xx-audio.c index 8263c4b0610b..2ca713b1c086 100644 --- a/drivers/media/usb/cx231xx/cx231xx-audio.c +++ b/drivers/media/usb/cx231xx/cx231xx-audio.c @@ -674,10 +674,8 @@ static int cx231xx_audio_init(struct cx231xx *dev) spin_lock_init(&adev->slock); err = snd_pcm_new(card, "Cx231xx Audio", 0, 0, 1, &pcm); - if (err < 0) { - snd_card_free(card); - return err; - } + if (err < 0) + goto err_free_card; snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_cx231xx_pcm_capture); @@ -691,10 +689,9 @@ static int cx231xx_audio_init(struct cx231xx *dev) INIT_WORK(&dev->wq_trigger, audio_trigger); err = snd_card_register(card); - if (err < 0) { - snd_card_free(card); - return err; - } + if (err < 0) + goto err_free_card; + adev->sndcard = card; adev->udev = dev->udev; @@ -713,9 +710,10 @@ static int cx231xx_audio_init(struct cx231xx *dev) "audio EndPoint Addr 0x%x, Alternate settings: %i\n", adev->end_point_addr, adev->num_alt); adev->alt_max_pkt_size = kmalloc(32 * adev->num_alt, GFP_KERNEL); - - if (adev->alt_max_pkt_size == NULL) - return -ENOMEM; + if (!adev->alt_max_pkt_size) { + err = -ENOMEM; + goto err_free_card; + } for (i = 0; i < adev->num_alt; i++) { u16 tmp = @@ -729,6 +727,11 @@ static int cx231xx_audio_init(struct cx231xx *dev) } return 0; + +err_free_card: + snd_card_free(card); + + return err; } static int cx231xx_audio_fini(struct cx231xx *dev) From 8ebb884009b60f662024630a6df8e565ed5956f1 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Mon, 13 Mar 2017 09:53:58 -0300 Subject: [PATCH 334/396] cx231xx-audio: fix NULL-deref at probe commit 65f921647f4c89a2068478c89691f39b309b58f7 upstream. Make sure to check the number of endpoints to avoid dereferencing a NULL-pointer or accessing memory beyond the endpoint array should a malicious device lack the expected endpoints. Fixes: e0d3bafd0258 ("V4L/DVB (10954): Add cx231xx USB driver") Cc: Sri Deevi Signed-off-by: Johan Hovold Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Greg Kroah-Hartman --- drivers/media/usb/cx231xx/cx231xx-audio.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/drivers/media/usb/cx231xx/cx231xx-audio.c b/drivers/media/usb/cx231xx/cx231xx-audio.c index 2ca713b1c086..bf4b3ca2abf9 100644 --- a/drivers/media/usb/cx231xx/cx231xx-audio.c +++ b/drivers/media/usb/cx231xx/cx231xx-audio.c @@ -701,6 +701,11 @@ static int cx231xx_audio_init(struct cx231xx *dev) hs_config_info[0].interface_info. audio_index + 1]; + if (uif->altsetting[0].desc.bNumEndpoints < isoc_pipe + 1) { + err = -ENODEV; + goto err_free_card; + } + adev->end_point_addr = uif->altsetting[0].endpoint[isoc_pipe].desc. bEndpointAddress; @@ -716,8 +721,14 @@ static int cx231xx_audio_init(struct cx231xx *dev) } for (i = 0; i < adev->num_alt; i++) { - u16 tmp = - le16_to_cpu(uif->altsetting[i].endpoint[isoc_pipe].desc. + u16 tmp; + + if (uif->altsetting[i].desc.bNumEndpoints < isoc_pipe + 1) { + err = -ENODEV; + goto err_free_pkt_size; + } + + tmp = le16_to_cpu(uif->altsetting[i].endpoint[isoc_pipe].desc. wMaxPacketSize); adev->alt_max_pkt_size[i] = (tmp & 0x07ff) * (((tmp & 0x1800) >> 11) + 1); @@ -728,6 +739,8 @@ static int cx231xx_audio_init(struct cx231xx *dev) return 0; +err_free_pkt_size: + kfree(adev->alt_max_pkt_size); err_free_card: snd_card_free(card); From 2338de43e234d7144c1dff900bf3422b1523ac00 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Mon, 13 Mar 2017 09:53:56 -0300 Subject: [PATCH 335/396] cx231xx-cards: fix NULL-deref at probe commit 0cd273bb5e4d1828efaaa8dfd11b7928131ed149 upstream. Make sure to check the number of endpoints to avoid dereferencing a NULL-pointer or accessing memory beyond the endpoint array should a malicious device lack the expected endpoints. Fixes: e0d3bafd0258 ("V4L/DVB (10954): Add cx231xx USB driver") Cc: Sri Deevi Signed-off-by: Johan Hovold Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Greg Kroah-Hartman --- drivers/media/usb/cx231xx/cx231xx-cards.c | 45 ++++++++++++++++++++--- 1 file changed, 40 insertions(+), 5 deletions(-) diff --git a/drivers/media/usb/cx231xx/cx231xx-cards.c b/drivers/media/usb/cx231xx/cx231xx-cards.c index 36bc25494319..be9e3335dcb7 100644 --- a/drivers/media/usb/cx231xx/cx231xx-cards.c +++ b/drivers/media/usb/cx231xx/cx231xx-cards.c @@ -1397,6 +1397,9 @@ static int cx231xx_init_v4l2(struct cx231xx *dev, uif = udev->actconfig->interface[idx]; + if (uif->altsetting[0].desc.bNumEndpoints < isoc_pipe + 1) + return -ENODEV; + dev->video_mode.end_point_addr = uif->altsetting[0].endpoint[isoc_pipe].desc.bEndpointAddress; dev->video_mode.num_alt = uif->num_altsetting; @@ -1410,7 +1413,12 @@ static int cx231xx_init_v4l2(struct cx231xx *dev, return -ENOMEM; for (i = 0; i < dev->video_mode.num_alt; i++) { - u16 tmp = le16_to_cpu(uif->altsetting[i].endpoint[isoc_pipe].desc.wMaxPacketSize); + u16 tmp; + + if (uif->altsetting[i].desc.bNumEndpoints < isoc_pipe + 1) + return -ENODEV; + + tmp = le16_to_cpu(uif->altsetting[i].endpoint[isoc_pipe].desc.wMaxPacketSize); dev->video_mode.alt_max_pkt_size[i] = (tmp & 0x07ff) * (((tmp & 0x1800) >> 11) + 1); dev_dbg(dev->dev, "Alternate setting %i, max size= %i\n", i, @@ -1427,6 +1435,9 @@ static int cx231xx_init_v4l2(struct cx231xx *dev, } uif = udev->actconfig->interface[idx]; + if (uif->altsetting[0].desc.bNumEndpoints < isoc_pipe + 1) + return -ENODEV; + dev->vbi_mode.end_point_addr = uif->altsetting[0].endpoint[isoc_pipe].desc. bEndpointAddress; @@ -1443,8 +1454,12 @@ static int cx231xx_init_v4l2(struct cx231xx *dev, return -ENOMEM; for (i = 0; i < dev->vbi_mode.num_alt; i++) { - u16 tmp = - le16_to_cpu(uif->altsetting[i].endpoint[isoc_pipe]. + u16 tmp; + + if (uif->altsetting[i].desc.bNumEndpoints < isoc_pipe + 1) + return -ENODEV; + + tmp = le16_to_cpu(uif->altsetting[i].endpoint[isoc_pipe]. desc.wMaxPacketSize); dev->vbi_mode.alt_max_pkt_size[i] = (tmp & 0x07ff) * (((tmp & 0x1800) >> 11) + 1); @@ -1464,6 +1479,9 @@ static int cx231xx_init_v4l2(struct cx231xx *dev, } uif = udev->actconfig->interface[idx]; + if (uif->altsetting[0].desc.bNumEndpoints < isoc_pipe + 1) + return -ENODEV; + dev->sliced_cc_mode.end_point_addr = uif->altsetting[0].endpoint[isoc_pipe].desc. bEndpointAddress; @@ -1478,7 +1496,12 @@ static int cx231xx_init_v4l2(struct cx231xx *dev, return -ENOMEM; for (i = 0; i < dev->sliced_cc_mode.num_alt; i++) { - u16 tmp = le16_to_cpu(uif->altsetting[i].endpoint[isoc_pipe]. + u16 tmp; + + if (uif->altsetting[i].desc.bNumEndpoints < isoc_pipe + 1) + return -ENODEV; + + tmp = le16_to_cpu(uif->altsetting[i].endpoint[isoc_pipe]. desc.wMaxPacketSize); dev->sliced_cc_mode.alt_max_pkt_size[i] = (tmp & 0x07ff) * (((tmp & 0x1800) >> 11) + 1); @@ -1647,6 +1670,11 @@ static int cx231xx_usb_probe(struct usb_interface *interface, } uif = udev->actconfig->interface[idx]; + if (uif->altsetting[0].desc.bNumEndpoints < isoc_pipe + 1) { + retval = -ENODEV; + goto err_video_alt; + } + dev->ts1_mode.end_point_addr = uif->altsetting[0].endpoint[isoc_pipe]. desc.bEndpointAddress; @@ -1664,7 +1692,14 @@ static int cx231xx_usb_probe(struct usb_interface *interface, } for (i = 0; i < dev->ts1_mode.num_alt; i++) { - u16 tmp = le16_to_cpu(uif->altsetting[i]. + u16 tmp; + + if (uif->altsetting[i].desc.bNumEndpoints < isoc_pipe + 1) { + retval = -ENODEV; + goto err_video_alt; + } + + tmp = le16_to_cpu(uif->altsetting[i]. endpoint[isoc_pipe].desc. wMaxPacketSize); dev->ts1_mode.alt_max_pkt_size[i] = From 690f09eb52bcedb9853878c98c4e90860f05d99f Mon Sep 17 00:00:00 2001 From: David Gibson Date: Wed, 19 Apr 2017 16:38:26 +1000 Subject: [PATCH 336/396] powerpc/mm: Ensure IRQs are off in switch_mm() commit 9765ad134a00a01cbcc69c78ff6defbfad209bc5 upstream. powerpc expects IRQs to already be (soft) disabled when switch_mm() is called, as made clear in the commit message of 9c1e105238c4 ("powerpc: Allow perf_counters to access user memory at interrupt time"). Aside from any race conditions that might exist between switch_mm() and an IRQ, there is also an unconditional hard_irq_disable() in switch_slb(). If that isn't followed at some point by an IRQ enable then interrupts will remain disabled until we return to userspace. It is true that when switch_mm() is called from the scheduler IRQs are off, but not when it's called by use_mm(). Looking closer we see that last year in commit f98db6013c55 ("sched/core: Add switch_mm_irqs_off() and use it in the scheduler") this was made more explicit by the addition of switch_mm_irqs_off() which is now called by the scheduler, vs switch_mm() which is used by use_mm(). Arguably it is a bug in use_mm() to call switch_mm() in a different context than it expects, but fixing that will take time. This was discovered recently when vhost started throwing warnings such as: BUG: sleeping function called from invalid context at kernel/mutex.c:578 in_atomic(): 0, irqs_disabled(): 1, pid: 10768, name: vhost-10760 no locks held by vhost-10760/10768. irq event stamp: 10 hardirqs last enabled at (9): _raw_spin_unlock_irq+0x40/0x80 hardirqs last disabled at (10): switch_slb+0x2e4/0x490 softirqs last enabled at (0): copy_process+0x5e8/0x1260 softirqs last disabled at (0): (null) Call Trace: show_stack+0x88/0x390 (unreliable) dump_stack+0x30/0x44 __might_sleep+0x1c4/0x2d0 mutex_lock_nested+0x74/0x5c0 cgroup_attach_task_all+0x5c/0x180 vhost_attach_cgroups_work+0x58/0x80 [vhost] vhost_worker+0x24c/0x3d0 [vhost] kthread+0xec/0x100 ret_from_kernel_thread+0x5c/0xd4 Prior to commit 04b96e5528ca ("vhost: lockless enqueuing") (Aug 2016) the vhost_worker() would do a spin_unlock_irq() not long after calling use_mm(), which had the effect of reenabling IRQs. Since that commit removed the locking in vhost_worker() the body of the vhost_worker() loop now runs with interrupts off causing the warnings. This patch addresses the problem by making the powerpc code mirror the x86 code, ie. we disable interrupts in switch_mm(), and optimise the scheduler case by defining switch_mm_irqs_off(). Signed-off-by: David Gibson [mpe: Flesh out/rewrite change log, add stable] Signed-off-by: Michael Ellerman Signed-off-by: Greg Kroah-Hartman --- arch/powerpc/include/asm/mmu_context.h | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/arch/powerpc/include/asm/mmu_context.h b/arch/powerpc/include/asm/mmu_context.h index b9e3f0aca261..0012f0353fd6 100644 --- a/arch/powerpc/include/asm/mmu_context.h +++ b/arch/powerpc/include/asm/mmu_context.h @@ -70,8 +70,9 @@ extern void drop_cop(unsigned long acop, struct mm_struct *mm); * switch_mm is the entry point called from the architecture independent * code in kernel/sched/core.c */ -static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, - struct task_struct *tsk) +static inline void switch_mm_irqs_off(struct mm_struct *prev, + struct mm_struct *next, + struct task_struct *tsk) { /* Mark this context has been used on the new CPU */ if (!cpumask_test_cpu(smp_processor_id(), mm_cpumask(next))) @@ -110,6 +111,18 @@ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, switch_mmu_context(prev, next, tsk); } +static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, + struct task_struct *tsk) +{ + unsigned long flags; + + local_irq_save(flags); + switch_mm_irqs_off(prev, next, tsk); + local_irq_restore(flags); +} +#define switch_mm_irqs_off switch_mm_irqs_off + + #define deactivate_mm(tsk,mm) do { } while (0) /* From 222f1d668d0004612360495a40e0cc003e27e8bc Mon Sep 17 00:00:00 2001 From: Russell Currey Date: Wed, 19 Apr 2017 17:39:26 +1000 Subject: [PATCH 337/396] powerpc/eeh: Avoid use after free in eeh_handle_special_event() commit daeba2956f32f91f3493788ff6ee02fb1b2f02fa upstream. eeh_handle_special_event() is called when an EEH event is detected but can't be narrowed down to a specific PE. This function looks through every PE to find one in an erroneous state, then calls the regular event handler eeh_handle_normal_event() once it knows which PE has an error. However, if eeh_handle_normal_event() found that the PE cannot possibly be recovered, it will free it, rendering the passed PE stale. This leads to a use after free in eeh_handle_special_event() as it attempts to clear the "recovering" state on the PE after eeh_handle_normal_event() returns. Thus, make sure the PE is valid when attempting to clear state in eeh_handle_special_event(). Fixes: 8a6b1bc70dbb ("powerpc/eeh: EEH core to handle special event") Reported-by: Alexey Kardashevskiy Signed-off-by: Russell Currey Reviewed-by: Gavin Shan Signed-off-by: Michael Ellerman Signed-off-by: Greg Kroah-Hartman --- arch/powerpc/kernel/eeh_driver.c | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/arch/powerpc/kernel/eeh_driver.c b/arch/powerpc/kernel/eeh_driver.c index a5dd493670a0..6ef8f0bceacd 100644 --- a/arch/powerpc/kernel/eeh_driver.c +++ b/arch/powerpc/kernel/eeh_driver.c @@ -724,7 +724,7 @@ static int eeh_reset_device(struct eeh_pe *pe, struct pci_bus *bus, */ #define MAX_WAIT_FOR_RECOVERY 300 -static void eeh_handle_normal_event(struct eeh_pe *pe) +static bool eeh_handle_normal_event(struct eeh_pe *pe) { struct pci_bus *frozen_bus; struct eeh_dev *edev, *tmp; @@ -736,7 +736,7 @@ static void eeh_handle_normal_event(struct eeh_pe *pe) if (!frozen_bus) { pr_err("%s: Cannot find PCI bus for PHB#%d-PE#%x\n", __func__, pe->phb->global_number, pe->addr); - return; + return false; } eeh_pe_update_time_stamp(pe); @@ -870,7 +870,7 @@ static void eeh_handle_normal_event(struct eeh_pe *pe) pr_info("EEH: Notify device driver to resume\n"); eeh_pe_dev_traverse(pe, eeh_report_resume, NULL); - return; + return false; excess_failures: /* @@ -915,8 +915,12 @@ perm_error: pci_lock_rescan_remove(); pci_hp_remove_devices(frozen_bus); pci_unlock_rescan_remove(); + + /* The passed PE should no longer be used */ + return true; } } + return false; } static void eeh_handle_special_event(void) @@ -982,7 +986,14 @@ static void eeh_handle_special_event(void) */ if (rc == EEH_NEXT_ERR_FROZEN_PE || rc == EEH_NEXT_ERR_FENCED_PHB) { - eeh_handle_normal_event(pe); + /* + * eeh_handle_normal_event() can make the PE stale if it + * determines that the PE cannot possibly be recovered. + * Don't modify the PE state if that's the case. + */ + if (eeh_handle_normal_event(pe)) + continue; + eeh_pe_state_clear(pe, EEH_PE_RECOVERING); } else { pci_lock_rescan_remove(); From a0da3e00df38673db6f311bb38d31a30de87e6c6 Mon Sep 17 00:00:00 2001 From: Mahesh Salgaonkar Date: Tue, 18 Apr 2017 22:08:17 +0530 Subject: [PATCH 338/396] powerpc/book3s/mce: Move add_taint() later in virtual mode commit d93b0ac01a9ce276ec39644be47001873d3d183c upstream. machine_check_early() gets called in real mode. The very first time when add_taint() is called, it prints a warning which ends up calling opal call (that uses OPAL_CALL wrapper) for writing it to console. If we get a very first machine check while we are in opal we are doomed. OPAL_CALL overwrites the PACASAVEDMSR in r13 and in this case when we are done with MCE handling the original opal call will use this new MSR on it's way back to opal_return. This usually leads to unexpected behaviour or the kernel to panic. Instead move the add_taint() call later in the virtual mode where it is safe to call. This is broken with current FW level. We got lucky so far for not getting very first MCE hit while in OPAL. But easily reproducible on Mambo. Fixes: 27ea2c420cad ("powerpc: Set the correct kernel taint on machine check errors.") Signed-off-by: Mahesh Salgaonkar Signed-off-by: Michael Ellerman Signed-off-by: Greg Kroah-Hartman --- arch/powerpc/kernel/mce.c | 2 ++ arch/powerpc/kernel/traps.c | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/arch/powerpc/kernel/mce.c b/arch/powerpc/kernel/mce.c index 5e7ece0fda9f..ea236bfd841f 100644 --- a/arch/powerpc/kernel/mce.c +++ b/arch/powerpc/kernel/mce.c @@ -205,6 +205,8 @@ static void machine_check_process_queued_event(struct irq_work *work) { int index; + add_taint(TAINT_MACHINE_CHECK, LOCKDEP_NOW_UNRELIABLE); + /* * For now just print it to console. * TODO: log this error event to FSP or nvram. diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c index 023a462725b5..43021f8e47a6 100644 --- a/arch/powerpc/kernel/traps.c +++ b/arch/powerpc/kernel/traps.c @@ -302,8 +302,6 @@ long machine_check_early(struct pt_regs *regs) __this_cpu_inc(irq_stat.mce_exceptions); - add_taint(TAINT_MACHINE_CHECK, LOCKDEP_NOW_UNRELIABLE); - if (cur_cpu_spec && cur_cpu_spec->machine_check_early) handled = cur_cpu_spec->machine_check_early(regs); return handled; @@ -737,6 +735,8 @@ void machine_check_exception(struct pt_regs *regs) __this_cpu_inc(irq_stat.mce_exceptions); + add_taint(TAINT_MACHINE_CHECK, LOCKDEP_NOW_UNRELIABLE); + /* See if any machine dependent calls. In theory, we would want * to call the CPU first, and call the ppc_md. one if the CPU * one returns a positive number. However there is existing code From 5ba5685a26b1e89e5fccd0373f614fd5d13253a6 Mon Sep 17 00:00:00 2001 From: Tyrel Datwyler Date: Mon, 17 Apr 2017 20:21:40 -0400 Subject: [PATCH 339/396] powerpc/pseries: Fix of_node_put() underflow during DLPAR remove commit 68baf692c435339e6295cb470ea5545cbc28160e upstream. Historically struct device_node references were tracked using a kref embedded as a struct field. Commit 75b57ecf9d1d ("of: Make device nodes kobjects so they show up in sysfs") (Mar 2014) refactored device_nodes to be kobjects such that the device tree could by more simply exposed to userspace using sysfs. Commit 0829f6d1f69e ("of: device_node kobject lifecycle fixes") (Mar 2014) followed up these changes to better control the kobject lifecycle and in particular the referecne counting via of_node_get(), of_node_put(), and of_node_init(). A result of this second commit was that it introduced an of_node_put() call when a dynamic node is detached, in of_node_remove(), that removes the initial kobj reference created by of_node_init(). Traditionally as the original dynamic device node user the pseries code had assumed responsibilty for releasing this final reference in its platform specific DLPAR detach code. This patch fixes a refcount underflow introduced by commit 0829f6d1f6, and recently exposed by the upstreaming of the recount API. Messages like the following are no longer seen in the kernel log with this patch following DLPAR remove operations of cpus and pci devices. rpadlpar_io: slot PHB 72 removed refcount_t: underflow; use-after-free. ------------[ cut here ]------------ WARNING: CPU: 5 PID: 3335 at lib/refcount.c:128 refcount_sub_and_test+0xf4/0x110 Fixes: 0829f6d1f69e ("of: device_node kobject lifecycle fixes") Signed-off-by: Tyrel Datwyler [mpe: Make change log commit references more verbose] Signed-off-by: Michael Ellerman Signed-off-by: Greg Kroah-Hartman --- arch/powerpc/platforms/pseries/dlpar.c | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/powerpc/platforms/pseries/dlpar.c b/arch/powerpc/platforms/pseries/dlpar.c index 423e450efe07..72ae2cdbcd6a 100644 --- a/arch/powerpc/platforms/pseries/dlpar.c +++ b/arch/powerpc/platforms/pseries/dlpar.c @@ -288,7 +288,6 @@ int dlpar_detach_node(struct device_node *dn) if (rc) return rc; - of_node_put(dn); /* Must decrement the refcount */ return 0; } From 3915c566ea9427947ddc1849c68f64c401a3d5c9 Mon Sep 17 00:00:00 2001 From: Alexey Kardashevskiy Date: Tue, 11 Apr 2017 17:54:57 +1000 Subject: [PATCH 340/396] powerpc/iommu: Do not call PageTransHuge() on tail pages commit e889e96e98e8da97bd39e46b7253615eabe14397 upstream. The CMA pages migration code does not support compound pages at the moment so it performs few tests before proceeding to actual page migration. One of the tests - PageTransHuge() - has VM_BUG_ON_PAGE(PageTail()) as it is designed to be called on head pages only. Since we also test for PageCompound(), and it contains PageTail() and PageHead(), we can simplify the check by leaving just PageCompound() and therefore avoid possible VM_BUG_ON_PAGE. Fixes: 2e5bbb5461f1 ("KVM: PPC: Book3S HV: Migrate pinned pages out of CMA") Signed-off-by: Alexey Kardashevskiy Acked-by: Balbir Singh Signed-off-by: Michael Ellerman Signed-off-by: Greg Kroah-Hartman --- arch/powerpc/mm/mmu_context_iommu.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/powerpc/mm/mmu_context_iommu.c b/arch/powerpc/mm/mmu_context_iommu.c index 7de7124ac91b..fd596808ac24 100644 --- a/arch/powerpc/mm/mmu_context_iommu.c +++ b/arch/powerpc/mm/mmu_context_iommu.c @@ -81,7 +81,7 @@ struct page *new_iommu_non_cma_page(struct page *page, unsigned long private, gfp_t gfp_mask = GFP_USER; struct page *new_page; - if (PageHuge(page) || PageTransHuge(page) || PageCompound(page)) + if (PageCompound(page)) return NULL; if (PageHighMem(page)) @@ -100,7 +100,7 @@ static int mm_iommu_move_page_from_cma(struct page *page) LIST_HEAD(cma_migrate_pages); /* Ignore huge pages for now */ - if (PageHuge(page) || PageTransHuge(page) || PageCompound(page)) + if (PageCompound(page)) return -EBUSY; lru_add_drain(); From 018b91870856035f9bdff45f690b933d67f6efc3 Mon Sep 17 00:00:00 2001 From: LiuHailong Date: Tue, 7 Feb 2017 10:35:52 +0800 Subject: [PATCH 341/396] powerpc/64e: Fix hang when debugging programs with relocated kernel commit fd615f69a18a9d4aa5ef02a1dc83f319f75da8e7 upstream. Debug interrupts can be taken during interrupt entry, since interrupt entry does not automatically turn them off. The kernel will check whether the faulting instruction is between [interrupt_base_book3e, __end_interrupts], and if so clear MSR[DE] and return. However, when the kernel is built with CONFIG_RELOCATABLE, it can't use LOAD_REG_IMMEDIATE(r14,interrupt_base_book3e) and LOAD_REG_IMMEDIATE(r15,__end_interrupts), as they ignore relocation. Thus, if the kernel is actually running at a different address than it was built at, the address comparison will fail, and the exception entry code will hang at kernel_dbg_exc. r2(toc) is also not usable here, as r2 still holds data from the interrupted context, so LOAD_REG_ADDR() doesn't work either. So we use the *name@got* to get the EV of two labels directly. Test programs test.c shows as follows: int main(int argc, char *argv[]) { if (access("/proc/sys/kernel/perf_event_paranoid", F_OK) == -1) printf("Kernel doesn't have perf_event support\n"); } Steps to reproduce the bug, for example: 1) ./gdb ./test 2) (gdb) b access 3) (gdb) r 4) (gdb) s Signed-off-by: Liu Hailong Signed-off-by: Jiang Xuexin Reviewed-by: Jiang Biao Reviewed-by: Liu Song Reviewed-by: Huang Jian [scottwood: cleaned up commit message, and specified bad behavior as a hang rather than an oops to correspond to mainline kernel behavior] Fixes: 1cb6e0649248 ("powerpc/book3e: support CONFIG_RELOCATABLE") Signed-off-by: Scott Wood Signed-off-by: Greg Kroah-Hartman --- arch/powerpc/kernel/exceptions-64e.S | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/arch/powerpc/kernel/exceptions-64e.S b/arch/powerpc/kernel/exceptions-64e.S index 38a1f96430e1..ca03eb229a9a 100644 --- a/arch/powerpc/kernel/exceptions-64e.S +++ b/arch/powerpc/kernel/exceptions-64e.S @@ -735,8 +735,14 @@ END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC) andis. r15,r14,(DBSR_IC|DBSR_BT)@h beq+ 1f +#ifdef CONFIG_RELOCATABLE + ld r15,PACATOC(r13) + ld r14,interrupt_base_book3e@got(r15) + ld r15,__end_interrupts@got(r15) +#else LOAD_REG_IMMEDIATE(r14,interrupt_base_book3e) LOAD_REG_IMMEDIATE(r15,__end_interrupts) +#endif cmpld cr0,r10,r14 cmpld cr1,r10,r15 blt+ cr0,1f @@ -799,8 +805,14 @@ kernel_dbg_exc: andis. r15,r14,(DBSR_IC|DBSR_BT)@h beq+ 1f +#ifdef CONFIG_RELOCATABLE + ld r15,PACATOC(r13) + ld r14,interrupt_base_book3e@got(r15) + ld r15,__end_interrupts@got(r15) +#else LOAD_REG_IMMEDIATE(r14,interrupt_base_book3e) LOAD_REG_IMMEDIATE(r15,__end_interrupts) +#endif cmpld cr0,r10,r14 cmpld cr1,r10,r15 blt+ cr0,1f From a685601f85331ec7f8cda1975bddba311441f333 Mon Sep 17 00:00:00 2001 From: Michael Neuling Date: Mon, 8 May 2017 17:16:26 +1000 Subject: [PATCH 342/396] powerpc/tm: Fix FP and VMX register corruption commit f48e91e87e67b56bef63393d1a02c6e22c1d7078 upstream. In commit dc3106690b20 ("powerpc: tm: Always use fp_state and vr_state to store live registers"), a section of code was removed that copied the current state to checkpointed state. That code should not have been removed. When an FP (Floating Point) unavailable is taken inside a transaction, we need to abort the transaction. This is because at the time of the tbegin, the FP state is bogus so the state stored in the checkpointed registers is incorrect. To fix this, we treclaim (to get the checkpointed GPRs) and then copy the thread_struct FP live state into the checkpointed state. We then trecheckpoint so that the FP state is correctly restored into the CPU. The copying of the FP registers from live to checkpointed is what was missing. This simplifies the logic slightly from the original patch. tm_reclaim_thread() will now always write the checkpointed FP state. Either the checkpointed FP state will be written as part of the actual treclaim (in tm.S), or it'll be a copy of the live state. Which one we use is based on MSR[FP] from userspace. Similarly for VMX. Fixes: dc3106690b20 ("powerpc: tm: Always use fp_state and vr_state to store live registers") Signed-off-by: Michael Neuling Reviewed-by: cyrilbur@gmail.com Signed-off-by: Michael Ellerman Signed-off-by: Greg Kroah-Hartman --- arch/powerpc/kernel/process.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c index 49a680d5ae37..c7164739dc75 100644 --- a/arch/powerpc/kernel/process.c +++ b/arch/powerpc/kernel/process.c @@ -839,6 +839,25 @@ static void tm_reclaim_thread(struct thread_struct *thr, if (!MSR_TM_SUSPENDED(mfmsr())) return; + /* + * If we are in a transaction and FP is off then we can't have + * used FP inside that transaction. Hence the checkpointed + * state is the same as the live state. We need to copy the + * live state to the checkpointed state so that when the + * transaction is restored, the checkpointed state is correct + * and the aborted transaction sees the correct state. We use + * ckpt_regs.msr here as that's what tm_reclaim will use to + * determine if it's going to write the checkpointed state or + * not. So either this will write the checkpointed registers, + * or reclaim will. Similarly for VMX. + */ + if ((thr->ckpt_regs.msr & MSR_FP) == 0) + memcpy(&thr->ckfp_state, &thr->fp_state, + sizeof(struct thread_fp_state)); + if ((thr->ckpt_regs.msr & MSR_VEC) == 0) + memcpy(&thr->ckvr_state, &thr->vr_state, + sizeof(struct thread_vr_state)); + giveup_all(container_of(thr, struct task_struct, thread)); tm_reclaim(thr, thr->ckpt_regs.msr, cause); From d0fb4b7d00bba1e11d05aa39bd7db50cb8cfed53 Mon Sep 17 00:00:00 2001 From: Marc Zyngier Date: Tue, 2 May 2017 14:30:37 +0100 Subject: [PATCH 343/396] arm64: KVM: Do not use stack-protector to compile EL2 code commit cde13b5dad60471886a3bccb4f4134c647c4a9dc upstream. We like living dangerously. Nothing explicitely forbids stack-protector to be used in the EL2 code, while distributions routinely compile their kernel with it. We're just lucky that no code actually triggers the instrumentation. Let's not try our luck for much longer, and disable stack-protector for code living at EL2. Signed-off-by: Marc Zyngier Acked-by: Christoffer Dall Signed-off-by: Christoffer Dall Signed-off-by: Greg Kroah-Hartman --- arch/arm64/kvm/hyp/Makefile | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm64/kvm/hyp/Makefile b/arch/arm64/kvm/hyp/Makefile index aaf42ae8d8c3..14c4e3b14bcb 100644 --- a/arch/arm64/kvm/hyp/Makefile +++ b/arch/arm64/kvm/hyp/Makefile @@ -2,6 +2,8 @@ # Makefile for Kernel-based Virtual Machine module, HYP part # +ccflags-y += -fno-stack-protector + KVM=../../../../virt/kvm obj-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/hyp/vgic-v2-sr.o From 0ba7e8e3419363c279f8cf68f3b3d3e1e14eb3bc Mon Sep 17 00:00:00 2001 From: Marc Zyngier Date: Tue, 2 May 2017 14:30:38 +0100 Subject: [PATCH 344/396] arm: KVM: Do not use stack-protector to compile HYP code commit 501ad27c67ed0b90df465f23d33e9aed64058a47 upstream. We like living dangerously. Nothing explicitely forbids stack-protector to be used in the HYP code, while distributions routinely compile their kernel with it. We're just lucky that no code actually triggers the instrumentation. Let's not try our luck for much longer, and disable stack-protector for code living at HYP. Signed-off-by: Marc Zyngier Acked-by: Christoffer Dall Signed-off-by: Christoffer Dall Signed-off-by: Greg Kroah-Hartman --- arch/arm/kvm/hyp/Makefile | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm/kvm/hyp/Makefile b/arch/arm/kvm/hyp/Makefile index 3023bb530edf..8679405b0b2b 100644 --- a/arch/arm/kvm/hyp/Makefile +++ b/arch/arm/kvm/hyp/Makefile @@ -2,6 +2,8 @@ # Makefile for Kernel-based Virtual Machine module, HYP part # +ccflags-y += -fno-stack-protector + KVM=../../../../virt/kvm obj-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/hyp/vgic-v2-sr.o From ee773459557d2242ddf6a2289e4615b4eb0668ae Mon Sep 17 00:00:00 2001 From: Zhichao Huang Date: Thu, 11 May 2017 13:46:11 +0100 Subject: [PATCH 345/396] KVM: arm: plug potential guest hardware debug leakage MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 661e6b02b5aa82db31897f36e96324b77450fd7a upstream. Hardware debugging in guests is not intercepted currently, it means that a malicious guest can bring down the entire machine by writing to the debug registers. This patch enable trapping of all debug registers, preventing the guests to access the debug registers. This includes access to the debug mode(DBGDSCR) in the guest world all the time which could otherwise mess with the host state. Reads return 0 and writes are ignored (RAZ_WI). The result is the guest cannot detect any working hardware based debug support. As debug exceptions are still routed to the guest normal debug using software based breakpoints still works. To support debugging using hardware registers we need to implement a debug register aware world switch as well as special trapping for registers that may affect the host state. Signed-off-by: Zhichao Huang Signed-off-by: Alex Bennée Reviewed-by: Christoffer Dall Signed-off-by: Christoffer Dall Signed-off-by: Greg Kroah-Hartman --- arch/arm/include/asm/kvm_coproc.h | 3 +- arch/arm/kvm/coproc.c | 77 +++++++++++++++++++++++-------- arch/arm/kvm/handle_exit.c | 4 +- arch/arm/kvm/hyp/switch.c | 4 +- 4 files changed, 66 insertions(+), 22 deletions(-) diff --git a/arch/arm/include/asm/kvm_coproc.h b/arch/arm/include/asm/kvm_coproc.h index 4917c2f7e459..e74ab0fbab79 100644 --- a/arch/arm/include/asm/kvm_coproc.h +++ b/arch/arm/include/asm/kvm_coproc.h @@ -31,7 +31,8 @@ void kvm_register_target_coproc_table(struct kvm_coproc_target_table *table); int kvm_handle_cp10_id(struct kvm_vcpu *vcpu, struct kvm_run *run); int kvm_handle_cp_0_13_access(struct kvm_vcpu *vcpu, struct kvm_run *run); int kvm_handle_cp14_load_store(struct kvm_vcpu *vcpu, struct kvm_run *run); -int kvm_handle_cp14_access(struct kvm_vcpu *vcpu, struct kvm_run *run); +int kvm_handle_cp14_32(struct kvm_vcpu *vcpu, struct kvm_run *run); +int kvm_handle_cp14_64(struct kvm_vcpu *vcpu, struct kvm_run *run); int kvm_handle_cp15_32(struct kvm_vcpu *vcpu, struct kvm_run *run); int kvm_handle_cp15_64(struct kvm_vcpu *vcpu, struct kvm_run *run); diff --git a/arch/arm/kvm/coproc.c b/arch/arm/kvm/coproc.c index 3e5e4194ef86..c3ed6bd5ddf3 100644 --- a/arch/arm/kvm/coproc.c +++ b/arch/arm/kvm/coproc.c @@ -93,12 +93,6 @@ int kvm_handle_cp14_load_store(struct kvm_vcpu *vcpu, struct kvm_run *run) return 1; } -int kvm_handle_cp14_access(struct kvm_vcpu *vcpu, struct kvm_run *run) -{ - kvm_inject_undefined(vcpu); - return 1; -} - static void reset_mpidr(struct kvm_vcpu *vcpu, const struct coproc_reg *r) { /* @@ -514,12 +508,7 @@ static int emulate_cp15(struct kvm_vcpu *vcpu, return 1; } -/** - * kvm_handle_cp15_64 -- handles a mrrc/mcrr trap on a guest CP15 access - * @vcpu: The VCPU pointer - * @run: The kvm_run struct - */ -int kvm_handle_cp15_64(struct kvm_vcpu *vcpu, struct kvm_run *run) +static struct coproc_params decode_64bit_hsr(struct kvm_vcpu *vcpu) { struct coproc_params params; @@ -533,9 +522,38 @@ int kvm_handle_cp15_64(struct kvm_vcpu *vcpu, struct kvm_run *run) params.Rt2 = (kvm_vcpu_get_hsr(vcpu) >> 10) & 0xf; params.CRm = 0; + return params; +} + +/** + * kvm_handle_cp15_64 -- handles a mrrc/mcrr trap on a guest CP15 access + * @vcpu: The VCPU pointer + * @run: The kvm_run struct + */ +int kvm_handle_cp15_64(struct kvm_vcpu *vcpu, struct kvm_run *run) +{ + struct coproc_params params = decode_64bit_hsr(vcpu); + return emulate_cp15(vcpu, ¶ms); } +/** + * kvm_handle_cp14_64 -- handles a mrrc/mcrr trap on a guest CP14 access + * @vcpu: The VCPU pointer + * @run: The kvm_run struct + */ +int kvm_handle_cp14_64(struct kvm_vcpu *vcpu, struct kvm_run *run) +{ + struct coproc_params params = decode_64bit_hsr(vcpu); + + /* raz_wi cp14 */ + pm_fake(vcpu, ¶ms, NULL); + + /* handled */ + kvm_skip_instr(vcpu, kvm_vcpu_trap_il_is32bit(vcpu)); + return 1; +} + static void reset_coproc_regs(struct kvm_vcpu *vcpu, const struct coproc_reg *table, size_t num) { @@ -546,12 +564,7 @@ static void reset_coproc_regs(struct kvm_vcpu *vcpu, table[i].reset(vcpu, &table[i]); } -/** - * kvm_handle_cp15_32 -- handles a mrc/mcr trap on a guest CP15 access - * @vcpu: The VCPU pointer - * @run: The kvm_run struct - */ -int kvm_handle_cp15_32(struct kvm_vcpu *vcpu, struct kvm_run *run) +static struct coproc_params decode_32bit_hsr(struct kvm_vcpu *vcpu) { struct coproc_params params; @@ -565,9 +578,37 @@ int kvm_handle_cp15_32(struct kvm_vcpu *vcpu, struct kvm_run *run) params.Op2 = (kvm_vcpu_get_hsr(vcpu) >> 17) & 0x7; params.Rt2 = 0; + return params; +} + +/** + * kvm_handle_cp15_32 -- handles a mrc/mcr trap on a guest CP15 access + * @vcpu: The VCPU pointer + * @run: The kvm_run struct + */ +int kvm_handle_cp15_32(struct kvm_vcpu *vcpu, struct kvm_run *run) +{ + struct coproc_params params = decode_32bit_hsr(vcpu); return emulate_cp15(vcpu, ¶ms); } +/** + * kvm_handle_cp14_32 -- handles a mrc/mcr trap on a guest CP14 access + * @vcpu: The VCPU pointer + * @run: The kvm_run struct + */ +int kvm_handle_cp14_32(struct kvm_vcpu *vcpu, struct kvm_run *run) +{ + struct coproc_params params = decode_32bit_hsr(vcpu); + + /* raz_wi cp14 */ + pm_fake(vcpu, ¶ms, NULL); + + /* handled */ + kvm_skip_instr(vcpu, kvm_vcpu_trap_il_is32bit(vcpu)); + return 1; +} + /****************************************************************************** * Userspace API *****************************************************************************/ diff --git a/arch/arm/kvm/handle_exit.c b/arch/arm/kvm/handle_exit.c index 4e40d1955e35..066b6d4508ce 100644 --- a/arch/arm/kvm/handle_exit.c +++ b/arch/arm/kvm/handle_exit.c @@ -83,9 +83,9 @@ static exit_handle_fn arm_exit_handlers[] = { [HSR_EC_WFI] = kvm_handle_wfx, [HSR_EC_CP15_32] = kvm_handle_cp15_32, [HSR_EC_CP15_64] = kvm_handle_cp15_64, - [HSR_EC_CP14_MR] = kvm_handle_cp14_access, + [HSR_EC_CP14_MR] = kvm_handle_cp14_32, [HSR_EC_CP14_LS] = kvm_handle_cp14_load_store, - [HSR_EC_CP14_64] = kvm_handle_cp14_access, + [HSR_EC_CP14_64] = kvm_handle_cp14_64, [HSR_EC_CP_0_13] = kvm_handle_cp_0_13_access, [HSR_EC_CP10_ID] = kvm_handle_cp10_id, [HSR_EC_HVC] = handle_hvc, diff --git a/arch/arm/kvm/hyp/switch.c b/arch/arm/kvm/hyp/switch.c index 92678b7bd046..624a510d31df 100644 --- a/arch/arm/kvm/hyp/switch.c +++ b/arch/arm/kvm/hyp/switch.c @@ -48,7 +48,9 @@ static void __hyp_text __activate_traps(struct kvm_vcpu *vcpu, u32 *fpexc_host) write_sysreg(HSTR_T(15), HSTR); write_sysreg(HCPTR_TTA | HCPTR_TCP(10) | HCPTR_TCP(11), HCPTR); val = read_sysreg(HDCR); - write_sysreg(val | HDCR_TPM | HDCR_TPMCR, HDCR); + val |= HDCR_TPM | HDCR_TPMCR; /* trap performance monitors */ + val |= HDCR_TDRA | HDCR_TDOSA | HDCR_TDA; /* trap debug regs */ + write_sysreg(val, HDCR); } static void __hyp_text __deactivate_traps(struct kvm_vcpu *vcpu) From 3304f5a1cb874c63fcc48f9021320510a73c03f9 Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Wed, 22 Feb 2017 19:40:12 +0100 Subject: [PATCH 346/396] ARM: 8662/1: module: split core and init PLT sections commit b7ede5a1f5905ac394cc8e61712a13e3c5cb7b8f upstream. Since commit 35fa91eed817 ("ARM: kernel: merge core and init PLTs"), the ARM module PLT code allocates all PLT entries in a single core section, since the overhead of having a separate init PLT section is not justified by the small number of PLT entries usually required for init code. However, the core and init module regions are allocated independently, and there is a corner case where the core region may be allocated from the VMALLOC region if the dedicated module region is exhausted, but the init region, being much smaller, can still be allocated from the module region. This puts the PLT entries out of reach of the relocated branch instructions, defeating the whole purpose of PLTs. So split the core and init PLT regions, and name the latter ".init.plt" so it gets allocated along with (and sufficiently close to) the .init sections that it serves. Also, given that init PLT entries may need to be emitted for branches that target the core module, modify the logic that disregards defined symbols to only disregard symbols that are defined in the same section. Fixes: 35fa91eed817 ("ARM: kernel: merge core and init PLTs") Reported-by: Angus Clark Tested-by: Angus Clark Signed-off-by: Ard Biesheuvel Signed-off-by: Russell King Signed-off-by: Greg Kroah-Hartman --- arch/arm/include/asm/module.h | 9 +++- arch/arm/kernel/module-plts.c | 85 ++++++++++++++++++++++++----------- arch/arm/kernel/module.lds | 1 + 3 files changed, 67 insertions(+), 28 deletions(-) diff --git a/arch/arm/include/asm/module.h b/arch/arm/include/asm/module.h index 464748b9fd7d..ed2319663a1e 100644 --- a/arch/arm/include/asm/module.h +++ b/arch/arm/include/asm/module.h @@ -18,13 +18,18 @@ enum { }; #endif +struct mod_plt_sec { + struct elf32_shdr *plt; + int plt_count; +}; + struct mod_arch_specific { #ifdef CONFIG_ARM_UNWIND struct unwind_table *unwind[ARM_SEC_MAX]; #endif #ifdef CONFIG_ARM_MODULE_PLTS - struct elf32_shdr *plt; - int plt_count; + struct mod_plt_sec core; + struct mod_plt_sec init; #endif }; diff --git a/arch/arm/kernel/module-plts.c b/arch/arm/kernel/module-plts.c index 3a5cba90c971..3d0c2e4dda1d 100644 --- a/arch/arm/kernel/module-plts.c +++ b/arch/arm/kernel/module-plts.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2014 Linaro Ltd. + * Copyright (C) 2014-2017 Linaro Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -31,9 +31,17 @@ struct plt_entries { u32 lit[PLT_ENT_COUNT]; }; +static bool in_init(const struct module *mod, unsigned long loc) +{ + return loc - (u32)mod->init_layout.base < mod->init_layout.size; +} + u32 get_module_plt(struct module *mod, unsigned long loc, Elf32_Addr val) { - struct plt_entries *plt = (struct plt_entries *)mod->arch.plt->sh_addr; + struct mod_plt_sec *pltsec = !in_init(mod, loc) ? &mod->arch.core : + &mod->arch.init; + + struct plt_entries *plt = (struct plt_entries *)pltsec->plt->sh_addr; int idx = 0; /* @@ -41,9 +49,9 @@ u32 get_module_plt(struct module *mod, unsigned long loc, Elf32_Addr val) * relocations are sorted, this will be the last entry we allocated. * (if one exists). */ - if (mod->arch.plt_count > 0) { - plt += (mod->arch.plt_count - 1) / PLT_ENT_COUNT; - idx = (mod->arch.plt_count - 1) % PLT_ENT_COUNT; + if (pltsec->plt_count > 0) { + plt += (pltsec->plt_count - 1) / PLT_ENT_COUNT; + idx = (pltsec->plt_count - 1) % PLT_ENT_COUNT; if (plt->lit[idx] == val) return (u32)&plt->ldr[idx]; @@ -53,8 +61,8 @@ u32 get_module_plt(struct module *mod, unsigned long loc, Elf32_Addr val) plt++; } - mod->arch.plt_count++; - BUG_ON(mod->arch.plt_count * PLT_ENT_SIZE > mod->arch.plt->sh_size); + pltsec->plt_count++; + BUG_ON(pltsec->plt_count * PLT_ENT_SIZE > pltsec->plt->sh_size); if (!idx) /* Populate a new set of entries */ @@ -129,7 +137,7 @@ static bool duplicate_rel(Elf32_Addr base, const Elf32_Rel *rel, int num) /* Count how many PLT entries we may need */ static unsigned int count_plts(const Elf32_Sym *syms, Elf32_Addr base, - const Elf32_Rel *rel, int num) + const Elf32_Rel *rel, int num, Elf32_Word dstidx) { unsigned int ret = 0; const Elf32_Sym *s; @@ -144,13 +152,17 @@ static unsigned int count_plts(const Elf32_Sym *syms, Elf32_Addr base, case R_ARM_THM_JUMP24: /* * We only have to consider branch targets that resolve - * to undefined symbols. This is not simply a heuristic, - * it is a fundamental limitation, since the PLT itself - * is part of the module, and needs to be within range - * as well, so modules can never grow beyond that limit. + * to symbols that are defined in a different section. + * This is not simply a heuristic, it is a fundamental + * limitation, since there is no guaranteed way to emit + * PLT entries sufficiently close to the branch if the + * section size exceeds the range of a branch + * instruction. So ignore relocations against defined + * symbols if they live in the same section as the + * relocation target. */ s = syms + ELF32_R_SYM(rel[i].r_info); - if (s->st_shndx != SHN_UNDEF) + if (s->st_shndx == dstidx) break; /* @@ -161,7 +173,12 @@ static unsigned int count_plts(const Elf32_Sym *syms, Elf32_Addr base, * So we need to support them, but there is no need to * take them into consideration when trying to optimize * this code. So let's only check for duplicates when - * the addend is zero. + * the addend is zero. (Note that calls into the core + * module via init PLT entries could involve section + * relative symbol references with non-zero addends, for + * which we may end up emitting duplicates, but the init + * PLT is released along with the rest of the .init + * region as soon as module loading completes.) */ if (!is_zero_addend_relocation(base, rel + i) || !duplicate_rel(base, rel, i)) @@ -174,7 +191,8 @@ static unsigned int count_plts(const Elf32_Sym *syms, Elf32_Addr base, int module_frob_arch_sections(Elf_Ehdr *ehdr, Elf_Shdr *sechdrs, char *secstrings, struct module *mod) { - unsigned long plts = 0; + unsigned long core_plts = 0; + unsigned long init_plts = 0; Elf32_Shdr *s, *sechdrs_end = sechdrs + ehdr->e_shnum; Elf32_Sym *syms = NULL; @@ -184,13 +202,15 @@ int module_frob_arch_sections(Elf_Ehdr *ehdr, Elf_Shdr *sechdrs, */ for (s = sechdrs; s < sechdrs_end; ++s) { if (strcmp(".plt", secstrings + s->sh_name) == 0) - mod->arch.plt = s; + mod->arch.core.plt = s; + else if (strcmp(".init.plt", secstrings + s->sh_name) == 0) + mod->arch.init.plt = s; else if (s->sh_type == SHT_SYMTAB) syms = (Elf32_Sym *)s->sh_addr; } - if (!mod->arch.plt) { - pr_err("%s: module PLT section missing\n", mod->name); + if (!mod->arch.core.plt || !mod->arch.init.plt) { + pr_err("%s: module PLT section(s) missing\n", mod->name); return -ENOEXEC; } if (!syms) { @@ -213,16 +233,29 @@ int module_frob_arch_sections(Elf_Ehdr *ehdr, Elf_Shdr *sechdrs, /* sort by type and symbol index */ sort(rels, numrels, sizeof(Elf32_Rel), cmp_rel, NULL); - plts += count_plts(syms, dstsec->sh_addr, rels, numrels); + if (strncmp(secstrings + dstsec->sh_name, ".init", 5) != 0) + core_plts += count_plts(syms, dstsec->sh_addr, rels, + numrels, s->sh_info); + else + init_plts += count_plts(syms, dstsec->sh_addr, rels, + numrels, s->sh_info); } - mod->arch.plt->sh_type = SHT_NOBITS; - mod->arch.plt->sh_flags = SHF_EXECINSTR | SHF_ALLOC; - mod->arch.plt->sh_addralign = L1_CACHE_BYTES; - mod->arch.plt->sh_size = round_up(plts * PLT_ENT_SIZE, - sizeof(struct plt_entries)); - mod->arch.plt_count = 0; + mod->arch.core.plt->sh_type = SHT_NOBITS; + mod->arch.core.plt->sh_flags = SHF_EXECINSTR | SHF_ALLOC; + mod->arch.core.plt->sh_addralign = L1_CACHE_BYTES; + mod->arch.core.plt->sh_size = round_up(core_plts * PLT_ENT_SIZE, + sizeof(struct plt_entries)); + mod->arch.core.plt_count = 0; - pr_debug("%s: plt=%x\n", __func__, mod->arch.plt->sh_size); + mod->arch.init.plt->sh_type = SHT_NOBITS; + mod->arch.init.plt->sh_flags = SHF_EXECINSTR | SHF_ALLOC; + mod->arch.init.plt->sh_addralign = L1_CACHE_BYTES; + mod->arch.init.plt->sh_size = round_up(init_plts * PLT_ENT_SIZE, + sizeof(struct plt_entries)); + mod->arch.init.plt_count = 0; + + pr_debug("%s: plt=%x, init.plt=%x\n", __func__, + mod->arch.core.plt->sh_size, mod->arch.init.plt->sh_size); return 0; } diff --git a/arch/arm/kernel/module.lds b/arch/arm/kernel/module.lds index 05881e2b414c..eacb5c67f61e 100644 --- a/arch/arm/kernel/module.lds +++ b/arch/arm/kernel/module.lds @@ -1,3 +1,4 @@ SECTIONS { .plt : { BYTE(0) } + .init.plt : { BYTE(0) } } From 9f6cea2e3bbd6f90b6328423c384083b4572069f Mon Sep 17 00:00:00 2001 From: Vladimir Murzin Date: Mon, 24 Apr 2017 10:40:48 +0100 Subject: [PATCH 347/396] ARM: 8670/1: V7M: Do not corrupt vector table around v7m_invalidate_l1 call commit 6d80594936914e798b1b54b3bfe4bd68d8418966 upstream. We save/restore registers around v7m_invalidate_l1 to address pointed by r12, which is vector table, so the first eight entries are overwritten with a garbage. We already have stack setup at that stage, so use it to save/restore register. Fixes: 6a8146f420be ("ARM: 8609/1: V7M: Add support for the Cortex-M7 processor") Signed-off-by: Vladimir Murzin Signed-off-by: Russell King Signed-off-by: Greg Kroah-Hartman --- arch/arm/mm/proc-v7m.S | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/mm/proc-v7m.S b/arch/arm/mm/proc-v7m.S index 8dea61640cc1..50497778c2e5 100644 --- a/arch/arm/mm/proc-v7m.S +++ b/arch/arm/mm/proc-v7m.S @@ -147,10 +147,10 @@ __v7m_setup_cont: @ Configure caches (if implemented) teq r8, #0 - stmneia r12, {r0-r6, lr} @ v7m_invalidate_l1 touches r0-r6 + stmneia sp, {r0-r6, lr} @ v7m_invalidate_l1 touches r0-r6 blne v7m_invalidate_l1 teq r8, #0 @ re-evalutae condition - ldmneia r12, {r0-r6, lr} + ldmneia sp, {r0-r6, lr} @ Configure the System Control Register to ensure 8-byte stack alignment @ Note the STKALIGN bit is either RW or RAO. From 086ea4b9510c5157e7ec168e977a40cdb5e3d14b Mon Sep 17 00:00:00 2001 From: Ludovic Desroches Date: Mon, 10 Apr 2017 10:25:16 +0200 Subject: [PATCH 348/396] ARM: dts: at91: sama5d3_xplained: fix ADC vref commit 9cdd31e5913c1f86dce7e201b086155b3f24896b upstream. The voltage reference for the ADC is not 3V but 3.3V since it is connected to VDDANA. Signed-off-by: Ludovic Desroches Acked-by: Nicolas Ferre Signed-off-by: Alexandre Belloni Signed-off-by: Greg Kroah-Hartman --- arch/arm/boot/dts/at91-sama5d3_xplained.dts | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/boot/dts/at91-sama5d3_xplained.dts b/arch/arm/boot/dts/at91-sama5d3_xplained.dts index c51fc652f6c7..7a0fa1aeb440 100644 --- a/arch/arm/boot/dts/at91-sama5d3_xplained.dts +++ b/arch/arm/boot/dts/at91-sama5d3_xplained.dts @@ -162,6 +162,7 @@ }; adc0: adc@f8018000 { + atmel,adc-vref = <3300>; pinctrl-0 = < &pinctrl_adc0_adtrg &pinctrl_adc0_ad0 From 03d8b264bcb9187a7127efc0bc18eb5dabdb4ce9 Mon Sep 17 00:00:00 2001 From: Ludovic Desroches Date: Mon, 10 Apr 2017 10:25:17 +0200 Subject: [PATCH 349/396] ARM: dts: at91: sama5d3_xplained: not all ADC channels are available commit d3df1ec06353e51fc44563d2e7e18d42811af290 upstream. Remove ADC channels that are not available by default on the sama5d3_xplained board (resistor not populated) in order to not create confusion. Signed-off-by: Ludovic Desroches Acked-by: Nicolas Ferre Signed-off-by: Alexandre Belloni Signed-off-by: Greg Kroah-Hartman --- arch/arm/boot/dts/at91-sama5d3_xplained.dts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/arch/arm/boot/dts/at91-sama5d3_xplained.dts b/arch/arm/boot/dts/at91-sama5d3_xplained.dts index 7a0fa1aeb440..5a53fcf542ab 100644 --- a/arch/arm/boot/dts/at91-sama5d3_xplained.dts +++ b/arch/arm/boot/dts/at91-sama5d3_xplained.dts @@ -163,9 +163,9 @@ adc0: adc@f8018000 { atmel,adc-vref = <3300>; + atmel,adc-channels-used = <0xfe>; pinctrl-0 = < &pinctrl_adc0_adtrg - &pinctrl_adc0_ad0 &pinctrl_adc0_ad1 &pinctrl_adc0_ad2 &pinctrl_adc0_ad3 @@ -173,8 +173,6 @@ &pinctrl_adc0_ad5 &pinctrl_adc0_ad6 &pinctrl_adc0_ad7 - &pinctrl_adc0_ad8 - &pinctrl_adc0_ad9 >; status = "okay"; }; From 5ee1c675ab92d3c8e25f35b5a4a83aa9d62d741d Mon Sep 17 00:00:00 2001 From: Leonard Crestez Date: Fri, 5 May 2017 14:00:17 +0300 Subject: [PATCH 350/396] ARM: dts: imx6sx-sdb: Remove OPP override commit d8581c7c8be172dac156a19d261f988a72ce596f upstream. The board file for imx6sx-sdb overrides cpufreq operating points to use higher voltages. This is done because the board has a shared rail for VDD_ARM_IN and VDD_SOC_IN and when using LDO bypass the shared voltage needs to be a value suitable for both ARM and SOC. This only applies to LDO bypass mode, a feature not present in upstream. When LDOs are enabled the effect is to use higher voltages than necessary for no good reason. Setting these higher voltages can make some boards fail to boot with ugly semi-random crashes reminiscent of memory corruption. These failures only happen on board rev. C, rev. B is reported to still work. Signed-off-by: Leonard Crestez Fixes: 54183bd7f766 ("ARM: imx6sx-sdb: add revb board and make it default") Signed-off-by: Shawn Guo Signed-off-by: Greg Kroah-Hartman --- arch/arm/boot/dts/imx6sx-sdb.dts | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/arch/arm/boot/dts/imx6sx-sdb.dts b/arch/arm/boot/dts/imx6sx-sdb.dts index 5bb8fd57e7f5..d71da30c9cff 100644 --- a/arch/arm/boot/dts/imx6sx-sdb.dts +++ b/arch/arm/boot/dts/imx6sx-sdb.dts @@ -12,23 +12,6 @@ model = "Freescale i.MX6 SoloX SDB RevB Board"; }; -&cpu0 { - operating-points = < - /* kHz uV */ - 996000 1250000 - 792000 1175000 - 396000 1175000 - 198000 1175000 - >; - fsl,soc-operating-points = < - /* ARM kHz SOC uV */ - 996000 1250000 - 792000 1175000 - 396000 1175000 - 198000 1175000 - >; -}; - &i2c1 { clock-frequency = <100000>; pinctrl-names = "default"; From 31a331c8cf2643b36c651fc94eccedcbf0de10c6 Mon Sep 17 00:00:00 2001 From: Daniel Lezcano Date: Thu, 16 Mar 2017 15:03:24 +0100 Subject: [PATCH 351/396] arm64: dts: hi6220: Reset the mmc hosts commit 0fbdf9953b41c28845fe8d05007ff09634ee3000 upstream. The MMC hosts could be left in an unconsistent or uninitialized state from the firmware. Instead of assuming, the firmware did the right things, let's reset the host controllers. This change fixes a bug when the mmc2/sdio is initialized leading to a hung task: [ 242.704294] INFO: task kworker/7:1:675 blocked for more than 120 seconds. [ 242.711129] Not tainted 4.9.0-rc8-00017-gcf0251f #3 [ 242.716571] "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message. [ 242.724435] kworker/7:1 D 0 675 2 0x00000000 [ 242.729973] Workqueue: events_freezable mmc_rescan [ 242.734796] Call trace: [ 242.737269] [] __switch_to+0xa8/0xb4 [ 242.742437] [] __schedule+0x1c0/0x67c [ 242.747689] [] schedule+0x40/0xa0 [ 242.752594] [] schedule_timeout+0x1c4/0x35c [ 242.758366] [] wait_for_common+0xd0/0x15c [ 242.763964] [] wait_for_completion+0x28/0x34 [ 242.769825] [] mmc_wait_for_req_done+0x40/0x124 [ 242.775949] [] mmc_wait_for_req+0xc0/0xf8 [ 242.781549] [] mmc_wait_for_cmd+0x6c/0x84 [ 242.787149] [] mmc_io_rw_direct_host+0x9c/0x114 [ 242.793270] [] sdio_reset+0x34/0x7c [ 242.798347] [] mmc_rescan+0x2fc/0x360 [ ... ] Signed-off-by: Daniel Lezcano Signed-off-by: Wei Xu Signed-off-by: Greg Kroah-Hartman --- arch/arm64/boot/dts/hisilicon/hi6220.dtsi | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/arm64/boot/dts/hisilicon/hi6220.dtsi b/arch/arm64/boot/dts/hisilicon/hi6220.dtsi index 17839db585d5..509a2eda2ce4 100644 --- a/arch/arm64/boot/dts/hisilicon/hi6220.dtsi +++ b/arch/arm64/boot/dts/hisilicon/hi6220.dtsi @@ -772,6 +772,7 @@ clocks = <&sys_ctrl 2>, <&sys_ctrl 1>; clock-names = "ciu", "biu"; resets = <&sys_ctrl PERIPH_RSTDIS0_MMC0>; + reset-names = "reset"; bus-width = <0x8>; vmmc-supply = <&ldo19>; pinctrl-names = "default"; @@ -795,6 +796,7 @@ clocks = <&sys_ctrl 4>, <&sys_ctrl 3>; clock-names = "ciu", "biu"; resets = <&sys_ctrl PERIPH_RSTDIS0_MMC1>; + reset-names = "reset"; vqmmc-supply = <&ldo7>; vmmc-supply = <&ldo10>; bus-width = <0x4>; @@ -813,6 +815,7 @@ clocks = <&sys_ctrl HI6220_MMC2_CIUCLK>, <&sys_ctrl HI6220_MMC2_CLK>; clock-names = "ciu", "biu"; resets = <&sys_ctrl PERIPH_RSTDIS0_MMC2>; + reset-names = "reset"; bus-width = <0x4>; broken-cd; pinctrl-names = "default", "idle"; From 88675139a81dcc1305270de5f22205668a1ea796 Mon Sep 17 00:00:00 2001 From: Mark Rutland Date: Wed, 3 May 2017 16:09:33 +0100 Subject: [PATCH 352/396] arm64: xchg: hazard against entire exchange variable commit fee960bed5e857eb126c4e56dd9ff85938356579 upstream. The inline assembly in __XCHG_CASE() uses a +Q constraint to hazard against other accesses to the memory location being exchanged. However, the pointer passed to the constraint is a u8 pointer, and thus the hazard only applies to the first byte of the location. GCC can take advantage of this, assuming that other portions of the location are unchanged, as demonstrated with the following test case: union u { unsigned long l; unsigned int i[2]; }; unsigned long update_char_hazard(union u *u) { unsigned int a, b; a = u->i[1]; asm ("str %1, %0" : "+Q" (*(char *)&u->l) : "r" (0UL)); b = u->i[1]; return a ^ b; } unsigned long update_long_hazard(union u *u) { unsigned int a, b; a = u->i[1]; asm ("str %1, %0" : "+Q" (*(long *)&u->l) : "r" (0UL)); b = u->i[1]; return a ^ b; } The linaro 15.08 GCC 5.1.1 toolchain compiles the above as follows when using -O2 or above: 0000000000000000 : 0: d2800001 mov x1, #0x0 // #0 4: f9000001 str x1, [x0] 8: d2800000 mov x0, #0x0 // #0 c: d65f03c0 ret 0000000000000010 : 10: b9400401 ldr w1, [x0,#4] 14: d2800002 mov x2, #0x0 // #0 18: f9000002 str x2, [x0] 1c: b9400400 ldr w0, [x0,#4] 20: 4a000020 eor w0, w1, w0 24: d65f03c0 ret This patch fixes the issue by passing an unsigned long pointer into the +Q constraint, as we do for our cmpxchg code. This may hazard against more than is necessary, but this is better than missing a necessary hazard. Fixes: 305d454aaa29 ("arm64: atomics: implement native {relaxed, acquire, release} atomics") Acked-by: Will Deacon Signed-off-by: Mark Rutland Signed-off-by: Catalin Marinas Signed-off-by: Greg Kroah-Hartman --- arch/arm64/include/asm/cmpxchg.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/include/asm/cmpxchg.h b/arch/arm64/include/asm/cmpxchg.h index 91b26d26af8a..ae852add053d 100644 --- a/arch/arm64/include/asm/cmpxchg.h +++ b/arch/arm64/include/asm/cmpxchg.h @@ -46,7 +46,7 @@ static inline unsigned long __xchg_case_##name(unsigned long x, \ " swp" #acq_lse #rel #sz "\t%" #w "3, %" #w "0, %2\n" \ __nops(3) \ " " #nop_lse) \ - : "=&r" (ret), "=&r" (tmp), "+Q" (*(u8 *)ptr) \ + : "=&r" (ret), "=&r" (tmp), "+Q" (*(unsigned long *)ptr) \ : "r" (x) \ : cl); \ \ From f2e4f4e538f073029e672d057e574ca8ba4c9c32 Mon Sep 17 00:00:00 2001 From: Mark Rutland Date: Wed, 3 May 2017 16:09:34 +0100 Subject: [PATCH 353/396] arm64: ensure extension of smp_store_release value commit 994870bead4ab19087a79492400a5478e2906196 upstream. When an inline assembly operand's type is narrower than the register it is allocated to, the least significant bits of the register (up to the operand type's width) are valid, and any other bits are permitted to contain any arbitrary value. This aligns with the AAPCS64 parameter passing rules. Our __smp_store_release() implementation does not account for this, and implicitly assumes that operands have been zero-extended to the width of the type being stored to. Thus, we may store unknown values to memory when the value type is narrower than the pointer type (e.g. when storing a char to a long). This patch fixes the issue by casting the value operand to the same width as the pointer operand in all cases, which ensures that the value is zero-extended as we expect. We use the same union trickery as __smp_load_acquire and {READ,WRITE}_ONCE() to avoid GCC complaining that pointers are potentially cast to narrower width integers in unreachable paths. A whitespace issue at the top of __smp_store_release() is also corrected. No changes are necessary for __smp_load_acquire(). Load instructions implicitly clear any upper bits of the register, and the compiler will only consider the least significant bits of the register as valid regardless. Fixes: 47933ad41a86 ("arch: Introduce smp_load_acquire(), smp_store_release()") Fixes: 878a84d5a8a1 ("arm64: add missing data types in smp_load_acquire/smp_store_release") Acked-by: Will Deacon Signed-off-by: Mark Rutland Cc: Matthias Kaehlcke Signed-off-by: Catalin Marinas Signed-off-by: Greg Kroah-Hartman --- arch/arm64/include/asm/barrier.h | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/arch/arm64/include/asm/barrier.h b/arch/arm64/include/asm/barrier.h index 4e0497f581a0..0fe7e43b7fbc 100644 --- a/arch/arm64/include/asm/barrier.h +++ b/arch/arm64/include/asm/barrier.h @@ -42,25 +42,35 @@ #define __smp_rmb() dmb(ishld) #define __smp_wmb() dmb(ishst) -#define __smp_store_release(p, v) \ +#define __smp_store_release(p, v) \ do { \ + union { typeof(*p) __val; char __c[1]; } __u = \ + { .__val = (__force typeof(*p)) (v) }; \ compiletime_assert_atomic_type(*p); \ switch (sizeof(*p)) { \ case 1: \ asm volatile ("stlrb %w1, %0" \ - : "=Q" (*p) : "r" (v) : "memory"); \ + : "=Q" (*p) \ + : "r" (*(__u8 *)__u.__c) \ + : "memory"); \ break; \ case 2: \ asm volatile ("stlrh %w1, %0" \ - : "=Q" (*p) : "r" (v) : "memory"); \ + : "=Q" (*p) \ + : "r" (*(__u16 *)__u.__c) \ + : "memory"); \ break; \ case 4: \ asm volatile ("stlr %w1, %0" \ - : "=Q" (*p) : "r" (v) : "memory"); \ + : "=Q" (*p) \ + : "r" (*(__u32 *)__u.__c) \ + : "memory"); \ break; \ case 8: \ asm volatile ("stlr %1, %0" \ - : "=Q" (*p) : "r" (v) : "memory"); \ + : "=Q" (*p) \ + : "r" (*(__u64 *)__u.__c) \ + : "memory"); \ break; \ } \ } while (0) From 4775fbcc92d79be414046dd208beb767ed5168e2 Mon Sep 17 00:00:00 2001 From: Mark Rutland Date: Wed, 3 May 2017 16:09:36 +0100 Subject: [PATCH 354/396] arm64: armv8_deprecated: ensure extension of addr commit 55de49f9aa17b0b2b144dd2af587177b9aadf429 upstream. Our compat swp emulation holds the compat user address in an unsigned int, which it passes to __user_swpX_asm(). When a 32-bit value is passed in a register, the upper 32 bits of the register are unknown, and we must extend the value to 64 bits before we can use it as a base address. This patch casts the address to unsigned long to ensure it has been suitably extended, avoiding the potential issue, and silencing a related warning from clang. Fixes: bd35a4adc413 ("arm64: Port SWP/SWPB emulation support from arm") Acked-by: Will Deacon Signed-off-by: Mark Rutland Signed-off-by: Catalin Marinas Signed-off-by: Greg Kroah-Hartman --- arch/arm64/kernel/armv8_deprecated.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/arm64/kernel/armv8_deprecated.c b/arch/arm64/kernel/armv8_deprecated.c index b0988bb1bf64..c0ede237c14b 100644 --- a/arch/arm64/kernel/armv8_deprecated.c +++ b/arch/arm64/kernel/armv8_deprecated.c @@ -309,7 +309,8 @@ static void __init register_insn_emulation_sysctl(struct ctl_table *table) ALTERNATIVE("nop", SET_PSTATE_PAN(1), ARM64_HAS_PAN, \ CONFIG_ARM64_PAN) \ : "=&r" (res), "+r" (data), "=&r" (temp), "=&r" (temp2) \ - : "r" (addr), "i" (-EAGAIN), "i" (-EFAULT), \ + : "r" ((unsigned long)addr), "i" (-EAGAIN), \ + "i" (-EFAULT), \ "i" (__SWP_LL_SC_LOOPS) \ : "memory") From e817a7fb2f31c2fafc8e6e2dbf649bbd65b2f604 Mon Sep 17 00:00:00 2001 From: Mark Rutland Date: Wed, 3 May 2017 16:09:35 +0100 Subject: [PATCH 355/396] arm64: uaccess: ensure extension of access_ok() addr commit a06040d7a791a9177581dcf7293941bd92400856 upstream. Our access_ok() simply hands its arguments over to __range_ok(), which implicitly assummes that the addr parameter is 64 bits wide. This isn't necessarily true for compat code, which might pass down a 32-bit address parameter. In these cases, we don't have a guarantee that the address has been zero extended to 64 bits, and the upper bits of the register may contain unknown values, potentially resulting in a suprious failure. Avoid this by explicitly casting the addr parameter to an unsigned long (as is done on other architectures), ensuring that the parameter is widened appropriately. Fixes: 0aea86a2176c ("arm64: User access library functions") Acked-by: Will Deacon Signed-off-by: Mark Rutland Signed-off-by: Catalin Marinas Signed-off-by: Greg Kroah-Hartman --- arch/arm64/include/asm/uaccess.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/arm64/include/asm/uaccess.h b/arch/arm64/include/asm/uaccess.h index 55d0adbf6509..14cca10aeb4e 100644 --- a/arch/arm64/include/asm/uaccess.h +++ b/arch/arm64/include/asm/uaccess.h @@ -93,11 +93,12 @@ static inline void set_fs(mm_segment_t fs) */ #define __range_ok(addr, size) \ ({ \ + unsigned long __addr = (unsigned long __force)(addr); \ unsigned long flag, roksum; \ __chk_user_ptr(addr); \ asm("adds %1, %1, %3; ccmp %1, %4, #2, cc; cset %0, ls" \ : "=&r" (flag), "=&r" (roksum) \ - : "1" (addr), "Ir" (size), \ + : "1" (__addr), "Ir" (size), \ "r" (current_thread_info()->addr_limit) \ : "cc"); \ flag; \ From e6b8f5ade3059be9cf8ab5a290c312d463b54a39 Mon Sep 17 00:00:00 2001 From: Kristina Martsenko Date: Wed, 3 May 2017 16:37:48 +0100 Subject: [PATCH 356/396] arm64: documentation: document tagged pointer stack constraints commit f0e421b1bf7af97f026e1bb8bfe4c5a7a8c08f42 upstream. Some kernel features don't currently work if a task puts a non-zero address tag in its stack pointer, frame pointer, or frame record entries (FP, LR). For example, with a tagged stack pointer, the kernel can't deliver signals to the process, and the task is killed instead. As another example, with a tagged frame pointer or frame records, perf fails to generate call graphs or resolve symbols. For now, just document these limitations, instead of finding and fixing everything that doesn't work, as it's not known if anyone needs to use tags in these places anyway. In addition, as requested by Dave Martin, generalize the limitations into a general kernel address tag policy, and refactor tagged-pointers.txt to include it. Fixes: d50240a5f6ce ("arm64: mm: permit use of tagged pointers at EL0") Reviewed-by: Dave Martin Acked-by: Will Deacon Signed-off-by: Kristina Martsenko Signed-off-by: Catalin Marinas Signed-off-by: Greg Kroah-Hartman --- Documentation/arm64/tagged-pointers.txt | 62 +++++++++++++++++++------ 1 file changed, 47 insertions(+), 15 deletions(-) diff --git a/Documentation/arm64/tagged-pointers.txt b/Documentation/arm64/tagged-pointers.txt index d9995f1f51b3..a25a99e82bb1 100644 --- a/Documentation/arm64/tagged-pointers.txt +++ b/Documentation/arm64/tagged-pointers.txt @@ -11,24 +11,56 @@ in AArch64 Linux. The kernel configures the translation tables so that translations made via TTBR0 (i.e. userspace mappings) have the top byte (bits 63:56) of the virtual address ignored by the translation hardware. This frees up -this byte for application use, with the following caveats: +this byte for application use. - (1) The kernel requires that all user addresses passed to EL1 - are tagged with tag 0x00. This means that any syscall - parameters containing user virtual addresses *must* have - their top byte cleared before trapping to the kernel. - (2) Non-zero tags are not preserved when delivering signals. - This means that signal handlers in applications making use - of tags cannot rely on the tag information for user virtual - addresses being maintained for fields inside siginfo_t. - One exception to this rule is for signals raised in response - to watchpoint debug exceptions, where the tag information - will be preserved. +Passing tagged addresses to the kernel +-------------------------------------- - (3) Special care should be taken when using tagged pointers, - since it is likely that C compilers will not hazard two - virtual addresses differing only in the upper byte. +All interpretation of userspace memory addresses by the kernel assumes +an address tag of 0x00. + +This includes, but is not limited to, addresses found in: + + - pointer arguments to system calls, including pointers in structures + passed to system calls, + + - the stack pointer (sp), e.g. when interpreting it to deliver a + signal, + + - the frame pointer (x29) and frame records, e.g. when interpreting + them to generate a backtrace or call graph. + +Using non-zero address tags in any of these locations may result in an +error code being returned, a (fatal) signal being raised, or other modes +of failure. + +For these reasons, passing non-zero address tags to the kernel via +system calls is forbidden, and using a non-zero address tag for sp is +strongly discouraged. + +Programs maintaining a frame pointer and frame records that use non-zero +address tags may suffer impaired or inaccurate debug and profiling +visibility. + + +Preserving tags +--------------- + +Non-zero tags are not preserved when delivering signals. This means that +signal handlers in applications making use of tags cannot rely on the +tag information for user virtual addresses being maintained for fields +inside siginfo_t. One exception to this rule is for signals raised in +response to watchpoint debug exceptions, where the tag information will +be preserved. The architecture prevents the use of a tagged PC, so the upper byte will be set to a sign-extension of bit 55 on exception return. + + +Other considerations +-------------------- + +Special care should be taken when using tagged pointers, since it is +likely that C compilers will not hazard two virtual addresses differing +only in the upper byte. From f4205502948b5825254e31d9c82d377beb85d100 Mon Sep 17 00:00:00 2001 From: Malcolm Priestley Date: Thu, 11 May 2017 18:57:43 +0100 Subject: [PATCH 357/396] staging: rtl8192e: rtl92e_fill_tx_desc fix write to mapped out memory. commit baabd567f87be05330faa5140f72a91960e7405a upstream. The driver attempts to alter memory that is mapped to PCI device. This is because tx_fwinfo_8190pci points to skb->data Move the pci_map_single to when completed buffer is ready to be mapped with psdec is empty to drop on mapping error. Signed-off-by: Malcolm Priestley Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8192e/rtl8192e/r8192E_dev.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/drivers/staging/rtl8192e/rtl8192e/r8192E_dev.c b/drivers/staging/rtl8192e/rtl8192e/r8192E_dev.c index 8d6bca61e7aa..fa1440e15382 100644 --- a/drivers/staging/rtl8192e/rtl8192e/r8192E_dev.c +++ b/drivers/staging/rtl8192e/rtl8192e/r8192E_dev.c @@ -1184,8 +1184,7 @@ void rtl92e_fill_tx_desc(struct net_device *dev, struct tx_desc *pdesc, struct cb_desc *cb_desc, struct sk_buff *skb) { struct r8192_priv *priv = rtllib_priv(dev); - dma_addr_t mapping = pci_map_single(priv->pdev, skb->data, skb->len, - PCI_DMA_TODEVICE); + dma_addr_t mapping; struct tx_fwinfo_8190pci *pTxFwInfo; pTxFwInfo = (struct tx_fwinfo_8190pci *)skb->data; @@ -1196,8 +1195,6 @@ void rtl92e_fill_tx_desc(struct net_device *dev, struct tx_desc *pdesc, pTxFwInfo->Short = _rtl92e_query_is_short(pTxFwInfo->TxHT, pTxFwInfo->TxRate, cb_desc); - if (pci_dma_mapping_error(priv->pdev, mapping)) - netdev_err(dev, "%s(): DMA Mapping error\n", __func__); if (cb_desc->bAMPDUEnable) { pTxFwInfo->AllowAggregation = 1; pTxFwInfo->RxMF = cb_desc->ampdu_factor; @@ -1232,6 +1229,14 @@ void rtl92e_fill_tx_desc(struct net_device *dev, struct tx_desc *pdesc, } memset((u8 *)pdesc, 0, 12); + + mapping = pci_map_single(priv->pdev, skb->data, skb->len, + PCI_DMA_TODEVICE); + if (pci_dma_mapping_error(priv->pdev, mapping)) { + netdev_err(dev, "%s(): DMA Mapping error\n", __func__); + return; + } + pdesc->LINIP = 0; pdesc->CmdInit = 1; pdesc->Offset = sizeof(struct tx_fwinfo_8190pci) + 8; From d0226f9adaf86597176dde4c794c935bb5d25656 Mon Sep 17 00:00:00 2001 From: Malcolm Priestley Date: Thu, 11 May 2017 18:57:44 +0100 Subject: [PATCH 358/396] staging: rtl8192e: fix 2 byte alignment of register BSSIDR. commit 867510bde14e7b7fc6dd0f50b48f6753cfbd227a upstream. BSSIDR has two byte alignment on PCI ioremap correct the write by swapping to 16 bits first. This fixes a problem that the device associates fail because the filter is not set correctly. Signed-off-by: Malcolm Priestley Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8192e/rtl8192e/r8192E_dev.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/staging/rtl8192e/rtl8192e/r8192E_dev.c b/drivers/staging/rtl8192e/rtl8192e/r8192E_dev.c index fa1440e15382..f1f307fa87dd 100644 --- a/drivers/staging/rtl8192e/rtl8192e/r8192E_dev.c +++ b/drivers/staging/rtl8192e/rtl8192e/r8192E_dev.c @@ -97,8 +97,9 @@ void rtl92e_set_reg(struct net_device *dev, u8 variable, u8 *val) switch (variable) { case HW_VAR_BSSID: - rtl92e_writel(dev, BSSIDR, ((u32 *)(val))[0]); - rtl92e_writew(dev, BSSIDR+2, ((u16 *)(val+2))[0]); + /* BSSIDR 2 byte alignment */ + rtl92e_writew(dev, BSSIDR, *(u16 *)val); + rtl92e_writel(dev, BSSIDR + 2, *(u32 *)(val + 2)); break; case HW_VAR_MEDIA_STATUS: @@ -963,8 +964,8 @@ static void _rtl92e_net_update(struct net_device *dev) rtl92e_config_rate(dev, &rate_config); priv->dot11CurrentPreambleMode = PREAMBLE_AUTO; priv->basic_rate = rate_config &= 0x15f; - rtl92e_writel(dev, BSSIDR, ((u32 *)net->bssid)[0]); - rtl92e_writew(dev, BSSIDR+4, ((u16 *)net->bssid)[2]); + rtl92e_writew(dev, BSSIDR, *(u16 *)net->bssid); + rtl92e_writel(dev, BSSIDR + 2, *(u32 *)(net->bssid + 2)); if (priv->rtllib->iw_mode == IW_MODE_ADHOC) { rtl92e_writew(dev, ATIMWND, 2); From 93a46fe4eb41e7fa575b9b995659af52c2241868 Mon Sep 17 00:00:00 2001 From: Malcolm Priestley Date: Thu, 11 May 2017 18:57:45 +0100 Subject: [PATCH 359/396] staging: rtl8192e: rtl92e_get_eeprom_size Fix read size of EPROM_CMD. commit 90be652c9f157d44b9c2803f902a8839796c090d upstream. EPROM_CMD is 2 byte aligned on PCI map so calling with rtl92e_readl will return invalid data so use rtl92e_readw. The device is unable to select the right eeprom type. Signed-off-by: Malcolm Priestley Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8192e/rtl8192e/r8192E_dev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/rtl8192e/rtl8192e/r8192E_dev.c b/drivers/staging/rtl8192e/rtl8192e/r8192E_dev.c index f1f307fa87dd..591f2740e5af 100644 --- a/drivers/staging/rtl8192e/rtl8192e/r8192E_dev.c +++ b/drivers/staging/rtl8192e/rtl8192e/r8192E_dev.c @@ -627,7 +627,7 @@ void rtl92e_get_eeprom_size(struct net_device *dev) struct r8192_priv *priv = rtllib_priv(dev); RT_TRACE(COMP_INIT, "===========>%s()\n", __func__); - curCR = rtl92e_readl(dev, EPROM_CMD); + curCR = rtl92e_readw(dev, EPROM_CMD); RT_TRACE(COMP_INIT, "read from Reg Cmd9346CR(%x):%x\n", EPROM_CMD, curCR); priv->epromtype = (curCR & EPROM_CMD_9356SEL) ? EEPROM_93C56 : From 58e36d6f7f11815d3be279f58fd44da1203b4aa1 Mon Sep 17 00:00:00 2001 From: Malcolm Priestley Date: Thu, 11 May 2017 18:57:46 +0100 Subject: [PATCH 360/396] staging: rtl8192e: GetTs Fix invalid TID 7 warning. commit 95d93e271d920dfda369d4740b1cc1061d41fe7f upstream. TID 7 is a valid value for QoS IEEE 802.11e. The switch statement that follows states 7 is valid. Remove function IsACValid and use the default case to filter invalid TIDs. Signed-off-by: Malcolm Priestley Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8192e/rtl819x_TSProc.c | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/drivers/staging/rtl8192e/rtl819x_TSProc.c b/drivers/staging/rtl8192e/rtl819x_TSProc.c index a966a8e490ab..4615a6f0128e 100644 --- a/drivers/staging/rtl8192e/rtl819x_TSProc.c +++ b/drivers/staging/rtl8192e/rtl819x_TSProc.c @@ -306,11 +306,6 @@ static void MakeTSEntry(struct ts_common_info *pTsCommonInfo, u8 *Addr, pTsCommonInfo->TClasNum = TCLAS_Num; } -static bool IsACValid(unsigned int tid) -{ - return tid < 7; -} - bool GetTs(struct rtllib_device *ieee, struct ts_common_info **ppTS, u8 *Addr, u8 TID, enum tr_select TxRxSelect, bool bAddNewTs) { @@ -328,12 +323,6 @@ bool GetTs(struct rtllib_device *ieee, struct ts_common_info **ppTS, if (ieee->current_network.qos_data.supported == 0) { UP = 0; } else { - if (!IsACValid(TID)) { - netdev_warn(ieee->dev, "%s(): TID(%d) is not valid\n", - __func__, TID); - return false; - } - switch (TID) { case 0: case 3: @@ -351,6 +340,10 @@ bool GetTs(struct rtllib_device *ieee, struct ts_common_info **ppTS, case 7: UP = 7; break; + default: + netdev_warn(ieee->dev, "%s(): TID(%d) is not valid\n", + __func__, TID); + return false; } } From 21f2950f91ff080b0d3f13f2983b9b39c95b8714 Mon Sep 17 00:00:00 2001 From: KarimAllah Ahmed Date: Fri, 5 May 2017 11:39:59 -0700 Subject: [PATCH 361/396] iommu/vt-d: Flush the IOTLB to get rid of the initial kdump mappings commit f73a7eee900e95404b61408a23a1df5c5811704c upstream. Ever since commit 091d42e43d ("iommu/vt-d: Copy translation tables from old kernel") the kdump kernel copies the IOMMU context tables from the previous kernel. Each device mappings will be destroyed once the driver for the respective device takes over. This unfortunately breaks the workflow of mapping and unmapping a new context to the IOMMU. The mapping function assumes that either: 1) Unmapping did the proper IOMMU flushing and it only ever flush if the IOMMU unit supports caching invalid entries. 2) The system just booted and the initialization code took care of flushing all IOMMU caches. This assumption is not true for the kdump kernel since the context tables have been copied from the previous kernel and translations could have been cached ever since. So make sure to flush the IOTLB as well when we destroy these old copied mappings. Cc: Joerg Roedel Cc: David Woodhouse Cc: David Woodhouse Cc: Anthony Liguori Signed-off-by: KarimAllah Ahmed Acked-by: David Woodhouse Fixes: 091d42e43d ("iommu/vt-d: Copy translation tables from old kernel") Signed-off-by: Joerg Roedel Signed-off-by: Greg Kroah-Hartman --- drivers/iommu/intel-iommu.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c index b9e50c10213b..87fcbf71b85a 100644 --- a/drivers/iommu/intel-iommu.c +++ b/drivers/iommu/intel-iommu.c @@ -2049,11 +2049,14 @@ static int domain_context_mapping_one(struct dmar_domain *domain, if (context_copied(context)) { u16 did_old = context_domain_id(context); - if (did_old >= 0 && did_old < cap_ndoms(iommu->cap)) + if (did_old >= 0 && did_old < cap_ndoms(iommu->cap)) { iommu->flush.flush_context(iommu, did_old, (((u16)bus) << 8) | devfn, DMA_CCMD_MASK_NOBIT, DMA_CCMD_DEVICE_INVL); + iommu->flush.flush_iotlb(iommu, did_old, 0, 0, + DMA_TLB_DSI_FLUSH); + } } pgd = domain->pgd; From 9fefcb947ec2c2b6900b4c10aface329af0fd9c5 Mon Sep 17 00:00:00 2001 From: James Hogan Date: Fri, 28 Apr 2017 10:50:26 +0100 Subject: [PATCH 362/396] metag/uaccess: Fix access_ok() commit 8a8b56638bcac4e64cccc88bf95a0f9f4b19a2fb upstream. The __user_bad() macro used by access_ok() has a few corner cases noticed by Al Viro where it doesn't behave correctly: - The kernel range check has off by 1 errors which permit access to the first and last byte of the kernel mapped range. - The kernel range check ends at LINCORE_BASE rather than META_MEMORY_LIMIT, which is ineffective when the kernel is in global space (an extremely uncommon configuration). There are a couple of other shortcomings here too: - Access to the whole of the other address space is permitted (i.e. the global half of the address space when the kernel is in local space). This isn't ideal as it could theoretically still contain privileged mappings set up by the bootloader. - The size argument is unused, permitting user copies which start on valid pages at the end of the user address range and cross the boundary into the kernel address space (e.g. addr = 0x3ffffff0, size > 0x10). It isn't very convenient to add size checks when disallowing certain regions, and it seems far safer to be sure and explicit about what userland is able to access, so invert the logic to allow certain regions instead, and fix the off by 1 errors and missing size checks. This also allows the get_fs() == KERNEL_DS check to be more easily optimised into the user address range case. We now have 3 such allowed regions: - The user address range (incorporating the get_fs() == KERNEL_DS check). - NULL (some kernel code expects this to work, and we'll always catch the fault anyway). - The core code memory region. Fixes: 373cd784d0fc ("metag: Memory handling") Reported-by: Al Viro Signed-off-by: James Hogan Cc: linux-metag@vger.kernel.org Signed-off-by: Greg Kroah-Hartman --- arch/metag/include/asm/uaccess.h | 40 +++++++++++++++++++------------- 1 file changed, 24 insertions(+), 16 deletions(-) diff --git a/arch/metag/include/asm/uaccess.h b/arch/metag/include/asm/uaccess.h index 07238b39638c..ed6cd90ec5ca 100644 --- a/arch/metag/include/asm/uaccess.h +++ b/arch/metag/include/asm/uaccess.h @@ -28,24 +28,32 @@ #define segment_eq(a, b) ((a).seg == (b).seg) -#define __kernel_ok (segment_eq(get_fs(), KERNEL_DS)) -/* - * Explicitly allow NULL pointers here. Parts of the kernel such - * as readv/writev use access_ok to validate pointers, but want - * to allow NULL pointers for various reasons. NULL pointers are - * safe to allow through because the first page is not mappable on - * Meta. - * - * We also wish to avoid letting user code access the system area - * and the kernel half of the address space. - */ -#define __user_bad(addr, size) (((addr) > 0 && (addr) < META_MEMORY_BASE) || \ - ((addr) > PAGE_OFFSET && \ - (addr) < LINCORE_BASE)) - static inline int __access_ok(unsigned long addr, unsigned long size) { - return __kernel_ok || !__user_bad(addr, size); + /* + * Allow access to the user mapped memory area, but not the system area + * before it. The check extends to the top of the address space when + * kernel access is allowed (there's no real reason to user copy to the + * system area in any case). + */ + if (likely(addr >= META_MEMORY_BASE && addr < get_fs().seg && + size <= get_fs().seg - addr)) + return true; + /* + * Explicitly allow NULL pointers here. Parts of the kernel such + * as readv/writev use access_ok to validate pointers, but want + * to allow NULL pointers for various reasons. NULL pointers are + * safe to allow through because the first page is not mappable on + * Meta. + */ + if (!addr) + return true; + /* Allow access to core code memory area... */ + if (addr >= LINCORE_CODE_BASE && addr <= LINCORE_CODE_LIMIT && + size <= LINCORE_CODE_LIMIT + 1 - addr) + return true; + /* ... but no other areas. */ + return false; } #define access_ok(type, addr, size) __access_ok((unsigned long)(addr), \ From e8a8a6972c5075e6057264c45614d13f9e0307e5 Mon Sep 17 00:00:00 2001 From: James Hogan Date: Tue, 2 May 2017 19:41:06 +0100 Subject: [PATCH 363/396] metag/uaccess: Check access_ok in strncpy_from_user commit 3a158a62da0673db918b53ac1440845a5b64fd90 upstream. The metag implementation of strncpy_from_user() doesn't validate the src pointer, which could allow reading of arbitrary kernel memory. Add a short access_ok() check to prevent that. Its still possible for it to read across the user/kernel boundary, but it will invariably reach a NUL character after only 9 bytes, leaking only a static kernel address being loaded into D0Re0 at the beginning of __start, which is acceptable for the immediate fix. Reported-by: Al Viro Signed-off-by: James Hogan Cc: linux-metag@vger.kernel.org Signed-off-by: Greg Kroah-Hartman --- arch/metag/include/asm/uaccess.h | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/arch/metag/include/asm/uaccess.h b/arch/metag/include/asm/uaccess.h index ed6cd90ec5ca..3db381205928 100644 --- a/arch/metag/include/asm/uaccess.h +++ b/arch/metag/include/asm/uaccess.h @@ -194,8 +194,13 @@ do { \ extern long __must_check __strncpy_from_user(char *dst, const char __user *src, long count); -#define strncpy_from_user(dst, src, count) __strncpy_from_user(dst, src, count) - +static inline long +strncpy_from_user(char *dst, const char __user *src, long count) +{ + if (!access_ok(VERIFY_READ, src, 1)) + return -EFAULT; + return __strncpy_from_user(dst, src, count); +} /* * Return the size of a string (including the ending 0) * From f157261b55a40a5fe38259d1dcc0a9ff30987b3c Mon Sep 17 00:00:00 2001 From: Daniel Micay Date: Thu, 4 May 2017 09:32:09 -0400 Subject: [PATCH 364/396] stackprotector: Increase the per-task stack canary's random range from 32 bits to 64 bits on 64-bit platforms commit 5ea30e4e58040cfd6434c2f33dc3ea76e2c15b05 upstream. The stack canary is an 'unsigned long' and should be fully initialized to random data rather than only 32 bits of random data. Signed-off-by: Daniel Micay Acked-by: Arjan van de Ven Acked-by: Rik van Riel Acked-by: Kees Cook Cc: Arjan van Ven Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: kernel-hardening@lists.openwall.com Link: http://lkml.kernel.org/r/20170504133209.3053-1-danielmicay@gmail.com Signed-off-by: Ingo Molnar Signed-off-by: Greg Kroah-Hartman --- kernel/fork.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/fork.c b/kernel/fork.c index c994a30f107d..59faac4de181 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -521,7 +521,7 @@ static struct task_struct *dup_task_struct(struct task_struct *orig, int node) set_task_stack_end_magic(tsk); #ifdef CONFIG_CC_STACKPROTECTOR - tsk->stack_canary = get_random_int(); + tsk->stack_canary = get_random_long(); #endif /* From 3fe116563d5ddc2e3a506eb4b227164e5ccaed23 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Fri, 12 May 2017 12:06:32 +0200 Subject: [PATCH 365/396] uwb: fix device quirk on big-endian hosts commit 41318a2b82f5d5fe1fb408f6d6e0b22aa557111d upstream. Add missing endianness conversion when using the USB device-descriptor idProduct field to apply a hardware quirk. Fixes: 1ba47da52712 ("uwb: add the i1480 DFU driver") Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/uwb/i1480/dfu/usb.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/uwb/i1480/dfu/usb.c b/drivers/uwb/i1480/dfu/usb.c index 6345e85822a4..a50cf45e530f 100644 --- a/drivers/uwb/i1480/dfu/usb.c +++ b/drivers/uwb/i1480/dfu/usb.c @@ -341,6 +341,7 @@ error_submit_ep1: static int i1480_usb_probe(struct usb_interface *iface, const struct usb_device_id *id) { + struct usb_device *udev = interface_to_usbdev(iface); struct i1480_usb *i1480_usb; struct i1480 *i1480; struct device *dev = &iface->dev; @@ -352,8 +353,8 @@ int i1480_usb_probe(struct usb_interface *iface, const struct usb_device_id *id) iface->cur_altsetting->desc.bInterfaceNumber); goto error; } - if (iface->num_altsetting > 1 - && interface_to_usbdev(iface)->descriptor.idProduct == 0xbabe) { + if (iface->num_altsetting > 1 && + le16_to_cpu(udev->descriptor.idProduct) == 0xbabe) { /* Need altsetting #1 [HW QUIRK] or EP1 won't work */ result = usb_set_interface(interface_to_usbdev(iface), 0, 1); if (result < 0) From 423f1752a0283b3f54f175be893f610f51b3aaf5 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Thu, 11 May 2017 13:54:11 +0200 Subject: [PATCH 366/396] genirq: Fix chained interrupt data ordering commit 2c4569ca26986d18243f282dd727da27e9adae4c upstream. irq_set_chained_handler_and_data() sets up the chained interrupt and then stores the handler data. That's racy against an immediate interrupt which gets handled before the store of the handler data happened. The handler will dereference a NULL pointer and crash. Cure it by storing handler data before installing the chained handler. Reported-by: Borislav Petkov Signed-off-by: Thomas Gleixner Signed-off-by: Greg Kroah-Hartman --- kernel/irq/chip.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/irq/chip.c b/kernel/irq/chip.c index be3c34e4f2ac..077c87f40f4d 100644 --- a/kernel/irq/chip.c +++ b/kernel/irq/chip.c @@ -877,8 +877,8 @@ irq_set_chained_handler_and_data(unsigned int irq, irq_flow_handler_t handle, if (!desc) return; - __irq_do_set_handler(desc, handle, 1, NULL); desc->irq_common_data.handler_data = data; + __irq_do_set_handler(desc, handle, 1, NULL); irq_put_desc_busunlock(desc, flags); } From 6d6a43a086117930b5acd79c9350e00ef56027fa Mon Sep 17 00:00:00 2001 From: Jon Derrick Date: Fri, 5 May 2017 14:52:06 -0600 Subject: [PATCH 367/396] nvme: unmap CMB and remove sysfs file in reset path commit f63572dff1421b6ca6abce71d46e03411e605c94 upstream. CMB doesn't get unmapped until removal while getting remapped on every reset. Add the unmapping and sysfs file removal to the reset path in nvme_pci_disable to match the mapping path in nvme_pci_enable. Fixes: 202021c1a ("nvme : Add sysfs entry for NVMe CMBs when appropriate") Signed-off-by: Jon Derrick Acked-by: Keith Busch Reviewed-By: Stephen Bates Signed-off-by: Christoph Hellwig Signed-off-by: Jens Axboe Signed-off-by: Greg Kroah-Hartman --- drivers/nvme/host/pci.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c index 8a9c186898c7..14eac73e8dbc 100644 --- a/drivers/nvme/host/pci.c +++ b/drivers/nvme/host/pci.c @@ -1384,6 +1384,11 @@ static inline void nvme_release_cmb(struct nvme_dev *dev) if (dev->cmb) { iounmap(dev->cmb); dev->cmb = NULL; + if (dev->cmbsz) { + sysfs_remove_file_from_group(&dev->ctrl.device->kobj, + &dev_attr_cmb.attr, NULL); + dev->cmbsz = 0; + } } } @@ -1655,6 +1660,7 @@ static void nvme_pci_disable(struct nvme_dev *dev) { struct pci_dev *pdev = to_pci_dev(dev->dev); + nvme_release_cmb(dev); pci_free_irq_vectors(pdev); if (pci_is_enabled(pdev)) { @@ -1993,7 +1999,6 @@ static void nvme_remove(struct pci_dev *pdev) nvme_dev_disable(dev, true); nvme_dev_remove_admin(dev); nvme_free_queues(dev, 0); - nvme_release_cmb(dev); nvme_release_prp_pools(dev); nvme_dev_unmap(dev); nvme_put_ctrl(&dev->ctrl); From 07d8aabff4903065bb472df9b040b8688fdc75a2 Mon Sep 17 00:00:00 2001 From: Huacai Chen Date: Thu, 16 Mar 2017 21:00:28 +0800 Subject: [PATCH 368/396] MIPS: Loongson-3: Select MIPS_L1_CACHE_SHIFT_6 commit 17c99d9421695a0e0de18bf1e7091d859e20ec1d upstream. Some newer Loongson-3 have 64 bytes cache lines, so select MIPS_L1_CACHE_SHIFT_6. Signed-off-by: Huacai Chen Cc: John Crispin Cc: Steven J . Hill Cc: Fuxin Zhang Cc: Zhangjin Wu Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/15755/ Signed-off-by: Ralf Baechle Signed-off-by: Greg Kroah-Hartman --- arch/mips/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 5a4f2eb9d0d5..5e844f68e847 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -1368,6 +1368,7 @@ config CPU_LOONGSON3 select WEAK_ORDERING select WEAK_REORDERING_BEYOND_LLSC select MIPS_PGD_C0_CONTEXT + select MIPS_L1_CACHE_SHIFT_6 select GPIOLIB help The Loongson 3 processor implements the MIPS64R2 instruction From 541c678441980b48d3600d1bda0737219eb81f61 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sun, 14 May 2017 21:47:25 -0400 Subject: [PATCH 369/396] osf_wait4(): fix infoleak commit a8c39544a6eb2093c04afd5005b6192bd0e880c6 upstream. failing sys_wait4() won't fill struct rusage... Signed-off-by: Al Viro Signed-off-by: Greg Kroah-Hartman --- arch/alpha/kernel/osf_sys.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/arch/alpha/kernel/osf_sys.c b/arch/alpha/kernel/osf_sys.c index ffb93f499c83..4f95577b0180 100644 --- a/arch/alpha/kernel/osf_sys.c +++ b/arch/alpha/kernel/osf_sys.c @@ -1188,8 +1188,10 @@ SYSCALL_DEFINE4(osf_wait4, pid_t, pid, int __user *, ustatus, int, options, if (!access_ok(VERIFY_WRITE, ur, sizeof(*ur))) return -EFAULT; - err = 0; - err |= put_user(status, ustatus); + err = put_user(status, ustatus); + if (ret < 0) + return err ? err : ret; + err |= __put_user(r.ru_utime.tv_sec, &ur->ru_utime.tv_sec); err |= __put_user(r.ru_utime.tv_usec, &ur->ru_utime.tv_usec); err |= __put_user(r.ru_stime.tv_sec, &ur->ru_stime.tv_sec); From cc0aa21de47c64f7eb557bd41447a9ebe312c0ab Mon Sep 17 00:00:00 2001 From: Masami Hiramatsu Date: Thu, 27 Apr 2017 12:15:10 +0900 Subject: [PATCH 370/396] um: Fix to call read_initrd after init_bootmem commit 5b4236e17cc1bd9fa14b2b0c7a4ae632d41f2e20 upstream. Since read_initrd() invokes alloc_bootmem() for allocating memory to load initrd image, it must be called after init_bootmem. This makes read_initrd() called directly from setup_arch() after init_bootmem() and mem_total_pages(). Fixes: b63236972e1 ("um: Setup physical memory in setup_arch()") Signed-off-by: Masami Hiramatsu Signed-off-by: Richard Weinberger Signed-off-by: Greg Kroah-Hartman --- arch/um/kernel/initrd.c | 4 +--- arch/um/kernel/um_arch.c | 6 ++++++ 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/arch/um/kernel/initrd.c b/arch/um/kernel/initrd.c index 48bae81f8dca..6f6e7896e53f 100644 --- a/arch/um/kernel/initrd.c +++ b/arch/um/kernel/initrd.c @@ -14,7 +14,7 @@ static char *initrd __initdata = NULL; static int load_initrd(char *filename, void *buf, int size); -static int __init read_initrd(void) +int __init read_initrd(void) { void *area; long long size; @@ -46,8 +46,6 @@ static int __init read_initrd(void) return 0; } -__uml_postsetup(read_initrd); - static int __init uml_initrd_setup(char *line, int *add) { initrd = line; diff --git a/arch/um/kernel/um_arch.c b/arch/um/kernel/um_arch.c index e8175a8aa22c..26b47deca2a0 100644 --- a/arch/um/kernel/um_arch.c +++ b/arch/um/kernel/um_arch.c @@ -336,11 +336,17 @@ int __init linux_main(int argc, char **argv) return start_uml(); } +int __init __weak read_initrd(void) +{ + return 0; +} + void __init setup_arch(char **cmdline_p) { stack_protections((unsigned long) &init_thread_info); setup_physmem(uml_physmem, uml_reserved, physmem_size, highmem); mem_total_pages(physmem_size, iomem_size, highmem); + read_initrd(); paging_init(); strlcpy(boot_command_line, command_line, COMMAND_LINE_SIZE); From dd0023d7105c4266adeb14881c479950d6a9ef2a Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Wed, 17 May 2017 10:19:49 +0200 Subject: [PATCH 371/396] tracing/kprobes: Enforce kprobes teardown after testing commit 30e7d894c1478c88d50ce94ddcdbd7f9763d9cdd upstream. Enabling the tracer selftest triggers occasionally the warning in text_poke(), which warns when the to be modified page is not marked reserved. The reason is that the tracer selftest installs kprobes on functions marked __init for testing. These probes are removed after the tests, but that removal schedules the delayed kprobes_optimizer work, which will do the actual text poke. If the work is executed after the init text is freed, then the warning triggers. The bug can be reproduced reliably when the work delay is increased. Flush the optimizer work and wait for the optimizing/unoptimizing lists to become empty before returning from the kprobes tracer selftest. That ensures that all operations which were queued due to the probes removal have completed. Link: http://lkml.kernel.org/r/20170516094802.76a468bb@gandalf.local.home Signed-off-by: Thomas Gleixner Acked-by: Masami Hiramatsu Fixes: 6274de498 ("kprobes: Support delayed unoptimizing") Signed-off-by: Steven Rostedt (VMware) Signed-off-by: Greg Kroah-Hartman --- include/linux/kprobes.h | 4 +++- kernel/kprobes.c | 2 +- kernel/trace/trace_kprobe.c | 5 +++++ 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/include/linux/kprobes.h b/include/linux/kprobes.h index 8f6849084248..e23392517db9 100644 --- a/include/linux/kprobes.h +++ b/include/linux/kprobes.h @@ -330,7 +330,9 @@ extern int proc_kprobes_optimization_handler(struct ctl_table *table, int write, void __user *buffer, size_t *length, loff_t *ppos); #endif - +extern void wait_for_kprobe_optimizer(void); +#else +static inline void wait_for_kprobe_optimizer(void) { } #endif /* CONFIG_OPTPROBES */ #ifdef CONFIG_KPROBES_ON_FTRACE extern void kprobe_ftrace_handler(unsigned long ip, unsigned long parent_ip, diff --git a/kernel/kprobes.c b/kernel/kprobes.c index d63095472ea9..a1a07cf1101f 100644 --- a/kernel/kprobes.c +++ b/kernel/kprobes.c @@ -563,7 +563,7 @@ static void kprobe_optimizer(struct work_struct *work) } /* Wait for completing optimization and unoptimization */ -static void wait_for_kprobe_optimizer(void) +void wait_for_kprobe_optimizer(void) { mutex_lock(&kprobe_mutex); diff --git a/kernel/trace/trace_kprobe.c b/kernel/trace/trace_kprobe.c index eb6c9f1d3a93..8d2b4d8fd714 100644 --- a/kernel/trace/trace_kprobe.c +++ b/kernel/trace/trace_kprobe.c @@ -1484,6 +1484,11 @@ static __init int kprobe_trace_self_tests_init(void) end: release_all_trace_kprobes(); + /* + * Wait for the optimizer work to finish. Otherwise it might fiddle + * with probes in already freed __init text. + */ + wait_for_kprobe_optimizer(); if (warn) pr_cont("NG: Some tests are failed. Please check them.\n"); else From d1d63f97dd76f7d90f801bcc9a6334d5df96367a Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Fri, 24 Mar 2017 11:07:22 -0700 Subject: [PATCH 372/396] PCI: hv: Allocate interrupt descriptors with GFP_ATOMIC commit 59c58ceeea9cdc6144d7b0303753e6bd26d87455 upstream. The memory allocation here needs to be non-blocking. Fix the issue. Signed-off-by: K. Y. Srinivasan Signed-off-by: Bjorn Helgaas Reviewed-by: Long Li Signed-off-by: Greg Kroah-Hartman --- drivers/pci/host/pci-hyperv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/pci/host/pci-hyperv.c b/drivers/pci/host/pci-hyperv.c index 61fc349c96d4..ddabf7b23bb5 100644 --- a/drivers/pci/host/pci-hyperv.c +++ b/drivers/pci/host/pci-hyperv.c @@ -868,7 +868,7 @@ static void hv_compose_msi_msg(struct irq_data *data, struct msi_msg *msg) hv_int_desc_free(hpdev, int_desc); } - int_desc = kzalloc(sizeof(*int_desc), GFP_KERNEL); + int_desc = kzalloc(sizeof(*int_desc), GFP_ATOMIC); if (!int_desc) goto drop_reference; From 87e7dc97c8a0544553aacf8705c6772db55f6691 Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Fri, 24 Mar 2017 11:07:21 -0700 Subject: [PATCH 373/396] PCI: hv: Specify CPU_AFFINITY_ALL for MSI affinity when >= 32 CPUs commit 433fcf6b7b31f1f233dd50aeb9d066a0f6ed4b9d upstream. When we have 32 or more CPUs in the affinity mask, we should use a special constant to specify that to the host. Fix this issue. Signed-off-by: K. Y. Srinivasan Signed-off-by: Bjorn Helgaas Reviewed-by: Long Li Signed-off-by: Greg Kroah-Hartman --- drivers/pci/host/pci-hyperv.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/drivers/pci/host/pci-hyperv.c b/drivers/pci/host/pci-hyperv.c index ddabf7b23bb5..dafb4cdb2b7f 100644 --- a/drivers/pci/host/pci-hyperv.c +++ b/drivers/pci/host/pci-hyperv.c @@ -72,6 +72,7 @@ enum { PCI_PROTOCOL_VERSION_CURRENT = PCI_PROTOCOL_VERSION_1_1 }; +#define CPU_AFFINITY_ALL -1ULL #define PCI_CONFIG_MMIO_LENGTH 0x2000 #define CFG_PAGE_OFFSET 0x1000 #define CFG_PAGE_SIZE (PCI_CONFIG_MMIO_LENGTH - CFG_PAGE_OFFSET) @@ -889,9 +890,13 @@ static void hv_compose_msi_msg(struct irq_data *data, struct msi_msg *msg) * processors because Hyper-V only supports 64 in a guest. */ affinity = irq_data_get_affinity_mask(data); - for_each_cpu_and(cpu, affinity, cpu_online_mask) { - int_pkt->int_desc.cpu_mask |= - (1ULL << vmbus_cpu_number_to_vp_number(cpu)); + if (cpumask_weight(affinity) >= 32) { + int_pkt->int_desc.cpu_mask = CPU_AFFINITY_ALL; + } else { + for_each_cpu_and(cpu, affinity, cpu_online_mask) { + int_pkt->int_desc.cpu_mask |= + (1ULL << vmbus_cpu_number_to_vp_number(cpu)); + } } ret = vmbus_sendpacket(hpdev->hbus->hdev->channel, int_pkt, From fa3bbb1c7f06e4e09f3c72ef42622ba260c77dc4 Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Wed, 12 Apr 2017 13:25:50 +0100 Subject: [PATCH 374/396] PCI: Fix pci_mmap_fits() for HAVE_PCI_RESOURCE_TO_USER platforms commit 6bccc7f426abd640f08d8c75fb22f99483f201b4 upstream. In the PCI_MMAP_PROCFS case when the address being passed by the user is a 'user visible' resource address based on the bus window, and not the actual contents of the resource, that's what we need to be checking it against. Signed-off-by: David Woodhouse Signed-off-by: Bjorn Helgaas Signed-off-by: Greg Kroah-Hartman --- drivers/pci/pci-sysfs.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c index bcd10c795284..1b0786555394 100644 --- a/drivers/pci/pci-sysfs.c +++ b/drivers/pci/pci-sysfs.c @@ -974,15 +974,19 @@ void pci_remove_legacy_files(struct pci_bus *b) int pci_mmap_fits(struct pci_dev *pdev, int resno, struct vm_area_struct *vma, enum pci_mmap_api mmap_api) { - unsigned long nr, start, size, pci_start; + unsigned long nr, start, size; + resource_size_t pci_start = 0, pci_end; if (pci_resource_len(pdev, resno) == 0) return 0; nr = vma_pages(vma); start = vma->vm_pgoff; size = ((pci_resource_len(pdev, resno) - 1) >> PAGE_SHIFT) + 1; - pci_start = (mmap_api == PCI_MMAP_PROCFS) ? - pci_resource_start(pdev, resno) >> PAGE_SHIFT : 0; + if (mmap_api == PCI_MMAP_PROCFS) { + pci_resource_to_user(pdev, resno, &pdev->resource[resno], + &pci_start, &pci_end); + pci_start >>= PAGE_SHIFT; + } if (start >= pci_start && start < pci_start + size && start + nr <= pci_start + size) return 1; From 6bec009a2f690c69239ab8c002aa1f5eca8c480e Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Wed, 12 Apr 2017 13:25:51 +0100 Subject: [PATCH 375/396] PCI: Fix another sanity check bug in /proc/pci mmap commit 17caf56731311c9596e7d38a70c88fcb6afa6a1b upstream. Don't match MMIO maps with I/O BARs and vice versa. Signed-off-by: David Woodhouse Signed-off-by: Bjorn Helgaas Signed-off-by: Greg Kroah-Hartman --- drivers/pci/proc.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/drivers/pci/proc.c b/drivers/pci/proc.c index 2408abe4ee8c..78802ee42878 100644 --- a/drivers/pci/proc.c +++ b/drivers/pci/proc.c @@ -231,14 +231,20 @@ static int proc_bus_pci_mmap(struct file *file, struct vm_area_struct *vma) { struct pci_dev *dev = PDE_DATA(file_inode(file)); struct pci_filp_private *fpriv = file->private_data; - int i, ret, write_combine; + int i, ret, write_combine, res_bit; if (!capable(CAP_SYS_RAWIO)) return -EPERM; + if (fpriv->mmap_state == pci_mmap_io) + res_bit = IORESOURCE_IO; + else + res_bit = IORESOURCE_MEM; + /* Make sure the caller is mapping a real resource for this device */ for (i = 0; i < PCI_ROM_RESOURCE; i++) { - if (pci_mmap_fits(dev, i, vma, PCI_MMAP_PROCFS)) + if (dev->resource[i].flags & res_bit && + pci_mmap_fits(dev, i, vma, PCI_MMAP_PROCFS)) break; } From 9ad81ecb28d611a07b59d8e899e0bd79a423aee2 Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Wed, 12 Apr 2017 13:25:52 +0100 Subject: [PATCH 376/396] PCI: Only allow WC mmap on prefetchable resources commit cef4d02305a06be581bb7f4353446717a1b319ec upstream. The /proc/bus/pci mmap interface allows the user to specify whether they want WC or not. Don't let them do so on non-prefetchable BARs. Signed-off-by: David Woodhouse Signed-off-by: Bjorn Helgaas Signed-off-by: Greg Kroah-Hartman --- drivers/pci/proc.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/drivers/pci/proc.c b/drivers/pci/proc.c index 78802ee42878..66c886365fbc 100644 --- a/drivers/pci/proc.c +++ b/drivers/pci/proc.c @@ -231,7 +231,7 @@ static int proc_bus_pci_mmap(struct file *file, struct vm_area_struct *vma) { struct pci_dev *dev = PDE_DATA(file_inode(file)); struct pci_filp_private *fpriv = file->private_data; - int i, ret, write_combine, res_bit; + int i, ret, write_combine = 0, res_bit; if (!capable(CAP_SYS_RAWIO)) return -EPERM; @@ -251,10 +251,13 @@ static int proc_bus_pci_mmap(struct file *file, struct vm_area_struct *vma) if (i >= PCI_ROM_RESOURCE) return -ENODEV; - if (fpriv->mmap_state == pci_mmap_mem) - write_combine = fpriv->write_combine; - else - write_combine = 0; + if (fpriv->mmap_state == pci_mmap_mem && + fpriv->write_combine) { + if (dev->resource[i].flags & IORESOURCE_PREFETCH) + write_combine = 1; + else + return -EINVAL; + } ret = pci_mmap_page_range(dev, vma, fpriv->mmap_state, write_combine); if (ret < 0) From db663641619558c9a1b8b77f5bfd351e131b57a7 Mon Sep 17 00:00:00 2001 From: Lukas Wunner Date: Tue, 18 Apr 2017 20:44:30 +0200 Subject: [PATCH 377/396] PCI: Freeze PME scan before suspending devices MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit ea00353f36b64375518662a8ad15e39218a1f324 upstream. Laurent Pinchart reported that the Renesas R-Car H2 Lager board (r8a7790) crashes during suspend tests. Geert Uytterhoeven managed to reproduce the issue on an M2-W Koelsch board (r8a7791): It occurs when the PME scan runs, once per second. During PME scan, the PCI host bridge (rcar-pci) registers are accessed while its module clock has already been disabled, leading to the crash. One reproducer is to configure s2ram to use "s2idle" instead of "deep" suspend: # echo 0 > /sys/module/printk/parameters/console_suspend # echo s2idle > /sys/power/mem_sleep # echo mem > /sys/power/state Another reproducer is to write either "platform" or "processors" to /sys/power/pm_test. It does not (or is less likely) to happen during full system suspend ("core" or "none") because system suspend also disables timers, and thus the workqueue handling PME scans no longer runs. Geert believes the issue may still happen in the small window between disabling module clocks and disabling timers: # echo 0 > /sys/module/printk/parameters/console_suspend # echo platform > /sys/power/pm_test # Or "processors" # echo mem > /sys/power/state (Make sure CONFIG_PCI_RCAR_GEN2 and CONFIG_USB_OHCI_HCD_PCI are enabled.) Rafael Wysocki agrees that PME scans should be suspended before the host bridge registers become inaccessible. To that end, queue the task on a workqueue that gets frozen before devices suspend. Rafael notes however that as a result, some wakeup events may be missed if they are delivered via PME from a device without working IRQ (which hence must be polled) and occur after the workqueue has been frozen. If that turns out to be an issue in practice, it may be possible to solve it by calling pci_pme_list_scan() once directly from one of the host bridge's pm_ops callbacks. Stacktrace for posterity: PM: Syncing filesystems ... [ 38.566237] done. PM: Preparing system for sleep (mem) Freezing user space processes ... [ 38.579813] (elapsed 0.001 seconds) done. Freezing remaining freezable tasks ... (elapsed 0.001 seconds) done. PM: Suspending system (mem) PM: suspend of devices complete after 152.456 msecs PM: late suspend of devices complete after 2.809 msecs PM: noirq suspend of devices complete after 29.863 msecs suspend debug: Waiting for 5 second(s). Unhandled fault: asynchronous external abort (0x1211) at 0x00000000 pgd = c0003000 [00000000] *pgd=80000040004003, *pmd=00000000 Internal error: : 1211 [#1] SMP ARM Modules linked in: CPU: 1 PID: 20 Comm: kworker/1:1 Not tainted 4.9.0-rc1-koelsch-00011-g68db9bc814362e7f #3383 Hardware name: Generic R8A7791 (Flattened Device Tree) Workqueue: events pci_pme_list_scan task: eb56e140 task.stack: eb58e000 PC is at pci_generic_config_read+0x64/0x6c LR is at rcar_pci_cfg_base+0x64/0x84 pc : [] lr : [] psr: 600d0093 sp : eb58fe98 ip : c041d750 fp : 00000008 r10: c0e2283c r9 : 00000000 r8 : 600d0013 r7 : 00000008 r6 : eb58fed6 r5 : 00000002 r4 : eb58feb4 r3 : 00000000 r2 : 00000044 r1 : 00000008 r0 : 00000000 Flags: nZCv IRQs off FIQs on Mode SVC_32 ISA ARM Segment user Control: 30c5387d Table: 6a9f6c80 DAC: 55555555 Process kworker/1:1 (pid: 20, stack limit = 0xeb58e210) Stack: (0xeb58fe98 to 0xeb590000) fe80: 00000002 00000044 fea0: eb6f5800 c041d9b0 eb58feb4 00000008 00000044 00000000 eb78a000 eb78a000 fec0: 00000044 00000000 eb9aff00 c0424bf0 eb78a000 00000000 eb78a000 c0e22830 fee0: ea8a6fc0 c0424c5c eaae79c0 c0424ce0 eb55f380 c0e22838 eb9a9800 c0235fbc ff00: eb55f380 c0e22838 eb55f380 eb9a9800 eb9a9800 eb58e000 eb9a9824 c0e02100 ff20: eb55f398 c02366c4 eb56e140 eb5631c0 00000000 eb55f380 c023641c 00000000 ff40: 00000000 00000000 00000000 c023a928 cd105598 00000000 40506a34 eb55f380 ff60: 00000000 00000000 dead4ead ffffffff ffffffff eb58ff74 eb58ff74 00000000 ff80: 00000000 dead4ead ffffffff ffffffff eb58ff90 eb58ff90 eb58ffac eb5631c0 ffa0: c023a844 00000000 00000000 c0206d68 00000000 00000000 00000000 00000000 ffc0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 ffe0: 00000000 00000000 00000000 00000000 00000013 00000000 3a81336c 10ccd1dd [] (pci_generic_config_read) from [] (pci_bus_read_config_word+0x58/0x80) [] (pci_bus_read_config_word) from [] (pci_check_pme_status+0x34/0x78) [] (pci_check_pme_status) from [] (pci_pme_wakeup+0x28/0x54) [] (pci_pme_wakeup) from [] (pci_pme_list_scan+0x58/0xb4) [] (pci_pme_list_scan) from [] (process_one_work+0x1bc/0x308) [] (process_one_work) from [] (worker_thread+0x2a8/0x3e0) [] (worker_thread) from [] (kthread+0xe4/0xfc) [] (kthread) from [] (ret_from_fork+0x14/0x2c) Code: ea000000 e5903000 f57ff04f e3a00000 (e5843000) ---[ end trace 667d43ba3aa9e589 ]--- Fixes: df17e62e5bff ("PCI: Add support for polling PME state on suspended legacy PCI devices") Reported-and-tested-by: Laurent Pinchart Reported-and-tested-by: Geert Uytterhoeven Signed-off-by: Lukas Wunner Signed-off-by: Bjorn Helgaas Reviewed-by: Laurent Pinchart Acked-by: Rafael J. Wysocki Cc: Mika Westerberg Cc: Niklas Söderlund Cc: Simon Horman Cc: Yinghai Lu Cc: Matthew Garrett Signed-off-by: Greg Kroah-Hartman --- drivers/pci/pci.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 6922964e3dff..579c4946dc6e 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -1782,8 +1782,8 @@ static void pci_pme_list_scan(struct work_struct *work) } } if (!list_empty(&pci_pme_list)) - schedule_delayed_work(&pci_pme_work, - msecs_to_jiffies(PME_TIMEOUT)); + queue_delayed_work(system_freezable_wq, &pci_pme_work, + msecs_to_jiffies(PME_TIMEOUT)); mutex_unlock(&pci_pme_list_mutex); } @@ -1848,8 +1848,9 @@ void pci_pme_active(struct pci_dev *dev, bool enable) mutex_lock(&pci_pme_list_mutex); list_add(&pme_dev->list, &pci_pme_list); if (list_is_singular(&pci_pme_list)) - schedule_delayed_work(&pci_pme_work, - msecs_to_jiffies(PME_TIMEOUT)); + queue_delayed_work(system_freezable_wq, + &pci_pme_work, + msecs_to_jiffies(PME_TIMEOUT)); mutex_unlock(&pci_pme_list_mutex); } else { mutex_lock(&pci_pme_list_mutex); From e437af936a49680ac509b9d51f1b51b11c8da605 Mon Sep 17 00:00:00 2001 From: Simon Baatz Date: Mon, 27 Mar 2017 20:02:07 +0200 Subject: [PATCH 378/396] mtd: nand: orion: fix clk handling commit 675b11d94ce9baa5eb365a51b35d2793f77c8ab8 upstream. The clk handling in orion_nand.c had two problems: - In the probe function, clk_put() was called for an enabled clock, which violates the API (see documentation for clk_put() in include/linux/clk.h) - In the error path of the probe function, clk_put() could be called twice for the same clock. In order to clean this up, use the managed function devm_clk_get() and store the pointer to the clk in the driver data. Fixes: baffab28b13120694fa3ebab08d3e99667a851d2 ('ARM: Orion: fix driver probe error handling with respect to clk') Signed-off-by: Simon Baatz Signed-off-by: Boris Brezillon Signed-off-by: Greg Kroah-Hartman --- drivers/mtd/nand/orion_nand.c | 42 +++++++++++++++++------------------ 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/drivers/mtd/nand/orion_nand.c b/drivers/mtd/nand/orion_nand.c index 40a7c4a2cf0d..af2f09135fb0 100644 --- a/drivers/mtd/nand/orion_nand.c +++ b/drivers/mtd/nand/orion_nand.c @@ -23,6 +23,11 @@ #include #include +struct orion_nand_info { + struct nand_chip chip; + struct clk *clk; +}; + static void orion_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl) { struct nand_chip *nc = mtd_to_nand(mtd); @@ -75,20 +80,21 @@ static void orion_nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len) static int __init orion_nand_probe(struct platform_device *pdev) { + struct orion_nand_info *info; struct mtd_info *mtd; struct nand_chip *nc; struct orion_nand_data *board; struct resource *res; - struct clk *clk; void __iomem *io_base; int ret = 0; u32 val = 0; - nc = devm_kzalloc(&pdev->dev, - sizeof(struct nand_chip), + info = devm_kzalloc(&pdev->dev, + sizeof(struct orion_nand_info), GFP_KERNEL); - if (!nc) + if (!info) return -ENOMEM; + nc = &info->chip; mtd = nand_to_mtd(nc); res = platform_get_resource(pdev, IORESOURCE_MEM, 0); @@ -145,15 +151,13 @@ static int __init orion_nand_probe(struct platform_device *pdev) if (board->dev_ready) nc->dev_ready = board->dev_ready; - platform_set_drvdata(pdev, mtd); + platform_set_drvdata(pdev, info); /* Not all platforms can gate the clock, so it is not an error if the clock does not exists. */ - clk = clk_get(&pdev->dev, NULL); - if (!IS_ERR(clk)) { - clk_prepare_enable(clk); - clk_put(clk); - } + info->clk = devm_clk_get(&pdev->dev, NULL); + if (!IS_ERR(info->clk)) + clk_prepare_enable(info->clk); if (nand_scan(mtd, 1)) { ret = -ENXIO; @@ -170,26 +174,22 @@ static int __init orion_nand_probe(struct platform_device *pdev) return 0; no_dev: - if (!IS_ERR(clk)) { - clk_disable_unprepare(clk); - clk_put(clk); - } + if (!IS_ERR(info->clk)) + clk_disable_unprepare(info->clk); return ret; } static int orion_nand_remove(struct platform_device *pdev) { - struct mtd_info *mtd = platform_get_drvdata(pdev); - struct clk *clk; + struct orion_nand_info *info = platform_get_drvdata(pdev); + struct nand_chip *chip = &info->chip; + struct mtd_info *mtd = nand_to_mtd(chip); nand_release(mtd); - clk = clk_get(&pdev->dev, NULL); - if (!IS_ERR(clk)) { - clk_disable_unprepare(clk); - clk_put(clk); - } + if (!IS_ERR(info->clk)) + clk_disable_unprepare(info->clk); return 0; } From 6639b27f5a4c5425a46b2f1039d390dd1ad7b94f Mon Sep 17 00:00:00 2001 From: Roger Quadros Date: Thu, 30 Mar 2017 10:37:50 +0300 Subject: [PATCH 379/396] mtd: nand: omap2: Fix partition creation via cmdline mtdparts commit 2d283ede59869159f4bb84ae689258c5caffce54 upstream. commit c9711ec5250b ("mtd: nand: omap: Clean up device tree support") caused the parent device name to be changed from "omap2-nand.0" to ".nand" (e.g. 30000000.nand on omap3 platforms). This caused mtd->name to be changed as well. This breaks partition creation via mtdparts passed by u-boot as it uses "omap2-nand.0" for the mtd-id. Fix this by explicitly setting the mtd->name to "omap2-nand." if it isn't already set by nand_set_flash_node(). CS number is the NAND controller instance ID. Fixes: c9711ec5250b ("mtd: nand: omap: Clean up device tree support") Reported-by: Leto Enrico Reported-by: Adam Ford Suggested-by: Boris Brezillon Tested-by: Adam Ford Signed-off-by: Roger Quadros Signed-off-by: Boris Brezillon Signed-off-by: Greg Kroah-Hartman --- drivers/mtd/nand/omap2.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c index 5513bfd9cdc9..c178cb0dd219 100644 --- a/drivers/mtd/nand/omap2.c +++ b/drivers/mtd/nand/omap2.c @@ -1856,6 +1856,15 @@ static int omap_nand_probe(struct platform_device *pdev) nand_chip->ecc.priv = NULL; nand_set_flash_node(nand_chip, dev->of_node); + if (!mtd->name) { + mtd->name = devm_kasprintf(&pdev->dev, GFP_KERNEL, + "omap2-nand.%d", info->gpmc_cs); + if (!mtd->name) { + dev_err(&pdev->dev, "Failed to set MTD name\n"); + return -ENOMEM; + } + } + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); nand_chip->IO_ADDR_R = devm_ioremap_resource(&pdev->dev, res); if (IS_ERR(nand_chip->IO_ADDR_R)) From 5956b2815f90e0749d98ea0baedc49b1792f598b Mon Sep 17 00:00:00 2001 From: Alexander Couzens Date: Tue, 2 May 2017 12:19:00 +0200 Subject: [PATCH 380/396] mtd: nand: add ooblayout for old hamming layout commit 6a623e07694437ad09f382a13f76cffc32239a7f upstream. The old 1-bit hamming layout requires ECC data to be placed at a fixed offset, and not necessarily at the end of the OOB area. Add this old layout back in order to fix legacy setups. Fixes: 41b207a70d3a ("mtd: nand: implement the default mtd_ooblayout_ops") Signed-off-by: Alexander Couzens Acked-by: Boris Brezillon Signed-off-by: Brian Norris Signed-off-by: Greg Kroah-Hartman --- drivers/mtd/nand/nand_base.c | 70 +++++++++++++++++++++++++++++++++++- 1 file changed, 69 insertions(+), 1 deletion(-) diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index 3bde96a3f7bf..f222f8a7ba52 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c @@ -138,6 +138,74 @@ const struct mtd_ooblayout_ops nand_ooblayout_lp_ops = { }; EXPORT_SYMBOL_GPL(nand_ooblayout_lp_ops); +/* + * Support the old "large page" layout used for 1-bit Hamming ECC where ECC + * are placed at a fixed offset. + */ +static int nand_ooblayout_ecc_lp_hamming(struct mtd_info *mtd, int section, + struct mtd_oob_region *oobregion) +{ + struct nand_chip *chip = mtd_to_nand(mtd); + struct nand_ecc_ctrl *ecc = &chip->ecc; + + if (section) + return -ERANGE; + + switch (mtd->oobsize) { + case 64: + oobregion->offset = 40; + break; + case 128: + oobregion->offset = 80; + break; + default: + return -EINVAL; + } + + oobregion->length = ecc->total; + if (oobregion->offset + oobregion->length > mtd->oobsize) + return -ERANGE; + + return 0; +} + +static int nand_ooblayout_free_lp_hamming(struct mtd_info *mtd, int section, + struct mtd_oob_region *oobregion) +{ + struct nand_chip *chip = mtd_to_nand(mtd); + struct nand_ecc_ctrl *ecc = &chip->ecc; + int ecc_offset = 0; + + if (section < 0 || section > 1) + return -ERANGE; + + switch (mtd->oobsize) { + case 64: + ecc_offset = 40; + break; + case 128: + ecc_offset = 80; + break; + default: + return -EINVAL; + } + + if (section == 0) { + oobregion->offset = 2; + oobregion->length = ecc_offset - 2; + } else { + oobregion->offset = ecc_offset + ecc->total; + oobregion->length = mtd->oobsize - oobregion->offset; + } + + return 0; +} + +const struct mtd_ooblayout_ops nand_ooblayout_lp_hamming_ops = { + .ecc = nand_ooblayout_ecc_lp_hamming, + .free = nand_ooblayout_free_lp_hamming, +}; + static int check_offs_len(struct mtd_info *mtd, loff_t ofs, uint64_t len) { @@ -4565,7 +4633,7 @@ int nand_scan_tail(struct mtd_info *mtd) break; case 64: case 128: - mtd_set_ooblayout(mtd, &nand_ooblayout_lp_ops); + mtd_set_ooblayout(mtd, &nand_ooblayout_lp_hamming_ops); break; default: WARN(1, "No oob scheme defined for oobsize %d\n", From 5438f89529065a936f31803e263adfd843f09bf8 Mon Sep 17 00:00:00 2001 From: Mario Kleiner Date: Fri, 21 Apr 2017 17:05:08 +0200 Subject: [PATCH 381/396] drm/edid: Add 10 bpc quirk for LGD 764 panel in HP zBook 17 G2 commit e345da82bd6bdfa8492f80b3ce4370acfd868d95 upstream. The builtin eDP panel in the HP zBook 17 G2 supports 10 bpc, as advertised by the Laptops product specs and verified via injecting a fixed edid + photometer measurements, but edid reports unknown depth, so drivers fall back to 6 bpc. Add a quirk to get the full 10 bpc. Signed-off-by: Mario Kleiner Acked-by: Harry Wentland Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/1492787108-23959-1-git-send-email-mario.kleiner.de@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/drm_edid.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index 0bc0afb6321e..0151ed2de770 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -76,6 +76,8 @@ #define EDID_QUIRK_FORCE_12BPC (1 << 9) /* Force 6bpc */ #define EDID_QUIRK_FORCE_6BPC (1 << 10) +/* Force 10bpc */ +#define EDID_QUIRK_FORCE_10BPC (1 << 11) struct detailed_mode_closure { struct drm_connector *connector; @@ -118,6 +120,9 @@ static const struct edid_quirk { { "FCM", 13600, EDID_QUIRK_PREFER_LARGE_75 | EDID_QUIRK_DETAILED_IN_CM }, + /* LGD panel of HP zBook 17 G2, eDP 10 bpc, but reports unknown bpc */ + { "LGD", 764, EDID_QUIRK_FORCE_10BPC }, + /* LG Philips LCD LP154W01-A5 */ { "LPL", 0, EDID_QUIRK_DETAILED_USE_MAXIMUM_SIZE }, { "LPL", 0x2a00, EDID_QUIRK_DETAILED_USE_MAXIMUM_SIZE }, @@ -4105,6 +4110,9 @@ int drm_add_edid_modes(struct drm_connector *connector, struct edid *edid) if (quirks & EDID_QUIRK_FORCE_8BPC) connector->display_info.bpc = 8; + if (quirks & EDID_QUIRK_FORCE_10BPC) + connector->display_info.bpc = 10; + if (quirks & EDID_QUIRK_FORCE_12BPC) connector->display_info.bpc = 12; From 88ac6b7e0c82b4d825e560d3c4512d540fe4231d Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Sat, 15 Apr 2017 19:20:01 -0400 Subject: [PATCH 382/396] NFSv4: Fix a hang in OPEN related to server reboot commit 56e0d71ef12f026d96213e45a662bde6bbff4676 upstream. If the server fails to return the attributes as part of an OPEN reply, and then reboots, we can end up hanging. The reason is that the client attempts to send a GETATTR in order to pick up the missing OPEN call, but fails to release the slot first, causing reboot recovery to deadlock. Signed-off-by: Trond Myklebust Fixes: 2e80dbe7ac51a ("NFSv4.1: Close callback races for OPEN, LAYOUTGET...") Signed-off-by: Greg Kroah-Hartman --- fs/nfs/nfs4proc.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 4e894d301c88..fc9b04941739 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c @@ -2385,8 +2385,10 @@ static int _nfs4_proc_open(struct nfs4_opendata *data) if (status != 0) return status; } - if (!(o_res->f_attr->valid & NFS_ATTR_FATTR)) + if (!(o_res->f_attr->valid & NFS_ATTR_FATTR)) { + nfs4_sequence_free_slot(&o_res->seq_res); nfs4_proc_getattr(server, &o_res->fh, o_res->f_attr, o_res->f_label); + } return 0; } From a8c35e5c88def2c07cd0ff1aca1af2b06363b293 Mon Sep 17 00:00:00 2001 From: Fred Isaman Date: Fri, 14 Apr 2017 14:24:28 -0400 Subject: [PATCH 383/396] NFS: Fix use after free in write error path commit 1f84ccdf37d0db3a70714d02d51b0b6d45887fb8 upstream. Signed-off-by: Fred Isaman Fixes: 0bcbf039f6b2b ("nfs: handle request add failure properly") Signed-off-by: Trond Myklebust Signed-off-by: Greg Kroah-Hartman --- fs/nfs/write.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/nfs/write.c b/fs/nfs/write.c index 53211838f72a..e4772a8340f8 100644 --- a/fs/nfs/write.c +++ b/fs/nfs/write.c @@ -548,9 +548,9 @@ static void nfs_write_error_remove_page(struct nfs_page *req) { nfs_unlock_request(req); nfs_end_page_writeback(req); - nfs_release_request(req); generic_error_remove_page(page_file_mapping(req->wb_page), req->wb_page); + nfs_release_request(req); } /* From f2b6f508c5417bc5f2a5a30268b5b75ae3b4a754 Mon Sep 17 00:00:00 2001 From: Benjamin Coddington Date: Wed, 19 Apr 2017 10:11:33 -0400 Subject: [PATCH 384/396] NFS: Use GFP_NOIO for two allocations in writeback commit ae97aa524ef495b6276fd26f5d5449fb22975d7c upstream. Prevent a deadlock that can occur if we wait on allocations that try to write back our pages. Signed-off-by: Benjamin Coddington Fixes: 00bfa30abe869 ("NFS: Create a common pgio_alloc and pgio_release...") Signed-off-by: Trond Myklebust Signed-off-by: Greg Kroah-Hartman --- fs/nfs/pagelist.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/fs/nfs/pagelist.c b/fs/nfs/pagelist.c index 965db474f4b0..142a74f3c59b 100644 --- a/fs/nfs/pagelist.c +++ b/fs/nfs/pagelist.c @@ -29,13 +29,14 @@ static struct kmem_cache *nfs_page_cachep; static const struct rpc_call_ops nfs_pgio_common_ops; -static bool nfs_pgarray_set(struct nfs_page_array *p, unsigned int pagecount) +static bool nfs_pgarray_set(struct nfs_page_array *p, unsigned int pagecount, + gfp_t gfp_flags) { p->npages = pagecount; if (pagecount <= ARRAY_SIZE(p->page_array)) p->pagevec = p->page_array; else { - p->pagevec = kcalloc(pagecount, sizeof(struct page *), GFP_KERNEL); + p->pagevec = kcalloc(pagecount, sizeof(struct page *), gfp_flags); if (!p->pagevec) p->npages = 0; } @@ -681,6 +682,7 @@ void nfs_pageio_init(struct nfs_pageio_descriptor *desc, { struct nfs_pgio_mirror *new; int i; + gfp_t gfp_flags = GFP_KERNEL; desc->pg_moreio = 0; desc->pg_inode = inode; @@ -700,8 +702,10 @@ void nfs_pageio_init(struct nfs_pageio_descriptor *desc, if (pg_ops->pg_get_mirror_count) { /* until we have a request, we don't have an lseg and no * idea how many mirrors there will be */ + if (desc->pg_rw_ops->rw_mode == FMODE_WRITE) + gfp_flags = GFP_NOIO; new = kcalloc(NFS_PAGEIO_DESCRIPTOR_MIRROR_MAX, - sizeof(struct nfs_pgio_mirror), GFP_KERNEL); + sizeof(struct nfs_pgio_mirror), gfp_flags); desc->pg_mirrors_dynamic = new; desc->pg_mirrors = new; @@ -755,9 +759,12 @@ int nfs_generic_pgio(struct nfs_pageio_descriptor *desc, struct list_head *head = &mirror->pg_list; struct nfs_commit_info cinfo; unsigned int pagecount, pageused; + gfp_t gfp_flags = GFP_KERNEL; pagecount = nfs_page_array_len(mirror->pg_base, mirror->pg_count); - if (!nfs_pgarray_set(&hdr->page_array, pagecount)) { + if (desc->pg_rw_ops->rw_mode == FMODE_WRITE) + gfp_flags = GFP_NOIO; + if (!nfs_pgarray_set(&hdr->page_array, pagecount, gfp_flags)) { nfs_pgio_error(hdr); desc->pg_error = -ENOMEM; return desc->pg_error; From ea465551af30146efea215da58786ff732da70fb Mon Sep 17 00:00:00 2001 From: Ari Kauppi Date: Fri, 5 May 2017 16:07:55 -0400 Subject: [PATCH 385/396] nfsd: fix undefined behavior in nfsd4_layout_verify commit b550a32e60a4941994b437a8d662432a486235a5 upstream. UBSAN: Undefined behaviour in fs/nfsd/nfs4proc.c:1262:34 shift exponent 128 is too large for 32-bit type 'int' Depending on compiler+architecture, this may cause the check for layout_type to succeed for overly large values (which seems to be the case with amd64). The large value will be later used in de-referencing nfsd4_layout_ops for function pointers. Reported-by: Jani Tuovila Signed-off-by: Ari Kauppi [colin.king@canonical.com: use LAYOUT_TYPE_MAX instead of 32] Reviewed-by: Dan Carpenter Reviewed-by: Christoph Hellwig Signed-off-by: J. Bruce Fields Signed-off-by: Greg Kroah-Hartman --- fs/nfsd/nfs4proc.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c index abb09b580389..650226f33298 100644 --- a/fs/nfsd/nfs4proc.c +++ b/fs/nfsd/nfs4proc.c @@ -1273,7 +1273,8 @@ nfsd4_layout_verify(struct svc_export *exp, unsigned int layout_type) return NULL; } - if (!(exp->ex_layout_types & (1 << layout_type))) { + if (layout_type >= LAYOUT_TYPE_MAX || + !(exp->ex_layout_types & (1 << layout_type))) { dprintk("%s: layout type %d not supported\n", __func__, layout_type); return NULL; From 51d9c51523ec6927a068ee54280b5a4ff3bf401d Mon Sep 17 00:00:00 2001 From: "J. Bruce Fields" Date: Fri, 5 May 2017 16:17:57 -0400 Subject: [PATCH 386/396] nfsd: encoders mustn't use unitialized values in error cases commit f961e3f2acae94b727380c0b74e2d3954d0edf79 upstream. In error cases, lgp->lg_layout_type may be out of bounds; so we shouldn't be using it until after the check of nfserr. This was seen to crash nfsd threads when the server receives a LAYOUTGET request with a large layout type. GETDEVICEINFO has the same problem. Reported-by: Ari Kauppi Reviewed-by: Christoph Hellwig Signed-off-by: J. Bruce Fields Signed-off-by: Greg Kroah-Hartman --- fs/nfsd/nfs4xdr.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c index c2d2895a1ec1..2ee80e1f5230 100644 --- a/fs/nfsd/nfs4xdr.c +++ b/fs/nfsd/nfs4xdr.c @@ -4081,8 +4081,7 @@ nfsd4_encode_getdeviceinfo(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_getdeviceinfo *gdev) { struct xdr_stream *xdr = &resp->xdr; - const struct nfsd4_layout_ops *ops = - nfsd4_layout_ops[gdev->gd_layout_type]; + const struct nfsd4_layout_ops *ops; u32 starting_len = xdr->buf->len, needed_len; __be32 *p; @@ -4099,6 +4098,7 @@ nfsd4_encode_getdeviceinfo(struct nfsd4_compoundres *resp, __be32 nfserr, /* If maxcount is 0 then just update notifications */ if (gdev->gd_maxcount != 0) { + ops = nfsd4_layout_ops[gdev->gd_layout_type]; nfserr = ops->encode_getdeviceinfo(xdr, gdev); if (nfserr) { /* @@ -4151,8 +4151,7 @@ nfsd4_encode_layoutget(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_layoutget *lgp) { struct xdr_stream *xdr = &resp->xdr; - const struct nfsd4_layout_ops *ops = - nfsd4_layout_ops[lgp->lg_layout_type]; + const struct nfsd4_layout_ops *ops; __be32 *p; dprintk("%s: err %d\n", __func__, nfserr); @@ -4175,6 +4174,7 @@ nfsd4_encode_layoutget(struct nfsd4_compoundres *resp, __be32 nfserr, *p++ = cpu_to_be32(lgp->lg_seg.iomode); *p++ = cpu_to_be32(lgp->lg_layout_type); + ops = nfsd4_layout_ops[lgp->lg_layout_type]; nfserr = ops->encode_layoutget(xdr, lgp); out: kfree(lgp->lg_content); From 1489183c2005676b2231fec00aced800093008ed Mon Sep 17 00:00:00 2001 From: Julius Werner Date: Fri, 12 May 2017 14:42:58 -0700 Subject: [PATCH 387/396] drivers: char: mem: Check for address space wraparound with mmap() commit b299cde245b0b76c977f4291162cf668e087b408 upstream. /dev/mem currently allows mmap() mappings that wrap around the end of the physical address space, which should probably be illegal. It circumvents the existing STRICT_DEVMEM permission check because the loop immediately terminates (as the start address is already higher than the end address). On the x86_64 architecture it will then cause a panic (from the BUG(start >= end) in arch/x86/mm/pat.c:reserve_memtype()). This patch adds an explicit check to make sure offset + size will not wrap around in the physical address type. Signed-off-by: Julius Werner Signed-off-by: Greg Kroah-Hartman --- drivers/char/mem.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/char/mem.c b/drivers/char/mem.c index 7e4a9d1296bb..6e0cbe092220 100644 --- a/drivers/char/mem.c +++ b/drivers/char/mem.c @@ -340,6 +340,11 @@ static const struct vm_operations_struct mmap_mem_ops = { static int mmap_mem(struct file *file, struct vm_area_struct *vma) { size_t size = vma->vm_end - vma->vm_start; + phys_addr_t offset = (phys_addr_t)vma->vm_pgoff << PAGE_SHIFT; + + /* It's illegal to wrap around the end of the physical address space. */ + if (offset + (phys_addr_t)size < offset) + return -EINVAL; if (!valid_mmap_phys_addr_range(vma->vm_pgoff, size)) return -EINVAL; From 5a597b225d48023bb10e38ea64adb277fc559247 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 9 Nov 2016 10:39:05 +0000 Subject: [PATCH 388/396] drm/i915/gvt: Disable access to stolen memory as a guest commit 04a68a35ce6d7b54749989f943993020f48fed62 upstream. Explicitly disable stolen memory when running as a guest in a virtual machine, since the memory is not mediated between clients and reserved entirely for the host. The actual size should be reported as zero, but like every other quirk we want to tell the user what is happening. Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=99028 Signed-off-by: Chris Wilson Cc: Zhenyu Wang Cc: Joonas Lahtinen Link: http://patchwork.freedesktop.org/patch/msgid/20161109103905.17860-1-chris@chris-wilson.co.uk Reviewed-by: Zhenyu Wang Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/i915/i915_gem_stolen.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_gem_stolen.c b/drivers/gpu/drm/i915/i915_gem_stolen.c index f46aac1e85fb..c75f4bb6a4bd 100644 --- a/drivers/gpu/drm/i915/i915_gem_stolen.c +++ b/drivers/gpu/drm/i915/i915_gem_stolen.c @@ -420,6 +420,11 @@ int i915_gem_init_stolen(struct drm_device *dev) return 0; } + if (intel_vgpu_active(dev_priv)) { + DRM_INFO("iGVT-g active, disabling use of stolen memory\n"); + return 0; + } + #ifdef CONFIG_INTEL_IOMMU if (intel_iommu_gfx_mapped && INTEL_INFO(dev)->gen < 8) { DRM_INFO("DMAR active, disabling use of stolen memory\n"); From db3fd4527ed32be44cbd8ffa6dd6a301c89d0d6d Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 25 May 2017 15:45:05 +0200 Subject: [PATCH 389/396] Linux 4.9.30 --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index c12e501a18b8..b78a45bcf9b1 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ VERSION = 4 PATCHLEVEL = 9 -SUBLEVEL = 29 +SUBLEVEL = 30 EXTRAVERSION = NAME = Roaring Lionus From 38ef41709456f93ec6360478345bb6052b000c61 Mon Sep 17 00:00:00 2001 From: Daniel Rosenberg Date: Mon, 29 May 2017 16:38:16 -0700 Subject: [PATCH 390/396] ANDROID: mnt: Fix next_descendent next_descendent did not properly handle the case where the initial mount had no slaves. In this case, we would look for the next slave, but since don't have a master, the check for wrapping around to the start of the list will always fail. Instead, we check for this case, and ensure that we end the iteration when we come back to the root. Signed-off-by: Daniel Rosenberg Bug: 62094374 Change-Id: I43dfcee041aa3730cb4b9a1161418974ef84812e --- fs/pnode.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/fs/pnode.c b/fs/pnode.c index b5f97c605d98..e4e428d621e9 100644 --- a/fs/pnode.c +++ b/fs/pnode.c @@ -504,9 +504,14 @@ static struct mount *next_descendent(struct mount *root, struct mount *cur) if (!IS_MNT_NEW(cur) && !list_empty(&cur->mnt_slave_list)) return first_slave(cur); do { - if (cur->mnt_slave.next != &cur->mnt_master->mnt_slave_list) - return next_slave(cur); - cur = cur->mnt_master; + struct mount *master = cur->mnt_master; + + if (!master || cur->mnt_slave.next != &master->mnt_slave_list) { + struct mount *next = next_slave(cur); + + return (next == root) ? NULL : next; + } + cur = master; } while (cur != root); return NULL; } From dd133231941b3acb34bd01626ed4bc7b1b71d0d9 Mon Sep 17 00:00:00 2001 From: Alexei Starovoitov Date: Wed, 30 Nov 2016 10:16:08 -0800 Subject: [PATCH 391/396] UPSTREAM: cgroup, bpf: remove unnecessary #include MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit this #include is unnecessary and brings whole set of other headers into cgroup-defs.h. Remove it. Fixes: 3007098494be ("cgroup: add support for eBPF programs") Signed-off-by: Alexei Starovoitov Acked-by: Rami Rosen Acked-by: Daniel Borkmann Acked-by: Daniel Mack Signed-off-by: David S. Miller Fixes: Change-Id: I3df35d8d3b1261503f9b5bcd90b18c9358f1ac28        ("cgroup: add support for eBPF programs") (cherry picked from commit b634d30a79ecc2d28e61cbe5b1f4443952f37a8f) Signed-off-by: Amit Pundir --- include/linux/bpf-cgroup.h | 1 - 1 file changed, 1 deletion(-) diff --git a/include/linux/bpf-cgroup.h b/include/linux/bpf-cgroup.h index ec80d0c0953e..0cf1adfadd2d 100644 --- a/include/linux/bpf-cgroup.h +++ b/include/linux/bpf-cgroup.h @@ -1,7 +1,6 @@ #ifndef _BPF_CGROUP_H #define _BPF_CGROUP_H -#include #include #include From a2adc7c5237b36a67f4eee71c3cde9a718a1983f Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Tue, 10 Jan 2017 13:08:06 +0100 Subject: [PATCH 392/396] UPSTREAM: cgroup: move CONFIG_SOCK_CGROUP_DATA to init/Kconfig We now 'select SOCK_CGROUP_DATA' but Kconfig complains that this is not right when CONFIG_NET is disabled and there is no socket interface: warning: (CGROUP_BPF) selects SOCK_CGROUP_DATA which has unmet direct dependencies (NET) I don't know what the correct solution for this is, but simply removing the dependency on NET from SOCK_CGROUP_DATA by moving it out of the 'if NET' section avoids the warning and does not produce other build errors. Fixes: 483c4933ea09 ("cgroup: Fix CGROUP_BPF config") Signed-off-by: Arnd Bergmann Signed-off-by: David S. Miller Fixes: Change-Id: Ib41ef78fba02eb9e592558ddbf06f9ec0aa337b6 ("UPSTREAM: cgroup: Fix CGROUP_BPF config") (cherry picked from commit 73b351473547e543e9c8166dd67fd99c64c15b0b) Signed-off-by: Amit Pundir --- init/Kconfig | 4 ++++ net/Kconfig | 4 ---- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/init/Kconfig b/init/Kconfig index 95270dd0a35c..3bb582498f39 100644 --- a/init/Kconfig +++ b/init/Kconfig @@ -1261,6 +1261,10 @@ config CGROUP_DEBUG Say N. +config SOCK_CGROUP_DATA + bool + default n + endif # CGROUPS config CHECKPOINT_RESTORE diff --git a/net/Kconfig b/net/Kconfig index 1870b35a7aba..28071fc1594c 100644 --- a/net/Kconfig +++ b/net/Kconfig @@ -264,10 +264,6 @@ config XPS config HWBM bool -config SOCK_CGROUP_DATA - bool - default n - config CGROUP_NET_PRIO bool "Network priority cgroup" depends on CGROUPS From 0e9efe2aa8382eb817086d31290be875e4549607 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Wed, 26 Apr 2017 09:09:23 -0700 Subject: [PATCH 393/396] UPSTREAM: bpf: restore skb->sk before pskb_trim() call While testing a fix [1] in ___pskb_trim(), addressing the WARN_ON_ONCE() in skb_try_coalesce() reported by Andrey, I found that we had an skb with skb->sk set but no skb->destructor. This invalidated heuristic found in commit 158f323b9868 ("net: adjust skb->truesize in pskb_expand_head()") and in cited patch. Considering the BUG_ON(skb->sk) we have in skb_orphan(), we should restrain the temporary setting to a minimal section. [1] https://patchwork.ozlabs.org/patch/755570/ net: adjust skb->truesize in ___pskb_trim() Fixes: 8f917bba0042 ("bpf: pass sk to helper functions") Signed-off-by: Eric Dumazet Cc: Willem de Bruijn Cc: Andrey Konovalov Acked-by: Daniel Borkmann Acked-by: Alexei Starovoitov Acked-by: Willem de Bruijn Signed-off-by: David S. Miller Fixes: Change-Id: Ifcbcbe2ab2882dc79c56f9707be1d6aef08c7fd3 ("BACKPORT: UPSTREAM: bpf: pass sk to helper functions") (cherry picked from commit d1f496fd8f34a40458d0eda6be0655926559e546) Signed-off-by: Amit Pundir --- net/core/filter.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/core/filter.c b/net/core/filter.c index 2cb4f0f1da2e..b21d0fcb95bf 100644 --- a/net/core/filter.c +++ b/net/core/filter.c @@ -95,8 +95,8 @@ int sk_filter_trim_cap(struct sock *sk, struct sk_buff *skb, unsigned int cap) skb->sk = sk; pkt_len = bpf_prog_run_save_cb(filter->prog, skb); - err = pkt_len ? pskb_trim(skb, max(cap, pkt_len)) : -EPERM; skb->sk = save_sk; + err = pkt_len ? pskb_trim(skb, max(cap, pkt_len)) : -EPERM; } rcu_read_unlock(); From 1ee2b4b8039375ea85faa63dde23b1f6c2906724 Mon Sep 17 00:00:00 2001 From: Alexei Starovoitov Date: Fri, 10 Feb 2017 20:28:24 -0800 Subject: [PATCH 394/396] BACKPORT: bpf: introduce BPF_F_ALLOW_OVERRIDE flag MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If BPF_F_ALLOW_OVERRIDE flag is used in BPF_PROG_ATTACH command to the given cgroup the descendent cgroup will be able to override effective bpf program that was inherited from this cgroup. By default it's not passed, therefore override is disallowed. Examples: 1. prog X attached to /A with default prog Y fails to attach to /A/B and /A/B/C Everything under /A runs prog X 2. prog X attached to /A with allow_override. prog Y fails to attach to /A/B with default (non-override) prog M attached to /A/B with allow_override. Everything under /A/B runs prog M only. 3. prog X attached to /A with allow_override. prog Y fails to attach to /A with default. The user has to detach first to switch the mode. In the future this behavior may be extended with a chain of non-overridable programs. Also fix the bug where detach from cgroup where nothing is attached was not throwing error. Return ENOENT in such case. Add several testcases and adjust libbpf. Fixes: 3007098494be ("cgroup: add support for eBPF programs") Signed-off-by: Alexei Starovoitov Acked-by: Daniel Borkmann Acked-by: Tejun Heo Acked-by: Daniel Mack Signed-off-by: David S. Miller Fixes: Change-Id: I3df35d8d3b1261503f9b5bcd90b18c9358f1ac28        ("cgroup: add support for eBPF programs") [AmitP: Refactored original patch for android-4.9 where libbpf sources are in samples/bpf/ and test_cgrp2_attach2, test_cgrp2_sock, and test_cgrp2_sock2 sample tests do not exist.] (cherry picked from commit 7f677633379b4abb3281cdbe7e7006f049305c03) Signed-off-by: Amit Pundir --- include/linux/bpf-cgroup.h | 13 ++++---- include/uapi/linux/bpf.h | 7 ++++ kernel/bpf/cgroup.c | 59 ++++++++++++++++++++++++++------- kernel/bpf/syscall.c | 18 +++++++--- kernel/cgroup.c | 9 ++--- samples/bpf/libbpf.c | 4 ++- samples/bpf/libbpf.h | 3 +- samples/bpf/test_cgrp2_attach.c | 2 +- 8 files changed, 84 insertions(+), 31 deletions(-) diff --git a/include/linux/bpf-cgroup.h b/include/linux/bpf-cgroup.h index 0cf1adfadd2d..ace92fce296d 100644 --- a/include/linux/bpf-cgroup.h +++ b/include/linux/bpf-cgroup.h @@ -21,20 +21,19 @@ struct cgroup_bpf { */ struct bpf_prog *prog[MAX_BPF_ATTACH_TYPE]; struct bpf_prog *effective[MAX_BPF_ATTACH_TYPE]; + bool disallow_override[MAX_BPF_ATTACH_TYPE]; }; void cgroup_bpf_put(struct cgroup *cgrp); void cgroup_bpf_inherit(struct cgroup *cgrp, struct cgroup *parent); -void __cgroup_bpf_update(struct cgroup *cgrp, - struct cgroup *parent, - struct bpf_prog *prog, - enum bpf_attach_type type); +int __cgroup_bpf_update(struct cgroup *cgrp, struct cgroup *parent, + struct bpf_prog *prog, enum bpf_attach_type type, + bool overridable); /* Wrapper for __cgroup_bpf_update() protected by cgroup_mutex */ -void cgroup_bpf_update(struct cgroup *cgrp, - struct bpf_prog *prog, - enum bpf_attach_type type); +int cgroup_bpf_update(struct cgroup *cgrp, struct bpf_prog *prog, + enum bpf_attach_type type, bool overridable); int __cgroup_bpf_run_filter(struct sock *sk, struct sk_buff *skb, diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h index 14eaf2d5ec13..b2d5be9fc909 100644 --- a/include/uapi/linux/bpf.h +++ b/include/uapi/linux/bpf.h @@ -109,6 +109,12 @@ enum bpf_attach_type { #define MAX_BPF_ATTACH_TYPE __MAX_BPF_ATTACH_TYPE +/* If BPF_F_ALLOW_OVERRIDE flag is used in BPF_PROG_ATTACH command + * to the given target_fd cgroup the descendent cgroup will be able to + * override effective bpf program that was inherited from this cgroup + */ +#define BPF_F_ALLOW_OVERRIDE (1U << 0) + #define BPF_PSEUDO_MAP_FD 1 /* flags for BPF_MAP_UPDATE_ELEM command */ @@ -157,6 +163,7 @@ union bpf_attr { __u32 target_fd; /* container object to attach to */ __u32 attach_bpf_fd; /* eBPF program to attach */ __u32 attach_type; + __u32 attach_flags; }; } __attribute__((aligned(8))); diff --git a/kernel/bpf/cgroup.c b/kernel/bpf/cgroup.c index d05c292290fe..a38d7cdb5ef8 100644 --- a/kernel/bpf/cgroup.c +++ b/kernel/bpf/cgroup.c @@ -52,6 +52,7 @@ void cgroup_bpf_inherit(struct cgroup *cgrp, struct cgroup *parent) e = rcu_dereference_protected(parent->bpf.effective[type], lockdep_is_held(&cgroup_mutex)); rcu_assign_pointer(cgrp->bpf.effective[type], e); + cgrp->bpf.disallow_override[type] = parent->bpf.disallow_override[type]; } } @@ -82,30 +83,63 @@ void cgroup_bpf_inherit(struct cgroup *cgrp, struct cgroup *parent) * * Must be called with cgroup_mutex held. */ -void __cgroup_bpf_update(struct cgroup *cgrp, - struct cgroup *parent, - struct bpf_prog *prog, - enum bpf_attach_type type) +int __cgroup_bpf_update(struct cgroup *cgrp, struct cgroup *parent, + struct bpf_prog *prog, enum bpf_attach_type type, + bool new_overridable) { - struct bpf_prog *old_prog, *effective; + struct bpf_prog *old_prog, *effective = NULL; struct cgroup_subsys_state *pos; + bool overridable = true; - old_prog = xchg(cgrp->bpf.prog + type, prog); + if (parent) { + overridable = !parent->bpf.disallow_override[type]; + effective = rcu_dereference_protected(parent->bpf.effective[type], + lockdep_is_held(&cgroup_mutex)); + } - effective = (!prog && parent) ? - rcu_dereference_protected(parent->bpf.effective[type], - lockdep_is_held(&cgroup_mutex)) : - prog; + if (prog && effective && !overridable) + /* if parent has non-overridable prog attached, disallow + * attaching new programs to descendent cgroup + */ + return -EPERM; + + if (prog && effective && overridable != new_overridable) + /* if parent has overridable prog attached, only + * allow overridable programs in descendent cgroup + */ + return -EPERM; + + old_prog = cgrp->bpf.prog[type]; + + if (prog) { + overridable = new_overridable; + effective = prog; + if (old_prog && + cgrp->bpf.disallow_override[type] == new_overridable) + /* disallow attaching non-overridable on top + * of existing overridable in this cgroup + * and vice versa + */ + return -EPERM; + } + + if (!prog && !old_prog) + /* report error when trying to detach and nothing is attached */ + return -ENOENT; + + cgrp->bpf.prog[type] = prog; css_for_each_descendant_pre(pos, &cgrp->self) { struct cgroup *desc = container_of(pos, struct cgroup, self); /* skip the subtree if the descendant has its own program */ - if (desc->bpf.prog[type] && desc != cgrp) + if (desc->bpf.prog[type] && desc != cgrp) { pos = css_rightmost_descendant(pos); - else + } else { rcu_assign_pointer(desc->bpf.effective[type], effective); + desc->bpf.disallow_override[type] = !overridable; + } } if (prog) @@ -115,6 +149,7 @@ void __cgroup_bpf_update(struct cgroup *cgrp, bpf_prog_put(old_prog); static_branch_dec(&cgroup_bpf_enabled_key); } + return 0; } /** diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c index e13157fd4253..9ab04796bce0 100644 --- a/kernel/bpf/syscall.c +++ b/kernel/bpf/syscall.c @@ -826,12 +826,13 @@ static int bpf_obj_get(const union bpf_attr *attr) #ifdef CONFIG_CGROUP_BPF -#define BPF_PROG_ATTACH_LAST_FIELD attach_type +#define BPF_PROG_ATTACH_LAST_FIELD attach_flags static int bpf_prog_attach(const union bpf_attr *attr) { struct bpf_prog *prog; struct cgroup *cgrp; + int ret; if (!capable(CAP_NET_ADMIN)) return -EPERM; @@ -839,6 +840,9 @@ static int bpf_prog_attach(const union bpf_attr *attr) if (CHECK_ATTR(BPF_PROG_ATTACH)) return -EINVAL; + if (attr->attach_flags & ~BPF_F_ALLOW_OVERRIDE) + return -EINVAL; + switch (attr->attach_type) { case BPF_CGROUP_INET_INGRESS: case BPF_CGROUP_INET_EGRESS: @@ -853,7 +857,10 @@ static int bpf_prog_attach(const union bpf_attr *attr) return PTR_ERR(cgrp); } - cgroup_bpf_update(cgrp, prog, attr->attach_type); + ret = cgroup_bpf_update(cgrp, prog, attr->attach_type, + attr->attach_flags & BPF_F_ALLOW_OVERRIDE); + if (ret) + bpf_prog_put(prog); cgroup_put(cgrp); break; @@ -861,7 +868,7 @@ static int bpf_prog_attach(const union bpf_attr *attr) return -EINVAL; } - return 0; + return ret; } #define BPF_PROG_DETACH_LAST_FIELD attach_type @@ -869,6 +876,7 @@ static int bpf_prog_attach(const union bpf_attr *attr) static int bpf_prog_detach(const union bpf_attr *attr) { struct cgroup *cgrp; + int ret; if (!capable(CAP_NET_ADMIN)) return -EPERM; @@ -883,7 +891,7 @@ static int bpf_prog_detach(const union bpf_attr *attr) if (IS_ERR(cgrp)) return PTR_ERR(cgrp); - cgroup_bpf_update(cgrp, NULL, attr->attach_type); + ret = cgroup_bpf_update(cgrp, NULL, attr->attach_type, false); cgroup_put(cgrp); break; @@ -891,7 +899,7 @@ static int bpf_prog_detach(const union bpf_attr *attr) return -EINVAL; } - return 0; + return ret; } #endif /* CONFIG_CGROUP_BPF */ diff --git a/kernel/cgroup.c b/kernel/cgroup.c index 70e1f486a0b3..5671c805842d 100644 --- a/kernel/cgroup.c +++ b/kernel/cgroup.c @@ -6500,15 +6500,16 @@ static __init int cgroup_namespaces_init(void) subsys_initcall(cgroup_namespaces_init); #ifdef CONFIG_CGROUP_BPF -void cgroup_bpf_update(struct cgroup *cgrp, - struct bpf_prog *prog, - enum bpf_attach_type type) +int cgroup_bpf_update(struct cgroup *cgrp, struct bpf_prog *prog, + enum bpf_attach_type type, bool overridable) { struct cgroup *parent = cgroup_parent(cgrp); + int ret; mutex_lock(&cgroup_mutex); - __cgroup_bpf_update(cgrp, parent, prog, type); + ret = __cgroup_bpf_update(cgrp, parent, prog, type, overridable); mutex_unlock(&cgroup_mutex); + return ret; } #endif /* CONFIG_CGROUP_BPF */ diff --git a/samples/bpf/libbpf.c b/samples/bpf/libbpf.c index 9ce707bf02a7..9cbc786e48e5 100644 --- a/samples/bpf/libbpf.c +++ b/samples/bpf/libbpf.c @@ -104,12 +104,14 @@ int bpf_prog_load(enum bpf_prog_type prog_type, return syscall(__NR_bpf, BPF_PROG_LOAD, &attr, sizeof(attr)); } -int bpf_prog_attach(int prog_fd, int target_fd, enum bpf_attach_type type) +int bpf_prog_attach(int prog_fd, int target_fd, enum bpf_attach_type type, + unsigned int flags) { union bpf_attr attr = { .target_fd = target_fd, .attach_bpf_fd = prog_fd, .attach_type = type, + .attach_flags = flags; }; return syscall(__NR_bpf, BPF_PROG_ATTACH, &attr, sizeof(attr)); diff --git a/samples/bpf/libbpf.h b/samples/bpf/libbpf.h index d0a799a52eaf..b06cf5aea097 100644 --- a/samples/bpf/libbpf.h +++ b/samples/bpf/libbpf.h @@ -15,7 +15,8 @@ int bpf_prog_load(enum bpf_prog_type prog_type, const struct bpf_insn *insns, int insn_len, const char *license, int kern_version); -int bpf_prog_attach(int prog_fd, int attachable_fd, enum bpf_attach_type type); +int bpf_prog_attach(int prog_fd, int attachable_fd, enum bpf_attach_type type, + unsigned int flags); int bpf_prog_detach(int attachable_fd, enum bpf_attach_type type); int bpf_obj_pin(int fd, const char *pathname); diff --git a/samples/bpf/test_cgrp2_attach.c b/samples/bpf/test_cgrp2_attach.c index 63ef2083f766..9de4896edeef 100644 --- a/samples/bpf/test_cgrp2_attach.c +++ b/samples/bpf/test_cgrp2_attach.c @@ -124,7 +124,7 @@ int main(int argc, char **argv) ret = bpf_prog_detach(cg_fd, type); printf("bpf_prog_detach() returned '%s' (%d)\n", strerror(errno), errno); - ret = bpf_prog_attach(prog_fd, cg_fd, type); + ret = bpf_prog_attach(prog_fd, cg_fd, type, 0); if (ret < 0) { printf("Failed to attach prog to cgroup: '%s'\n", strerror(errno)); From a5d371cda6de55234238d98556f7da6acac1d7b6 Mon Sep 17 00:00:00 2001 From: Daniel Mack Date: Mon, 28 Nov 2016 14:11:04 +0100 Subject: [PATCH 395/396] UPSTREAM: bpf: cgroup: fix documentation of __cgroup_bpf_update() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There's a 'not' missing in one paragraph. Add it. Fixes: 3007098494be ("cgroup: add support for eBPF programs") Signed-off-by: Daniel Mack Reported-by: Rami Rosen Acked-by: Daniel Borkmann Acked-by: Alexei Starovoitov Signed-off-by: David S. Miller Fixes: Change-Id: I3df35d8d3b1261503f9b5bcd90b18c9358f1ac28        ("cgroup: add support for eBPF programs") (cherry picked from commit 01ae87eab53675cbdabd5c4d727c4a35e397cce0) Signed-off-by: Amit Pundir --- kernel/bpf/cgroup.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/kernel/bpf/cgroup.c b/kernel/bpf/cgroup.c index a38d7cdb5ef8..a44a7e4c23d2 100644 --- a/kernel/bpf/cgroup.c +++ b/kernel/bpf/cgroup.c @@ -67,8 +67,8 @@ void cgroup_bpf_inherit(struct cgroup *cgrp, struct cgroup *parent) * Each cgroup has a set of two pointers for bpf programs; one for eBPF * programs it owns, and which is effective for execution. * - * If @prog is %NULL, this function attaches a new program to the cgroup and - * releases the one that is currently attached, if any. @prog is then made + * If @prog is not %NULL, this function attaches a new program to the cgroup + * and releases the one that is currently attached, if any. @prog is then made * the effective program of type @type in that cgroup. * * If @prog is %NULL, the currently attached program of type @type is released, From 3fe100ef0cb755374f6e91a26f155c344df40d68 Mon Sep 17 00:00:00 2001 From: Chenbo Feng Date: Wed, 5 Apr 2017 19:00:55 -0700 Subject: [PATCH 396/396] BACKPORT [FROMLIST] New getsockopt option to get socket cookie Cherry-pick from linux net-next branch commit http://patchwork.ozlabs.org/patch/747590/ Introduce a new getsockopt operation to retrieve the socket cookie for a specific socket based on the socket fd. It returns a unique non-decreasing cookie for each socket. Tested: https://android-review.googlesource.com/#/c/358163/ Test: Unit test added in kernel/tests Acked-by: Willem de Bruijn Signed-off-by: Chenbo Feng Signed-off-by: David S. Miller --- arch/alpha/include/uapi/asm/socket.h | 2 ++ arch/avr32/include/uapi/asm/socket.h | 2 ++ arch/frv/include/uapi/asm/socket.h | 2 ++ arch/ia64/include/uapi/asm/socket.h | 2 ++ arch/m32r/include/uapi/asm/socket.h | 2 ++ arch/mips/include/uapi/asm/socket.h | 2 ++ arch/mn10300/include/uapi/asm/socket.h | 2 ++ arch/parisc/include/uapi/asm/socket.h | 2 ++ arch/powerpc/include/uapi/asm/socket.h | 2 ++ arch/s390/include/uapi/asm/socket.h | 2 ++ arch/sparc/include/uapi/asm/socket.h | 2 ++ arch/xtensa/include/uapi/asm/socket.h | 2 ++ include/uapi/asm-generic/socket.h | 2 ++ net/core/sock.c | 8 ++++++++ 14 files changed, 34 insertions(+) diff --git a/arch/alpha/include/uapi/asm/socket.h b/arch/alpha/include/uapi/asm/socket.h index 9e46d6e656d9..fa47df6a953a 100644 --- a/arch/alpha/include/uapi/asm/socket.h +++ b/arch/alpha/include/uapi/asm/socket.h @@ -97,4 +97,6 @@ #define SO_CNX_ADVICE 53 +#define SO_COOKIE 57 + #endif /* _UAPI_ASM_SOCKET_H */ diff --git a/arch/avr32/include/uapi/asm/socket.h b/arch/avr32/include/uapi/asm/socket.h index 1fd147f09a38..5f10f9bcd417 100644 --- a/arch/avr32/include/uapi/asm/socket.h +++ b/arch/avr32/include/uapi/asm/socket.h @@ -90,4 +90,6 @@ #define SO_CNX_ADVICE 53 +#define SO_COOKIE 57 + #endif /* _UAPI__ASM_AVR32_SOCKET_H */ diff --git a/arch/frv/include/uapi/asm/socket.h b/arch/frv/include/uapi/asm/socket.h index afbc98f02d27..ed960d3af35d 100644 --- a/arch/frv/include/uapi/asm/socket.h +++ b/arch/frv/include/uapi/asm/socket.h @@ -90,5 +90,7 @@ #define SO_CNX_ADVICE 53 +#define SO_COOKIE 57 + #endif /* _ASM_SOCKET_H */ diff --git a/arch/ia64/include/uapi/asm/socket.h b/arch/ia64/include/uapi/asm/socket.h index 0018fad9039f..9790d139f1c9 100644 --- a/arch/ia64/include/uapi/asm/socket.h +++ b/arch/ia64/include/uapi/asm/socket.h @@ -99,4 +99,6 @@ #define SO_CNX_ADVICE 53 +#define SO_COOKIE 57 + #endif /* _ASM_IA64_SOCKET_H */ diff --git a/arch/m32r/include/uapi/asm/socket.h b/arch/m32r/include/uapi/asm/socket.h index 5fe42fc7b6c5..ad2567655e65 100644 --- a/arch/m32r/include/uapi/asm/socket.h +++ b/arch/m32r/include/uapi/asm/socket.h @@ -90,4 +90,6 @@ #define SO_CNX_ADVICE 53 +#define SO_COOKIE 57 + #endif /* _ASM_M32R_SOCKET_H */ diff --git a/arch/mips/include/uapi/asm/socket.h b/arch/mips/include/uapi/asm/socket.h index 2027240aafbb..2f106d0357f4 100644 --- a/arch/mips/include/uapi/asm/socket.h +++ b/arch/mips/include/uapi/asm/socket.h @@ -108,4 +108,6 @@ #define SO_CNX_ADVICE 53 +#define SO_COOKIE 57 + #endif /* _UAPI_ASM_SOCKET_H */ diff --git a/arch/mn10300/include/uapi/asm/socket.h b/arch/mn10300/include/uapi/asm/socket.h index 5129f23a9ee1..69f96180a3f4 100644 --- a/arch/mn10300/include/uapi/asm/socket.h +++ b/arch/mn10300/include/uapi/asm/socket.h @@ -90,4 +90,6 @@ #define SO_CNX_ADVICE 53 +#define SO_COOKIE 57 + #endif /* _ASM_SOCKET_H */ diff --git a/arch/parisc/include/uapi/asm/socket.h b/arch/parisc/include/uapi/asm/socket.h index 9c935d717df9..b96a193a2a4d 100644 --- a/arch/parisc/include/uapi/asm/socket.h +++ b/arch/parisc/include/uapi/asm/socket.h @@ -89,4 +89,6 @@ #define SO_CNX_ADVICE 0x402E +#define SO_COOKIE 0x4032 + #endif /* _UAPI_ASM_SOCKET_H */ diff --git a/arch/powerpc/include/uapi/asm/socket.h b/arch/powerpc/include/uapi/asm/socket.h index 1672e3398270..e78550f71833 100644 --- a/arch/powerpc/include/uapi/asm/socket.h +++ b/arch/powerpc/include/uapi/asm/socket.h @@ -97,4 +97,6 @@ #define SO_CNX_ADVICE 53 +#define SO_COOKIE 57 + #endif /* _ASM_POWERPC_SOCKET_H */ diff --git a/arch/s390/include/uapi/asm/socket.h b/arch/s390/include/uapi/asm/socket.h index 41b51c2f4f1b..04fe908755b5 100644 --- a/arch/s390/include/uapi/asm/socket.h +++ b/arch/s390/include/uapi/asm/socket.h @@ -96,4 +96,6 @@ #define SO_CNX_ADVICE 53 +#define SO_COOKIE 57 + #endif /* _ASM_SOCKET_H */ diff --git a/arch/sparc/include/uapi/asm/socket.h b/arch/sparc/include/uapi/asm/socket.h index 31aede3af088..de15f0a09b32 100644 --- a/arch/sparc/include/uapi/asm/socket.h +++ b/arch/sparc/include/uapi/asm/socket.h @@ -86,6 +86,8 @@ #define SO_CNX_ADVICE 0x0037 +#define SO_COOKIE 0x003b + /* Security levels - as per NRL IPv6 - don't actually do anything */ #define SO_SECURITY_AUTHENTICATION 0x5001 #define SO_SECURITY_ENCRYPTION_TRANSPORT 0x5002 diff --git a/arch/xtensa/include/uapi/asm/socket.h b/arch/xtensa/include/uapi/asm/socket.h index 81435d995e11..fc7ca2841206 100644 --- a/arch/xtensa/include/uapi/asm/socket.h +++ b/arch/xtensa/include/uapi/asm/socket.h @@ -101,4 +101,6 @@ #define SO_CNX_ADVICE 53 +#define SO_COOKIE 57 + #endif /* _XTENSA_SOCKET_H */ diff --git a/include/uapi/asm-generic/socket.h b/include/uapi/asm-generic/socket.h index 67d632f1743d..2d078c20abcb 100644 --- a/include/uapi/asm-generic/socket.h +++ b/include/uapi/asm-generic/socket.h @@ -92,4 +92,6 @@ #define SO_CNX_ADVICE 53 +#define SO_COOKIE 57 + #endif /* __ASM_GENERIC_SOCKET_H */ diff --git a/net/core/sock.c b/net/core/sock.c index 19562f7c6ad6..facffabd3960 100644 --- a/net/core/sock.c +++ b/net/core/sock.c @@ -1034,6 +1034,7 @@ int sock_getsockopt(struct socket *sock, int level, int optname, union { int val; + u64 val64; struct linger ling; struct timeval tm; } v; @@ -1264,6 +1265,13 @@ int sock_getsockopt(struct socket *sock, int level, int optname, v.val = sk->sk_incoming_cpu; break; + + case SO_COOKIE: + lv = sizeof(u64); + if (len < lv) + return -EINVAL; + v.val64 = sock_gen_cookie(sk); + break; default: /* We implement the SO_SNDLOWAT etc to not be settable * (1003.1g 7).