From: Greg Kroah-Hartman Date: Sun, 2 Sep 2018 17:54:59 +0000 (+0200) Subject: 4.14-stable patches X-Git-Tag: v3.18.121~19 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=bdd590344757dabc3d8b88e3cbbbb6bacb8ba5b4;p=thirdparty%2Fkernel%2Fstable-queue.git 4.14-stable patches added patches: asoc-dpcm-don-t-merge-format-from-invalid-codec-dai.patch asoc-sirf-fix-potential-null-pointer-dereference.patch asoc-zte-fix-incorrect-pcm-format-bit-usages.patch b43-leds-ensure-nul-termination-of-led-name-string.patch b43legacy-leds-ensure-nul-termination-of-led-name-string.patch pinctrl-freescale-off-by-one-in-imx1_pinconf_group_dbg_show.patch udl-kms-avoid-division.patch udl-kms-change-down_interruptible-to-down.patch udl-kms-fix-crash-due-to-uninitialized-memory.patch udl-kms-handle-allocation-failure.patch --- diff --git a/queue-4.14/asoc-dpcm-don-t-merge-format-from-invalid-codec-dai.patch b/queue-4.14/asoc-dpcm-don-t-merge-format-from-invalid-codec-dai.patch new file mode 100644 index 00000000000..5216cb5b8c4 --- /dev/null +++ b/queue-4.14/asoc-dpcm-don-t-merge-format-from-invalid-codec-dai.patch @@ -0,0 +1,45 @@ +From 4febced15ac8ddb9cf3e603edb111842e4863d9a Mon Sep 17 00:00:00 2001 +From: Jerome Brunet +Date: Wed, 27 Jun 2018 17:36:38 +0200 +Subject: ASoC: dpcm: don't merge format from invalid codec dai + +From: Jerome Brunet + +commit 4febced15ac8ddb9cf3e603edb111842e4863d9a upstream. + +When merging codec formats, dpcm_runtime_base_format() should skip +the codecs which are not supporting the current stream direction. + +At the moment, if a BE link has more than one codec, and only one +of these codecs has no capture DAI, it becomes impossible to start +a capture stream because the merged format would be 0. + +Skipping invalid codec DAI solves the problem. + +Fixes: b073ed4e2126 ("ASoC: soc-pcm: DPCM cares BE format") +Signed-off-by: Jerome Brunet +Signed-off-by: Mark Brown +Cc: stable@vger.kernel.org +Signed-off-by: Greg Kroah-Hartman + +--- + sound/soc/soc-pcm.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +--- a/sound/soc/soc-pcm.c ++++ b/sound/soc/soc-pcm.c +@@ -1607,6 +1607,14 @@ static u64 dpcm_runtime_base_format(stru + int i; + + for (i = 0; i < be->num_codecs; i++) { ++ /* ++ * Skip CODECs which don't support the current stream ++ * type. See soc_pcm_init_runtime_hw() for more details ++ */ ++ if (!snd_soc_dai_stream_valid(be->codec_dais[i], ++ stream)) ++ continue; ++ + codec_dai_drv = be->codec_dais[i]->driver; + if (stream == SNDRV_PCM_STREAM_PLAYBACK) + codec_stream = &codec_dai_drv->playback; diff --git a/queue-4.14/asoc-sirf-fix-potential-null-pointer-dereference.patch b/queue-4.14/asoc-sirf-fix-potential-null-pointer-dereference.patch new file mode 100644 index 00000000000..f72eb2f84b7 --- /dev/null +++ b/queue-4.14/asoc-sirf-fix-potential-null-pointer-dereference.patch @@ -0,0 +1,44 @@ +From ae1c696a480c67c45fb23b35162183f72c6be0e1 Mon Sep 17 00:00:00 2001 +From: "Gustavo A. R. Silva" +Date: Thu, 26 Jul 2018 15:49:10 -0500 +Subject: ASoC: sirf: Fix potential NULL pointer dereference + +From: Gustavo A. R. Silva + +commit ae1c696a480c67c45fb23b35162183f72c6be0e1 upstream. + +There is a potential execution path in which function +platform_get_resource() returns NULL. If this happens, +we will end up having a NULL pointer dereference. + +Fix this by replacing devm_ioremap with devm_ioremap_resource, +which has the NULL check and the memory region request. + +This code was detected with the help of Coccinelle. + +Cc: stable@vger.kernel.org +Fixes: 2bd8d1d5cf89 ("ASoC: sirf: Add audio usp interface driver") +Signed-off-by: Gustavo A. R. Silva +Signed-off-by: Mark Brown +Signed-off-by: Greg Kroah-Hartman + +--- + sound/soc/sirf/sirf-usp.c | 7 +++---- + 1 file changed, 3 insertions(+), 4 deletions(-) + +--- a/sound/soc/sirf/sirf-usp.c ++++ b/sound/soc/sirf/sirf-usp.c +@@ -370,10 +370,9 @@ static int sirf_usp_pcm_probe(struct pla + platform_set_drvdata(pdev, usp); + + mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); +- base = devm_ioremap(&pdev->dev, mem_res->start, +- resource_size(mem_res)); +- if (base == NULL) +- return -ENOMEM; ++ base = devm_ioremap_resource(&pdev->dev, mem_res); ++ if (IS_ERR(base)) ++ return PTR_ERR(base); + usp->regmap = devm_regmap_init_mmio(&pdev->dev, base, + &sirf_usp_regmap_config); + if (IS_ERR(usp->regmap)) diff --git a/queue-4.14/asoc-zte-fix-incorrect-pcm-format-bit-usages.patch b/queue-4.14/asoc-zte-fix-incorrect-pcm-format-bit-usages.patch new file mode 100644 index 00000000000..e28a466262d --- /dev/null +++ b/queue-4.14/asoc-zte-fix-incorrect-pcm-format-bit-usages.patch @@ -0,0 +1,40 @@ +From c889a45d229938a94b50aadb819def8bb11a6a54 Mon Sep 17 00:00:00 2001 +From: Takashi Iwai +Date: Wed, 25 Jul 2018 22:40:49 +0200 +Subject: ASoC: zte: Fix incorrect PCM format bit usages + +From: Takashi Iwai + +commit c889a45d229938a94b50aadb819def8bb11a6a54 upstream. + +zx-tdm driver sets the DAI driver definitions with the format bits +wrongly set with SNDRV_PCM_FORMAT_*, instead of SNDRV_PCM_FMTBIT_*. + +This patch corrects the definitions. + +Spotted by a sparse warning: + sound/soc/zte/zx-tdm.c:363:35: warning: restricted snd_pcm_format_t degrades to integer + +Fixes: 870e0ddc4345 ("ASoC: zx-tdm: add zte's tdm controller driver") +Cc: +Signed-off-by: Takashi Iwai +Signed-off-by: Mark Brown +Signed-off-by: Greg Kroah-Hartman + +--- + sound/soc/zte/zx-tdm.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/sound/soc/zte/zx-tdm.c ++++ b/sound/soc/zte/zx-tdm.c +@@ -144,8 +144,8 @@ static void zx_tdm_rx_dma_en(struct zx_t + #define ZX_TDM_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000) + + #define ZX_TDM_FMTBIT \ +- (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FORMAT_MU_LAW | \ +- SNDRV_PCM_FORMAT_A_LAW) ++ (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_MU_LAW | \ ++ SNDRV_PCM_FMTBIT_A_LAW) + + static int zx_tdm_dai_probe(struct snd_soc_dai *dai) + { diff --git a/queue-4.14/b43-leds-ensure-nul-termination-of-led-name-string.patch b/queue-4.14/b43-leds-ensure-nul-termination-of-led-name-string.patch new file mode 100644 index 00000000000..009379d074c --- /dev/null +++ b/queue-4.14/b43-leds-ensure-nul-termination-of-led-name-string.patch @@ -0,0 +1,32 @@ +From 2aa650d1950fce94f696ebd7db30b8830c2c946f Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Michael=20B=C3=BCsch?= +Date: Tue, 31 Jul 2018 21:14:04 +0200 +Subject: b43/leds: Ensure NUL-termination of LED name string + +From: Michael Buesch + +commit 2aa650d1950fce94f696ebd7db30b8830c2c946f upstream. + +strncpy might not NUL-terminate the string, if the name equals the buffer size. +Use strlcpy instead. + +Signed-off-by: Michael Buesch +Cc: stable@vger.kernel.org +Signed-off-by: Kalle Valo +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/net/wireless/broadcom/b43/leds.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/net/wireless/broadcom/b43/leds.c ++++ b/drivers/net/wireless/broadcom/b43/leds.c +@@ -131,7 +131,7 @@ static int b43_register_led(struct b43_w + led->wl = dev->wl; + led->index = led_index; + led->activelow = activelow; +- strncpy(led->name, name, sizeof(led->name)); ++ strlcpy(led->name, name, sizeof(led->name)); + atomic_set(&led->state, 0); + + led->led_dev.name = led->name; diff --git a/queue-4.14/b43legacy-leds-ensure-nul-termination-of-led-name-string.patch b/queue-4.14/b43legacy-leds-ensure-nul-termination-of-led-name-string.patch new file mode 100644 index 00000000000..aab1eb12587 --- /dev/null +++ b/queue-4.14/b43legacy-leds-ensure-nul-termination-of-led-name-string.patch @@ -0,0 +1,32 @@ +From 4d77a89e3924b12f4a5628b21237e57ab4703866 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Michael=20B=C3=BCsch?= +Date: Tue, 31 Jul 2018 21:14:16 +0200 +Subject: b43legacy/leds: Ensure NUL-termination of LED name string + +From: Michael Buesch + +commit 4d77a89e3924b12f4a5628b21237e57ab4703866 upstream. + +strncpy might not NUL-terminate the string, if the name equals the buffer size. +Use strlcpy instead. + +Signed-off-by: Michael Buesch +Cc: stable@vger.kernel.org +Signed-off-by: Kalle Valo +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/net/wireless/broadcom/b43legacy/leds.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/net/wireless/broadcom/b43legacy/leds.c ++++ b/drivers/net/wireless/broadcom/b43legacy/leds.c +@@ -101,7 +101,7 @@ static int b43legacy_register_led(struct + led->dev = dev; + led->index = led_index; + led->activelow = activelow; +- strncpy(led->name, name, sizeof(led->name)); ++ strlcpy(led->name, name, sizeof(led->name)); + + led->led_dev.name = led->name; + led->led_dev.default_trigger = default_trigger; diff --git a/queue-4.14/kvm-x86-ensure-all-msrs-can-always-be-kvm_get-set_msr-d.patch b/queue-4.14/kvm-x86-ensure-all-msrs-can-always-be-kvm_get-set_msr-d.patch deleted file mode 100644 index adf96231f26..00000000000 --- a/queue-4.14/kvm-x86-ensure-all-msrs-can-always-be-kvm_get-set_msr-d.patch +++ /dev/null @@ -1,185 +0,0 @@ -From 44883f01fe6ae436a8604c47d8435276fef369b0 Mon Sep 17 00:00:00 2001 -From: Paolo Bonzini -Date: Thu, 26 Jul 2018 13:01:52 +0200 -Subject: KVM: x86: ensure all MSRs can always be KVM_GET/SET_MSR'd - -From: Paolo Bonzini - -commit 44883f01fe6ae436a8604c47d8435276fef369b0 upstream. - -Some of the MSRs returned by GET_MSR_INDEX_LIST currently cannot be sent back -to KVM_GET_MSR and/or KVM_SET_MSR; either they can never be sent back, or you -they are only accepted under special conditions. This makes the API a pain to -use. - -To avoid this pain, this patch makes it so that the result of the get-list -ioctl can always be used for host-initiated get and set. Since we don't have -a separate way to check for read-only MSRs, this means some Hyper-V MSRs are -ignored when written. Arguably they should not even be in the result of -GET_MSR_INDEX_LIST, but I am leaving there in case userspace is using the -outcome of GET_MSR_INDEX_LIST to derive the support for the corresponding -Hyper-V feature. - -Cc: stable@vger.kernel.org -Signed-off-by: Paolo Bonzini -Signed-off-by: Greg Kroah-Hartman - ---- - arch/x86/kvm/hyperv.c | 27 ++++++++++++++++++++------- - arch/x86/kvm/hyperv.h | 2 +- - arch/x86/kvm/x86.c | 15 +++++++++------ - 3 files changed, 30 insertions(+), 14 deletions(-) - ---- a/arch/x86/kvm/hyperv.c -+++ b/arch/x86/kvm/hyperv.c -@@ -214,7 +214,7 @@ static int synic_set_msr(struct kvm_vcpu - struct kvm_vcpu *vcpu = synic_to_vcpu(synic); - int ret; - -- if (!synic->active) -+ if (!synic->active && !host) - return 1; - - trace_kvm_hv_synic_set_msr(vcpu->vcpu_id, msr, data, host); -@@ -274,11 +274,12 @@ static int synic_set_msr(struct kvm_vcpu - return ret; - } - --static int synic_get_msr(struct kvm_vcpu_hv_synic *synic, u32 msr, u64 *pdata) -+static int synic_get_msr(struct kvm_vcpu_hv_synic *synic, u32 msr, u64 *pdata, -+ bool host) - { - int ret; - -- if (!synic->active) -+ if (!synic->active && !host) - return 1; - - ret = 0; -@@ -981,6 +982,11 @@ static int kvm_hv_set_msr_pw(struct kvm_ - kvm_make_request(KVM_REQ_HV_RESET, vcpu); - } - break; -+ case HV_X64_MSR_TIME_REF_COUNT: -+ /* read-only, but still ignore it if host-initiated */ -+ if (!host) -+ return 1; -+ break; - default: - vcpu_unimpl(vcpu, "Hyper-V uhandled wrmsr: 0x%x data 0x%llx\n", - msr, data); -@@ -1068,6 +1074,12 @@ static int kvm_hv_set_msr(struct kvm_vcp - return stimer_set_count(vcpu_to_stimer(vcpu, timer_index), - data, host); - } -+ case HV_X64_MSR_TSC_FREQUENCY: -+ case HV_X64_MSR_APIC_FREQUENCY: -+ /* read-only, but still ignore it if host-initiated */ -+ if (!host) -+ return 1; -+ break; - default: - vcpu_unimpl(vcpu, "Hyper-V uhandled wrmsr: 0x%x data 0x%llx\n", - msr, data); -@@ -1114,7 +1126,8 @@ static int kvm_hv_get_msr_pw(struct kvm_ - return 0; - } - --static int kvm_hv_get_msr(struct kvm_vcpu *vcpu, u32 msr, u64 *pdata) -+static int kvm_hv_get_msr(struct kvm_vcpu *vcpu, u32 msr, u64 *pdata, -+ bool host) - { - u64 data = 0; - struct kvm_vcpu_hv *hv = &vcpu->arch.hyperv; -@@ -1141,7 +1154,7 @@ static int kvm_hv_get_msr(struct kvm_vcp - case HV_X64_MSR_SIMP: - case HV_X64_MSR_EOM: - case HV_X64_MSR_SINT0 ... HV_X64_MSR_SINT15: -- return synic_get_msr(vcpu_to_synic(vcpu), msr, pdata); -+ return synic_get_msr(vcpu_to_synic(vcpu), msr, pdata, host); - case HV_X64_MSR_STIMER0_CONFIG: - case HV_X64_MSR_STIMER1_CONFIG: - case HV_X64_MSR_STIMER2_CONFIG: -@@ -1187,7 +1200,7 @@ int kvm_hv_set_msr_common(struct kvm_vcp - return kvm_hv_set_msr(vcpu, msr, data, host); - } - --int kvm_hv_get_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 *pdata) -+int kvm_hv_get_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 *pdata, bool host) - { - if (kvm_hv_msr_partition_wide(msr)) { - int r; -@@ -1197,7 +1210,7 @@ int kvm_hv_get_msr_common(struct kvm_vcp - mutex_unlock(&vcpu->kvm->arch.hyperv.hv_lock); - return r; - } else -- return kvm_hv_get_msr(vcpu, msr, pdata); -+ return kvm_hv_get_msr(vcpu, msr, pdata, host); - } - - bool kvm_hv_hypercall_enabled(struct kvm *kvm) ---- a/arch/x86/kvm/hyperv.h -+++ b/arch/x86/kvm/hyperv.h -@@ -48,7 +48,7 @@ static inline struct kvm_vcpu *synic_to_ - } - - int kvm_hv_set_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 data, bool host); --int kvm_hv_get_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 *pdata); -+int kvm_hv_get_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 *pdata, bool host); - - bool kvm_hv_hypercall_enabled(struct kvm *kvm); - int kvm_hv_hypercall(struct kvm_vcpu *vcpu); ---- a/arch/x86/kvm/x86.c -+++ b/arch/x86/kvm/x86.c -@@ -2090,10 +2090,11 @@ static int set_msr_mce(struct kvm_vcpu * - vcpu->arch.mcg_status = data; - break; - case MSR_IA32_MCG_CTL: -- if (!(mcg_cap & MCG_CTL_P)) -+ if (!(mcg_cap & MCG_CTL_P) && -+ (data || !msr_info->host_initiated)) - return 1; - if (data != 0 && data != ~(u64)0) -- return -1; -+ return 1; - vcpu->arch.mcg_ctl = data; - break; - default: -@@ -2452,7 +2453,7 @@ int kvm_get_msr(struct kvm_vcpu *vcpu, s - } - EXPORT_SYMBOL_GPL(kvm_get_msr); - --static int get_msr_mce(struct kvm_vcpu *vcpu, u32 msr, u64 *pdata) -+static int get_msr_mce(struct kvm_vcpu *vcpu, u32 msr, u64 *pdata, bool host) - { - u64 data; - u64 mcg_cap = vcpu->arch.mcg_cap; -@@ -2467,7 +2468,7 @@ static int get_msr_mce(struct kvm_vcpu * - data = vcpu->arch.mcg_cap; - break; - case MSR_IA32_MCG_CTL: -- if (!(mcg_cap & MCG_CTL_P)) -+ if (!(mcg_cap & MCG_CTL_P) && !host) - return 1; - data = vcpu->arch.mcg_ctl; - break; -@@ -2593,7 +2594,8 @@ int kvm_get_msr_common(struct kvm_vcpu * - case MSR_IA32_MCG_CTL: - case MSR_IA32_MCG_STATUS: - case MSR_IA32_MC0_CTL ... MSR_IA32_MCx_CTL(KVM_MAX_MCE_BANKS) - 1: -- return get_msr_mce(vcpu, msr_info->index, &msr_info->data); -+ return get_msr_mce(vcpu, msr_info->index, &msr_info->data, -+ msr_info->host_initiated); - case MSR_K7_CLK_CTL: - /* - * Provide expected ramp-up count for K7. All other -@@ -2611,7 +2613,8 @@ int kvm_get_msr_common(struct kvm_vcpu * - case HV_X64_MSR_CRASH_CTL: - case HV_X64_MSR_STIMER0_CONFIG ... HV_X64_MSR_STIMER3_COUNT: - return kvm_hv_get_msr_common(vcpu, -- msr_info->index, &msr_info->data); -+ msr_info->index, &msr_info->data, -+ msr_info->host_initiated); - break; - case MSR_IA32_BBL_CR_CTL3: - /* This legacy MSR exists but isn't fully documented in current diff --git a/queue-4.14/pinctrl-freescale-off-by-one-in-imx1_pinconf_group_dbg_show.patch b/queue-4.14/pinctrl-freescale-off-by-one-in-imx1_pinconf_group_dbg_show.patch new file mode 100644 index 00000000000..b2202c90277 --- /dev/null +++ b/queue-4.14/pinctrl-freescale-off-by-one-in-imx1_pinconf_group_dbg_show.patch @@ -0,0 +1,39 @@ +From 19da44cd33a3a6ff7c97fff0189999ff15b241e4 Mon Sep 17 00:00:00 2001 +From: Dan Carpenter +Date: Fri, 13 Jul 2018 17:55:15 +0300 +Subject: pinctrl: freescale: off by one in imx1_pinconf_group_dbg_show() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Dan Carpenter + +commit 19da44cd33a3a6ff7c97fff0189999ff15b241e4 upstream. + +The info->groups[] array is allocated in imx1_pinctrl_parse_dt(). It +has info->ngroups elements. Thus the > here should be >= to prevent +reading one element beyond the end of the array. + +Cc: stable@vger.kernel.org +Fixes: 30612cd90005 ("pinctrl: imx1 core driver") +Signed-off-by: Dan Carpenter +Reviewed-by: Uwe Kleine-König +Acked-by: Dong Aisheng +Signed-off-by: Linus Walleij +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/pinctrl/freescale/pinctrl-imx1-core.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/pinctrl/freescale/pinctrl-imx1-core.c ++++ b/drivers/pinctrl/freescale/pinctrl-imx1-core.c +@@ -433,7 +433,7 @@ static void imx1_pinconf_group_dbg_show( + const char *name; + int i, ret; + +- if (group > info->ngroups) ++ if (group >= info->ngroups) + return; + + seq_puts(s, "\n"); diff --git a/queue-4.14/series b/queue-4.14/series index 8fd23fd85f2..f1b6b12a70c 100644 --- a/queue-4.14/series +++ b/queue-4.14/series @@ -113,7 +113,6 @@ x86-speculation-l1tf-fix-off-by-one-error-when-warning-that-system-has-too-much- x86-speculation-l1tf-suggest-what-to-do-on-systems-with-too-much-ram.patch x86-vdso-fix-vdso-build-if-a-retpoline-is-emitted.patch x86-process-re-export-start_thread.patch -kvm-x86-ensure-all-msrs-can-always-be-kvm_get-set_msr-d.patch kvm-x86-svm-call-x86_spec_ctrl_set_guest-host-with-interrupts-disabled.patch x86-kvm-vmx-remove-duplicate-l1d-flush-definitions.patch fuse-don-t-access-pipe-buffers-without-pipe_lock.patch @@ -123,3 +122,13 @@ fuse-fix-unlocked-access-to-processing-queue.patch fuse-umount-should-wait-for-all-requests.patch fuse-fix-oops-at-process_init_reply.patch fuse-add-missed-unlock_page-to-fuse_readpages_fill.patch +udl-kms-change-down_interruptible-to-down.patch +udl-kms-handle-allocation-failure.patch +udl-kms-fix-crash-due-to-uninitialized-memory.patch +udl-kms-avoid-division.patch +b43legacy-leds-ensure-nul-termination-of-led-name-string.patch +b43-leds-ensure-nul-termination-of-led-name-string.patch +asoc-dpcm-don-t-merge-format-from-invalid-codec-dai.patch +asoc-zte-fix-incorrect-pcm-format-bit-usages.patch +asoc-sirf-fix-potential-null-pointer-dereference.patch +pinctrl-freescale-off-by-one-in-imx1_pinconf_group_dbg_show.patch diff --git a/queue-4.14/udl-kms-avoid-division.patch b/queue-4.14/udl-kms-avoid-division.patch new file mode 100644 index 00000000000..60a289b41b1 --- /dev/null +++ b/queue-4.14/udl-kms-avoid-division.patch @@ -0,0 +1,194 @@ +From 91ba11fb7d7ca0a3bbe8a512e65e666e2ec1e889 Mon Sep 17 00:00:00 2001 +From: Mikulas Patocka +Date: Sun, 3 Jun 2018 16:41:00 +0200 +Subject: udl-kms: avoid division + +From: Mikulas Patocka + +commit 91ba11fb7d7ca0a3bbe8a512e65e666e2ec1e889 upstream. + +Division is slow, so it shouldn't be done by the pixel generating code. +The driver supports only 2 or 4 bytes per pixel, so we can replace +division with a shift. + +Signed-off-by: Mikulas Patocka +Cc: stable@vger.kernel.org +Signed-off-by: Dave Airlie +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/udl/udl_drv.h | 2 - + drivers/gpu/drm/udl/udl_fb.c | 15 ++++++++------ + drivers/gpu/drm/udl/udl_transfer.c | 39 ++++++++++++++++++------------------- + 3 files changed, 30 insertions(+), 26 deletions(-) + +--- a/drivers/gpu/drm/udl/udl_drv.h ++++ b/drivers/gpu/drm/udl/udl_drv.h +@@ -110,7 +110,7 @@ udl_fb_user_fb_create(struct drm_device + struct drm_file *file, + const struct drm_mode_fb_cmd2 *mode_cmd); + +-int udl_render_hline(struct drm_device *dev, int bpp, struct urb **urb_ptr, ++int udl_render_hline(struct drm_device *dev, int log_bpp, struct urb **urb_ptr, + const char *front, char **urb_buf_ptr, + u32 byte_offset, u32 device_byte_offset, u32 byte_width, + int *ident_ptr, int *sent_ptr); +--- a/drivers/gpu/drm/udl/udl_fb.c ++++ b/drivers/gpu/drm/udl/udl_fb.c +@@ -90,7 +90,10 @@ int udl_handle_damage(struct udl_framebu + int bytes_identical = 0; + struct urb *urb; + int aligned_x; +- int bpp = fb->base.format->cpp[0]; ++ int log_bpp; ++ ++ BUG_ON(!is_power_of_2(fb->base.format->cpp[0])); ++ log_bpp = __ffs(fb->base.format->cpp[0]); + + if (!fb->active_16) + return 0; +@@ -125,12 +128,12 @@ int udl_handle_damage(struct udl_framebu + + for (i = y; i < y + height ; i++) { + const int line_offset = fb->base.pitches[0] * i; +- const int byte_offset = line_offset + (x * bpp); +- const int dev_byte_offset = (fb->base.width * bpp * i) + (x * bpp); +- if (udl_render_hline(dev, bpp, &urb, ++ const int byte_offset = line_offset + (x << log_bpp); ++ const int dev_byte_offset = (fb->base.width * i + x) << log_bpp; ++ if (udl_render_hline(dev, log_bpp, &urb, + (char *) fb->obj->vmapping, + &cmd, byte_offset, dev_byte_offset, +- width * bpp, ++ width << log_bpp, + &bytes_identical, &bytes_sent)) + goto error; + } +@@ -149,7 +152,7 @@ int udl_handle_damage(struct udl_framebu + error: + atomic_add(bytes_sent, &udl->bytes_sent); + atomic_add(bytes_identical, &udl->bytes_identical); +- atomic_add(width*height*bpp, &udl->bytes_rendered); ++ atomic_add((width * height) << log_bpp, &udl->bytes_rendered); + end_cycles = get_cycles(); + atomic_add(((unsigned int) ((end_cycles - start_cycles) + >> 10)), /* Kcycles */ +--- a/drivers/gpu/drm/udl/udl_transfer.c ++++ b/drivers/gpu/drm/udl/udl_transfer.c +@@ -83,12 +83,12 @@ static inline u16 pixel32_to_be16(const + ((pixel >> 8) & 0xf800)); + } + +-static inline u16 get_pixel_val16(const uint8_t *pixel, int bpp) ++static inline u16 get_pixel_val16(const uint8_t *pixel, int log_bpp) + { +- u16 pixel_val16 = 0; +- if (bpp == 2) ++ u16 pixel_val16; ++ if (log_bpp == 1) + pixel_val16 = *(const uint16_t *)pixel; +- else if (bpp == 4) ++ else + pixel_val16 = pixel32_to_be16(*(const uint32_t *)pixel); + return pixel_val16; + } +@@ -125,8 +125,9 @@ static void udl_compress_hline16( + const u8 *const pixel_end, + uint32_t *device_address_ptr, + uint8_t **command_buffer_ptr, +- const uint8_t *const cmd_buffer_end, int bpp) ++ const uint8_t *const cmd_buffer_end, int log_bpp) + { ++ const int bpp = 1 << log_bpp; + const u8 *pixel = *pixel_start_ptr; + uint32_t dev_addr = *device_address_ptr; + uint8_t *cmd = *command_buffer_ptr; +@@ -153,12 +154,12 @@ static void udl_compress_hline16( + raw_pixels_count_byte = cmd++; /* we'll know this later */ + raw_pixel_start = pixel; + +- cmd_pixel_end = pixel + min3(MAX_CMD_PIXELS + 1UL, +- (unsigned long)(pixel_end - pixel) / bpp, +- (unsigned long)(cmd_buffer_end - 1 - cmd) / 2) * bpp; ++ cmd_pixel_end = pixel + (min3(MAX_CMD_PIXELS + 1UL, ++ (unsigned long)(pixel_end - pixel) >> log_bpp, ++ (unsigned long)(cmd_buffer_end - 1 - cmd) / 2) << log_bpp); + + prefetch_range((void *) pixel, cmd_pixel_end - pixel); +- pixel_val16 = get_pixel_val16(pixel, bpp); ++ pixel_val16 = get_pixel_val16(pixel, log_bpp); + + while (pixel < cmd_pixel_end) { + const u8 *const start = pixel; +@@ -170,7 +171,7 @@ static void udl_compress_hline16( + pixel += bpp; + + while (pixel < cmd_pixel_end) { +- pixel_val16 = get_pixel_val16(pixel, bpp); ++ pixel_val16 = get_pixel_val16(pixel, log_bpp); + if (pixel_val16 != repeating_pixel_val16) + break; + pixel += bpp; +@@ -179,10 +180,10 @@ static void udl_compress_hline16( + if (unlikely(pixel > start + bpp)) { + /* go back and fill in raw pixel count */ + *raw_pixels_count_byte = (((start - +- raw_pixel_start) / bpp) + 1) & 0xFF; ++ raw_pixel_start) >> log_bpp) + 1) & 0xFF; + + /* immediately after raw data is repeat byte */ +- *cmd++ = (((pixel - start) / bpp) - 1) & 0xFF; ++ *cmd++ = (((pixel - start) >> log_bpp) - 1) & 0xFF; + + /* Then start another raw pixel span */ + raw_pixel_start = pixel; +@@ -192,14 +193,14 @@ static void udl_compress_hline16( + + if (pixel > raw_pixel_start) { + /* finalize last RAW span */ +- *raw_pixels_count_byte = ((pixel-raw_pixel_start) / bpp) & 0xFF; ++ *raw_pixels_count_byte = ((pixel - raw_pixel_start) >> log_bpp) & 0xFF; + } else { + /* undo unused byte */ + cmd--; + } + +- *cmd_pixels_count_byte = ((pixel - cmd_pixel_start) / bpp) & 0xFF; +- dev_addr += ((pixel - cmd_pixel_start) / bpp) * 2; ++ *cmd_pixels_count_byte = ((pixel - cmd_pixel_start) >> log_bpp) & 0xFF; ++ dev_addr += ((pixel - cmd_pixel_start) >> log_bpp) * 2; + } + + if (cmd_buffer_end <= MIN_RLX_CMD_BYTES + cmd) { +@@ -222,19 +223,19 @@ static void udl_compress_hline16( + * (that we can only write to, slowly, and can never read), and (optionally) + * our shadow copy that tracks what's been sent to that hardware buffer. + */ +-int udl_render_hline(struct drm_device *dev, int bpp, struct urb **urb_ptr, ++int udl_render_hline(struct drm_device *dev, int log_bpp, struct urb **urb_ptr, + const char *front, char **urb_buf_ptr, + u32 byte_offset, u32 device_byte_offset, + u32 byte_width, + int *ident_ptr, int *sent_ptr) + { + const u8 *line_start, *line_end, *next_pixel; +- u32 base16 = 0 + (device_byte_offset / bpp) * 2; ++ u32 base16 = 0 + (device_byte_offset >> log_bpp) * 2; + struct urb *urb = *urb_ptr; + u8 *cmd = *urb_buf_ptr; + u8 *cmd_end = (u8 *) urb->transfer_buffer + urb->transfer_buffer_length; + +- BUG_ON(!(bpp == 2 || bpp == 4)); ++ BUG_ON(!(log_bpp == 1 || log_bpp == 2)); + + line_start = (u8 *) (front + byte_offset); + next_pixel = line_start; +@@ -244,7 +245,7 @@ int udl_render_hline(struct drm_device * + + udl_compress_hline16(&next_pixel, + line_end, &base16, +- (u8 **) &cmd, (u8 *) cmd_end, bpp); ++ (u8 **) &cmd, (u8 *) cmd_end, log_bpp); + + if (cmd >= cmd_end) { + int len = cmd - (u8 *) urb->transfer_buffer; diff --git a/queue-4.14/udl-kms-change-down_interruptible-to-down.patch b/queue-4.14/udl-kms-change-down_interruptible-to-down.patch new file mode 100644 index 00000000000..a3b53355734 --- /dev/null +++ b/queue-4.14/udl-kms-change-down_interruptible-to-down.patch @@ -0,0 +1,44 @@ +From 8456b99c16d193c4c3b7df305cf431e027f0189c Mon Sep 17 00:00:00 2001 +From: Mikulas Patocka +Date: Sun, 3 Jun 2018 16:40:55 +0200 +Subject: udl-kms: change down_interruptible to down + +From: Mikulas Patocka + +commit 8456b99c16d193c4c3b7df305cf431e027f0189c upstream. + +If we leave urbs around, it causes not only leak, but also memory +corruption. This patch fixes the function udl_free_urb_list, so that it +always waits for all urbs that are in progress. + +Signed-off-by: Mikulas Patocka +Cc: stable@vger.kernel.org +Signed-off-by: Dave Airlie +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/udl/udl_main.c | 7 +------ + 1 file changed, 1 insertion(+), 6 deletions(-) + +--- a/drivers/gpu/drm/udl/udl_main.c ++++ b/drivers/gpu/drm/udl/udl_main.c +@@ -169,18 +169,13 @@ static void udl_free_urb_list(struct drm + struct list_head *node; + struct urb_node *unode; + struct urb *urb; +- int ret; + unsigned long flags; + + DRM_DEBUG("Waiting for completes and freeing all render urbs\n"); + + /* keep waiting and freeing, until we've got 'em all */ + while (count--) { +- +- /* Getting interrupted means a leak, but ok at shutdown*/ +- ret = down_interruptible(&udl->urbs.limit_sem); +- if (ret) +- break; ++ down(&udl->urbs.limit_sem); + + spin_lock_irqsave(&udl->urbs.lock, flags); + diff --git a/queue-4.14/udl-kms-fix-crash-due-to-uninitialized-memory.patch b/queue-4.14/udl-kms-fix-crash-due-to-uninitialized-memory.patch new file mode 100644 index 00000000000..7ce4ef2d1f3 --- /dev/null +++ b/queue-4.14/udl-kms-fix-crash-due-to-uninitialized-memory.patch @@ -0,0 +1,32 @@ +From 09a00abe3a9941c2715ca83eb88172cd2f54d8fd Mon Sep 17 00:00:00 2001 +From: Mikulas Patocka +Date: Sun, 3 Jun 2018 16:40:57 +0200 +Subject: udl-kms: fix crash due to uninitialized memory + +From: Mikulas Patocka + +commit 09a00abe3a9941c2715ca83eb88172cd2f54d8fd upstream. + +We must use kzalloc when allocating the fb_deferred_io structure. +Otherwise, the field first_io is undefined and it causes a crash. + +Signed-off-by: Mikulas Patocka +Cc: stable@vger.kernel.org +Signed-off-by: Dave Airlie +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/udl/udl_fb.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/gpu/drm/udl/udl_fb.c ++++ b/drivers/gpu/drm/udl/udl_fb.c +@@ -221,7 +221,7 @@ static int udl_fb_open(struct fb_info *i + + struct fb_deferred_io *fbdefio; + +- fbdefio = kmalloc(sizeof(struct fb_deferred_io), GFP_KERNEL); ++ fbdefio = kzalloc(sizeof(struct fb_deferred_io), GFP_KERNEL); + + if (fbdefio) { + fbdefio->delay = DL_DEFIO_WRITE_DELAY; diff --git a/queue-4.14/udl-kms-handle-allocation-failure.patch b/queue-4.14/udl-kms-handle-allocation-failure.patch new file mode 100644 index 00000000000..2734182d6bd --- /dev/null +++ b/queue-4.14/udl-kms-handle-allocation-failure.patch @@ -0,0 +1,89 @@ +From 542bb9788a1f485eb1a2229178f665d8ea166156 Mon Sep 17 00:00:00 2001 +From: Mikulas Patocka +Date: Sun, 3 Jun 2018 16:40:56 +0200 +Subject: udl-kms: handle allocation failure + +From: Mikulas Patocka + +commit 542bb9788a1f485eb1a2229178f665d8ea166156 upstream. + +Allocations larger than PAGE_ALLOC_COSTLY_ORDER are unreliable and they +may fail anytime. This patch fixes the udl kms driver so that when a large +alloactions fails, it tries to do multiple smaller allocations. + +Signed-off-by: Mikulas Patocka +Cc: stable@vger.kernel.org +Signed-off-by: Dave Airlie +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/udl/udl_main.c | 28 ++++++++++++++++++---------- + 1 file changed, 18 insertions(+), 10 deletions(-) + +--- a/drivers/gpu/drm/udl/udl_main.c ++++ b/drivers/gpu/drm/udl/udl_main.c +@@ -199,17 +199,22 @@ static void udl_free_urb_list(struct drm + static int udl_alloc_urb_list(struct drm_device *dev, int count, size_t size) + { + struct udl_device *udl = dev->dev_private; +- int i = 0; + struct urb *urb; + struct urb_node *unode; + char *buf; ++ size_t wanted_size = count * size; + + spin_lock_init(&udl->urbs.lock); + ++retry: + udl->urbs.size = size; + INIT_LIST_HEAD(&udl->urbs.list); + +- while (i < count) { ++ sema_init(&udl->urbs.limit_sem, 0); ++ udl->urbs.count = 0; ++ udl->urbs.available = 0; ++ ++ while (udl->urbs.count * size < wanted_size) { + unode = kzalloc(sizeof(struct urb_node), GFP_KERNEL); + if (!unode) + break; +@@ -225,11 +230,16 @@ static int udl_alloc_urb_list(struct drm + } + unode->urb = urb; + +- buf = usb_alloc_coherent(udl->udev, MAX_TRANSFER, GFP_KERNEL, ++ buf = usb_alloc_coherent(udl->udev, size, GFP_KERNEL, + &urb->transfer_dma); + if (!buf) { + kfree(unode); + usb_free_urb(urb); ++ if (size > PAGE_SIZE) { ++ size /= 2; ++ udl_free_urb_list(dev); ++ goto retry; ++ } + break; + } + +@@ -240,16 +250,14 @@ static int udl_alloc_urb_list(struct drm + + list_add_tail(&unode->entry, &udl->urbs.list); + +- i++; ++ up(&udl->urbs.limit_sem); ++ udl->urbs.count++; ++ udl->urbs.available++; + } + +- sema_init(&udl->urbs.limit_sem, i); +- udl->urbs.count = i; +- udl->urbs.available = i; +- +- DRM_DEBUG("allocated %d %d byte urbs\n", i, (int) size); ++ DRM_DEBUG("allocated %d %d byte urbs\n", udl->urbs.count, (int) size); + +- return i; ++ return udl->urbs.count; + } + + struct urb *udl_get_urb(struct drm_device *dev)