From: Greg Kroah-Hartman Date: Mon, 5 Jun 2017 12:47:22 +0000 (+0200) Subject: 4.11-stable patches X-Git-Tag: v3.18.56~22 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=149232c5c7d0ca95555c8e738a598b340660e888;p=thirdparty%2Fkernel%2Fstable-queue.git 4.11-stable patches added patches: alsa-hda-apply-stac_9200_dell_m22-quirk-for-dell-latitude-d430.patch alsa-hda-no-loopback-on-alc299-codec.patch alsa-usb-fix-a-typo-in-tascam-us-16x08-mixer-element.patch drm-amd-powerplay-smu7-add-vblank-check-for-mclk-switching-v2.patch drm-amd-powerplay-smu7-disable-mclk-switching-for-high-refresh-rates.patch drm-gma500-psb-actually-use-vbt-mode-when-it-is-found.patch drm-radeon-ci-disable-mclk-switching-for-high-refresh-rates-v2.patch drm-radeon-unbreak-hpd-handling-for-r600.patch hid-wacom-have-wacom_tpc_irq-guard-against-possible-null-dereference.patch ibmvscsis-clear-left-over-abort_cmd-pointers.patch ibmvscsis-fix-the-incorrect-req_lim_delta.patch iscsi-target-always-wait-for-kthread_should_stop-before-kthread-exit.patch iscsi-target-fix-initial-login-pdu-asynchronous-socket-close-oops.patch ksm-prevent-crash-after-write_protect_page-fails.patch nvme-avoid-to-use-blk_mq_abort_requeue_list.patch nvme-rdma-support-devices-with-queue-size-32.patch nvme-use-blk_mq_start_hw_queues-in-nvme_kill_queues.patch pcmcia-remove-left-over-z-format.patch revert-alsa-usb-audio-purge-needless-variable-length-array.patch scsi-scsi_dh_rdac-use-ctlr-directly-in-rdac_failover_get.patch scsi-zero-per-cmd-private-driver-data-for-each-mq-i-o.patch slub-memcg-cure-the-brainless-abuse-of-sysfs-attributes.patch x86-boot-use-cross_compile-prefix-for-readelf.patch x86-mce-export-memory_error.patch x86-pat-fix-xorg-regression-on-cpus-that-don-t-support-pat.patch --- diff --git a/queue-4.11/alsa-hda-apply-stac_9200_dell_m22-quirk-for-dell-latitude-d430.patch b/queue-4.11/alsa-hda-apply-stac_9200_dell_m22-quirk-for-dell-latitude-d430.patch new file mode 100644 index 00000000000..60198bf5b8d --- /dev/null +++ b/queue-4.11/alsa-hda-apply-stac_9200_dell_m22-quirk-for-dell-latitude-d430.patch @@ -0,0 +1,34 @@ +From 1fc2e41f7af4572b07190f9dec28396b418e9a36 Mon Sep 17 00:00:00 2001 +From: Alexander Tsoy +Date: Mon, 22 May 2017 20:58:11 +0300 +Subject: ALSA: hda - apply STAC_9200_DELL_M22 quirk for Dell Latitude D430 + +From: Alexander Tsoy + +commit 1fc2e41f7af4572b07190f9dec28396b418e9a36 upstream. + +This model is actually called 92XXM2-8 in Windows driver. But since pin +configs for M22 and M28 are identical, just reuse M22 quirk. + +Fixes external microphone (tested) and probably docking station ports +(not tested). + +Signed-off-by: Alexander Tsoy +Signed-off-by: Takashi Iwai +Signed-off-by: Greg Kroah-Hartman + +--- + sound/pci/hda/patch_sigmatel.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/sound/pci/hda/patch_sigmatel.c ++++ b/sound/pci/hda/patch_sigmatel.c +@@ -1559,6 +1559,8 @@ static const struct snd_pci_quirk stac92 + "Dell Inspiron 1501", STAC_9200_DELL_M26), + SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01f6, + "unknown Dell", STAC_9200_DELL_M26), ++ SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0201, ++ "Dell Latitude D430", STAC_9200_DELL_M22), + /* Panasonic */ + SND_PCI_QUIRK(0x10f7, 0x8338, "Panasonic CF-74", STAC_9200_PANASONIC), + /* Gateway machines needs EAPD to be set on resume */ diff --git a/queue-4.11/alsa-hda-no-loopback-on-alc299-codec.patch b/queue-4.11/alsa-hda-no-loopback-on-alc299-codec.patch new file mode 100644 index 00000000000..4ec38f8ffaf --- /dev/null +++ b/queue-4.11/alsa-hda-no-loopback-on-alc299-codec.patch @@ -0,0 +1,36 @@ +From fa16b69f1299004b60b625f181143500a246e5cb Mon Sep 17 00:00:00 2001 +From: Takashi Iwai +Date: Tue, 16 May 2017 09:11:33 +0200 +Subject: ALSA: hda - No loopback on ALC299 codec + +From: Takashi Iwai + +commit fa16b69f1299004b60b625f181143500a246e5cb upstream. + +ALC299 has no loopback mixer, but the driver still tries to add a beep +control over the mixer NID which leads to the error at accessing it. +This patch fixes it by properly declaring mixer_nid=0 for this codec. + +Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=195775 +Fixes: 28f1f9b26cee ("ALSA: hda/realtek - Add new codec ID ALC299") +Signed-off-by: Takashi Iwai +Signed-off-by: Greg Kroah-Hartman + +--- + sound/pci/hda/patch_realtek.c | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/sound/pci/hda/patch_realtek.c ++++ b/sound/pci/hda/patch_realtek.c +@@ -6276,8 +6276,11 @@ static int patch_alc269(struct hda_codec + break; + case 0x10ec0225: + case 0x10ec0295: ++ spec->codec_variant = ALC269_TYPE_ALC225; ++ break; + case 0x10ec0299: + spec->codec_variant = ALC269_TYPE_ALC225; ++ spec->gen.mixer_nid = 0; /* no loopback on ALC299 */ + break; + case 0x10ec0234: + case 0x10ec0274: diff --git a/queue-4.11/alsa-usb-fix-a-typo-in-tascam-us-16x08-mixer-element.patch b/queue-4.11/alsa-usb-fix-a-typo-in-tascam-us-16x08-mixer-element.patch new file mode 100644 index 00000000000..cc234cf044e --- /dev/null +++ b/queue-4.11/alsa-usb-fix-a-typo-in-tascam-us-16x08-mixer-element.patch @@ -0,0 +1,32 @@ +From 617163fc2580da3d489b6c1bacb6312e0e2aac02 Mon Sep 17 00:00:00 2001 +From: Takashi Iwai +Date: Tue, 30 May 2017 23:21:07 +0200 +Subject: ALSA: usb: Fix a typo in Tascam US-16x08 mixer element + +From: Takashi Iwai + +commit 617163fc2580da3d489b6c1bacb6312e0e2aac02 upstream. + +A mixer element created in a quirk for Tascam US-16x08 contains a +typo: it should be "EQ MidLow Q" instead of "EQ MidQLow Q". + +Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=195875 +Fixes: d2bb390a2081 ("ALSA: usb-audio: Tascam US-16x08 DSP mixer quirk") +Signed-off-by: Takashi Iwai +Signed-off-by: Greg Kroah-Hartman + +--- + sound/usb/mixer_us16x08.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/sound/usb/mixer_us16x08.c ++++ b/sound/usb/mixer_us16x08.c +@@ -1135,7 +1135,7 @@ static const struct snd_us16x08_control_ + .control_id = SND_US16X08_ID_EQLOWMIDWIDTH, + .type = USB_MIXER_U8, + .num_channels = 16, +- .name = "EQ MidQLow Q", ++ .name = "EQ MidLow Q", + }, + { /* EQ mid high gain */ + .kcontrol_new = &snd_us16x08_eq_gain_ctl, diff --git a/queue-4.11/drm-amd-powerplay-smu7-add-vblank-check-for-mclk-switching-v2.patch b/queue-4.11/drm-amd-powerplay-smu7-add-vblank-check-for-mclk-switching-v2.patch new file mode 100644 index 00000000000..fd34294465f --- /dev/null +++ b/queue-4.11/drm-amd-powerplay-smu7-add-vblank-check-for-mclk-switching-v2.patch @@ -0,0 +1,96 @@ +From 09be4a5219610a6fae3215d4f51f948d6f5d2609 Mon Sep 17 00:00:00 2001 +From: Alex Deucher +Date: Thu, 11 May 2017 13:46:12 -0400 +Subject: drm/amd/powerplay/smu7: add vblank check for mclk switching (v2) +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Alex Deucher + +commit 09be4a5219610a6fae3215d4f51f948d6f5d2609 upstream. + +Check to make sure the vblank period is long enough to support +mclk switching. + +v2: drop needless initial assignment (Nils) + +bug: https://bugs.freedesktop.org/show_bug.cgi?id=96868 + +Acked-by: Christian König +Reviewed-by: Rex Zhu +Signed-off-by: Alex Deucher +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c | 31 ++++++++++++++++++++--- + 1 file changed, 27 insertions(+), 4 deletions(-) + +--- a/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c ++++ b/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c +@@ -2656,6 +2656,28 @@ static int smu7_get_power_state_size(str + return sizeof(struct smu7_power_state); + } + ++static int smu7_vblank_too_short(struct pp_hwmgr *hwmgr, ++ uint32_t vblank_time_us) ++{ ++ struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); ++ uint32_t switch_limit_us; ++ ++ switch (hwmgr->chip_id) { ++ case CHIP_POLARIS10: ++ case CHIP_POLARIS11: ++ case CHIP_POLARIS12: ++ switch_limit_us = data->is_memory_gddr5 ? 190 : 150; ++ break; ++ default: ++ switch_limit_us = data->is_memory_gddr5 ? 450 : 150; ++ break; ++ } ++ ++ if (vblank_time_us < switch_limit_us) ++ return true; ++ else ++ return false; ++} + + static int smu7_apply_state_adjust_rules(struct pp_hwmgr *hwmgr, + struct pp_power_state *request_ps, +@@ -2670,6 +2692,7 @@ static int smu7_apply_state_adjust_rules + bool disable_mclk_switching; + bool disable_mclk_switching_for_frame_lock; + struct cgs_display_info info = {0}; ++ struct cgs_mode_info mode_info = {0}; + const struct phm_clock_and_voltage_limits *max_limits; + uint32_t i; + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); +@@ -2678,6 +2701,7 @@ static int smu7_apply_state_adjust_rules + int32_t count; + int32_t stable_pstate_sclk = 0, stable_pstate_mclk = 0; + ++ info.mode_info = &mode_info; + data->battery_state = (PP_StateUILabel_Battery == + request_ps->classification.ui_label); + +@@ -2704,8 +2728,6 @@ static int smu7_apply_state_adjust_rules + + cgs_get_active_displays_info(hwmgr->device, &info); + +- /*TO DO result = PHM_CheckVBlankTime(hwmgr, &vblankTooShort);*/ +- + minimum_clocks.engineClock = hwmgr->display_config.min_core_set_clock; + minimum_clocks.memoryClock = hwmgr->display_config.min_mem_set_clock; + +@@ -2770,8 +2792,9 @@ static int smu7_apply_state_adjust_rules + PHM_PlatformCaps_DisableMclkSwitchingForFrameLock); + + +- disable_mclk_switching = (1 < info.display_count) || +- disable_mclk_switching_for_frame_lock; ++ disable_mclk_switching = ((1 < info.display_count) || ++ disable_mclk_switching_for_frame_lock || ++ smu7_vblank_too_short(hwmgr, mode_info.vblank_time_us)); + + sclk = smu7_ps->performance_levels[0].engine_clock; + mclk = smu7_ps->performance_levels[0].memory_clock; diff --git a/queue-4.11/drm-amd-powerplay-smu7-disable-mclk-switching-for-high-refresh-rates.patch b/queue-4.11/drm-amd-powerplay-smu7-disable-mclk-switching-for-high-refresh-rates.patch new file mode 100644 index 00000000000..d984e4cf412 --- /dev/null +++ b/queue-4.11/drm-amd-powerplay-smu7-disable-mclk-switching-for-high-refresh-rates.patch @@ -0,0 +1,37 @@ +From 2275a3a2fe9914ba6d76c8ea490da3c08342bd19 Mon Sep 17 00:00:00 2001 +From: Alex Deucher +Date: Thu, 11 May 2017 13:57:41 -0400 +Subject: drm/amd/powerplay/smu7: disable mclk switching for high refresh rates +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Alex Deucher + +commit 2275a3a2fe9914ba6d76c8ea490da3c08342bd19 upstream. + +Even if the vblank period would allow it, it still seems to +be problematic on some cards. + +bug: https://bugs.freedesktop.org/show_bug.cgi?id=96868 + +Acked-by: Christian König +Signed-off-by: Alex Deucher +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c ++++ b/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c +@@ -2794,7 +2794,8 @@ static int smu7_apply_state_adjust_rules + + disable_mclk_switching = ((1 < info.display_count) || + disable_mclk_switching_for_frame_lock || +- smu7_vblank_too_short(hwmgr, mode_info.vblank_time_us)); ++ smu7_vblank_too_short(hwmgr, mode_info.vblank_time_us) || ++ (mode_info.refresh_rate > 120)); + + sclk = smu7_ps->performance_levels[0].engine_clock; + mclk = smu7_ps->performance_levels[0].memory_clock; diff --git a/queue-4.11/drm-gma500-psb-actually-use-vbt-mode-when-it-is-found.patch b/queue-4.11/drm-gma500-psb-actually-use-vbt-mode-when-it-is-found.patch new file mode 100644 index 00000000000..74902ba0f51 --- /dev/null +++ b/queue-4.11/drm-gma500-psb-actually-use-vbt-mode-when-it-is-found.patch @@ -0,0 +1,64 @@ +From 82bc9a42cf854fdf63155759c0aa790bd1f361b0 Mon Sep 17 00:00:00 2001 +From: Patrik Jakobsson +Date: Tue, 18 Apr 2017 13:43:32 +0200 +Subject: drm/gma500/psb: Actually use VBT mode when it is found + +From: Patrik Jakobsson + +commit 82bc9a42cf854fdf63155759c0aa790bd1f361b0 upstream. + +With LVDS we were incorrectly picking the pre-programmed mode instead of +the prefered mode provided by VBT. Make sure we pick the VBT mode if +one is provided. It is likely that the mode read-out code is still wrong +but this patch fixes the immediate problem on most machines. + +Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=78562 +Signed-off-by: Patrik Jakobsson +Link: http://patchwork.freedesktop.org/patch/msgid/20170418114332.12183-1-patrik.r.jakobsson@gmail.com +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/gma500/psb_intel_lvds.c | 18 +++++++++++------- + 1 file changed, 11 insertions(+), 7 deletions(-) + +--- a/drivers/gpu/drm/gma500/psb_intel_lvds.c ++++ b/drivers/gpu/drm/gma500/psb_intel_lvds.c +@@ -760,20 +760,23 @@ void psb_intel_lvds_init(struct drm_devi + if (scan->type & DRM_MODE_TYPE_PREFERRED) { + mode_dev->panel_fixed_mode = + drm_mode_duplicate(dev, scan); ++ DRM_DEBUG_KMS("Using mode from DDC\n"); + goto out; /* FIXME: check for quirks */ + } + } + + /* Failed to get EDID, what about VBT? do we need this? */ +- if (mode_dev->vbt_mode) ++ if (dev_priv->lfp_lvds_vbt_mode) { + mode_dev->panel_fixed_mode = +- drm_mode_duplicate(dev, mode_dev->vbt_mode); ++ drm_mode_duplicate(dev, dev_priv->lfp_lvds_vbt_mode); + +- if (!mode_dev->panel_fixed_mode) +- if (dev_priv->lfp_lvds_vbt_mode) +- mode_dev->panel_fixed_mode = +- drm_mode_duplicate(dev, +- dev_priv->lfp_lvds_vbt_mode); ++ if (mode_dev->panel_fixed_mode) { ++ mode_dev->panel_fixed_mode->type |= ++ DRM_MODE_TYPE_PREFERRED; ++ DRM_DEBUG_KMS("Using mode from VBT\n"); ++ goto out; ++ } ++ } + + /* + * If we didn't get EDID, try checking if the panel is already turned +@@ -790,6 +793,7 @@ void psb_intel_lvds_init(struct drm_devi + if (mode_dev->panel_fixed_mode) { + mode_dev->panel_fixed_mode->type |= + DRM_MODE_TYPE_PREFERRED; ++ DRM_DEBUG_KMS("Using pre-programmed mode\n"); + goto out; /* FIXME: check for quirks */ + } + } diff --git a/queue-4.11/drm-radeon-ci-disable-mclk-switching-for-high-refresh-rates-v2.patch b/queue-4.11/drm-radeon-ci-disable-mclk-switching-for-high-refresh-rates-v2.patch new file mode 100644 index 00000000000..378ec5dc293 --- /dev/null +++ b/queue-4.11/drm-radeon-ci-disable-mclk-switching-for-high-refresh-rates-v2.patch @@ -0,0 +1,42 @@ +From 58d7e3e427db1bd68f33025519a9468140280a75 Mon Sep 17 00:00:00 2001 +From: Alex Deucher +Date: Thu, 11 May 2017 13:14:14 -0400 +Subject: drm/radeon/ci: disable mclk switching for high refresh rates (v2) +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Alex Deucher + +commit 58d7e3e427db1bd68f33025519a9468140280a75 upstream. + +Even if the vblank period would allow it, it still seems to +be problematic on some cards. + +v2: fix logic inversion (Nils) + +bug: https://bugs.freedesktop.org/show_bug.cgi?id=96868 + +Acked-by: Christian König +Signed-off-by: Alex Deucher +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/radeon/ci_dpm.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +--- a/drivers/gpu/drm/radeon/ci_dpm.c ++++ b/drivers/gpu/drm/radeon/ci_dpm.c +@@ -776,6 +776,12 @@ bool ci_dpm_vblank_too_short(struct rade + u32 vblank_time = r600_dpm_get_vblank_time(rdev); + u32 switch_limit = pi->mem_gddr5 ? 450 : 300; + ++ /* disable mclk switching if the refresh is >120Hz, even if the ++ * blanking period would allow it ++ */ ++ if (r600_dpm_get_vrefresh(rdev) > 120) ++ return true; ++ + if (vblank_time < switch_limit) + return true; + else diff --git a/queue-4.11/drm-radeon-unbreak-hpd-handling-for-r600.patch b/queue-4.11/drm-radeon-unbreak-hpd-handling-for-r600.patch new file mode 100644 index 00000000000..90697eab5af --- /dev/null +++ b/queue-4.11/drm-radeon-unbreak-hpd-handling-for-r600.patch @@ -0,0 +1,103 @@ +From 3d18e33735a02b1a90aecf14410bf3edbfd4d3dc Mon Sep 17 00:00:00 2001 +From: Lyude +Date: Thu, 11 May 2017 19:31:12 -0400 +Subject: drm/radeon: Unbreak HPD handling for r600+ +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Lyude + +commit 3d18e33735a02b1a90aecf14410bf3edbfd4d3dc upstream. + +We end up reading the interrupt register for HPD5, and then writing it +to HPD6 which on systems without anything using HPD5 results in +permanently disabling hotplug on one of the display outputs after the +first time we acknowledge a hotplug interrupt from the GPU. + +This code is really bad. But for now, let's just fix this. I will +hopefully have a large patch series to refactor all of this soon. + +Reviewed-by: Christian König +Signed-off-by: Lyude +Signed-off-by: Alex Deucher +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/radeon/cik.c | 4 ++-- + drivers/gpu/drm/radeon/evergreen.c | 4 ++-- + drivers/gpu/drm/radeon/r600.c | 2 +- + drivers/gpu/drm/radeon/si.c | 4 ++-- + 4 files changed, 7 insertions(+), 7 deletions(-) + +--- a/drivers/gpu/drm/radeon/cik.c ++++ b/drivers/gpu/drm/radeon/cik.c +@@ -7416,7 +7416,7 @@ static inline void cik_irq_ack(struct ra + WREG32(DC_HPD5_INT_CONTROL, tmp); + } + if (rdev->irq.stat_regs.cik.disp_int_cont5 & DC_HPD6_INTERRUPT) { +- tmp = RREG32(DC_HPD5_INT_CONTROL); ++ tmp = RREG32(DC_HPD6_INT_CONTROL); + tmp |= DC_HPDx_INT_ACK; + WREG32(DC_HPD6_INT_CONTROL, tmp); + } +@@ -7446,7 +7446,7 @@ static inline void cik_irq_ack(struct ra + WREG32(DC_HPD5_INT_CONTROL, tmp); + } + if (rdev->irq.stat_regs.cik.disp_int_cont5 & DC_HPD6_RX_INTERRUPT) { +- tmp = RREG32(DC_HPD5_INT_CONTROL); ++ tmp = RREG32(DC_HPD6_INT_CONTROL); + tmp |= DC_HPDx_RX_INT_ACK; + WREG32(DC_HPD6_INT_CONTROL, tmp); + } +--- a/drivers/gpu/drm/radeon/evergreen.c ++++ b/drivers/gpu/drm/radeon/evergreen.c +@@ -4933,7 +4933,7 @@ static void evergreen_irq_ack(struct rad + WREG32(DC_HPD5_INT_CONTROL, tmp); + } + if (rdev->irq.stat_regs.evergreen.disp_int_cont5 & DC_HPD6_INTERRUPT) { +- tmp = RREG32(DC_HPD5_INT_CONTROL); ++ tmp = RREG32(DC_HPD6_INT_CONTROL); + tmp |= DC_HPDx_INT_ACK; + WREG32(DC_HPD6_INT_CONTROL, tmp); + } +@@ -4964,7 +4964,7 @@ static void evergreen_irq_ack(struct rad + WREG32(DC_HPD5_INT_CONTROL, tmp); + } + if (rdev->irq.stat_regs.evergreen.disp_int_cont5 & DC_HPD6_RX_INTERRUPT) { +- tmp = RREG32(DC_HPD5_INT_CONTROL); ++ tmp = RREG32(DC_HPD6_INT_CONTROL); + tmp |= DC_HPDx_RX_INT_ACK; + WREG32(DC_HPD6_INT_CONTROL, tmp); + } +--- a/drivers/gpu/drm/radeon/r600.c ++++ b/drivers/gpu/drm/radeon/r600.c +@@ -3995,7 +3995,7 @@ static void r600_irq_ack(struct radeon_d + WREG32(DC_HPD5_INT_CONTROL, tmp); + } + if (rdev->irq.stat_regs.r600.disp_int_cont2 & DC_HPD6_INTERRUPT) { +- tmp = RREG32(DC_HPD5_INT_CONTROL); ++ tmp = RREG32(DC_HPD6_INT_CONTROL); + tmp |= DC_HPDx_INT_ACK; + WREG32(DC_HPD6_INT_CONTROL, tmp); + } +--- a/drivers/gpu/drm/radeon/si.c ++++ b/drivers/gpu/drm/radeon/si.c +@@ -6345,7 +6345,7 @@ static inline void si_irq_ack(struct rad + WREG32(DC_HPD5_INT_CONTROL, tmp); + } + if (rdev->irq.stat_regs.evergreen.disp_int_cont5 & DC_HPD6_INTERRUPT) { +- tmp = RREG32(DC_HPD5_INT_CONTROL); ++ tmp = RREG32(DC_HPD6_INT_CONTROL); + tmp |= DC_HPDx_INT_ACK; + WREG32(DC_HPD6_INT_CONTROL, tmp); + } +@@ -6376,7 +6376,7 @@ static inline void si_irq_ack(struct rad + WREG32(DC_HPD5_INT_CONTROL, tmp); + } + if (rdev->irq.stat_regs.evergreen.disp_int_cont5 & DC_HPD6_RX_INTERRUPT) { +- tmp = RREG32(DC_HPD5_INT_CONTROL); ++ tmp = RREG32(DC_HPD6_INT_CONTROL); + tmp |= DC_HPDx_RX_INT_ACK; + WREG32(DC_HPD6_INT_CONTROL, tmp); + } diff --git a/queue-4.11/hid-wacom-have-wacom_tpc_irq-guard-against-possible-null-dereference.patch b/queue-4.11/hid-wacom-have-wacom_tpc_irq-guard-against-possible-null-dereference.patch new file mode 100644 index 00000000000..60895518a06 --- /dev/null +++ b/queue-4.11/hid-wacom-have-wacom_tpc_irq-guard-against-possible-null-dereference.patch @@ -0,0 +1,99 @@ +From 2ac97f0f6654da14312d125005c77a6010e0ea38 Mon Sep 17 00:00:00 2001 +From: Jason Gerecke +Date: Tue, 25 Apr 2017 11:29:56 -0700 +Subject: HID: wacom: Have wacom_tpc_irq guard against possible NULL dereference + +From: Jason Gerecke + +commit 2ac97f0f6654da14312d125005c77a6010e0ea38 upstream. + +The following Smatch complaint was generated in response to commit +2a6cdbd ("HID: wacom: Introduce new 'touch_input' device"): + + drivers/hid/wacom_wac.c:1586 wacom_tpc_irq() + error: we previously assumed 'wacom->touch_input' could be null (see line 1577) + +The 'touch_input' and 'pen_input' variables point to the 'struct input_dev' +used for relaying touch and pen events to userspace, respectively. If a +device does not have a touch interface or pen interface, the associated +input variable is NULL. The 'wacom_tpc_irq()' function is responsible for +forwarding input reports to a more-specific IRQ handler function. An +unknown report could theoretically be mistaken as e.g. a touch report +on a device which does not have a touch interface. This can be prevented +by only calling the pen/touch functions are called when the pen/touch +pointers are valid. + +Fixes: 2a6cdbd ("HID: wacom: Introduce new 'touch_input' device") +Signed-off-by: Jason Gerecke +Reviewed-by: Ping Cheng +Signed-off-by: Jiri Kosina +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/hid/wacom_wac.c | 47 ++++++++++++++++++++++++----------------------- + 1 file changed, 24 insertions(+), 23 deletions(-) + +--- a/drivers/hid/wacom_wac.c ++++ b/drivers/hid/wacom_wac.c +@@ -1571,37 +1571,38 @@ static int wacom_tpc_irq(struct wacom_wa + { + unsigned char *data = wacom->data; + +- if (wacom->pen_input) ++ if (wacom->pen_input) { + dev_dbg(wacom->pen_input->dev.parent, + "%s: received report #%d\n", __func__, data[0]); +- else if (wacom->touch_input) ++ ++ if (len == WACOM_PKGLEN_PENABLED || ++ data[0] == WACOM_REPORT_PENABLED) ++ return wacom_tpc_pen(wacom); ++ } ++ else if (wacom->touch_input) { + dev_dbg(wacom->touch_input->dev.parent, + "%s: received report #%d\n", __func__, data[0]); + +- switch (len) { +- case WACOM_PKGLEN_TPC1FG: +- return wacom_tpc_single_touch(wacom, len); +- +- case WACOM_PKGLEN_TPC2FG: +- return wacom_tpc_mt_touch(wacom); +- +- case WACOM_PKGLEN_PENABLED: +- return wacom_tpc_pen(wacom); +- +- default: +- switch (data[0]) { +- case WACOM_REPORT_TPC1FG: +- case WACOM_REPORT_TPCHID: +- case WACOM_REPORT_TPCST: +- case WACOM_REPORT_TPC1FGE: ++ switch (len) { ++ case WACOM_PKGLEN_TPC1FG: + return wacom_tpc_single_touch(wacom, len); + +- case WACOM_REPORT_TPCMT: +- case WACOM_REPORT_TPCMT2: +- return wacom_mt_touch(wacom); ++ case WACOM_PKGLEN_TPC2FG: ++ return wacom_tpc_mt_touch(wacom); + +- case WACOM_REPORT_PENABLED: +- return wacom_tpc_pen(wacom); ++ default: ++ switch (data[0]) { ++ case WACOM_REPORT_TPC1FG: ++ case WACOM_REPORT_TPCHID: ++ case WACOM_REPORT_TPCST: ++ case WACOM_REPORT_TPC1FGE: ++ return wacom_tpc_single_touch(wacom, len); ++ ++ case WACOM_REPORT_TPCMT: ++ case WACOM_REPORT_TPCMT2: ++ return wacom_mt_touch(wacom); ++ ++ } + } + } + diff --git a/queue-4.11/ibmvscsis-clear-left-over-abort_cmd-pointers.patch b/queue-4.11/ibmvscsis-clear-left-over-abort_cmd-pointers.patch new file mode 100644 index 00000000000..822411e0779 --- /dev/null +++ b/queue-4.11/ibmvscsis-clear-left-over-abort_cmd-pointers.patch @@ -0,0 +1,46 @@ +From 98883f1b5415ea9dce60d5178877d15f4faa10b8 Mon Sep 17 00:00:00 2001 +From: "Bryant G. Ly" +Date: Tue, 9 May 2017 11:50:26 -0500 +Subject: ibmvscsis: Clear left-over abort_cmd pointers + +From: Bryant G. Ly + +commit 98883f1b5415ea9dce60d5178877d15f4faa10b8 upstream. + +With the addition of ibmvscsis->abort_cmd pointer within +commit 25e78531268e ("ibmvscsis: Do not send aborted task response"), +make sure to explicitly NULL these pointers when clearing +DELAY_SEND flag. + +Do this for two cases, when getting the new new ibmvscsis +descriptor in ibmvscsis_get_free_cmd() and before posting +the response completion in ibmvscsis_send_messages(). + +Signed-off-by: Bryant G. Ly +Reviewed-by: Michael Cyr +Signed-off-by: Nicholas Bellinger +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c ++++ b/drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c +@@ -1170,6 +1170,8 @@ static struct ibmvscsis_cmd *ibmvscsis_g + cmd = list_first_entry_or_null(&vscsi->free_cmd, + struct ibmvscsis_cmd, list); + if (cmd) { ++ if (cmd->abort_cmd) ++ cmd->abort_cmd = NULL; + cmd->flags &= ~(DELAY_SEND); + list_del(&cmd->list); + cmd->iue = iue; +@@ -1774,6 +1776,7 @@ static void ibmvscsis_send_messages(stru + if (cmd->abort_cmd) { + retry = true; + cmd->abort_cmd->flags &= ~(DELAY_SEND); ++ cmd->abort_cmd = NULL; + } + + /* diff --git a/queue-4.11/ibmvscsis-fix-the-incorrect-req_lim_delta.patch b/queue-4.11/ibmvscsis-fix-the-incorrect-req_lim_delta.patch new file mode 100644 index 00000000000..704e2ae6c43 --- /dev/null +++ b/queue-4.11/ibmvscsis-fix-the-incorrect-req_lim_delta.patch @@ -0,0 +1,77 @@ +From 75dbf2d36f6b122ad3c1070fe4bf95f71bbff321 Mon Sep 17 00:00:00 2001 +From: "Bryant G. Ly" +Date: Wed, 10 May 2017 14:35:47 -0500 +Subject: ibmvscsis: Fix the incorrect req_lim_delta + +From: Bryant G. Ly + +commit 75dbf2d36f6b122ad3c1070fe4bf95f71bbff321 upstream. + +The current code is not correctly calculating the req_lim_delta. + +We want to make sure vscsi->credit is always incremented when +we do not send a response for the scsi op. Thus for the case where +there is a successfully aborted task we need to make sure the +vscsi->credit is incremented. + +v2 - Moves the original location of the vscsi->credit increment +to a better spot. Since if we increment credit, the next command +we send back will have increased req_lim_delta. But we probably +shouldn't be doing that until the aborted cmd is actually released. +Otherwise the client will think that it can send a new command, and +we could find ourselves short of command elements. Not likely, but could +happen. + +This patch depends on both: +commit 25e78531268e ("ibmvscsis: Do not send aborted task response") +commit 98883f1b5415 ("ibmvscsis: Clear left-over abort_cmd pointers") + +Signed-off-by: Bryant G. Ly +Reviewed-by: Michael Cyr +Signed-off-by: Nicholas Bellinger +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c | 24 ++++++++++++++++++++---- + 1 file changed, 20 insertions(+), 4 deletions(-) + +--- a/drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c ++++ b/drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c +@@ -1791,6 +1791,25 @@ static void ibmvscsis_send_messages(stru + list_del(&cmd->list); + ibmvscsis_free_cmd_resources(vscsi, + cmd); ++ /* ++ * With a successfully aborted op ++ * through LIO we want to increment the ++ * the vscsi credit so that when we dont ++ * send a rsp to the original scsi abort ++ * op (h_send_crq), but the tm rsp to ++ * the abort is sent, the credit is ++ * correctly sent with the abort tm rsp. ++ * We would need 1 for the abort tm rsp ++ * and 1 credit for the aborted scsi op. ++ * Thus we need to increment here. ++ * Also we want to increment the credit ++ * here because we want to make sure ++ * cmd is actually released first ++ * otherwise the client will think it ++ * it can send a new cmd, and we could ++ * find ourselves short of cmd elements. ++ */ ++ vscsi->credit += 1; + } else { + iue = cmd->iue; + +@@ -2965,10 +2984,7 @@ static long srp_build_response(struct sc + + rsp->opcode = SRP_RSP; + +- if (vscsi->credit > 0 && vscsi->state == SRP_PROCESSING) +- rsp->req_lim_delta = cpu_to_be32(vscsi->credit); +- else +- rsp->req_lim_delta = cpu_to_be32(1 + vscsi->credit); ++ rsp->req_lim_delta = cpu_to_be32(1 + vscsi->credit); + rsp->tag = cmd->rsp.tag; + rsp->flags = 0; + diff --git a/queue-4.11/iscsi-target-always-wait-for-kthread_should_stop-before-kthread-exit.patch b/queue-4.11/iscsi-target-always-wait-for-kthread_should_stop-before-kthread-exit.patch new file mode 100644 index 00000000000..6c4937e247d --- /dev/null +++ b/queue-4.11/iscsi-target-always-wait-for-kthread_should_stop-before-kthread-exit.patch @@ -0,0 +1,171 @@ +From 5e0cf5e6c43b9e19fc0284f69e5cd2b4a47523b0 Mon Sep 17 00:00:00 2001 +From: Jiang Yi +Date: Tue, 16 May 2017 17:57:55 +0800 +Subject: iscsi-target: Always wait for kthread_should_stop() before kthread exit + +From: Jiang Yi + +commit 5e0cf5e6c43b9e19fc0284f69e5cd2b4a47523b0 upstream. + +There are three timing problems in the kthread usages of iscsi_target_mod: + + - np_thread of struct iscsi_np + - rx_thread and tx_thread of struct iscsi_conn + +In iscsit_close_connection(), it calls + + send_sig(SIGINT, conn->tx_thread, 1); + kthread_stop(conn->tx_thread); + +In conn->tx_thread, which is iscsi_target_tx_thread(), when it receive +SIGINT the kthread will exit without checking the return value of +kthread_should_stop(). + +So if iscsi_target_tx_thread() exit right between send_sig(SIGINT...) +and kthread_stop(...), the kthread_stop() will try to stop an already +stopped kthread. + +This is invalid according to the documentation of kthread_stop(). + +(Fix -ECONNRESET logout handling in iscsi_target_tx_thread and + early iscsi_target_rx_thread failure case - nab) + +Signed-off-by: Jiang Yi +Signed-off-by: Nicholas Bellinger +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/target/iscsi/iscsi_target.c | 30 ++++++++++++++++++++++++------ + drivers/target/iscsi/iscsi_target_erl0.c | 6 +++++- + drivers/target/iscsi/iscsi_target_erl0.h | 2 +- + drivers/target/iscsi/iscsi_target_login.c | 4 ++++ + 4 files changed, 34 insertions(+), 8 deletions(-) + +--- a/drivers/target/iscsi/iscsi_target.c ++++ b/drivers/target/iscsi/iscsi_target.c +@@ -3810,6 +3810,8 @@ int iscsi_target_tx_thread(void *arg) + { + int ret = 0; + struct iscsi_conn *conn = arg; ++ bool conn_freed = false; ++ + /* + * Allow ourselves to be interrupted by SIGINT so that a + * connection recovery / failure event can be triggered externally. +@@ -3835,12 +3837,14 @@ get_immediate: + goto transport_err; + + ret = iscsit_handle_response_queue(conn); +- if (ret == 1) ++ if (ret == 1) { + goto get_immediate; +- else if (ret == -ECONNRESET) ++ } else if (ret == -ECONNRESET) { ++ conn_freed = true; + goto out; +- else if (ret < 0) ++ } else if (ret < 0) { + goto transport_err; ++ } + } + + transport_err: +@@ -3850,8 +3854,13 @@ transport_err: + * responsible for cleaning up the early connection failure. + */ + if (conn->conn_state != TARG_CONN_STATE_IN_LOGIN) +- iscsit_take_action_for_connection_exit(conn); ++ iscsit_take_action_for_connection_exit(conn, &conn_freed); + out: ++ if (!conn_freed) { ++ while (!kthread_should_stop()) { ++ msleep(100); ++ } ++ } + return 0; + } + +@@ -4024,6 +4033,7 @@ int iscsi_target_rx_thread(void *arg) + { + int rc; + struct iscsi_conn *conn = arg; ++ bool conn_freed = false; + + /* + * Allow ourselves to be interrupted by SIGINT so that a +@@ -4036,7 +4046,7 @@ int iscsi_target_rx_thread(void *arg) + */ + rc = wait_for_completion_interruptible(&conn->rx_login_comp); + if (rc < 0 || iscsi_target_check_conn_state(conn)) +- return 0; ++ goto out; + + if (!conn->conn_transport->iscsit_get_rx_pdu) + return 0; +@@ -4045,7 +4055,15 @@ int iscsi_target_rx_thread(void *arg) + + if (!signal_pending(current)) + atomic_set(&conn->transport_failed, 1); +- iscsit_take_action_for_connection_exit(conn); ++ iscsit_take_action_for_connection_exit(conn, &conn_freed); ++ ++out: ++ if (!conn_freed) { ++ while (!kthread_should_stop()) { ++ msleep(100); ++ } ++ } ++ + return 0; + } + +--- a/drivers/target/iscsi/iscsi_target_erl0.c ++++ b/drivers/target/iscsi/iscsi_target_erl0.c +@@ -930,8 +930,10 @@ static void iscsit_handle_connection_cle + } + } + +-void iscsit_take_action_for_connection_exit(struct iscsi_conn *conn) ++void iscsit_take_action_for_connection_exit(struct iscsi_conn *conn, bool *conn_freed) + { ++ *conn_freed = false; ++ + spin_lock_bh(&conn->state_lock); + if (atomic_read(&conn->connection_exit)) { + spin_unlock_bh(&conn->state_lock); +@@ -942,6 +944,7 @@ void iscsit_take_action_for_connection_e + if (conn->conn_state == TARG_CONN_STATE_IN_LOGOUT) { + spin_unlock_bh(&conn->state_lock); + iscsit_close_connection(conn); ++ *conn_freed = true; + return; + } + +@@ -955,4 +958,5 @@ void iscsit_take_action_for_connection_e + spin_unlock_bh(&conn->state_lock); + + iscsit_handle_connection_cleanup(conn); ++ *conn_freed = true; + } +--- a/drivers/target/iscsi/iscsi_target_erl0.h ++++ b/drivers/target/iscsi/iscsi_target_erl0.h +@@ -15,6 +15,6 @@ extern int iscsit_stop_time2retain_timer + extern void iscsit_connection_reinstatement_rcfr(struct iscsi_conn *); + extern void iscsit_cause_connection_reinstatement(struct iscsi_conn *, int); + extern void iscsit_fall_back_to_erl0(struct iscsi_session *); +-extern void iscsit_take_action_for_connection_exit(struct iscsi_conn *); ++extern void iscsit_take_action_for_connection_exit(struct iscsi_conn *, bool *); + + #endif /*** ISCSI_TARGET_ERL0_H ***/ +--- a/drivers/target/iscsi/iscsi_target_login.c ++++ b/drivers/target/iscsi/iscsi_target_login.c +@@ -1464,5 +1464,9 @@ int iscsi_target_login_thread(void *arg) + break; + } + ++ while (!kthread_should_stop()) { ++ msleep(100); ++ } ++ + return 0; + } diff --git a/queue-4.11/iscsi-target-fix-initial-login-pdu-asynchronous-socket-close-oops.patch b/queue-4.11/iscsi-target-fix-initial-login-pdu-asynchronous-socket-close-oops.patch new file mode 100644 index 00000000000..aedc86bca5c --- /dev/null +++ b/queue-4.11/iscsi-target-fix-initial-login-pdu-asynchronous-socket-close-oops.patch @@ -0,0 +1,367 @@ +From 25cdda95fda78d22d44157da15aa7ea34be3c804 Mon Sep 17 00:00:00 2001 +From: Nicholas Bellinger +Date: Wed, 24 May 2017 21:47:09 -0700 +Subject: iscsi-target: Fix initial login PDU asynchronous socket close OOPs + +From: Nicholas Bellinger + +commit 25cdda95fda78d22d44157da15aa7ea34be3c804 upstream. + +This patch fixes a OOPs originally introduced by: + + commit bb048357dad6d604520c91586334c9c230366a14 + Author: Nicholas Bellinger + Date: Thu Sep 5 14:54:04 2013 -0700 + + iscsi-target: Add sk->sk_state_change to cleanup after TCP failure + +which would trigger a NULL pointer dereference when a TCP connection +was closed asynchronously via iscsi_target_sk_state_change(), but only +when the initial PDU processing in iscsi_target_do_login() from iscsi_np +process context was blocked waiting for backend I/O to complete. + +To address this issue, this patch makes the following changes. + +First, it introduces some common helper functions used for checking +socket closing state, checking login_flags, and atomically checking +socket closing state + setting login_flags. + +Second, it introduces a LOGIN_FLAGS_INITIAL_PDU bit to know when a TCP +connection has dropped via iscsi_target_sk_state_change(), but the +initial PDU processing within iscsi_target_do_login() in iscsi_np +context is still running. For this case, it sets LOGIN_FLAGS_CLOSED, +but doesn't invoke schedule_delayed_work(). + +The original NULL pointer dereference case reported by MNC is now handled +by iscsi_target_do_login() doing a iscsi_target_sk_check_close() before +transitioning to FFP to determine when the socket has already closed, +or iscsi_target_start_negotiation() if the login needs to exchange +more PDUs (eg: iscsi_target_do_login returned 0) but the socket has +closed. For both of these cases, the cleanup up of remaining connection +resources will occur in iscsi_target_start_negotiation() from iscsi_np +process context once the failure is detected. + +Finally, to handle to case where iscsi_target_sk_state_change() is +called after the initial PDU procesing is complete, it now invokes +conn->login_work -> iscsi_target_do_login_rx() to perform cleanup once +existing iscsi_target_sk_check_close() checks detect connection failure. +For this case, the cleanup of remaining connection resources will occur +in iscsi_target_do_login_rx() from delayed workqueue process context +once the failure is detected. + +Reported-by: Mike Christie +Reviewed-by: Mike Christie +Tested-by: Mike Christie +Cc: Mike Christie +Reported-by: Hannes Reinecke +Cc: Hannes Reinecke +Cc: Sagi Grimberg +Cc: Varun Prakash +Signed-off-by: Nicholas Bellinger +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/target/iscsi/iscsi_target_nego.c | 194 +++++++++++++++++++++---------- + include/target/iscsi/iscsi_target_core.h | 1 + 2 files changed, 133 insertions(+), 62 deletions(-) + +--- a/drivers/target/iscsi/iscsi_target_nego.c ++++ b/drivers/target/iscsi/iscsi_target_nego.c +@@ -493,14 +493,60 @@ static void iscsi_target_restore_sock_ca + + static int iscsi_target_do_login(struct iscsi_conn *, struct iscsi_login *); + +-static bool iscsi_target_sk_state_check(struct sock *sk) ++static bool __iscsi_target_sk_check_close(struct sock *sk) + { + if (sk->sk_state == TCP_CLOSE_WAIT || sk->sk_state == TCP_CLOSE) { +- pr_debug("iscsi_target_sk_state_check: TCP_CLOSE_WAIT|TCP_CLOSE," ++ pr_debug("__iscsi_target_sk_check_close: TCP_CLOSE_WAIT|TCP_CLOSE," + "returning FALSE\n"); +- return false; ++ return true; + } +- return true; ++ return false; ++} ++ ++static bool iscsi_target_sk_check_close(struct iscsi_conn *conn) ++{ ++ bool state = false; ++ ++ if (conn->sock) { ++ struct sock *sk = conn->sock->sk; ++ ++ read_lock_bh(&sk->sk_callback_lock); ++ state = (__iscsi_target_sk_check_close(sk) || ++ test_bit(LOGIN_FLAGS_CLOSED, &conn->login_flags)); ++ read_unlock_bh(&sk->sk_callback_lock); ++ } ++ return state; ++} ++ ++static bool iscsi_target_sk_check_flag(struct iscsi_conn *conn, unsigned int flag) ++{ ++ bool state = false; ++ ++ if (conn->sock) { ++ struct sock *sk = conn->sock->sk; ++ ++ read_lock_bh(&sk->sk_callback_lock); ++ state = test_bit(flag, &conn->login_flags); ++ read_unlock_bh(&sk->sk_callback_lock); ++ } ++ return state; ++} ++ ++static bool iscsi_target_sk_check_and_clear(struct iscsi_conn *conn, unsigned int flag) ++{ ++ bool state = false; ++ ++ if (conn->sock) { ++ struct sock *sk = conn->sock->sk; ++ ++ write_lock_bh(&sk->sk_callback_lock); ++ state = (__iscsi_target_sk_check_close(sk) || ++ test_bit(LOGIN_FLAGS_CLOSED, &conn->login_flags)); ++ if (!state) ++ clear_bit(flag, &conn->login_flags); ++ write_unlock_bh(&sk->sk_callback_lock); ++ } ++ return state; + } + + static void iscsi_target_login_drop(struct iscsi_conn *conn, struct iscsi_login *login) +@@ -540,6 +586,20 @@ static void iscsi_target_do_login_rx(str + + pr_debug("entering iscsi_target_do_login_rx, conn: %p, %s:%d\n", + conn, current->comm, current->pid); ++ /* ++ * If iscsi_target_do_login_rx() has been invoked by ->sk_data_ready() ++ * before initial PDU processing in iscsi_target_start_negotiation() ++ * has completed, go ahead and retry until it's cleared. ++ * ++ * Otherwise if the TCP connection drops while this is occuring, ++ * iscsi_target_start_negotiation() will detect the failure, call ++ * cancel_delayed_work_sync(&conn->login_work), and cleanup the ++ * remaining iscsi connection resources from iscsi_np process context. ++ */ ++ if (iscsi_target_sk_check_flag(conn, LOGIN_FLAGS_INITIAL_PDU)) { ++ schedule_delayed_work(&conn->login_work, msecs_to_jiffies(10)); ++ return; ++ } + + spin_lock(&tpg->tpg_state_lock); + state = (tpg->tpg_state == TPG_STATE_ACTIVE); +@@ -547,26 +607,12 @@ static void iscsi_target_do_login_rx(str + + if (!state) { + pr_debug("iscsi_target_do_login_rx: tpg_state != TPG_STATE_ACTIVE\n"); +- iscsi_target_restore_sock_callbacks(conn); +- iscsi_target_login_drop(conn, login); +- iscsit_deaccess_np(np, tpg, tpg_np); +- return; ++ goto err; + } + +- if (conn->sock) { +- struct sock *sk = conn->sock->sk; +- +- read_lock_bh(&sk->sk_callback_lock); +- state = iscsi_target_sk_state_check(sk); +- read_unlock_bh(&sk->sk_callback_lock); +- +- if (!state) { +- pr_debug("iscsi_target_do_login_rx, TCP state CLOSE\n"); +- iscsi_target_restore_sock_callbacks(conn); +- iscsi_target_login_drop(conn, login); +- iscsit_deaccess_np(np, tpg, tpg_np); +- return; +- } ++ if (iscsi_target_sk_check_close(conn)) { ++ pr_debug("iscsi_target_do_login_rx, TCP state CLOSE\n"); ++ goto err; + } + + conn->login_kworker = current; +@@ -584,34 +630,29 @@ static void iscsi_target_do_login_rx(str + flush_signals(current); + conn->login_kworker = NULL; + +- if (rc < 0) { +- iscsi_target_restore_sock_callbacks(conn); +- iscsi_target_login_drop(conn, login); +- iscsit_deaccess_np(np, tpg, tpg_np); +- return; +- } ++ if (rc < 0) ++ goto err; + + pr_debug("iscsi_target_do_login_rx after rx_login_io, %p, %s:%d\n", + conn, current->comm, current->pid); + + rc = iscsi_target_do_login(conn, login); + if (rc < 0) { +- iscsi_target_restore_sock_callbacks(conn); +- iscsi_target_login_drop(conn, login); +- iscsit_deaccess_np(np, tpg, tpg_np); ++ goto err; + } else if (!rc) { +- if (conn->sock) { +- struct sock *sk = conn->sock->sk; +- +- write_lock_bh(&sk->sk_callback_lock); +- clear_bit(LOGIN_FLAGS_READ_ACTIVE, &conn->login_flags); +- write_unlock_bh(&sk->sk_callback_lock); +- } ++ if (iscsi_target_sk_check_and_clear(conn, LOGIN_FLAGS_READ_ACTIVE)) ++ goto err; + } else if (rc == 1) { + iscsi_target_nego_release(conn); + iscsi_post_login_handler(np, conn, zero_tsih); + iscsit_deaccess_np(np, tpg, tpg_np); + } ++ return; ++ ++err: ++ iscsi_target_restore_sock_callbacks(conn); ++ iscsi_target_login_drop(conn, login); ++ iscsit_deaccess_np(np, tpg, tpg_np); + } + + static void iscsi_target_do_cleanup(struct work_struct *work) +@@ -659,31 +700,54 @@ static void iscsi_target_sk_state_change + orig_state_change(sk); + return; + } ++ state = __iscsi_target_sk_check_close(sk); ++ pr_debug("__iscsi_target_sk_close_change: state: %d\n", state); ++ + if (test_bit(LOGIN_FLAGS_READ_ACTIVE, &conn->login_flags)) { + pr_debug("Got LOGIN_FLAGS_READ_ACTIVE=1 sk_state_change" + " conn: %p\n", conn); ++ if (state) ++ set_bit(LOGIN_FLAGS_CLOSED, &conn->login_flags); + write_unlock_bh(&sk->sk_callback_lock); + orig_state_change(sk); + return; + } +- if (test_and_set_bit(LOGIN_FLAGS_CLOSED, &conn->login_flags)) { ++ if (test_bit(LOGIN_FLAGS_CLOSED, &conn->login_flags)) { + pr_debug("Got LOGIN_FLAGS_CLOSED=1 sk_state_change conn: %p\n", + conn); + write_unlock_bh(&sk->sk_callback_lock); + orig_state_change(sk); + return; + } ++ /* ++ * If the TCP connection has dropped, go ahead and set LOGIN_FLAGS_CLOSED, ++ * but only queue conn->login_work -> iscsi_target_do_login_rx() ++ * processing if LOGIN_FLAGS_INITIAL_PDU has already been cleared. ++ * ++ * When iscsi_target_do_login_rx() runs, iscsi_target_sk_check_close() ++ * will detect the dropped TCP connection from delayed workqueue context. ++ * ++ * If LOGIN_FLAGS_INITIAL_PDU is still set, which means the initial ++ * iscsi_target_start_negotiation() is running, iscsi_target_do_login() ++ * via iscsi_target_sk_check_close() or iscsi_target_start_negotiation() ++ * via iscsi_target_sk_check_and_clear() is responsible for detecting the ++ * dropped TCP connection in iscsi_np process context, and cleaning up ++ * the remaining iscsi connection resources. ++ */ ++ if (state) { ++ pr_debug("iscsi_target_sk_state_change got failed state\n"); ++ set_bit(LOGIN_FLAGS_CLOSED, &conn->login_flags); ++ state = test_bit(LOGIN_FLAGS_INITIAL_PDU, &conn->login_flags); ++ write_unlock_bh(&sk->sk_callback_lock); + +- state = iscsi_target_sk_state_check(sk); +- write_unlock_bh(&sk->sk_callback_lock); +- +- pr_debug("iscsi_target_sk_state_change: state: %d\n", state); ++ orig_state_change(sk); + +- if (!state) { +- pr_debug("iscsi_target_sk_state_change got failed state\n"); +- schedule_delayed_work(&conn->login_cleanup_work, 0); ++ if (!state) ++ schedule_delayed_work(&conn->login_work, 0); + return; + } ++ write_unlock_bh(&sk->sk_callback_lock); ++ + orig_state_change(sk); + } + +@@ -946,6 +1010,15 @@ static int iscsi_target_do_login(struct + if (iscsi_target_handle_csg_one(conn, login) < 0) + return -1; + if (login_rsp->flags & ISCSI_FLAG_LOGIN_TRANSIT) { ++ /* ++ * Check to make sure the TCP connection has not ++ * dropped asynchronously while session reinstatement ++ * was occuring in this kthread context, before ++ * transitioning to full feature phase operation. ++ */ ++ if (iscsi_target_sk_check_close(conn)) ++ return -1; ++ + login->tsih = conn->sess->tsih; + login->login_complete = 1; + iscsi_target_restore_sock_callbacks(conn); +@@ -972,21 +1045,6 @@ static int iscsi_target_do_login(struct + break; + } + +- if (conn->sock) { +- struct sock *sk = conn->sock->sk; +- bool state; +- +- read_lock_bh(&sk->sk_callback_lock); +- state = iscsi_target_sk_state_check(sk); +- read_unlock_bh(&sk->sk_callback_lock); +- +- if (!state) { +- pr_debug("iscsi_target_do_login() failed state for" +- " conn: %p\n", conn); +- return -1; +- } +- } +- + return 0; + } + +@@ -1255,10 +1313,22 @@ int iscsi_target_start_negotiation( + + write_lock_bh(&sk->sk_callback_lock); + set_bit(LOGIN_FLAGS_READY, &conn->login_flags); ++ set_bit(LOGIN_FLAGS_INITIAL_PDU, &conn->login_flags); + write_unlock_bh(&sk->sk_callback_lock); + } +- ++ /* ++ * If iscsi_target_do_login returns zero to signal more PDU ++ * exchanges are required to complete the login, go ahead and ++ * clear LOGIN_FLAGS_INITIAL_PDU but only if the TCP connection ++ * is still active. ++ * ++ * Otherwise if TCP connection dropped asynchronously, go ahead ++ * and perform connection cleanup now. ++ */ + ret = iscsi_target_do_login(conn, login); ++ if (!ret && iscsi_target_sk_check_and_clear(conn, LOGIN_FLAGS_INITIAL_PDU)) ++ ret = -1; ++ + if (ret < 0) { + cancel_delayed_work_sync(&conn->login_work); + cancel_delayed_work_sync(&conn->login_cleanup_work); +--- a/include/target/iscsi/iscsi_target_core.h ++++ b/include/target/iscsi/iscsi_target_core.h +@@ -557,6 +557,7 @@ struct iscsi_conn { + #define LOGIN_FLAGS_READ_ACTIVE 1 + #define LOGIN_FLAGS_CLOSED 2 + #define LOGIN_FLAGS_READY 4 ++#define LOGIN_FLAGS_INITIAL_PDU 8 + unsigned long login_flags; + struct delayed_work login_work; + struct delayed_work login_cleanup_work; diff --git a/queue-4.11/ksm-prevent-crash-after-write_protect_page-fails.patch b/queue-4.11/ksm-prevent-crash-after-write_protect_page-fails.patch new file mode 100644 index 00000000000..0bbe05c848f --- /dev/null +++ b/queue-4.11/ksm-prevent-crash-after-write_protect_page-fails.patch @@ -0,0 +1,66 @@ +From a7306c3436e9c8e584a4b9fad5f3dc91be2a6076 Mon Sep 17 00:00:00 2001 +From: Andrea Arcangeli +Date: Fri, 2 Jun 2017 14:46:11 -0700 +Subject: ksm: prevent crash after write_protect_page fails + +From: Andrea Arcangeli + +commit a7306c3436e9c8e584a4b9fad5f3dc91be2a6076 upstream. + +"err" needs to be left set to -EFAULT if split_huge_page succeeds. +Otherwise if "err" gets clobbered with zero and write_protect_page +fails, try_to_merge_one_page() will succeed instead of returning -EFAULT +and then try_to_merge_with_ksm_page() will continue thinking kpage is a +PageKsm when in fact it's still an anonymous page. Eventually it'll +crash in page_add_anon_rmap. + +This has been reproduced on Fedora25 kernel but I can reproduce with +upstream too. + +The bug was introduced in commit f765f540598a ("ksm: prepare to new THP +semantics") introduced in v4.5. + + page:fffff67546ce1cc0 count:4 mapcount:2 mapping:ffffa094551e36e1 index:0x7f0f46673 + flags: 0x2ffffc0004007c(referenced|uptodate|dirty|lru|active|swapbacked) + page dumped because: VM_BUG_ON_PAGE(!PageLocked(page)) + page->mem_cgroup:ffffa09674bf0000 + ------------[ cut here ]------------ + kernel BUG at mm/rmap.c:1222! + CPU: 1 PID: 76 Comm: ksmd Not tainted 4.9.3-200.fc25.x86_64 #1 + RIP: do_page_add_anon_rmap+0x1c4/0x240 + Call Trace: + page_add_anon_rmap+0x18/0x20 + try_to_merge_with_ksm_page+0x50b/0x780 + ksm_scan_thread+0x1211/0x1410 + ? prepare_to_wait_event+0x100/0x100 + ? try_to_merge_with_ksm_page+0x780/0x780 + kthread+0xd9/0xf0 + ? kthread_park+0x60/0x60 + ret_from_fork+0x25/0x30 + +Fixes: f765f54059 ("ksm: prepare to new THP semantics") +Link: http://lkml.kernel.org/r/20170513131040.21732-1-aarcange@redhat.com +Signed-off-by: Andrea Arcangeli +Reported-by: Federico Simoncelli +Acked-by: Kirill A. Shutemov +Cc: Hugh Dickins +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman + +--- + mm/ksm.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +--- a/mm/ksm.c ++++ b/mm/ksm.c +@@ -1028,8 +1028,7 @@ static int try_to_merge_one_page(struct + goto out; + + if (PageTransCompound(page)) { +- err = split_huge_page(page); +- if (err) ++ if (split_huge_page(page)) + goto out_unlock; + } + diff --git a/queue-4.11/nvme-avoid-to-use-blk_mq_abort_requeue_list.patch b/queue-4.11/nvme-avoid-to-use-blk_mq_abort_requeue_list.patch new file mode 100644 index 00000000000..cc022e76a11 --- /dev/null +++ b/queue-4.11/nvme-avoid-to-use-blk_mq_abort_requeue_list.patch @@ -0,0 +1,61 @@ +From 986f75c876dbafed98eba7cb516c5118f155db23 Mon Sep 17 00:00:00 2001 +From: Ming Lei +Date: Mon, 22 May 2017 23:05:04 +0800 +Subject: nvme: avoid to use blk_mq_abort_requeue_list() + +From: Ming Lei + +commit 986f75c876dbafed98eba7cb516c5118f155db23 upstream. + +NVMe may add request into requeue list simply and not kick off the +requeue if hw queues are stopped. Then blk_mq_abort_requeue_list() +is called in both nvme_kill_queues() and nvme_ns_remove() for +dealing with this issue. + +Unfortunately blk_mq_abort_requeue_list() is absolutely a +race maker, for example, one request may be requeued during +the aborting. So this patch just calls blk_mq_kick_requeue_list() in +nvme_kill_queues() to handle this issue like what nvme_start_queues() +does. Now all requests in requeue list when queues are stopped will be +handled by blk_mq_kick_requeue_list() when queues are restarted, either +in nvme_start_queues() or in nvme_kill_queues(). + +Reported-by: Zhang Yi +Reviewed-by: Keith Busch +Reviewed-by: Johannes Thumshirn +Signed-off-by: Ming Lei +Signed-off-by: Christoph Hellwig +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/nvme/host/core.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +--- a/drivers/nvme/host/core.c ++++ b/drivers/nvme/host/core.c +@@ -2006,7 +2006,6 @@ static void nvme_ns_remove(struct nvme_n + if (ns->ndev) + nvme_nvm_unregister_sysfs(ns); + del_gendisk(ns->disk); +- blk_mq_abort_requeue_list(ns->queue); + blk_cleanup_queue(ns->queue); + } + +@@ -2344,7 +2343,6 @@ void nvme_kill_queues(struct nvme_ctrl * + continue; + revalidate_disk(ns->disk); + blk_set_queue_dying(ns->queue); +- blk_mq_abort_requeue_list(ns->queue); + + /* + * Forcibly start all queues to avoid having stuck requests. +@@ -2352,6 +2350,9 @@ void nvme_kill_queues(struct nvme_ctrl * + * when the final removal happens. + */ + blk_mq_start_hw_queues(ns->queue); ++ ++ /* draining requests in requeue list */ ++ blk_mq_kick_requeue_list(ns->queue); + } + mutex_unlock(&ctrl->namespaces_mutex); + } diff --git a/queue-4.11/nvme-rdma-support-devices-with-queue-size-32.patch b/queue-4.11/nvme-rdma-support-devices-with-queue-size-32.patch new file mode 100644 index 00000000000..264f75167c9 --- /dev/null +++ b/queue-4.11/nvme-rdma-support-devices-with-queue-size-32.patch @@ -0,0 +1,71 @@ +From 0544f5494a03b8846db74e02be5685d1f32b06c9 Mon Sep 17 00:00:00 2001 +From: Marta Rybczynska +Date: Mon, 10 Apr 2017 17:12:34 +0200 +Subject: nvme-rdma: support devices with queue size < 32 + +From: Marta Rybczynska + +commit 0544f5494a03b8846db74e02be5685d1f32b06c9 upstream. + +In the case of small NVMe-oF queue size (<32) we may enter a deadlock +caused by the fact that the IB completions aren't sent waiting for 32 +and the send queue will fill up. + +The error is seen as (using mlx5): +[ 2048.693355] mlx5_0:mlx5_ib_post_send:3765:(pid 7273): +[ 2048.693360] nvme nvme1: nvme_rdma_post_send failed with error code -12 + +This patch changes the way the signaling is done so that it depends on +the queue depth now. The magic define has been removed completely. + +Signed-off-by: Marta Rybczynska +Signed-off-by: Samuel Jones +Acked-by: Sagi Grimberg +Signed-off-by: Christoph Hellwig +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/nvme/host/rdma.c | 18 ++++++++++++++---- + 1 file changed, 14 insertions(+), 4 deletions(-) + +--- a/drivers/nvme/host/rdma.c ++++ b/drivers/nvme/host/rdma.c +@@ -1029,6 +1029,19 @@ static void nvme_rdma_send_done(struct i + nvme_rdma_wr_error(cq, wc, "SEND"); + } + ++static inline int nvme_rdma_queue_sig_limit(struct nvme_rdma_queue *queue) ++{ ++ int sig_limit; ++ ++ /* ++ * We signal completion every queue depth/2 and also handle the ++ * degenerated case of a device with queue_depth=1, where we ++ * would need to signal every message. ++ */ ++ sig_limit = max(queue->queue_size / 2, 1); ++ return (++queue->sig_count % sig_limit) == 0; ++} ++ + static int nvme_rdma_post_send(struct nvme_rdma_queue *queue, + struct nvme_rdma_qe *qe, struct ib_sge *sge, u32 num_sge, + struct ib_send_wr *first, bool flush) +@@ -1056,9 +1069,6 @@ static int nvme_rdma_post_send(struct nv + * Would have been way to obvious to handle this in hardware or + * at least the RDMA stack.. + * +- * This messy and racy code sniplet is copy and pasted from the iSER +- * initiator, and the magic '32' comes from there as well. +- * + * Always signal the flushes. The magic request used for the flush + * sequencer is not allocated in our driver's tagset and it's + * triggered to be freed by blk_cleanup_queue(). So we need to +@@ -1066,7 +1076,7 @@ static int nvme_rdma_post_send(struct nv + * embedded in request's payload, is not freed when __ib_process_cq() + * calls wr_cqe->done(). + */ +- if ((++queue->sig_count % 32) == 0 || flush) ++ if (nvme_rdma_queue_sig_limit(queue) || flush) + wr.send_flags |= IB_SEND_SIGNALED; + + if (first) diff --git a/queue-4.11/nvme-use-blk_mq_start_hw_queues-in-nvme_kill_queues.patch b/queue-4.11/nvme-use-blk_mq_start_hw_queues-in-nvme_kill_queues.patch new file mode 100644 index 00000000000..7a849ebde76 --- /dev/null +++ b/queue-4.11/nvme-use-blk_mq_start_hw_queues-in-nvme_kill_queues.patch @@ -0,0 +1,51 @@ +From 806f026f9b901eaf1a6baeb48b5da18d6a4f818e Mon Sep 17 00:00:00 2001 +From: Ming Lei +Date: Mon, 22 May 2017 23:05:03 +0800 +Subject: nvme: use blk_mq_start_hw_queues() in nvme_kill_queues() + +From: Ming Lei + +commit 806f026f9b901eaf1a6baeb48b5da18d6a4f818e upstream. + +Inside nvme_kill_queues(), we have to start hw queues for +draining requests in sw queues, .dispatch list and requeue list, +so use blk_mq_start_hw_queues() instead of blk_mq_start_stopped_hw_queues() +which only run queues if queues are stopped, but the queues may have +been started already, for example nvme_start_queues() is called in reset work +function. + +blk_mq_start_hw_queues() run hw queues in current context, instead +of running asynchronously like before. Given nvme_kill_queues() is +run from either remove context or reset worker context, both are fine +to run hw queue directly. And the mutex of namespaces_mutex isn't a +problem too becasue nvme_start_freeze() runs hw queue in this way +already. + +Reported-by: Zhang Yi +Reviewed-by: Keith Busch +Reviewed-by: Johannes Thumshirn +Signed-off-by: Ming Lei +Signed-off-by: Christoph Hellwig +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/nvme/host/core.c | 8 +++++++- + 1 file changed, 7 insertions(+), 1 deletion(-) + +--- a/drivers/nvme/host/core.c ++++ b/drivers/nvme/host/core.c +@@ -2345,7 +2345,13 @@ void nvme_kill_queues(struct nvme_ctrl * + revalidate_disk(ns->disk); + blk_set_queue_dying(ns->queue); + blk_mq_abort_requeue_list(ns->queue); +- blk_mq_start_stopped_hw_queues(ns->queue, true); ++ ++ /* ++ * Forcibly start all queues to avoid having stuck requests. ++ * Note that we must ensure the queues are not stopped ++ * when the final removal happens. ++ */ ++ blk_mq_start_hw_queues(ns->queue); + } + mutex_unlock(&ctrl->namespaces_mutex); + } diff --git a/queue-4.11/pcmcia-remove-left-over-z-format.patch b/queue-4.11/pcmcia-remove-left-over-z-format.patch new file mode 100644 index 00000000000..5f8c82a002b --- /dev/null +++ b/queue-4.11/pcmcia-remove-left-over-z-format.patch @@ -0,0 +1,56 @@ +From ff5a20169b98d84ad8d7f99f27c5ebbb008204d6 Mon Sep 17 00:00:00 2001 +From: Nicolas Iooss +Date: Fri, 2 Jun 2017 14:46:28 -0700 +Subject: pcmcia: remove left-over %Z format + +From: Nicolas Iooss + +commit ff5a20169b98d84ad8d7f99f27c5ebbb008204d6 upstream. + +Commit 5b5e0928f742 ("lib/vsprintf.c: remove %Z support") removed some +usages of format %Z but forgot "%.2Zx". This makes clang 4.0 reports a +-Wformat-extra-args warning because it does not know about %Z. + +Replace %Z with %z. + +Link: http://lkml.kernel.org/r/20170520090946.22562-1-nicolas.iooss_linux@m4x.org +Signed-off-by: Nicolas Iooss +Cc: Harald Welte +Cc: Alexey Dobriyan +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/char/pcmcia/cm4040_cs.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +--- a/drivers/char/pcmcia/cm4040_cs.c ++++ b/drivers/char/pcmcia/cm4040_cs.c +@@ -374,7 +374,7 @@ static ssize_t cm4040_write(struct file + + rc = write_sync_reg(SCR_HOST_TO_READER_START, dev); + if (rc <= 0) { +- DEBUGP(5, dev, "write_sync_reg c=%.2Zx\n", rc); ++ DEBUGP(5, dev, "write_sync_reg c=%.2zx\n", rc); + DEBUGP(2, dev, "<- cm4040_write (failed)\n"); + if (rc == -ERESTARTSYS) + return rc; +@@ -387,7 +387,7 @@ static ssize_t cm4040_write(struct file + for (i = 0; i < bytes_to_write; i++) { + rc = wait_for_bulk_out_ready(dev); + if (rc <= 0) { +- DEBUGP(5, dev, "wait_for_bulk_out_ready rc=%.2Zx\n", ++ DEBUGP(5, dev, "wait_for_bulk_out_ready rc=%.2zx\n", + rc); + DEBUGP(2, dev, "<- cm4040_write (failed)\n"); + if (rc == -ERESTARTSYS) +@@ -403,7 +403,7 @@ static ssize_t cm4040_write(struct file + rc = write_sync_reg(SCR_HOST_TO_READER_DONE, dev); + + if (rc <= 0) { +- DEBUGP(5, dev, "write_sync_reg c=%.2Zx\n", rc); ++ DEBUGP(5, dev, "write_sync_reg c=%.2zx\n", rc); + DEBUGP(2, dev, "<- cm4040_write (failed)\n"); + if (rc == -ERESTARTSYS) + return rc; diff --git a/queue-4.11/revert-alsa-usb-audio-purge-needless-variable-length-array.patch b/queue-4.11/revert-alsa-usb-audio-purge-needless-variable-length-array.patch new file mode 100644 index 00000000000..090832f02e1 --- /dev/null +++ b/queue-4.11/revert-alsa-usb-audio-purge-needless-variable-length-array.patch @@ -0,0 +1,56 @@ +From 64188cfbe5245d412de2139a3864e4e00b4136f0 Mon Sep 17 00:00:00 2001 +From: Takashi Iwai +Date: Tue, 30 May 2017 09:23:41 +0200 +Subject: Revert "ALSA: usb-audio: purge needless variable length array" + +From: Takashi Iwai + +commit 64188cfbe5245d412de2139a3864e4e00b4136f0 upstream. + +This reverts commit 89b593c30e83 ("ALSA: usb-audio: purge needless +variable length array"). The patch turned out to cause a severe +regression, triggering an Oops at snd_usb_ctl_msg(). It was overseen +that snd_usb_ctl_msg() writes back the response to the given buffer, +while the patch changed it to a read-only const buffer. (One should +always double-check when an extra pointer cast is present...) + +As a simple fix, just revert the affected commit. It was merely a +cleanup. Although it brings VLA again, it's clearer as a fix. We'll +address the VLA later in another patch. + +Fixes: 89b593c30e83 ("ALSA: usb-audio: purge needless variable length array") +Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=195875 +Signed-off-by: Takashi Iwai +Signed-off-by: Greg Kroah-Hartman + +--- + sound/usb/mixer_us16x08.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +--- a/sound/usb/mixer_us16x08.c ++++ b/sound/usb/mixer_us16x08.c +@@ -698,12 +698,12 @@ static int snd_us16x08_meter_get(struct + struct snd_usb_audio *chip = elem->head.mixer->chip; + struct snd_us16x08_meter_store *store = elem->private_data; + u8 meter_urb[64]; +- char tmp[sizeof(mix_init_msg2)] = {0}; ++ char tmp[max(sizeof(mix_init_msg1), sizeof(mix_init_msg2))]; + + switch (kcontrol->private_value) { + case 0: +- snd_us16x08_send_urb(chip, (char *)mix_init_msg1, +- sizeof(mix_init_msg1)); ++ memcpy(tmp, mix_init_msg1, sizeof(mix_init_msg1)); ++ snd_us16x08_send_urb(chip, tmp, 4); + snd_us16x08_recv_urb(chip, meter_urb, + sizeof(meter_urb)); + kcontrol->private_value++; +@@ -721,7 +721,7 @@ static int snd_us16x08_meter_get(struct + case 3: + memcpy(tmp, mix_init_msg2, sizeof(mix_init_msg2)); + tmp[2] = snd_get_meter_comp_index(store); +- snd_us16x08_send_urb(chip, tmp, sizeof(mix_init_msg2)); ++ snd_us16x08_send_urb(chip, tmp, 10); + snd_us16x08_recv_urb(chip, meter_urb, + sizeof(meter_urb)); + kcontrol->private_value = 0; diff --git a/queue-4.11/scsi-scsi_dh_rdac-use-ctlr-directly-in-rdac_failover_get.patch b/queue-4.11/scsi-scsi_dh_rdac-use-ctlr-directly-in-rdac_failover_get.patch new file mode 100644 index 00000000000..c691628b43f --- /dev/null +++ b/queue-4.11/scsi-scsi_dh_rdac-use-ctlr-directly-in-rdac_failover_get.patch @@ -0,0 +1,107 @@ +From 0648a07c9b22acc33ead0645cf8f607b0c9c7e32 Mon Sep 17 00:00:00 2001 +From: Artem Savkov +Date: Sat, 20 May 2017 09:58:10 +0200 +Subject: scsi: scsi_dh_rdac: Use ctlr directly in rdac_failover_get() + +From: Artem Savkov + +commit 0648a07c9b22acc33ead0645cf8f607b0c9c7e32 upstream. + +rdac_failover_get references struct rdac_controller as +ctlr->ms_sdev->handler_data->ctlr for no apparent reason. Besides being +inefficient this also introduces a null-pointer dereference as +send_mode_select() sets ctlr->ms_sdev to NULL before calling +rdac_failover_get(): + +[ 18.432550] device-mapper: multipath service-time: version 0.3.0 loaded +[ 18.436124] BUG: unable to handle kernel NULL pointer dereference at 0000000000000790 +[ 18.436129] IP: send_mode_select+0xca/0x560 +[ 18.436129] PGD 0 +[ 18.436130] P4D 0 +[ 18.436130] +[ 18.436132] Oops: 0000 [#1] SMP +[ 18.436133] Modules linked in: dm_service_time sd_mod dm_multipath amdkfd amd_iommu_v2 radeon(+) i2c_algo_bit drm_kms_helper syscopyarea sysfillrect sysimgblt fb_sys_fops ttm qla2xxx drm serio_raw scsi_transport_fc bnx2 i2c_core dm_mirror dm_region_hash dm_log dm_mod +[ 18.436143] CPU: 4 PID: 443 Comm: kworker/u16:2 Not tainted 4.12.0-rc1.1.el7.test.x86_64 #1 +[ 18.436144] Hardware name: IBM BladeCenter LS22 -[79013SG]-/Server Blade, BIOS -[L8E164AUS-1.07]- 05/25/2011 +[ 18.436145] Workqueue: kmpath_rdacd send_mode_select +[ 18.436146] task: ffff880225116a40 task.stack: ffffc90002bd8000 +[ 18.436148] RIP: 0010:send_mode_select+0xca/0x560 +[ 18.436148] RSP: 0018:ffffc90002bdbda8 EFLAGS: 00010246 +[ 18.436149] RAX: 0000000000000000 RBX: ffffc90002bdbe08 RCX: ffff88017ef04a80 +[ 18.436150] RDX: ffffc90002bdbe08 RSI: ffff88017ef04a80 RDI: ffff8802248e4388 +[ 18.436151] RBP: ffffc90002bdbe48 R08: 0000000000000000 R09: ffffffff81c104c0 +[ 18.436151] R10: 00000000000001ff R11: 000000000000035a R12: ffffc90002bdbdd8 +[ 18.436152] R13: ffff8802248e4390 R14: ffff880225152800 R15: ffff8802248e4400 +[ 18.436153] FS: 0000000000000000(0000) GS:ffff880227d00000(0000) knlGS:0000000000000000 +[ 18.436154] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 +[ 18.436154] CR2: 0000000000000790 CR3: 000000042535b000 CR4: 00000000000006e0 +[ 18.436155] Call Trace: +[ 18.436159] ? rdac_activate+0x14e/0x150 +[ 18.436161] ? refcount_dec_and_test+0x11/0x20 +[ 18.436162] ? kobject_put+0x1c/0x50 +[ 18.436165] ? scsi_dh_activate+0x6f/0xd0 +[ 18.436168] process_one_work+0x149/0x360 +[ 18.436170] worker_thread+0x4d/0x3c0 +[ 18.436172] kthread+0x109/0x140 +[ 18.436173] ? rescuer_thread+0x380/0x380 +[ 18.436174] ? kthread_park+0x60/0x60 +[ 18.436176] ret_from_fork+0x2c/0x40 +[ 18.436177] Code: 49 c7 46 20 00 00 00 00 4c 89 ef c6 07 00 0f 1f 40 00 45 31 ed c7 45 b0 05 00 00 00 44 89 6d b4 4d 89 f5 4c 8b 75 a8 49 8b 45 20 <48> 8b b0 90 07 00 00 48 8b 56 10 8b 42 10 48 8d 7a 28 85 c0 0f +[ 18.436192] RIP: send_mode_select+0xca/0x560 RSP: ffffc90002bdbda8 +[ 18.436192] CR2: 0000000000000790 +[ 18.436198] ---[ end trace 40f3e4dca1ffabdd ]--- +[ 18.436199] Kernel panic - not syncing: Fatal exception +[ 18.436222] Kernel Offset: disabled +[-- MARK -- Thu May 18 11:45:00 2017] + +Fixes: 327825574132 scsi_dh_rdac: switch to scsi_execute_req_flags() +Signed-off-by: Artem Savkov +Reviewed-by: Christoph Hellwig +Signed-off-by: Martin K. Petersen +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/scsi/device_handler/scsi_dh_rdac.c | 10 ++++------ + 1 file changed, 4 insertions(+), 6 deletions(-) + +--- a/drivers/scsi/device_handler/scsi_dh_rdac.c ++++ b/drivers/scsi/device_handler/scsi_dh_rdac.c +@@ -265,18 +265,16 @@ static unsigned int rdac_failover_get(st + struct list_head *list, + unsigned char *cdb) + { +- struct scsi_device *sdev = ctlr->ms_sdev; +- struct rdac_dh_data *h = sdev->handler_data; + struct rdac_mode_common *common; + unsigned data_size; + struct rdac_queue_data *qdata; + u8 *lun_table; + +- if (h->ctlr->use_ms10) { ++ if (ctlr->use_ms10) { + struct rdac_pg_expanded *rdac_pg; + + data_size = sizeof(struct rdac_pg_expanded); +- rdac_pg = &h->ctlr->mode_select.expanded; ++ rdac_pg = &ctlr->mode_select.expanded; + memset(rdac_pg, 0, data_size); + common = &rdac_pg->common; + rdac_pg->page_code = RDAC_PAGE_CODE_REDUNDANT_CONTROLLER + 0x40; +@@ -288,7 +286,7 @@ static unsigned int rdac_failover_get(st + struct rdac_pg_legacy *rdac_pg; + + data_size = sizeof(struct rdac_pg_legacy); +- rdac_pg = &h->ctlr->mode_select.legacy; ++ rdac_pg = &ctlr->mode_select.legacy; + memset(rdac_pg, 0, data_size); + common = &rdac_pg->common; + rdac_pg->page_code = RDAC_PAGE_CODE_REDUNDANT_CONTROLLER; +@@ -304,7 +302,7 @@ static unsigned int rdac_failover_get(st + } + + /* Prepare the command. */ +- if (h->ctlr->use_ms10) { ++ if (ctlr->use_ms10) { + cdb[0] = MODE_SELECT_10; + cdb[7] = data_size >> 8; + cdb[8] = data_size & 0xff; diff --git a/queue-4.11/scsi-zero-per-cmd-private-driver-data-for-each-mq-i-o.patch b/queue-4.11/scsi-zero-per-cmd-private-driver-data-for-each-mq-i-o.patch new file mode 100644 index 00000000000..45e9000e746 --- /dev/null +++ b/queue-4.11/scsi-zero-per-cmd-private-driver-data-for-each-mq-i-o.patch @@ -0,0 +1,45 @@ +From 1bad6c4a57efda0d5f5bf8a2403b21b1ed24875c Mon Sep 17 00:00:00 2001 +From: Long Li +Date: Thu, 18 May 2017 15:40:05 -0700 +Subject: scsi: zero per-cmd private driver data for each MQ I/O + +From: Long Li + +commit 1bad6c4a57efda0d5f5bf8a2403b21b1ed24875c upstream. + +In lower layer driver's (LLD) scsi_host_template, the driver may +optionally ask SCSI to allocate its private driver memory for each +command, by specifying cmd_size. This memory is allocated at the end of +scsi_cmnd by SCSI. Later when SCSI queues a command, the LLD can use +scsi_cmd_priv to get to its private data. + +Some LLD, e.g. hv_storvsc, doesn't clear its private data before use. In +this case, the LLD may get to stale or uninitialized data in its private +driver memory. This may result in unexpected driver and hardware +behavior. + +Fix this problem by also zeroing the private driver memory before +passing them to LLD. + +Signed-off-by: Long Li +Reviewed-by: Bart Van Assche +Reviewed-by: KY Srinivasan +Reviewed-by: Christoph Hellwig +Signed-off-by: Martin K. Petersen +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/scsi/scsi_lib.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/scsi/scsi_lib.c ++++ b/drivers/scsi/scsi_lib.c +@@ -1850,7 +1850,7 @@ static int scsi_mq_prep_fn(struct reques + + /* zero out the cmd, except for the embedded scsi_request */ + memset((char *)cmd + sizeof(cmd->req), 0, +- sizeof(*cmd) - sizeof(cmd->req)); ++ sizeof(*cmd) - sizeof(cmd->req) + shost->hostt->cmd_size); + + req->special = cmd; + diff --git a/queue-4.11/series b/queue-4.11/series index a2c5e49e07b..e446d339376 100644 --- a/queue-4.11/series +++ b/queue-4.11/series @@ -51,8 +51,33 @@ drivers-tty-8250-only-call-fintek_8250_probe-when-doing-port-i-o.patch i2c-i2c-tiny-usb-fix-buffer-not-being-dma-capable.patch crypto-skcipher-add-missing-api-setkey-checks.patch revert-acpi-button-remove-lid_init_state-method-mode.patch +x86-mce-export-memory_error.patch acpi-nfit-fix-the-memory-error-check-in-nfit_handle_mce.patch acpi-sysfs-fix-acpi_get_table-leak-acpi-sysfs-denial-of-service.patch acpica-tables-fix-regression-introduced-by-a-too-early-mechanism-enabling.patch revert-acpi-button-change-default-behavior-to-lid_init_state-open.patch mmc-sdhci-iproc-suppress-spurious-interrupt-with-multiblock-read.patch +scsi-zero-per-cmd-private-driver-data-for-each-mq-i-o.patch +iscsi-target-always-wait-for-kthread_should_stop-before-kthread-exit.patch +iscsi-target-fix-initial-login-pdu-asynchronous-socket-close-oops.patch +scsi-scsi_dh_rdac-use-ctlr-directly-in-rdac_failover_get.patch +ibmvscsis-clear-left-over-abort_cmd-pointers.patch +ibmvscsis-fix-the-incorrect-req_lim_delta.patch +hid-wacom-have-wacom_tpc_irq-guard-against-possible-null-dereference.patch +nvme-rdma-support-devices-with-queue-size-32.patch +nvme-use-blk_mq_start_hw_queues-in-nvme_kill_queues.patch +nvme-avoid-to-use-blk_mq_abort_requeue_list.patch +drm-amd-powerplay-smu7-add-vblank-check-for-mclk-switching-v2.patch +drm-amd-powerplay-smu7-disable-mclk-switching-for-high-refresh-rates.patch +drm-radeon-ci-disable-mclk-switching-for-high-refresh-rates-v2.patch +drm-radeon-unbreak-hpd-handling-for-r600.patch +pcmcia-remove-left-over-z-format.patch +alsa-hda-no-loopback-on-alc299-codec.patch +alsa-hda-apply-stac_9200_dell_m22-quirk-for-dell-latitude-d430.patch +revert-alsa-usb-audio-purge-needless-variable-length-array.patch +alsa-usb-fix-a-typo-in-tascam-us-16x08-mixer-element.patch +x86-pat-fix-xorg-regression-on-cpus-that-don-t-support-pat.patch +x86-boot-use-cross_compile-prefix-for-readelf.patch +ksm-prevent-crash-after-write_protect_page-fails.patch +slub-memcg-cure-the-brainless-abuse-of-sysfs-attributes.patch +drm-gma500-psb-actually-use-vbt-mode-when-it-is-found.patch diff --git a/queue-4.11/slub-memcg-cure-the-brainless-abuse-of-sysfs-attributes.patch b/queue-4.11/slub-memcg-cure-the-brainless-abuse-of-sysfs-attributes.patch new file mode 100644 index 00000000000..773fef7bcb4 --- /dev/null +++ b/queue-4.11/slub-memcg-cure-the-brainless-abuse-of-sysfs-attributes.patch @@ -0,0 +1,89 @@ +From 478fe3037b2278d276d4cd9cd0ab06c4cb2e9b32 Mon Sep 17 00:00:00 2001 +From: Thomas Gleixner +Date: Fri, 2 Jun 2017 14:46:25 -0700 +Subject: slub/memcg: cure the brainless abuse of sysfs attributes + +From: Thomas Gleixner + +commit 478fe3037b2278d276d4cd9cd0ab06c4cb2e9b32 upstream. + +memcg_propagate_slab_attrs() abuses the sysfs attribute file functions +to propagate settings from the root kmem_cache to a newly created +kmem_cache. It does that with: + + attr->show(root, buf); + attr->store(new, buf, strlen(bug); + +Aside of being a lazy and absurd hackery this is broken because it does +not check the return value of the show() function. + +Some of the show() functions return 0 w/o touching the buffer. That +means in such a case the store function is called with the stale content +of the previous show(). That causes nonsense like invoking +kmem_cache_shrink() on a newly created kmem_cache. In the worst case it +would cause handing in an uninitialized buffer. + +This should be rewritten proper by adding a propagate() callback to +those slub_attributes which must be propagated and avoid that insane +conversion to and from ASCII, but that's too large for a hot fix. + +Check at least the return value of the show() function, so calling +store() with stale content is prevented. + +Steven said: + "It can cause a deadlock with get_online_cpus() that has been uncovered + by recent cpu hotplug and lockdep changes that Thomas and Peter have + been doing. + + Possible unsafe locking scenario: + + CPU0 CPU1 + ---- ---- + lock(cpu_hotplug.lock); + lock(slab_mutex); + lock(cpu_hotplug.lock); + lock(slab_mutex); + + *** DEADLOCK ***" + +Link: http://lkml.kernel.org/r/alpine.DEB.2.20.1705201244540.2255@nanos +Signed-off-by: Thomas Gleixner +Reported-by: Steven Rostedt +Acked-by: David Rientjes +Cc: Johannes Weiner +Cc: Michal Hocko +Cc: Peter Zijlstra +Cc: Christoph Lameter +Cc: Pekka Enberg +Cc: Joonsoo Kim +Cc: Christoph Hellwig +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman + +--- + mm/slub.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +--- a/mm/slub.c ++++ b/mm/slub.c +@@ -5512,6 +5512,7 @@ static void memcg_propagate_slab_attrs(s + char mbuf[64]; + char *buf; + struct slab_attribute *attr = to_slab_attr(slab_attrs[i]); ++ ssize_t len; + + if (!attr || !attr->store || !attr->show) + continue; +@@ -5536,8 +5537,9 @@ static void memcg_propagate_slab_attrs(s + buf = buffer; + } + +- attr->show(root_cache, buf); +- attr->store(s, buf, strlen(buf)); ++ len = attr->show(root_cache, buf); ++ if (len > 0) ++ attr->store(s, buf, len); + } + + if (buffer) diff --git a/queue-4.11/x86-boot-use-cross_compile-prefix-for-readelf.patch b/queue-4.11/x86-boot-use-cross_compile-prefix-for-readelf.patch new file mode 100644 index 00000000000..83b589ff8c7 --- /dev/null +++ b/queue-4.11/x86-boot-use-cross_compile-prefix-for-readelf.patch @@ -0,0 +1,42 @@ +From 3780578761921f094179c6289072a74b2228c602 Mon Sep 17 00:00:00 2001 +From: Rob Landley +Date: Sat, 20 May 2017 15:03:29 -0500 +Subject: x86/boot: Use CROSS_COMPILE prefix for readelf + +From: Rob Landley + +commit 3780578761921f094179c6289072a74b2228c602 upstream. + +The boot code Makefile contains a straight 'readelf' invocation. This +causes build warnings in cross compile environments, when there is no +unprefixed readelf accessible via $PATH. + +Add the missing $(CROSS_COMPILE) prefix. + +[ tglx: Rewrote changelog ] + +Fixes: 98f78525371b ("x86/boot: Refuse to build with data relocations") +Signed-off-by: Rob Landley +Acked-by: Kees Cook +Cc: Jiri Kosina +Cc: Paul Bolle +Cc: "H.J. Lu" +Link: http://lkml.kernel.org/r/ced18878-693a-9576-a024-113ef39a22c0@landley.net +Signed-off-by: Thomas Gleixner +Signed-off-by: Greg Kroah-Hartman + +--- + arch/x86/boot/compressed/Makefile | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/arch/x86/boot/compressed/Makefile ++++ b/arch/x86/boot/compressed/Makefile +@@ -94,7 +94,7 @@ vmlinux-objs-$(CONFIG_EFI_MIXED) += $(ob + quiet_cmd_check_data_rel = DATAREL $@ + define cmd_check_data_rel + for obj in $(filter %.o,$^); do \ +- readelf -S $$obj | grep -qF .rel.local && { \ ++ ${CROSS_COMPILE}readelf -S $$obj | grep -qF .rel.local && { \ + echo "error: $$obj has data relocations!" >&2; \ + exit 1; \ + } || true; \ diff --git a/queue-4.11/x86-mce-export-memory_error.patch b/queue-4.11/x86-mce-export-memory_error.patch new file mode 100644 index 00000000000..27815bc8644 --- /dev/null +++ b/queue-4.11/x86-mce-export-memory_error.patch @@ -0,0 +1,81 @@ +From 2d1f406139ec20320bf38bcd2461aa8e358084b5 Mon Sep 17 00:00:00 2001 +From: Borislav Petkov +Date: Fri, 19 May 2017 11:39:09 +0200 +Subject: x86/MCE: Export memory_error() + +From: Borislav Petkov + +commit 2d1f406139ec20320bf38bcd2461aa8e358084b5 upstream. + +Export the function which checks whether an MCE is a memory error to +other users so that we can reuse the logic. Drop the boot_cpu_data use, +while at it, as mce.cpuvendor already has the CPU vendor in there. + +Integrate a piece from a patch from Vishal Verma + to export it for modules (nfit). + +The main reason we're exporting it is that the nfit handler +nfit_handle_mce() needs to detect a memory error properly before doing +its recovery actions. + +Signed-off-by: Borislav Petkov +Cc: Tony Luck +Cc: Vishal Verma +Link: http://lkml.kernel.org/r/20170519093915.15413-2-bp@alien8.de +Signed-off-by: Thomas Gleixner +Signed-off-by: Greg Kroah-Hartman + +--- + arch/x86/include/asm/mce.h | 1 + + arch/x86/kernel/cpu/mcheck/mce.c | 11 +++++------ + 2 files changed, 6 insertions(+), 6 deletions(-) + +--- a/arch/x86/include/asm/mce.h ++++ b/arch/x86/include/asm/mce.h +@@ -264,6 +264,7 @@ static inline int umc_normaddr_to_sysadd + #endif + + int mce_available(struct cpuinfo_x86 *c); ++bool mce_is_memory_error(struct mce *m); + + DECLARE_PER_CPU(unsigned, mce_exception_count); + DECLARE_PER_CPU(unsigned, mce_poll_count); +--- a/arch/x86/kernel/cpu/mcheck/mce.c ++++ b/arch/x86/kernel/cpu/mcheck/mce.c +@@ -643,16 +643,14 @@ static void mce_read_aux(struct mce *m, + } + } + +-static bool memory_error(struct mce *m) ++bool mce_is_memory_error(struct mce *m) + { +- struct cpuinfo_x86 *c = &boot_cpu_data; +- +- if (c->x86_vendor == X86_VENDOR_AMD) { ++ if (m->cpuvendor == X86_VENDOR_AMD) { + /* ErrCodeExt[20:16] */ + u8 xec = (m->status >> 16) & 0x1f; + + return (xec == 0x0 || xec == 0x8); +- } else if (c->x86_vendor == X86_VENDOR_INTEL) { ++ } else if (m->cpuvendor == X86_VENDOR_INTEL) { + /* + * Intel SDM Volume 3B - 15.9.2 Compound Error Codes + * +@@ -673,6 +671,7 @@ static bool memory_error(struct mce *m) + + return false; + } ++EXPORT_SYMBOL_GPL(mce_is_memory_error); + + DEFINE_PER_CPU(unsigned, mce_poll_count); + +@@ -734,7 +733,7 @@ bool machine_check_poll(enum mcp_flags f + + severity = mce_severity(&m, mca_cfg.tolerant, NULL, false); + +- if (severity == MCE_DEFERRED_SEVERITY && memory_error(&m)) ++ if (severity == MCE_DEFERRED_SEVERITY && mce_is_memory_error(&m)) + if (m.status & MCI_STATUS_ADDRV) + m.severity = severity; + diff --git a/queue-4.11/x86-pat-fix-xorg-regression-on-cpus-that-don-t-support-pat.patch b/queue-4.11/x86-pat-fix-xorg-regression-on-cpus-that-don-t-support-pat.patch new file mode 100644 index 00000000000..2e3a0ef0e09 --- /dev/null +++ b/queue-4.11/x86-pat-fix-xorg-regression-on-cpus-that-don-t-support-pat.patch @@ -0,0 +1,96 @@ +From cbed27cdf0e3f7ea3b2259e86b9e34df02be3fe4 Mon Sep 17 00:00:00 2001 +From: Mikulas Patocka +Date: Tue, 18 Apr 2017 15:07:11 -0400 +Subject: x86/PAT: Fix Xorg regression on CPUs that don't support PAT + +From: Mikulas Patocka + +commit cbed27cdf0e3f7ea3b2259e86b9e34df02be3fe4 upstream. + +In the file arch/x86/mm/pat.c, there's a '__pat_enabled' variable. The +variable is set to 1 by default and the function pat_init() sets +__pat_enabled to 0 if the CPU doesn't support PAT. + +However, on AMD K6-3 CPUs, the processor initialization code never calls +pat_init() and so __pat_enabled stays 1 and the function pat_enabled() +returns true, even though the K6-3 CPU doesn't support PAT. + +The result of this bug is that a kernel warning is produced when attempting to +start the Xserver and the Xserver doesn't start (fork() returns ENOMEM). +Another symptom of this bug is that the framebuffer driver doesn't set the +K6-3 MTRR registers: + + x86/PAT: Xorg:3891 map pfn expected mapping type uncached-minus for [mem 0xe4000000-0xe5ffffff], got write-combining + ------------[ cut here ]------------ + WARNING: CPU: 0 PID: 3891 at arch/x86/mm/pat.c:1020 untrack_pfn+0x5c/0x9f + ... + x86/PAT: Xorg:3891 map pfn expected mapping type uncached-minus for [mem 0xe4000000-0xe5ffffff], got write-combining + +To fix the bug change pat_enabled() so that it returns true only if PAT +initialization was actually done. + +Also, I changed boot_cpu_has(X86_FEATURE_PAT) to +this_cpu_has(X86_FEATURE_PAT) in pat_ap_init(), so that we check the PAT +feature on the processor that is being initialized. + +Signed-off-by: Mikulas Patocka +Cc: Andrew Morton +Cc: Andy Lutomirski +Cc: Borislav Petkov +Cc: Brian Gerst +Cc: Denys Vlasenko +Cc: H. Peter Anvin +Cc: Josh Poimboeuf +Cc: Linus Torvalds +Cc: Luis R. Rodriguez +Cc: Peter Zijlstra +Cc: Thomas Gleixner +Cc: Toshi Kani +Link: http://lkml.kernel.org/r/alpine.LRH.2.02.1704181501450.26399@file01.intranet.prod.int.rdu2.redhat.com +Signed-off-by: Ingo Molnar +Signed-off-by: Greg Kroah-Hartman + +--- + arch/x86/mm/pat.c | 9 ++++++--- + 1 file changed, 6 insertions(+), 3 deletions(-) + +--- a/arch/x86/mm/pat.c ++++ b/arch/x86/mm/pat.c +@@ -64,9 +64,11 @@ static int __init nopat(char *str) + } + early_param("nopat", nopat); + ++static bool __read_mostly __pat_initialized = false; ++ + bool pat_enabled(void) + { +- return !!__pat_enabled; ++ return __pat_initialized; + } + EXPORT_SYMBOL_GPL(pat_enabled); + +@@ -224,13 +226,14 @@ static void pat_bsp_init(u64 pat) + } + + wrmsrl(MSR_IA32_CR_PAT, pat); ++ __pat_initialized = true; + + __init_cache_modes(pat); + } + + static void pat_ap_init(u64 pat) + { +- if (!boot_cpu_has(X86_FEATURE_PAT)) { ++ if (!this_cpu_has(X86_FEATURE_PAT)) { + /* + * If this happens we are on a secondary CPU, but switched to + * PAT on the boot CPU. We have no way to undo PAT. +@@ -305,7 +308,7 @@ void pat_init(void) + u64 pat; + struct cpuinfo_x86 *c = &boot_cpu_data; + +- if (!pat_enabled()) { ++ if (!__pat_enabled) { + init_cache_modes(); + return; + }