From b19b6649cb4b2b39347a2f6158e9a2c774c2692c Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sun, 14 Nov 2021 15:12:32 +0100 Subject: [PATCH] 5.4-stable patches added patches: alsa-mixer-fix-deadlock-in-snd_mixer_oss_set_volume.patch alsa-mixer-oss-fix-racy-access-to-slots.patch pci-aardvark-do-not-clear-status-bits-of-masked-interrupts.patch pci-aardvark-do-not-unmask-unused-interrupts.patch pci-aardvark-fix-checking-for-link-up-via-ltssm-state.patch pci-aardvark-fix-reporting-data-link-layer-link-active.patch pci-aardvark-fix-return-value-of-msi-domain-.alloc-method.patch pci-aardvark-read-all-16-bits-from-pcie_msi_payload_reg.patch pci-pci-bridge-emul-fix-emulation-of-w1c-bits.patch quota-check-block-number-when-reading-the-block-in-quota-file.patch quota-correct-error-number-in-free_dqentry.patch xen-balloon-add-late_initcall_sync-for-initial-ballooning-done.patch --- ...deadlock-in-snd_mixer_oss_set_volume.patch | 35 +++ ...a-mixer-oss-fix-racy-access-to-slots.patch | 176 +++++++++++++ ...ear-status-bits-of-masked-interrupts.patch | 51 ++++ ...vark-do-not-unmask-unused-interrupts.patch | 56 ++++ ...checking-for-link-up-via-ltssm-state.patch | 148 +++++++++++ ...eporting-data-link-layer-link-active.patch | 87 +++++++ ...rn-value-of-msi-domain-.alloc-method.patch | 44 ++++ ...ll-16-bits-from-pcie_msi_payload_reg.patch | 51 ++++ ...ridge-emul-fix-emulation-of-w1c-bits.patch | 62 +++++ ...when-reading-the-block-in-quota-file.patch | 54 ++++ ...correct-error-number-in-free_dqentry.patch | 32 +++ queue-5.4/series | 12 + ...all_sync-for-initial-ballooning-done.patch | 245 ++++++++++++++++++ 13 files changed, 1053 insertions(+) create mode 100644 queue-5.4/alsa-mixer-fix-deadlock-in-snd_mixer_oss_set_volume.patch create mode 100644 queue-5.4/alsa-mixer-oss-fix-racy-access-to-slots.patch create mode 100644 queue-5.4/pci-aardvark-do-not-clear-status-bits-of-masked-interrupts.patch create mode 100644 queue-5.4/pci-aardvark-do-not-unmask-unused-interrupts.patch create mode 100644 queue-5.4/pci-aardvark-fix-checking-for-link-up-via-ltssm-state.patch create mode 100644 queue-5.4/pci-aardvark-fix-reporting-data-link-layer-link-active.patch create mode 100644 queue-5.4/pci-aardvark-fix-return-value-of-msi-domain-.alloc-method.patch create mode 100644 queue-5.4/pci-aardvark-read-all-16-bits-from-pcie_msi_payload_reg.patch create mode 100644 queue-5.4/pci-pci-bridge-emul-fix-emulation-of-w1c-bits.patch create mode 100644 queue-5.4/quota-check-block-number-when-reading-the-block-in-quota-file.patch create mode 100644 queue-5.4/quota-correct-error-number-in-free_dqentry.patch create mode 100644 queue-5.4/xen-balloon-add-late_initcall_sync-for-initial-ballooning-done.patch diff --git a/queue-5.4/alsa-mixer-fix-deadlock-in-snd_mixer_oss_set_volume.patch b/queue-5.4/alsa-mixer-fix-deadlock-in-snd_mixer_oss_set_volume.patch new file mode 100644 index 00000000000..3442927a305 --- /dev/null +++ b/queue-5.4/alsa-mixer-fix-deadlock-in-snd_mixer_oss_set_volume.patch @@ -0,0 +1,35 @@ +From 3ab7992018455ac63c33e9b3eaa7264e293e40f4 Mon Sep 17 00:00:00 2001 +From: Pavel Skripkin +Date: Sun, 24 Oct 2021 17:03:15 +0300 +Subject: ALSA: mixer: fix deadlock in snd_mixer_oss_set_volume + +From: Pavel Skripkin + +commit 3ab7992018455ac63c33e9b3eaa7264e293e40f4 upstream. + +In commit 411cef6adfb3 ("ALSA: mixer: oss: Fix racy access to slots") +added mutex protection in snd_mixer_oss_set_volume(). Second +mutex_lock() in same function looks like typo, fix it. + +Reported-by: syzbot+ace149a75a9a0a399ac7@syzkaller.appspotmail.com +Fixes: 411cef6adfb3 ("ALSA: mixer: oss: Fix racy access to slots") +Cc: +Signed-off-by: Pavel Skripkin +Link: https://lore.kernel.org/r/20211024140315.16704-1-paskripkin@gmail.com +Signed-off-by: Takashi Iwai +Signed-off-by: Greg Kroah-Hartman +--- + sound/core/oss/mixer_oss.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/sound/core/oss/mixer_oss.c ++++ b/sound/core/oss/mixer_oss.c +@@ -313,7 +313,7 @@ static int snd_mixer_oss_set_volume(stru + pslot->volume[1] = right; + result = (left & 0xff) | ((right & 0xff) << 8); + unlock: +- mutex_lock(&mixer->reg_mutex); ++ mutex_unlock(&mixer->reg_mutex); + return result; + } + diff --git a/queue-5.4/alsa-mixer-oss-fix-racy-access-to-slots.patch b/queue-5.4/alsa-mixer-oss-fix-racy-access-to-slots.patch new file mode 100644 index 00000000000..da315f036cb --- /dev/null +++ b/queue-5.4/alsa-mixer-oss-fix-racy-access-to-slots.patch @@ -0,0 +1,176 @@ +From 411cef6adfb38a5bb6bd9af3941b28198e7fb680 Mon Sep 17 00:00:00 2001 +From: Takashi Iwai +Date: Wed, 20 Oct 2021 18:48:46 +0200 +Subject: ALSA: mixer: oss: Fix racy access to slots + +From: Takashi Iwai + +commit 411cef6adfb38a5bb6bd9af3941b28198e7fb680 upstream. + +The OSS mixer can reassign the mapping slots dynamically via proc +file. Although the addition and deletion of those slots are protected +by mixer->reg_mutex, the access to slots aren't, hence this may cause +UAF when the slots in use are deleted concurrently. + +This patch applies the mixer->reg_mutex in all appropriate code paths +(i.e. the ioctl functions) that may access slots. + +Reported-by: syzbot+9988f17cf72a1045a189@syzkaller.appspotmail.com +Reviewed-by: Jaroslav Kysela +Cc: +Link: https://lore.kernel.org/r/00000000000036adc005ceca9175@google.com +Link: https://lore.kernel.org/r/20211020164846.922-1-tiwai@suse.de +Signed-off-by: Takashi Iwai +Signed-off-by: Greg Kroah-Hartman +--- + sound/core/oss/mixer_oss.c | 43 +++++++++++++++++++++++++++++++++---------- + 1 file changed, 33 insertions(+), 10 deletions(-) + +--- a/sound/core/oss/mixer_oss.c ++++ b/sound/core/oss/mixer_oss.c +@@ -130,11 +130,13 @@ static int snd_mixer_oss_devmask(struct + + if (mixer == NULL) + return -EIO; ++ mutex_lock(&mixer->reg_mutex); + for (chn = 0; chn < 31; chn++) { + pslot = &mixer->slots[chn]; + if (pslot->put_volume || pslot->put_recsrc) + result |= 1 << chn; + } ++ mutex_unlock(&mixer->reg_mutex); + return result; + } + +@@ -146,11 +148,13 @@ static int snd_mixer_oss_stereodevs(stru + + if (mixer == NULL) + return -EIO; ++ mutex_lock(&mixer->reg_mutex); + for (chn = 0; chn < 31; chn++) { + pslot = &mixer->slots[chn]; + if (pslot->put_volume && pslot->stereo) + result |= 1 << chn; + } ++ mutex_unlock(&mixer->reg_mutex); + return result; + } + +@@ -161,6 +165,7 @@ static int snd_mixer_oss_recmask(struct + + if (mixer == NULL) + return -EIO; ++ mutex_lock(&mixer->reg_mutex); + if (mixer->put_recsrc && mixer->get_recsrc) { /* exclusive */ + result = mixer->mask_recsrc; + } else { +@@ -172,6 +177,7 @@ static int snd_mixer_oss_recmask(struct + result |= 1 << chn; + } + } ++ mutex_unlock(&mixer->reg_mutex); + return result; + } + +@@ -182,11 +188,12 @@ static int snd_mixer_oss_get_recsrc(stru + + if (mixer == NULL) + return -EIO; ++ mutex_lock(&mixer->reg_mutex); + if (mixer->put_recsrc && mixer->get_recsrc) { /* exclusive */ +- int err; + unsigned int index; +- if ((err = mixer->get_recsrc(fmixer, &index)) < 0) +- return err; ++ result = mixer->get_recsrc(fmixer, &index); ++ if (result < 0) ++ goto unlock; + result = 1 << index; + } else { + struct snd_mixer_oss_slot *pslot; +@@ -201,7 +208,10 @@ static int snd_mixer_oss_get_recsrc(stru + } + } + } +- return mixer->oss_recsrc = result; ++ mixer->oss_recsrc = result; ++ unlock: ++ mutex_unlock(&mixer->reg_mutex); ++ return result; + } + + static int snd_mixer_oss_set_recsrc(struct snd_mixer_oss_file *fmixer, int recsrc) +@@ -214,6 +224,7 @@ static int snd_mixer_oss_set_recsrc(stru + + if (mixer == NULL) + return -EIO; ++ mutex_lock(&mixer->reg_mutex); + if (mixer->get_recsrc && mixer->put_recsrc) { /* exclusive input */ + if (recsrc & ~mixer->oss_recsrc) + recsrc &= ~mixer->oss_recsrc; +@@ -239,6 +250,7 @@ static int snd_mixer_oss_set_recsrc(stru + } + } + } ++ mutex_unlock(&mixer->reg_mutex); + return result; + } + +@@ -250,6 +262,7 @@ static int snd_mixer_oss_get_volume(stru + + if (mixer == NULL || slot > 30) + return -EIO; ++ mutex_lock(&mixer->reg_mutex); + pslot = &mixer->slots[slot]; + left = pslot->volume[0]; + right = pslot->volume[1]; +@@ -257,15 +270,21 @@ static int snd_mixer_oss_get_volume(stru + result = pslot->get_volume(fmixer, pslot, &left, &right); + if (!pslot->stereo) + right = left; +- if (snd_BUG_ON(left < 0 || left > 100)) +- return -EIO; +- if (snd_BUG_ON(right < 0 || right > 100)) +- return -EIO; ++ if (snd_BUG_ON(left < 0 || left > 100)) { ++ result = -EIO; ++ goto unlock; ++ } ++ if (snd_BUG_ON(right < 0 || right > 100)) { ++ result = -EIO; ++ goto unlock; ++ } + if (result >= 0) { + pslot->volume[0] = left; + pslot->volume[1] = right; + result = (left & 0xff) | ((right & 0xff) << 8); + } ++ unlock: ++ mutex_unlock(&mixer->reg_mutex); + return result; + } + +@@ -278,6 +297,7 @@ static int snd_mixer_oss_set_volume(stru + + if (mixer == NULL || slot > 30) + return -EIO; ++ mutex_lock(&mixer->reg_mutex); + pslot = &mixer->slots[slot]; + if (left > 100) + left = 100; +@@ -288,10 +308,13 @@ static int snd_mixer_oss_set_volume(stru + if (pslot->put_volume) + result = pslot->put_volume(fmixer, pslot, left, right); + if (result < 0) +- return result; ++ goto unlock; + pslot->volume[0] = left; + pslot->volume[1] = right; +- return (left & 0xff) | ((right & 0xff) << 8); ++ result = (left & 0xff) | ((right & 0xff) << 8); ++ unlock: ++ mutex_lock(&mixer->reg_mutex); ++ return result; + } + + static int snd_mixer_oss_ioctl1(struct snd_mixer_oss_file *fmixer, unsigned int cmd, unsigned long arg) diff --git a/queue-5.4/pci-aardvark-do-not-clear-status-bits-of-masked-interrupts.patch b/queue-5.4/pci-aardvark-do-not-clear-status-bits-of-masked-interrupts.patch new file mode 100644 index 00000000000..e6fc437a39e --- /dev/null +++ b/queue-5.4/pci-aardvark-do-not-clear-status-bits-of-masked-interrupts.patch @@ -0,0 +1,51 @@ +From a7ca6d7fa3c02c032db5440ff392d96c04684c21 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Pali=20Roh=C3=A1r?= +Date: Tue, 5 Oct 2021 20:09:45 +0200 +Subject: PCI: aardvark: Do not clear status bits of masked interrupts +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Pali Rohár + +commit a7ca6d7fa3c02c032db5440ff392d96c04684c21 upstream. + +The PCIE_ISR1_REG says which interrupts are currently set / active, +including those which are masked. + +The driver currently reads this register and looks if some unmasked +interrupts are active, and if not, it clears status bits of _all_ +interrupts, including the masked ones. + +This is incorrect, since, for example, some drivers may poll these bits. + +Remove this clearing, and also remove this early return statement +completely, since it does not change functionality in any way. + +Link: https://lore.kernel.org/r/20211005180952.6812-7-kabel@kernel.org +Fixes: 8c39d710363c ("PCI: aardvark: Add Aardvark PCI host controller driver") +Signed-off-by: Pali Rohár +Signed-off-by: Marek Behún +Signed-off-by: Lorenzo Pieralisi +Reviewed-by: Marek Behún +Cc: stable@vger.kernel.org +Signed-off-by: Greg Kroah-Hartman +--- + drivers/pci/controller/pci-aardvark.c | 6 ------ + 1 file changed, 6 deletions(-) + +--- a/drivers/pci/controller/pci-aardvark.c ++++ b/drivers/pci/controller/pci-aardvark.c +@@ -1055,12 +1055,6 @@ static void advk_pcie_handle_int(struct + isr1_mask = advk_readl(pcie, PCIE_ISR1_MASK_REG); + isr1_status = isr1_val & ((~isr1_mask) & PCIE_ISR1_ALL_MASK); + +- if (!isr0_status && !isr1_status) { +- advk_writel(pcie, isr0_val, PCIE_ISR0_REG); +- advk_writel(pcie, isr1_val, PCIE_ISR1_REG); +- return; +- } +- + /* Process MSI interrupts */ + if (isr0_status & PCIE_ISR0_MSI_INT_PENDING) + advk_pcie_handle_msi(pcie); diff --git a/queue-5.4/pci-aardvark-do-not-unmask-unused-interrupts.patch b/queue-5.4/pci-aardvark-do-not-unmask-unused-interrupts.patch new file mode 100644 index 00000000000..68a280665ea --- /dev/null +++ b/queue-5.4/pci-aardvark-do-not-unmask-unused-interrupts.patch @@ -0,0 +1,56 @@ +From 1fb95d7d3c7a926b002fe8a6bd27a1cb428b46dc Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Pali=20Roh=C3=A1r?= +Date: Tue, 5 Oct 2021 20:09:46 +0200 +Subject: PCI: aardvark: Do not unmask unused interrupts +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Pali Rohár + +commit 1fb95d7d3c7a926b002fe8a6bd27a1cb428b46dc upstream. + +There are lot of undocumented interrupt bits. To prevent unwanted +spurious interrupts, fix all *_ALL_MASK macros to define all interrupt +bits, so that driver can properly mask all interrupts, including those +which are undocumented. + +Link: https://lore.kernel.org/r/20211005180952.6812-8-kabel@kernel.org +Fixes: 8c39d710363c ("PCI: aardvark: Add Aardvark PCI host controller driver") +Signed-off-by: Pali Rohár +Signed-off-by: Marek Behún +Signed-off-by: Lorenzo Pieralisi +Reviewed-by: Marek Behún +Cc: stable@vger.kernel.org +Signed-off-by: Greg Kroah-Hartman +--- + drivers/pci/controller/pci-aardvark.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +--- a/drivers/pci/controller/pci-aardvark.c ++++ b/drivers/pci/controller/pci-aardvark.c +@@ -108,13 +108,13 @@ + #define PCIE_ISR0_MSI_INT_PENDING BIT(24) + #define PCIE_ISR0_INTX_ASSERT(val) BIT(16 + (val)) + #define PCIE_ISR0_INTX_DEASSERT(val) BIT(20 + (val)) +-#define PCIE_ISR0_ALL_MASK GENMASK(26, 0) ++#define PCIE_ISR0_ALL_MASK GENMASK(31, 0) + #define PCIE_ISR1_REG (CONTROL_BASE_ADDR + 0x48) + #define PCIE_ISR1_MASK_REG (CONTROL_BASE_ADDR + 0x4C) + #define PCIE_ISR1_POWER_STATE_CHANGE BIT(4) + #define PCIE_ISR1_FLUSH BIT(5) + #define PCIE_ISR1_INTX_ASSERT(val) BIT(8 + (val)) +-#define PCIE_ISR1_ALL_MASK GENMASK(11, 4) ++#define PCIE_ISR1_ALL_MASK GENMASK(31, 0) + #define PCIE_MSI_ADDR_LOW_REG (CONTROL_BASE_ADDR + 0x50) + #define PCIE_MSI_ADDR_HIGH_REG (CONTROL_BASE_ADDR + 0x54) + #define PCIE_MSI_STATUS_REG (CONTROL_BASE_ADDR + 0x58) +@@ -202,7 +202,7 @@ enum { + #define PCIE_IRQ_MSI_INT2_DET BIT(21) + #define PCIE_IRQ_RC_DBELL_DET BIT(22) + #define PCIE_IRQ_EP_STATUS BIT(23) +-#define PCIE_IRQ_ALL_MASK 0xfff0fb ++#define PCIE_IRQ_ALL_MASK GENMASK(31, 0) + #define PCIE_IRQ_ENABLE_INTS_MASK PCIE_IRQ_CORE_INT + + /* Transaction types */ diff --git a/queue-5.4/pci-aardvark-fix-checking-for-link-up-via-ltssm-state.patch b/queue-5.4/pci-aardvark-fix-checking-for-link-up-via-ltssm-state.patch new file mode 100644 index 00000000000..777a8db1e0d --- /dev/null +++ b/queue-5.4/pci-aardvark-fix-checking-for-link-up-via-ltssm-state.patch @@ -0,0 +1,148 @@ +From 661c399a651c11aaf83c45cbfe0b4a1fb7bc3179 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Pali=20Roh=C3=A1r?= +Date: Tue, 5 Oct 2021 20:09:51 +0200 +Subject: PCI: aardvark: Fix checking for link up via LTSSM state +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Pali Rohár + +commit 661c399a651c11aaf83c45cbfe0b4a1fb7bc3179 upstream. + +Current implementation of advk_pcie_link_up() is wrong as it marks also +link disabled or hot reset states as link up. + +Fix it by marking link up only to those states which are defined in PCIe +Base specification 3.0, Table 4-14: Link Status Mapped to the LTSSM. + +To simplify implementation, Define macros for every LTSSM state which +aardvark hardware can return in CFG_REG register. + +Fix also checking for link training according to the same Table 4-14. +Define a new function advk_pcie_link_training() for this purpose. + +Link: https://lore.kernel.org/r/20211005180952.6812-13-kabel@kernel.org +Fixes: 8c39d710363c ("PCI: aardvark: Add Aardvark PCI host controller driver") +Signed-off-by: Pali Rohár +Signed-off-by: Marek Behún +Signed-off-by: Lorenzo Pieralisi +Reviewed-by: Marek Behún +Cc: stable@vger.kernel.org +Cc: Remi Pommarel +Signed-off-by: Greg Kroah-Hartman +--- + drivers/pci/controller/pci-aardvark.c | 76 +++++++++++++++++++++++++++++++--- + 1 file changed, 70 insertions(+), 6 deletions(-) + +--- a/drivers/pci/controller/pci-aardvark.c ++++ b/drivers/pci/controller/pci-aardvark.c +@@ -126,8 +126,50 @@ + #define CFG_REG (LMI_BASE_ADDR + 0x0) + #define LTSSM_SHIFT 24 + #define LTSSM_MASK 0x3f +-#define LTSSM_L0 0x10 + #define RC_BAR_CONFIG 0x300 ++ ++/* LTSSM values in CFG_REG */ ++enum { ++ LTSSM_DETECT_QUIET = 0x0, ++ LTSSM_DETECT_ACTIVE = 0x1, ++ LTSSM_POLLING_ACTIVE = 0x2, ++ LTSSM_POLLING_COMPLIANCE = 0x3, ++ LTSSM_POLLING_CONFIGURATION = 0x4, ++ LTSSM_CONFIG_LINKWIDTH_START = 0x5, ++ LTSSM_CONFIG_LINKWIDTH_ACCEPT = 0x6, ++ LTSSM_CONFIG_LANENUM_ACCEPT = 0x7, ++ LTSSM_CONFIG_LANENUM_WAIT = 0x8, ++ LTSSM_CONFIG_COMPLETE = 0x9, ++ LTSSM_CONFIG_IDLE = 0xa, ++ LTSSM_RECOVERY_RCVR_LOCK = 0xb, ++ LTSSM_RECOVERY_SPEED = 0xc, ++ LTSSM_RECOVERY_RCVR_CFG = 0xd, ++ LTSSM_RECOVERY_IDLE = 0xe, ++ LTSSM_L0 = 0x10, ++ LTSSM_RX_L0S_ENTRY = 0x11, ++ LTSSM_RX_L0S_IDLE = 0x12, ++ LTSSM_RX_L0S_FTS = 0x13, ++ LTSSM_TX_L0S_ENTRY = 0x14, ++ LTSSM_TX_L0S_IDLE = 0x15, ++ LTSSM_TX_L0S_FTS = 0x16, ++ LTSSM_L1_ENTRY = 0x17, ++ LTSSM_L1_IDLE = 0x18, ++ LTSSM_L2_IDLE = 0x19, ++ LTSSM_L2_TRANSMIT_WAKE = 0x1a, ++ LTSSM_DISABLED = 0x20, ++ LTSSM_LOOPBACK_ENTRY_MASTER = 0x21, ++ LTSSM_LOOPBACK_ACTIVE_MASTER = 0x22, ++ LTSSM_LOOPBACK_EXIT_MASTER = 0x23, ++ LTSSM_LOOPBACK_ENTRY_SLAVE = 0x24, ++ LTSSM_LOOPBACK_ACTIVE_SLAVE = 0x25, ++ LTSSM_LOOPBACK_EXIT_SLAVE = 0x26, ++ LTSSM_HOT_RESET = 0x27, ++ LTSSM_RECOVERY_EQUALIZATION_PHASE0 = 0x28, ++ LTSSM_RECOVERY_EQUALIZATION_PHASE1 = 0x29, ++ LTSSM_RECOVERY_EQUALIZATION_PHASE2 = 0x2a, ++ LTSSM_RECOVERY_EQUALIZATION_PHASE3 = 0x2b, ++}; ++ + #define VENDOR_ID_REG (LMI_BASE_ADDR + 0x44) + + /* PCIe core controller registers */ +@@ -219,13 +261,35 @@ static inline u32 advk_readl(struct advk + return readl(pcie->base + reg); + } + +-static int advk_pcie_link_up(struct advk_pcie *pcie) ++static u8 advk_pcie_ltssm_state(struct advk_pcie *pcie) + { +- u32 val, ltssm_state; ++ u32 val; ++ u8 ltssm_state; + + val = advk_readl(pcie, CFG_REG); + ltssm_state = (val >> LTSSM_SHIFT) & LTSSM_MASK; +- return ltssm_state >= LTSSM_L0; ++ return ltssm_state; ++} ++ ++static inline bool advk_pcie_link_up(struct advk_pcie *pcie) ++{ ++ /* check if LTSSM is in normal operation - some L* state */ ++ u8 ltssm_state = advk_pcie_ltssm_state(pcie); ++ return ltssm_state >= LTSSM_L0 && ltssm_state < LTSSM_DISABLED; ++} ++ ++static inline bool advk_pcie_link_training(struct advk_pcie *pcie) ++{ ++ /* ++ * According to PCIe Base specification 3.0, Table 4-14: Link ++ * Status Mapped to the LTSSM is Link Training mapped to LTSSM ++ * Configuration and Recovery states. ++ */ ++ u8 ltssm_state = advk_pcie_ltssm_state(pcie); ++ return ((ltssm_state >= LTSSM_CONFIG_LINKWIDTH_START && ++ ltssm_state < LTSSM_L0) || ++ (ltssm_state >= LTSSM_RECOVERY_EQUALIZATION_PHASE0 && ++ ltssm_state <= LTSSM_RECOVERY_EQUALIZATION_PHASE3)); + } + + static int advk_pcie_wait_for_link(struct advk_pcie *pcie) +@@ -252,7 +316,7 @@ static void advk_pcie_wait_for_retrain(s + size_t retries; + + for (retries = 0; retries < RETRAIN_WAIT_MAX_RETRIES; ++retries) { +- if (!advk_pcie_link_up(pcie)) ++ if (advk_pcie_link_training(pcie)) + break; + udelay(RETRAIN_WAIT_USLEEP_US); + } +@@ -516,7 +580,7 @@ advk_pci_bridge_emul_pcie_conf_read(stru + /* u32 contains both PCI_EXP_LNKCTL and PCI_EXP_LNKSTA */ + u32 val = advk_readl(pcie, PCIE_CORE_PCIEXP_CAP + reg) & + ~(PCI_EXP_LNKSTA_LT << 16); +- if (!advk_pcie_link_up(pcie)) ++ if (advk_pcie_link_training(pcie)) + val |= (PCI_EXP_LNKSTA_LT << 16); + *value = val; + return PCI_BRIDGE_EMUL_HANDLED; diff --git a/queue-5.4/pci-aardvark-fix-reporting-data-link-layer-link-active.patch b/queue-5.4/pci-aardvark-fix-reporting-data-link-layer-link-active.patch new file mode 100644 index 00000000000..7b4cf09b2ad --- /dev/null +++ b/queue-5.4/pci-aardvark-fix-reporting-data-link-layer-link-active.patch @@ -0,0 +1,87 @@ +From 2b650b7ff20eb7ea8ef9031d20fb657286ab90cc Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Pali=20Roh=C3=A1r?= +Date: Tue, 5 Oct 2021 20:09:52 +0200 +Subject: PCI: aardvark: Fix reporting Data Link Layer Link Active +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Pali Rohár + +commit 2b650b7ff20eb7ea8ef9031d20fb657286ab90cc upstream. + +Add support for reporting PCI_EXP_LNKSTA_DLLLA bit in Link Control register +on emulated bridge via current LTSSM state. Also correctly indicate DLLLA +capability via PCI_EXP_LNKCAP_DLLLARC bit in Link Control Capability +register. + +Link: https://lore.kernel.org/r/20211005180952.6812-14-kabel@kernel.org +Fixes: 8a3ebd8de328 ("PCI: aardvark: Implement emulated root PCI bridge config space") +Signed-off-by: Pali Rohár +Signed-off-by: Marek Behún +Signed-off-by: Lorenzo Pieralisi +Reviewed-by: Marek Behún +Cc: stable@vger.kernel.org +Signed-off-by: Greg Kroah-Hartman +--- + drivers/pci/controller/pci-aardvark.c | 29 ++++++++++++++++++++++++++++- + 1 file changed, 28 insertions(+), 1 deletion(-) + +--- a/drivers/pci/controller/pci-aardvark.c ++++ b/drivers/pci/controller/pci-aardvark.c +@@ -278,6 +278,20 @@ static inline bool advk_pcie_link_up(str + return ltssm_state >= LTSSM_L0 && ltssm_state < LTSSM_DISABLED; + } + ++static inline bool advk_pcie_link_active(struct advk_pcie *pcie) ++{ ++ /* ++ * According to PCIe Base specification 3.0, Table 4-14: Link ++ * Status Mapped to the LTSSM, and 4.2.6.3.6 Configuration.Idle ++ * is Link Up mapped to LTSSM Configuration.Idle, Recovery, L0, ++ * L0s, L1 and L2 states. And according to 3.2.1. Data Link ++ * Control and Management State Machine Rules is DL Up status ++ * reported in DL Active state. ++ */ ++ u8 ltssm_state = advk_pcie_ltssm_state(pcie); ++ return ltssm_state >= LTSSM_CONFIG_IDLE && ltssm_state < LTSSM_DISABLED; ++} ++ + static inline bool advk_pcie_link_training(struct advk_pcie *pcie) + { + /* +@@ -576,12 +590,26 @@ advk_pci_bridge_emul_pcie_conf_read(stru + return PCI_BRIDGE_EMUL_HANDLED; + } + ++ case PCI_EXP_LNKCAP: { ++ u32 val = advk_readl(pcie, PCIE_CORE_PCIEXP_CAP + reg); ++ /* ++ * PCI_EXP_LNKCAP_DLLLARC bit is hardwired in aardvark HW to 0. ++ * But support for PCI_EXP_LNKSTA_DLLLA is emulated via ltssm ++ * state so explicitly enable PCI_EXP_LNKCAP_DLLLARC flag. ++ */ ++ val |= PCI_EXP_LNKCAP_DLLLARC; ++ *value = val; ++ return PCI_BRIDGE_EMUL_HANDLED; ++ } ++ + case PCI_EXP_LNKCTL: { + /* u32 contains both PCI_EXP_LNKCTL and PCI_EXP_LNKSTA */ + u32 val = advk_readl(pcie, PCIE_CORE_PCIEXP_CAP + reg) & + ~(PCI_EXP_LNKSTA_LT << 16); + if (advk_pcie_link_training(pcie)) + val |= (PCI_EXP_LNKSTA_LT << 16); ++ if (advk_pcie_link_active(pcie)) ++ val |= (PCI_EXP_LNKSTA_DLLLA << 16); + *value = val; + return PCI_BRIDGE_EMUL_HANDLED; + } +@@ -589,7 +617,6 @@ advk_pci_bridge_emul_pcie_conf_read(stru + case PCI_CAP_LIST_ID: + case PCI_EXP_DEVCAP: + case PCI_EXP_DEVCTL: +- case PCI_EXP_LNKCAP: + *value = advk_readl(pcie, PCIE_CORE_PCIEXP_CAP + reg); + return PCI_BRIDGE_EMUL_HANDLED; + default: diff --git a/queue-5.4/pci-aardvark-fix-return-value-of-msi-domain-.alloc-method.patch b/queue-5.4/pci-aardvark-fix-return-value-of-msi-domain-.alloc-method.patch new file mode 100644 index 00000000000..d51c1e80c49 --- /dev/null +++ b/queue-5.4/pci-aardvark-fix-return-value-of-msi-domain-.alloc-method.patch @@ -0,0 +1,44 @@ +From e4313be1599d397625c14fb7826996813622decf Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Marek=20Beh=C3=BAn?= +Date: Thu, 28 Oct 2021 20:56:54 +0200 +Subject: PCI: aardvark: Fix return value of MSI domain .alloc() method +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Marek Behún + +commit e4313be1599d397625c14fb7826996813622decf upstream. + +MSI domain callback .alloc() (implemented by advk_msi_irq_domain_alloc() +function) should return zero on success, since non-zero value indicates +failure. + +When the driver was converted to generic MSI API in commit f21a8b1b6837 +("PCI: aardvark: Move to MSI handling using generic MSI support"), it +was converted so that it returns hwirq number. + +Fix this. + +Link: https://lore.kernel.org/r/20211028185659.20329-3-kabel@kernel.org +Fixes: f21a8b1b6837 ("PCI: aardvark: Move to MSI handling using generic MSI support") +Signed-off-by: Pali Rohár +Signed-off-by: Marek Behún +Signed-off-by: Lorenzo Pieralisi +Cc: stable@vger.kernel.org +Signed-off-by: Greg Kroah-Hartman +--- + drivers/pci/controller/pci-aardvark.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/pci/controller/pci-aardvark.c ++++ b/drivers/pci/controller/pci-aardvark.c +@@ -942,7 +942,7 @@ static int advk_msi_irq_domain_alloc(str + domain->host_data, handle_simple_irq, + NULL, NULL); + +- return hwirq; ++ return 0; + } + + static void advk_msi_irq_domain_free(struct irq_domain *domain, diff --git a/queue-5.4/pci-aardvark-read-all-16-bits-from-pcie_msi_payload_reg.patch b/queue-5.4/pci-aardvark-read-all-16-bits-from-pcie_msi_payload_reg.patch new file mode 100644 index 00000000000..82672fdd122 --- /dev/null +++ b/queue-5.4/pci-aardvark-read-all-16-bits-from-pcie_msi_payload_reg.patch @@ -0,0 +1,51 @@ +From 95997723b6402cd6c53e0f9e7ac640ec64eaaff8 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Marek=20Beh=C3=BAn?= +Date: Thu, 28 Oct 2021 20:56:55 +0200 +Subject: PCI: aardvark: Read all 16-bits from PCIE_MSI_PAYLOAD_REG +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Marek Behún + +commit 95997723b6402cd6c53e0f9e7ac640ec64eaaff8 upstream. + +The PCIE_MSI_PAYLOAD_REG contains 16-bit MSI number, not only lower +8 bits. Fix reading content of this register and add a comment +describing the access to this register. + +Link: https://lore.kernel.org/r/20211028185659.20329-4-kabel@kernel.org +Fixes: 8c39d710363c ("PCI: aardvark: Add Aardvark PCI host controller driver") +Signed-off-by: Pali Rohár +Signed-off-by: Marek Behún +Signed-off-by: Lorenzo Pieralisi +Cc: stable@vger.kernel.org +Signed-off-by: Greg Kroah-Hartman +--- + drivers/pci/controller/pci-aardvark.c | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +--- a/drivers/pci/controller/pci-aardvark.c ++++ b/drivers/pci/controller/pci-aardvark.c +@@ -120,6 +120,7 @@ + #define PCIE_MSI_STATUS_REG (CONTROL_BASE_ADDR + 0x58) + #define PCIE_MSI_MASK_REG (CONTROL_BASE_ADDR + 0x5C) + #define PCIE_MSI_PAYLOAD_REG (CONTROL_BASE_ADDR + 0x9C) ++#define PCIE_MSI_DATA_MASK GENMASK(15, 0) + + /* LMI registers base address and register offsets */ + #define LMI_BASE_ADDR 0x6000 +@@ -1123,8 +1124,12 @@ static void advk_pcie_handle_msi(struct + if (!(BIT(msi_idx) & msi_status)) + continue; + ++ /* ++ * msi_idx contains bits [4:0] of the msi_data and msi_data ++ * contains 16bit MSI interrupt number ++ */ + advk_writel(pcie, BIT(msi_idx), PCIE_MSI_STATUS_REG); +- msi_data = advk_readl(pcie, PCIE_MSI_PAYLOAD_REG) & 0xFF; ++ msi_data = advk_readl(pcie, PCIE_MSI_PAYLOAD_REG) & PCIE_MSI_DATA_MASK; + generic_handle_irq(msi_data); + } + diff --git a/queue-5.4/pci-pci-bridge-emul-fix-emulation-of-w1c-bits.patch b/queue-5.4/pci-pci-bridge-emul-fix-emulation-of-w1c-bits.patch new file mode 100644 index 00000000000..953fa569dc2 --- /dev/null +++ b/queue-5.4/pci-pci-bridge-emul-fix-emulation-of-w1c-bits.patch @@ -0,0 +1,62 @@ +From 7a41ae80bdcb17e14dd7d83239b8a0cf368f18be Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Marek=20Beh=C3=BAn?= +Date: Thu, 28 Oct 2021 20:56:53 +0200 +Subject: PCI: pci-bridge-emul: Fix emulation of W1C bits +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Marek Behún + +commit 7a41ae80bdcb17e14dd7d83239b8a0cf368f18be upstream. + +The pci_bridge_emul_conf_write() function correctly clears W1C bits in +cfgspace cache, but it does not inform the underlying implementation +about the clear request: the .write_op() method is given the value with +these bits cleared. + +This is wrong if the .write_op() needs to know which bits were requested +to be cleared. + +Fix the value to be passed into the .write_op() method to have requested +W1C bits set, so that it can clear them. + +Both pci-bridge-emul users (mvebu and aardvark) are compatible with this +change. + +Link: https://lore.kernel.org/r/20211028185659.20329-2-kabel@kernel.org +Fixes: 23a5fba4d941 ("PCI: Introduce PCI bridge emulated config space common logic") +Signed-off-by: Pali Rohár +Signed-off-by: Marek Behún +Signed-off-by: Lorenzo Pieralisi +Cc: stable@vger.kernel.org +Cc: Russell King +Signed-off-by: Greg Kroah-Hartman +--- + drivers/pci/pci-bridge-emul.c | 13 +++++++++++++ + 1 file changed, 13 insertions(+) + +--- a/drivers/pci/pci-bridge-emul.c ++++ b/drivers/pci/pci-bridge-emul.c +@@ -432,8 +432,21 @@ int pci_bridge_emul_conf_write(struct pc + /* Clear the W1C bits */ + new &= ~((value << shift) & (behavior[reg / 4].w1c & mask)); + ++ /* Save the new value with the cleared W1C bits into the cfgspace */ + cfgspace[reg / 4] = cpu_to_le32(new); + ++ /* ++ * Clear the W1C bits not specified by the write mask, so that the ++ * write_op() does not clear them. ++ */ ++ new &= ~(behavior[reg / 4].w1c & ~mask); ++ ++ /* ++ * Set the W1C bits specified by the write mask, so that write_op() ++ * knows about that they are to be cleared. ++ */ ++ new |= (value << shift) & (behavior[reg / 4].w1c & mask); ++ + if (write_op) + write_op(bridge, reg, old, new, mask); + diff --git a/queue-5.4/quota-check-block-number-when-reading-the-block-in-quota-file.patch b/queue-5.4/quota-check-block-number-when-reading-the-block-in-quota-file.patch new file mode 100644 index 00000000000..8806c15ddfc --- /dev/null +++ b/queue-5.4/quota-check-block-number-when-reading-the-block-in-quota-file.patch @@ -0,0 +1,54 @@ +From 9bf3d20331295b1ecb81f4ed9ef358c51699a050 Mon Sep 17 00:00:00 2001 +From: Zhang Yi +Date: Fri, 8 Oct 2021 17:38:20 +0800 +Subject: quota: check block number when reading the block in quota file + +From: Zhang Yi + +commit 9bf3d20331295b1ecb81f4ed9ef358c51699a050 upstream. + +The block number in the quota tree on disk should be smaller than the +v2_disk_dqinfo.dqi_blocks. If the quota file was corrupted, we may be +allocating an 'allocated' block and that would lead to a loop in a tree, +which will probably trigger oops later. This patch adds a check for the +block number in the quota tree to prevent such potential issue. + +Link: https://lore.kernel.org/r/20211008093821.1001186-2-yi.zhang@huawei.com +Signed-off-by: Zhang Yi +Cc: stable@kernel.org +Signed-off-by: Jan Kara +Signed-off-by: Greg Kroah-Hartman +--- + fs/quota/quota_tree.c | 14 ++++++++++++++ + 1 file changed, 14 insertions(+) + +--- a/fs/quota/quota_tree.c ++++ b/fs/quota/quota_tree.c +@@ -488,6 +488,13 @@ static int remove_tree(struct qtree_mem_ + goto out_buf; + } + newblk = le32_to_cpu(ref[get_index(info, dquot->dq_id, depth)]); ++ if (newblk < QT_TREEOFF || newblk >= info->dqi_blocks) { ++ quota_error(dquot->dq_sb, "Getting block too big (%u >= %u)", ++ newblk, info->dqi_blocks); ++ ret = -EUCLEAN; ++ goto out_buf; ++ } ++ + if (depth == info->dqi_qtree_depth - 1) { + ret = free_dqentry(info, dquot, newblk); + newblk = 0; +@@ -587,6 +594,13 @@ static loff_t find_tree_dqentry(struct q + blk = le32_to_cpu(ref[get_index(info, dquot->dq_id, depth)]); + if (!blk) /* No reference? */ + goto out_buf; ++ if (blk < QT_TREEOFF || blk >= info->dqi_blocks) { ++ quota_error(dquot->dq_sb, "Getting block too big (%u >= %u)", ++ blk, info->dqi_blocks); ++ ret = -EUCLEAN; ++ goto out_buf; ++ } ++ + if (depth < info->dqi_qtree_depth - 1) + ret = find_tree_dqentry(info, dquot, blk, depth+1); + else diff --git a/queue-5.4/quota-correct-error-number-in-free_dqentry.patch b/queue-5.4/quota-correct-error-number-in-free_dqentry.patch new file mode 100644 index 00000000000..bf511818203 --- /dev/null +++ b/queue-5.4/quota-correct-error-number-in-free_dqentry.patch @@ -0,0 +1,32 @@ +From d0e36a62bd4c60c09acc40e06ba4831a4d0bc75b Mon Sep 17 00:00:00 2001 +From: Zhang Yi +Date: Fri, 8 Oct 2021 17:38:21 +0800 +Subject: quota: correct error number in free_dqentry() + +From: Zhang Yi + +commit d0e36a62bd4c60c09acc40e06ba4831a4d0bc75b upstream. + +Fix the error path in free_dqentry(), pass out the error number if the +block to free is not correct. + +Fixes: 1ccd14b9c271 ("quota: Split off quota tree handling into a separate file") +Link: https://lore.kernel.org/r/20211008093821.1001186-3-yi.zhang@huawei.com +Signed-off-by: Zhang Yi +Cc: stable@kernel.org +Signed-off-by: Jan Kara +Signed-off-by: Greg Kroah-Hartman +--- + fs/quota/quota_tree.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/fs/quota/quota_tree.c ++++ b/fs/quota/quota_tree.c +@@ -423,6 +423,7 @@ static int free_dqentry(struct qtree_mem + quota_error(dquot->dq_sb, "Quota structure has offset to " + "other block (%u) than it should (%u)", blk, + (uint)(dquot->dq_off >> info->dqi_blocksize_bits)); ++ ret = -EIO; + goto out_buf; + } + ret = read_blk(info, blk, buf); diff --git a/queue-5.4/series b/queue-5.4/series index f366c92f976..4e0f30eb655 100644 --- a/queue-5.4/series +++ b/queue-5.4/series @@ -94,3 +94,15 @@ can-j1939-j1939_can_recv-ignore-messages-with-invalid-source-address.patch powerpc-85xx-fix-oops-when-mpc85xx_smp_guts_ids-node-cannot-be-found.patch serial-core-fix-initializing-and-restoring-termios-speed.patch ifb-fix-building-without-config_net_cls_act.patch +alsa-mixer-oss-fix-racy-access-to-slots.patch +alsa-mixer-fix-deadlock-in-snd_mixer_oss_set_volume.patch +xen-balloon-add-late_initcall_sync-for-initial-ballooning-done.patch +pci-pci-bridge-emul-fix-emulation-of-w1c-bits.patch +pci-aardvark-do-not-clear-status-bits-of-masked-interrupts.patch +pci-aardvark-fix-checking-for-link-up-via-ltssm-state.patch +pci-aardvark-do-not-unmask-unused-interrupts.patch +pci-aardvark-fix-reporting-data-link-layer-link-active.patch +pci-aardvark-fix-return-value-of-msi-domain-.alloc-method.patch +pci-aardvark-read-all-16-bits-from-pcie_msi_payload_reg.patch +quota-check-block-number-when-reading-the-block-in-quota-file.patch +quota-correct-error-number-in-free_dqentry.patch diff --git a/queue-5.4/xen-balloon-add-late_initcall_sync-for-initial-ballooning-done.patch b/queue-5.4/xen-balloon-add-late_initcall_sync-for-initial-ballooning-done.patch new file mode 100644 index 00000000000..9be979bee1d --- /dev/null +++ b/queue-5.4/xen-balloon-add-late_initcall_sync-for-initial-ballooning-done.patch @@ -0,0 +1,245 @@ +From 40fdea0284bb20814399da0484a658a96c735d90 Mon Sep 17 00:00:00 2001 +From: Juergen Gross +Date: Tue, 2 Nov 2021 10:19:44 +0100 +Subject: xen/balloon: add late_initcall_sync() for initial ballooning done +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Juergen Gross + +commit 40fdea0284bb20814399da0484a658a96c735d90 upstream. + +When running as PVH or HVM guest with actual memory < max memory the +hypervisor is using "populate on demand" in order to allow the guest +to balloon down from its maximum memory size. For this to work +correctly the guest must not touch more memory pages than its target +memory size as otherwise the PoD cache will be exhausted and the guest +is crashed as a result of that. + +In extreme cases ballooning down might not be finished today before +the init process is started, which can consume lots of memory. + +In order to avoid random boot crashes in such cases, add a late init +call to wait for ballooning down having finished for PVH/HVM guests. + +Warn on console if initial ballooning fails, panic() after stalling +for more than 3 minutes per default. Add a module parameter for +changing this timeout. + +[boris: replaced pr_info() with pr_notice()] + +Cc: +Reported-by: Marek Marczykowski-Górecki +Signed-off-by: Juergen Gross +Link: https://lore.kernel.org/r/20211102091944.17487-1-jgross@suse.com +Reviewed-by: Boris Ostrovsky +Signed-off-by: Boris Ostrovsky +Signed-off-by: Greg Kroah-Hartman +--- + Documentation/admin-guide/kernel-parameters.txt | 7 + + drivers/xen/balloon.c | 86 +++++++++++++++++------- + 2 files changed, 70 insertions(+), 23 deletions(-) + +--- a/Documentation/admin-guide/kernel-parameters.txt ++++ b/Documentation/admin-guide/kernel-parameters.txt +@@ -5480,6 +5480,13 @@ + as generic guest with no PV drivers. Currently support + XEN HVM, KVM, HYPER_V and VMWARE guest. + ++ xen.balloon_boot_timeout= [XEN] ++ The time (in seconds) to wait before giving up to boot ++ in case initial ballooning fails to free enough memory. ++ Applies only when running as HVM or PVH guest and ++ started with less memory configured than allowed at ++ max. Default is 180. ++ + xen.event_eoi_delay= [XEN] + How long to delay EOI handling in case of event + storms (jiffies). Default is 10. +--- a/drivers/xen/balloon.c ++++ b/drivers/xen/balloon.c +@@ -58,6 +58,7 @@ + #include + #include + #include ++#include + + #include + #include +@@ -75,6 +76,12 @@ + #include + #include + ++#undef MODULE_PARAM_PREFIX ++#define MODULE_PARAM_PREFIX "xen." ++ ++static uint __read_mostly balloon_boot_timeout = 180; ++module_param(balloon_boot_timeout, uint, 0444); ++ + static int xen_hotplug_unpopulated; + + #ifdef CONFIG_XEN_BALLOON_MEMORY_HOTPLUG +@@ -127,12 +134,12 @@ static struct ctl_table xen_root[] = { + * BP_ECANCELED: error, balloon operation canceled. + */ + +-enum bp_state { ++static enum bp_state { + BP_DONE, + BP_WAIT, + BP_EAGAIN, + BP_ECANCELED +-}; ++} balloon_state = BP_DONE; + + /* Main waiting point for xen-balloon thread. */ + static DECLARE_WAIT_QUEUE_HEAD(balloon_thread_wq); +@@ -201,18 +208,15 @@ static struct page *balloon_next_page(st + return list_entry(next, struct page, lru); + } + +-static enum bp_state update_schedule(enum bp_state state) ++static void update_schedule(void) + { +- if (state == BP_WAIT) +- return BP_WAIT; +- +- if (state == BP_ECANCELED) +- return BP_ECANCELED; ++ if (balloon_state == BP_WAIT || balloon_state == BP_ECANCELED) ++ return; + +- if (state == BP_DONE) { ++ if (balloon_state == BP_DONE) { + balloon_stats.schedule_delay = 1; + balloon_stats.retry_count = 1; +- return BP_DONE; ++ return; + } + + ++balloon_stats.retry_count; +@@ -221,7 +225,8 @@ static enum bp_state update_schedule(enu + balloon_stats.retry_count > balloon_stats.max_retry_count) { + balloon_stats.schedule_delay = 1; + balloon_stats.retry_count = 1; +- return BP_ECANCELED; ++ balloon_state = BP_ECANCELED; ++ return; + } + + balloon_stats.schedule_delay <<= 1; +@@ -229,7 +234,7 @@ static enum bp_state update_schedule(enu + if (balloon_stats.schedule_delay > balloon_stats.max_schedule_delay) + balloon_stats.schedule_delay = balloon_stats.max_schedule_delay; + +- return BP_EAGAIN; ++ balloon_state = BP_EAGAIN; + } + + #ifdef CONFIG_XEN_BALLOON_MEMORY_HOTPLUG +@@ -511,9 +516,9 @@ static enum bp_state decrease_reservatio + * Stop waiting if either state is BP_DONE and ballooning action is + * needed, or if the credit has changed while state is not BP_DONE. + */ +-static bool balloon_thread_cond(enum bp_state state, long credit) ++static bool balloon_thread_cond(long credit) + { +- if (state == BP_DONE) ++ if (balloon_state == BP_DONE) + credit = 0; + + return current_credit() != credit || kthread_should_stop(); +@@ -527,13 +532,12 @@ static bool balloon_thread_cond(enum bp_ + */ + static int balloon_thread(void *unused) + { +- enum bp_state state = BP_DONE; + long credit; + unsigned long timeout; + + set_freezable(); + for (;;) { +- switch (state) { ++ switch (balloon_state) { + case BP_DONE: + case BP_ECANCELED: + timeout = 3600 * HZ; +@@ -549,7 +553,7 @@ static int balloon_thread(void *unused) + credit = current_credit(); + + wait_event_freezable_timeout(balloon_thread_wq, +- balloon_thread_cond(state, credit), timeout); ++ balloon_thread_cond(credit), timeout); + + if (kthread_should_stop()) + return 0; +@@ -560,22 +564,23 @@ static int balloon_thread(void *unused) + + if (credit > 0) { + if (balloon_is_inflated()) +- state = increase_reservation(credit); ++ balloon_state = increase_reservation(credit); + else +- state = reserve_additional_memory(); ++ balloon_state = reserve_additional_memory(); + } + + if (credit < 0) { + long n_pages; + + n_pages = min(-credit, si_mem_available()); +- state = decrease_reservation(n_pages, GFP_BALLOON); +- if (state == BP_DONE && n_pages != -credit && ++ balloon_state = decrease_reservation(n_pages, ++ GFP_BALLOON); ++ if (balloon_state == BP_DONE && n_pages != -credit && + n_pages < totalreserve_pages) +- state = BP_EAGAIN; ++ balloon_state = BP_EAGAIN; + } + +- state = update_schedule(state); ++ update_schedule(); + + mutex_unlock(&balloon_mutex); + +@@ -782,3 +787,38 @@ static int __init balloon_init(void) + return 0; + } + subsys_initcall(balloon_init); ++ ++static int __init balloon_wait_finish(void) ++{ ++ long credit, last_credit = 0; ++ unsigned long last_changed = 0; ++ ++ if (!xen_domain()) ++ return -ENODEV; ++ ++ /* PV guests don't need to wait. */ ++ if (xen_pv_domain() || !current_credit()) ++ return 0; ++ ++ pr_notice("Waiting for initial ballooning down having finished.\n"); ++ ++ while ((credit = current_credit()) < 0) { ++ if (credit != last_credit) { ++ last_changed = jiffies; ++ last_credit = credit; ++ } ++ if (balloon_state == BP_ECANCELED) { ++ pr_warn_once("Initial ballooning failed, %ld pages need to be freed.\n", ++ -credit); ++ if (jiffies - last_changed >= HZ * balloon_boot_timeout) ++ panic("Initial ballooning failed!\n"); ++ } ++ ++ schedule_timeout_interruptible(HZ / 10); ++ } ++ ++ pr_notice("Initial ballooning down finished.\n"); ++ ++ return 0; ++} ++late_initcall_sync(balloon_wait_finish); -- 2.47.2