]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
5.4-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sun, 14 Nov 2021 14:12:32 +0000 (15:12 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sun, 14 Nov 2021 14:12:32 +0000 (15:12 +0100)
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

13 files changed:
queue-5.4/alsa-mixer-fix-deadlock-in-snd_mixer_oss_set_volume.patch [new file with mode: 0644]
queue-5.4/alsa-mixer-oss-fix-racy-access-to-slots.patch [new file with mode: 0644]
queue-5.4/pci-aardvark-do-not-clear-status-bits-of-masked-interrupts.patch [new file with mode: 0644]
queue-5.4/pci-aardvark-do-not-unmask-unused-interrupts.patch [new file with mode: 0644]
queue-5.4/pci-aardvark-fix-checking-for-link-up-via-ltssm-state.patch [new file with mode: 0644]
queue-5.4/pci-aardvark-fix-reporting-data-link-layer-link-active.patch [new file with mode: 0644]
queue-5.4/pci-aardvark-fix-return-value-of-msi-domain-.alloc-method.patch [new file with mode: 0644]
queue-5.4/pci-aardvark-read-all-16-bits-from-pcie_msi_payload_reg.patch [new file with mode: 0644]
queue-5.4/pci-pci-bridge-emul-fix-emulation-of-w1c-bits.patch [new file with mode: 0644]
queue-5.4/quota-check-block-number-when-reading-the-block-in-quota-file.patch [new file with mode: 0644]
queue-5.4/quota-correct-error-number-in-free_dqentry.patch [new file with mode: 0644]
queue-5.4/series
queue-5.4/xen-balloon-add-late_initcall_sync-for-initial-ballooning-done.patch [new file with mode: 0644]

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 (file)
index 0000000..3442927
--- /dev/null
@@ -0,0 +1,35 @@
+From 3ab7992018455ac63c33e9b3eaa7264e293e40f4 Mon Sep 17 00:00:00 2001
+From: Pavel Skripkin <paskripkin@gmail.com>
+Date: Sun, 24 Oct 2021 17:03:15 +0300
+Subject: ALSA: mixer: fix deadlock in snd_mixer_oss_set_volume
+
+From: Pavel Skripkin <paskripkin@gmail.com>
+
+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: <stable@vger.kernel.org>
+Signed-off-by: Pavel Skripkin <paskripkin@gmail.com>
+Link: https://lore.kernel.org/r/20211024140315.16704-1-paskripkin@gmail.com
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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 (file)
index 0000000..da315f0
--- /dev/null
@@ -0,0 +1,176 @@
+From 411cef6adfb38a5bb6bd9af3941b28198e7fb680 Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Wed, 20 Oct 2021 18:48:46 +0200
+Subject: ALSA: mixer: oss: Fix racy access to slots
+
+From: Takashi Iwai <tiwai@suse.de>
+
+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 <perex@perex.cz>
+Cc: <stable@vger.kernel.org>
+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 <tiwai@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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 (file)
index 0000000..e6fc437
--- /dev/null
@@ -0,0 +1,51 @@
+From a7ca6d7fa3c02c032db5440ff392d96c04684c21 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Pali=20Roh=C3=A1r?= <pali@kernel.org>
+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 <pali@kernel.org>
+
+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 <pali@kernel.org>
+Signed-off-by: Marek Behún <kabel@kernel.org>
+Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
+Reviewed-by: Marek Behún <kabel@kernel.org>
+Cc: stable@vger.kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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 (file)
index 0000000..68a2806
--- /dev/null
@@ -0,0 +1,56 @@
+From 1fb95d7d3c7a926b002fe8a6bd27a1cb428b46dc Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Pali=20Roh=C3=A1r?= <pali@kernel.org>
+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 <pali@kernel.org>
+
+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 <pali@kernel.org>
+Signed-off-by: Marek Behún <kabel@kernel.org>
+Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
+Reviewed-by: Marek Behún <kabel@kernel.org>
+Cc: stable@vger.kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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 (file)
index 0000000..777a8db
--- /dev/null
@@ -0,0 +1,148 @@
+From 661c399a651c11aaf83c45cbfe0b4a1fb7bc3179 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Pali=20Roh=C3=A1r?= <pali@kernel.org>
+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 <pali@kernel.org>
+
+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 <pali@kernel.org>
+Signed-off-by: Marek Behún <kabel@kernel.org>
+Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
+Reviewed-by: Marek Behún <kabel@kernel.org>
+Cc: stable@vger.kernel.org
+Cc: Remi Pommarel <repk@triplefau.lt>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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 (file)
index 0000000..7b4cf09
--- /dev/null
@@ -0,0 +1,87 @@
+From 2b650b7ff20eb7ea8ef9031d20fb657286ab90cc Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Pali=20Roh=C3=A1r?= <pali@kernel.org>
+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 <pali@kernel.org>
+
+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 <pali@kernel.org>
+Signed-off-by: Marek Behún <kabel@kernel.org>
+Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
+Reviewed-by: Marek Behún <kabel@kernel.org>
+Cc: stable@vger.kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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 (file)
index 0000000..d51c1e8
--- /dev/null
@@ -0,0 +1,44 @@
+From e4313be1599d397625c14fb7826996813622decf Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Marek=20Beh=C3=BAn?= <kabel@kernel.org>
+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 <kabel@kernel.org>
+
+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 <pali@kernel.org>
+Signed-off-by: Marek Behún <kabel@kernel.org>
+Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
+Cc: stable@vger.kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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 (file)
index 0000000..82672fd
--- /dev/null
@@ -0,0 +1,51 @@
+From 95997723b6402cd6c53e0f9e7ac640ec64eaaff8 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Marek=20Beh=C3=BAn?= <kabel@kernel.org>
+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 <kabel@kernel.org>
+
+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 <pali@kernel.org>
+Signed-off-by: Marek Behún <kabel@kernel.org>
+Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
+Cc: stable@vger.kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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 (file)
index 0000000..953fa56
--- /dev/null
@@ -0,0 +1,62 @@
+From 7a41ae80bdcb17e14dd7d83239b8a0cf368f18be Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Marek=20Beh=C3=BAn?= <kabel@kernel.org>
+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 <kabel@kernel.org>
+
+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 <pali@kernel.org>
+Signed-off-by: Marek Behún <kabel@kernel.org>
+Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
+Cc: stable@vger.kernel.org
+Cc: Russell King <rmk+kernel@armlinux.org.uk>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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 (file)
index 0000000..8806c15
--- /dev/null
@@ -0,0 +1,54 @@
+From 9bf3d20331295b1ecb81f4ed9ef358c51699a050 Mon Sep 17 00:00:00 2001
+From: Zhang Yi <yi.zhang@huawei.com>
+Date: Fri, 8 Oct 2021 17:38:20 +0800
+Subject: quota: check block number when reading the block in quota file
+
+From: Zhang Yi <yi.zhang@huawei.com>
+
+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 <yi.zhang@huawei.com>
+Cc: stable@kernel.org
+Signed-off-by: Jan Kara <jack@suse.cz>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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 (file)
index 0000000..bf51181
--- /dev/null
@@ -0,0 +1,32 @@
+From d0e36a62bd4c60c09acc40e06ba4831a4d0bc75b Mon Sep 17 00:00:00 2001
+From: Zhang Yi <yi.zhang@huawei.com>
+Date: Fri, 8 Oct 2021 17:38:21 +0800
+Subject: quota: correct error number in free_dqentry()
+
+From: Zhang Yi <yi.zhang@huawei.com>
+
+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 <yi.zhang@huawei.com>
+Cc: stable@kernel.org
+Signed-off-by: Jan Kara <jack@suse.cz>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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);
index f366c92f9765da5fc3b61dde9267a69f796fb9d5..4e0f30eb6551d88c0297c3c2f39b8e27ea23151e 100644 (file)
@@ -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 (file)
index 0000000..9be979b
--- /dev/null
@@ -0,0 +1,245 @@
+From 40fdea0284bb20814399da0484a658a96c735d90 Mon Sep 17 00:00:00 2001
+From: Juergen Gross <jgross@suse.com>
+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 <jgross@suse.com>
+
+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: <stable@vger.kernel.org>
+Reported-by: Marek Marczykowski-Górecki <marmarek@invisiblethingslab.com>
+Signed-off-by: Juergen Gross <jgross@suse.com>
+Link: https://lore.kernel.org/r/20211102091944.17487-1-jgross@suse.com
+Reviewed-by: Boris Ostrovsky <boris.ostrovsky@oracle.com>
+Signed-off-by: Boris Ostrovsky <boris.ostrovsky@oracle.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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 <linux/percpu-defs.h>
+ #include <linux/slab.h>
+ #include <linux/sysctl.h>
++#include <linux/moduleparam.h>
+ #include <asm/page.h>
+ #include <asm/pgalloc.h>
+@@ -75,6 +76,12 @@
+ #include <xen/page.h>
+ #include <xen/mem-reservation.h>
++#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);