--- /dev/null
+From 84351dd7a949a5edb18716765e9e1ebbdde122e7 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 4 Feb 2022 10:53:01 +0100
+Subject: ASoC: tas2770: Insert post reset delay
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Martin Povišer <povik+lin@cutebit.org>
+
+[ Upstream commit 307f31452078792aab94a729fce33200c6e42dc4 ]
+
+Per TAS2770 datasheet there must be a 1 ms delay from reset to first
+command. So insert delays into the driver where appropriate.
+
+Fixes: 1a476abc723e ("tas2770: add tas2770 smart PA kernel driver")
+Signed-off-by: Martin Povišer <povik+lin@cutebit.org>
+Link: https://lore.kernel.org/r/20220204095301.5554-1-povik+lin@cutebit.org
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/soc/codecs/tas2770.c | 7 ++++++-
+ 1 file changed, 6 insertions(+), 1 deletion(-)
+
+diff --git a/sound/soc/codecs/tas2770.c b/sound/soc/codecs/tas2770.c
+index 61c3238bc2656..315fd9d971c8c 100644
+--- a/sound/soc/codecs/tas2770.c
++++ b/sound/soc/codecs/tas2770.c
+@@ -38,10 +38,12 @@ static void tas2770_reset(struct tas2770_priv *tas2770)
+ gpiod_set_value_cansleep(tas2770->reset_gpio, 0);
+ msleep(20);
+ gpiod_set_value_cansleep(tas2770->reset_gpio, 1);
++ usleep_range(1000, 2000);
+ }
+
+ snd_soc_component_write(tas2770->component, TAS2770_SW_RST,
+ TAS2770_RST);
++ usleep_range(1000, 2000);
+ }
+
+ static int tas2770_set_bias_level(struct snd_soc_component *component,
+@@ -110,6 +112,7 @@ static int tas2770_codec_resume(struct snd_soc_component *component)
+
+ if (tas2770->sdz_gpio) {
+ gpiod_set_value_cansleep(tas2770->sdz_gpio, 1);
++ usleep_range(1000, 2000);
+ } else {
+ ret = snd_soc_component_update_bits(component, TAS2770_PWR_CTRL,
+ TAS2770_PWR_CTRL_MASK,
+@@ -510,8 +513,10 @@ static int tas2770_codec_probe(struct snd_soc_component *component)
+
+ tas2770->component = component;
+
+- if (tas2770->sdz_gpio)
++ if (tas2770->sdz_gpio) {
+ gpiod_set_value_cansleep(tas2770->sdz_gpio, 1);
++ usleep_range(1000, 2000);
++ }
+
+ tas2770_reset(tas2770);
+
+--
+2.34.1
+
--- /dev/null
+From b687439c422df871dfaf0a066d5ecbe79dacf340 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 22 Jan 2022 19:10:45 +0800
+Subject: block/wbt: fix negative inflight counter when remove scsi device
+
+From: Laibin Qiu <qiulaibin@huawei.com>
+
+[ Upstream commit e92bc4cd34de2ce454bdea8cd198b8067ee4e123 ]
+
+Now that we disable wbt by set WBT_STATE_OFF_DEFAULT in
+wbt_disable_default() when switch elevator to bfq. And when
+we remove scsi device, wbt will be enabled by wbt_enable_default.
+If it become false positive between wbt_wait() and wbt_track()
+when submit write request.
+
+The following is the scenario that triggered the problem.
+
+T1 T2 T3
+ elevator_switch_mq
+ bfq_init_queue
+ wbt_disable_default <= Set
+ rwb->enable_state (OFF)
+Submit_bio
+blk_mq_make_request
+rq_qos_throttle
+<= rwb->enable_state (OFF)
+ scsi_remove_device
+ sd_remove
+ del_gendisk
+ blk_unregister_queue
+ elv_unregister_queue
+ wbt_enable_default
+ <= Set rwb->enable_state (ON)
+q_qos_track
+<= rwb->enable_state (ON)
+^^^^^^ this request will mark WBT_TRACKED without inflight add and will
+lead to drop rqw->inflight to -1 in wbt_done() which will trigger IO hung.
+
+Fix this by move wbt_enable_default() from elv_unregister to
+bfq_exit_queue(). Only re-enable wbt when bfq exit.
+
+Fixes: 76a8040817b4b ("blk-wbt: make sure throttle is enabled properly")
+
+Remove oneline stale comment, and kill one oneshot local variable.
+
+Signed-off-by: Ming Lei <ming.lei@rehdat.com>
+Reviewed-by: Christoph Hellwig <hch@lst.de>
+Link: https://lore.kernel.org/linux-block/20211214133103.551813-1-qiulaibin@huawei.com/
+Signed-off-by: Laibin Qiu <qiulaibin@huawei.com>
+Signed-off-by: Jens Axboe <axboe@kernel.dk>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ block/bfq-iosched.c | 2 ++
+ block/elevator.c | 2 --
+ 2 files changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/block/bfq-iosched.c b/block/bfq-iosched.c
+index b8c2ddc01aec3..8d95bf7765b19 100644
+--- a/block/bfq-iosched.c
++++ b/block/bfq-iosched.c
+@@ -6404,6 +6404,8 @@ static void bfq_exit_queue(struct elevator_queue *e)
+ spin_unlock_irq(&bfqd->lock);
+ #endif
+
++ wbt_enable_default(bfqd->queue);
++
+ kfree(bfqd);
+ }
+
+diff --git a/block/elevator.c b/block/elevator.c
+index 2a525863d4e92..2f962662c32a1 100644
+--- a/block/elevator.c
++++ b/block/elevator.c
+@@ -518,8 +518,6 @@ void elv_unregister_queue(struct request_queue *q)
+ kobject_del(&e->kobj);
+
+ e->registered = 0;
+- /* Re-enable throttling in case elevator disabled it */
+- wbt_enable_default(q);
+ }
+ }
+
+--
+2.34.1
+
--- /dev/null
+From 7a94c886809fe6e27acfcc032f4bf6a9f64d4e8e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 4 Feb 2022 01:30:08 +0800
+Subject: Drivers: hv: vmbus: Fix memory leak in vmbus_add_channel_kobj
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Miaoqian Lin <linmq006@gmail.com>
+
+[ Upstream commit 8bc69f86328e87a0ffa79438430cc82f3aa6a194 ]
+
+kobject_init_and_add() takes reference even when it fails.
+According to the doc of kobject_init_and_add():
+
+ If this function returns an error, kobject_put() must be called to
+ properly clean up the memory associated with the object.
+
+Fix memory leak by calling kobject_put().
+
+Fixes: c2e5df616e1a ("vmbus: add per-channel sysfs info")
+Signed-off-by: Miaoqian Lin <linmq006@gmail.com>
+Reviewed-by: Juan Vazquez <juvazq@linux.microsoft.com>
+Link: https://lore.kernel.org/r/20220203173008.43480-1-linmq006@gmail.com
+Signed-off-by: Wei Liu <wei.liu@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/hv/vmbus_drv.c | 5 ++++-
+ 1 file changed, 4 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c
+index a5a402e776c77..362da2a83b470 100644
+--- a/drivers/hv/vmbus_drv.c
++++ b/drivers/hv/vmbus_drv.c
+@@ -1944,8 +1944,10 @@ int vmbus_add_channel_kobj(struct hv_device *dev, struct vmbus_channel *channel)
+ kobj->kset = dev->channels_kset;
+ ret = kobject_init_and_add(kobj, &vmbus_chan_ktype, NULL,
+ "%u", relid);
+- if (ret)
++ if (ret) {
++ kobject_put(kobj);
+ return ret;
++ }
+
+ ret = sysfs_create_group(kobj, &vmbus_chan_group);
+
+@@ -1954,6 +1956,7 @@ int vmbus_add_channel_kobj(struct hv_device *dev, struct vmbus_channel *channel)
+ * The calling functions' error handling paths will cleanup the
+ * empty channel directory.
+ */
++ kobject_put(kobj);
+ dev_err(device, "Unable to set up channel sysfs files\n");
+ return ret;
+ }
+--
+2.34.1
+
--- /dev/null
+From befa75cf310a91e20b1ff91179a3c62181c2d205 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 2 Feb 2022 17:48:12 -0800
+Subject: KVM: x86/pmu: Don't truncate the PerfEvtSeln MSR when creating a perf
+ event
+
+From: Jim Mattson <jmattson@google.com>
+
+[ Upstream commit b8bfee85f1307426e0242d654f3a14c06ef639c5 ]
+
+AMD's event select is 3 nybbles, with the high nybble in bits 35:32 of
+a PerfEvtSeln MSR. Don't drop the high nybble when setting up the
+config field of a perf_event_attr structure for a call to
+perf_event_create_kernel_counter().
+
+Fixes: ca724305a2b0 ("KVM: x86/vPMU: Implement AMD vPMU code for KVM")
+Reported-by: Stephane Eranian <eranian@google.com>
+Signed-off-by: Jim Mattson <jmattson@google.com>
+Message-Id: <20220203014813.2130559-1-jmattson@google.com>
+Reviewed-by: David Dunn <daviddunn@google.com>
+Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/x86/kvm/pmu.c | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+diff --git a/arch/x86/kvm/pmu.c b/arch/x86/kvm/pmu.c
+index 20092a56de8b0..2d91e39dbdf67 100644
+--- a/arch/x86/kvm/pmu.c
++++ b/arch/x86/kvm/pmu.c
+@@ -95,7 +95,7 @@ static void kvm_perf_overflow_intr(struct perf_event *perf_event,
+ }
+
+ static void pmc_reprogram_counter(struct kvm_pmc *pmc, u32 type,
+- unsigned config, bool exclude_user,
++ u64 config, bool exclude_user,
+ bool exclude_kernel, bool intr,
+ bool in_tx, bool in_tx_cp)
+ {
+@@ -170,7 +170,8 @@ static bool pmc_resume_counter(struct kvm_pmc *pmc)
+
+ void reprogram_gp_counter(struct kvm_pmc *pmc, u64 eventsel)
+ {
+- unsigned config, type = PERF_TYPE_RAW;
++ u64 config;
++ u32 type = PERF_TYPE_RAW;
+ struct kvm *kvm = pmc->vcpu->kvm;
+ struct kvm_pmu_event_filter *filter;
+ int i;
+--
+2.34.1
+
--- /dev/null
+From 0864e573c2bc533fead9659a68511d56d5107e2e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 30 Nov 2021 15:42:17 +0800
+Subject: KVM: x86/pmu: Refactoring find_arch_event() to pmc_perf_hw_id()
+
+From: Like Xu <likexu@tencent.com>
+
+[ Upstream commit 7c174f305cbee6bdba5018aae02b84369e7ab995 ]
+
+The find_arch_event() returns a "unsigned int" value,
+which is used by the pmc_reprogram_counter() to
+program a PERF_TYPE_HARDWARE type perf_event.
+
+The returned value is actually the kernel defined generic
+perf_hw_id, let's rename it to pmc_perf_hw_id() with simpler
+incoming parameters for better self-explanation.
+
+Signed-off-by: Like Xu <likexu@tencent.com>
+Message-Id: <20211130074221.93635-3-likexu@tencent.com>
+Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/x86/kvm/pmu.c | 8 +-------
+ arch/x86/kvm/pmu.h | 3 +--
+ arch/x86/kvm/svm/pmu.c | 8 ++++----
+ arch/x86/kvm/vmx/pmu_intel.c | 9 +++++----
+ 4 files changed, 11 insertions(+), 17 deletions(-)
+
+diff --git a/arch/x86/kvm/pmu.c b/arch/x86/kvm/pmu.c
+index 67741d2a03085..20092a56de8b0 100644
+--- a/arch/x86/kvm/pmu.c
++++ b/arch/x86/kvm/pmu.c
+@@ -171,7 +171,6 @@ static bool pmc_resume_counter(struct kvm_pmc *pmc)
+ void reprogram_gp_counter(struct kvm_pmc *pmc, u64 eventsel)
+ {
+ unsigned config, type = PERF_TYPE_RAW;
+- u8 event_select, unit_mask;
+ struct kvm *kvm = pmc->vcpu->kvm;
+ struct kvm_pmu_event_filter *filter;
+ int i;
+@@ -203,17 +202,12 @@ void reprogram_gp_counter(struct kvm_pmc *pmc, u64 eventsel)
+ if (!allow_event)
+ return;
+
+- event_select = eventsel & ARCH_PERFMON_EVENTSEL_EVENT;
+- unit_mask = (eventsel & ARCH_PERFMON_EVENTSEL_UMASK) >> 8;
+-
+ if (!(eventsel & (ARCH_PERFMON_EVENTSEL_EDGE |
+ ARCH_PERFMON_EVENTSEL_INV |
+ ARCH_PERFMON_EVENTSEL_CMASK |
+ HSW_IN_TX |
+ HSW_IN_TX_CHECKPOINTED))) {
+- config = kvm_x86_ops.pmu_ops->find_arch_event(pmc_to_pmu(pmc),
+- event_select,
+- unit_mask);
++ config = kvm_x86_ops.pmu_ops->pmc_perf_hw_id(pmc);
+ if (config != PERF_COUNT_HW_MAX)
+ type = PERF_TYPE_HARDWARE;
+ }
+diff --git a/arch/x86/kvm/pmu.h b/arch/x86/kvm/pmu.h
+index 067fef51760c4..1a44e29e73330 100644
+--- a/arch/x86/kvm/pmu.h
++++ b/arch/x86/kvm/pmu.h
+@@ -24,8 +24,7 @@ struct kvm_event_hw_type_mapping {
+ };
+
+ struct kvm_pmu_ops {
+- unsigned (*find_arch_event)(struct kvm_pmu *pmu, u8 event_select,
+- u8 unit_mask);
++ unsigned int (*pmc_perf_hw_id)(struct kvm_pmc *pmc);
+ unsigned (*find_fixed_event)(int idx);
+ bool (*pmc_is_enabled)(struct kvm_pmc *pmc);
+ struct kvm_pmc *(*pmc_idx_to_pmc)(struct kvm_pmu *pmu, int pmc_idx);
+diff --git a/arch/x86/kvm/svm/pmu.c b/arch/x86/kvm/svm/pmu.c
+index 5a5c165a30ed1..4e7093bcb64b6 100644
+--- a/arch/x86/kvm/svm/pmu.c
++++ b/arch/x86/kvm/svm/pmu.c
+@@ -126,10 +126,10 @@ static inline struct kvm_pmc *get_gp_pmc_amd(struct kvm_pmu *pmu, u32 msr,
+ return &pmu->gp_counters[msr_to_index(msr)];
+ }
+
+-static unsigned amd_find_arch_event(struct kvm_pmu *pmu,
+- u8 event_select,
+- u8 unit_mask)
++static unsigned int amd_pmc_perf_hw_id(struct kvm_pmc *pmc)
+ {
++ u8 event_select = pmc->eventsel & ARCH_PERFMON_EVENTSEL_EVENT;
++ u8 unit_mask = (pmc->eventsel & ARCH_PERFMON_EVENTSEL_UMASK) >> 8;
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(amd_event_mapping); i++)
+@@ -312,7 +312,7 @@ static void amd_pmu_reset(struct kvm_vcpu *vcpu)
+ }
+
+ struct kvm_pmu_ops amd_pmu_ops = {
+- .find_arch_event = amd_find_arch_event,
++ .pmc_perf_hw_id = amd_pmc_perf_hw_id,
+ .find_fixed_event = amd_find_fixed_event,
+ .pmc_is_enabled = amd_pmc_is_enabled,
+ .pmc_idx_to_pmc = amd_pmc_idx_to_pmc,
+diff --git a/arch/x86/kvm/vmx/pmu_intel.c b/arch/x86/kvm/vmx/pmu_intel.c
+index cdf5f34518f43..bd70c1d7f3458 100644
+--- a/arch/x86/kvm/vmx/pmu_intel.c
++++ b/arch/x86/kvm/vmx/pmu_intel.c
+@@ -68,10 +68,11 @@ static void global_ctrl_changed(struct kvm_pmu *pmu, u64 data)
+ reprogram_counter(pmu, bit);
+ }
+
+-static unsigned intel_find_arch_event(struct kvm_pmu *pmu,
+- u8 event_select,
+- u8 unit_mask)
++static unsigned int intel_pmc_perf_hw_id(struct kvm_pmc *pmc)
+ {
++ struct kvm_pmu *pmu = pmc_to_pmu(pmc);
++ u8 event_select = pmc->eventsel & ARCH_PERFMON_EVENTSEL_EVENT;
++ u8 unit_mask = (pmc->eventsel & ARCH_PERFMON_EVENTSEL_UMASK) >> 8;
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(intel_arch_events); i++)
+@@ -432,7 +433,7 @@ static void intel_pmu_reset(struct kvm_vcpu *vcpu)
+ }
+
+ struct kvm_pmu_ops intel_pmu_ops = {
+- .find_arch_event = intel_find_arch_event,
++ .pmc_perf_hw_id = intel_pmc_perf_hw_id,
+ .find_fixed_event = intel_find_fixed_event,
+ .pmc_is_enabled = intel_pmc_is_enabled,
+ .pmc_idx_to_pmc = intel_pmc_idx_to_pmc,
+--
+2.34.1
+
--- /dev/null
+From 3bda16f23753fa32976c42a30930a3d90749a183 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 2 Feb 2022 17:48:13 -0800
+Subject: KVM: x86/pmu: Use AMD64_RAW_EVENT_MASK for PERF_TYPE_RAW
+
+From: Jim Mattson <jmattson@google.com>
+
+[ Upstream commit 710c476514313c74045c41c0571bb5178fd16e3d ]
+
+AMD's event select is 3 nybbles, with the high nybble in bits 35:32 of
+a PerfEvtSeln MSR. Don't mask off the high nybble when configuring a
+RAW perf event.
+
+Fixes: ca724305a2b0 ("KVM: x86/vPMU: Implement AMD vPMU code for KVM")
+Signed-off-by: Jim Mattson <jmattson@google.com>
+Message-Id: <20220203014813.2130559-2-jmattson@google.com>
+Reviewed-by: David Dunn <daviddunn@google.com>
+Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/x86/kvm/pmu.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/arch/x86/kvm/pmu.c b/arch/x86/kvm/pmu.c
+index 2d91e39dbdf67..2f83b5d948b33 100644
+--- a/arch/x86/kvm/pmu.c
++++ b/arch/x86/kvm/pmu.c
+@@ -214,7 +214,7 @@ void reprogram_gp_counter(struct kvm_pmc *pmc, u64 eventsel)
+ }
+
+ if (type == PERF_TYPE_RAW)
+- config = eventsel & X86_RAW_EVENT_MASK;
++ config = eventsel & AMD64_RAW_EVENT_MASK;
+
+ if (pmc->current_config == eventsel && pmc_resume_counter(pmc))
+ return;
+--
+2.34.1
+
--- /dev/null
+From 0f0d550a0ecd0347e308ebe462399348c7afe9a8 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 26 Jan 2022 23:43:44 +0100
+Subject: mtd: rawnand: brcmnand: Fixed incorrect sub-page ECC status
+
+From: david regan <dregan@mail.com>
+
+[ Upstream commit 36415a7964711822e63695ea67fede63979054d9 ]
+
+The brcmnand driver contains a bug in which if a page (example 2k byte)
+is read from the parallel/ONFI NAND and within that page a subpage (512
+byte) has correctable errors which is followed by a subpage with
+uncorrectable errors, the page read will return the wrong status of
+correctable (as opposed to the actual status of uncorrectable.)
+
+The bug is in function brcmnand_read_by_pio where there is a check for
+uncorrectable bits which will be preempted if a previous status for
+correctable bits is detected.
+
+The fix is to stop checking for bad bits only if we already have a bad
+bits status.
+
+Fixes: 27c5b17cd1b1 ("mtd: nand: add NAND driver "library" for Broadcom STB NAND controller")
+Signed-off-by: david regan <dregan@mail.com>
+Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
+Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
+Link: https://lore.kernel.org/linux-mtd/trinity-478e0c09-9134-40e8-8f8c-31c371225eda-1643237024774@3c-app-mailcom-lxa02
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/mtd/nand/raw/brcmnand/brcmnand.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/mtd/nand/raw/brcmnand/brcmnand.c b/drivers/mtd/nand/raw/brcmnand/brcmnand.c
+index 909b14cc8e55c..580b91cbd18de 100644
+--- a/drivers/mtd/nand/raw/brcmnand/brcmnand.c
++++ b/drivers/mtd/nand/raw/brcmnand/brcmnand.c
+@@ -2062,7 +2062,7 @@ static int brcmnand_read_by_pio(struct mtd_info *mtd, struct nand_chip *chip,
+ mtd->oobsize / trans,
+ host->hwcfg.sector_size_1k);
+
+- if (!ret) {
++ if (ret != -EBADMSG) {
+ *err_addr = brcmnand_get_uncorrecc_addr(ctrl);
+
+ if (*err_addr)
+--
+2.34.1
+
--- /dev/null
+From 3587f3ebb1d66cfafa06a559bd051aab28a8e9f9 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 3 Jan 2022 03:03:15 +0000
+Subject: mtd: rawnand: qcom: Fix clock sequencing in qcom_nandc_probe()
+
+From: Bryan O'Donoghue <bryan.odonoghue@linaro.org>
+
+[ Upstream commit 5c23b3f965bc9ee696bf2ed4bdc54d339dd9a455 ]
+
+Interacting with a NAND chip on an IPQ6018 I found that the qcomsmem NAND
+partition parser was returning -EPROBE_DEFER waiting for the main smem
+driver to load.
+
+This caused the board to reset. Playing about with the probe() function
+shows that the problem lies in the core clock being switched off before the
+nandc_unalloc() routine has completed.
+
+If we look at how qcom_nandc_remove() tears down allocated resources we see
+the expected order is
+
+qcom_nandc_unalloc(nandc);
+
+clk_disable_unprepare(nandc->aon_clk);
+clk_disable_unprepare(nandc->core_clk);
+
+dma_unmap_resource(&pdev->dev, nandc->base_dma, resource_size(res),
+ DMA_BIDIRECTIONAL, 0);
+
+Tweaking probe() to both bring up and tear-down in that order removes the
+reset if we end up deferring elsewhere.
+
+Fixes: c76b78d8ec05 ("mtd: nand: Qualcomm NAND controller driver")
+Signed-off-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org>
+Reviewed-by: Manivannan Sadhasivam <mani@kernel.org>
+Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
+Link: https://lore.kernel.org/linux-mtd/20220103030316.58301-2-bryan.odonoghue@linaro.org
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/mtd/nand/raw/qcom_nandc.c | 14 ++++++--------
+ 1 file changed, 6 insertions(+), 8 deletions(-)
+
+diff --git a/drivers/mtd/nand/raw/qcom_nandc.c b/drivers/mtd/nand/raw/qcom_nandc.c
+index b99d2e9d1e2c4..bb181e18c7c52 100644
+--- a/drivers/mtd/nand/raw/qcom_nandc.c
++++ b/drivers/mtd/nand/raw/qcom_nandc.c
+@@ -2,7 +2,6 @@
+ /*
+ * Copyright (c) 2016, The Linux Foundation. All rights reserved.
+ */
+-
+ #include <linux/clk.h>
+ #include <linux/slab.h>
+ #include <linux/bitops.h>
+@@ -2968,10 +2967,6 @@ static int qcom_nandc_probe(struct platform_device *pdev)
+ if (!nandc->base_dma)
+ return -ENXIO;
+
+- ret = qcom_nandc_alloc(nandc);
+- if (ret)
+- goto err_nandc_alloc;
+-
+ ret = clk_prepare_enable(nandc->core_clk);
+ if (ret)
+ goto err_core_clk;
+@@ -2980,6 +2975,10 @@ static int qcom_nandc_probe(struct platform_device *pdev)
+ if (ret)
+ goto err_aon_clk;
+
++ ret = qcom_nandc_alloc(nandc);
++ if (ret)
++ goto err_nandc_alloc;
++
+ ret = qcom_nandc_setup(nandc);
+ if (ret)
+ goto err_setup;
+@@ -2991,15 +2990,14 @@ static int qcom_nandc_probe(struct platform_device *pdev)
+ return 0;
+
+ err_setup:
++ qcom_nandc_unalloc(nandc);
++err_nandc_alloc:
+ clk_disable_unprepare(nandc->aon_clk);
+ err_aon_clk:
+ clk_disable_unprepare(nandc->core_clk);
+ err_core_clk:
+- qcom_nandc_unalloc(nandc);
+-err_nandc_alloc:
+ dma_unmap_resource(dev, res->start, resource_size(res),
+ DMA_BIDIRECTIONAL, 0);
+-
+ return ret;
+ }
+
+--
+2.34.1
+
--- /dev/null
+From afaf47295666b5763ba9bf1bf47b591cbc36f134 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 15 Feb 2022 18:05:18 -0500
+Subject: NFS: Do not report writeback errors in nfs_getattr()
+
+From: Trond Myklebust <trond.myklebust@hammerspace.com>
+
+[ Upstream commit d19e0183a88306acda07f4a01fedeeffe2a2a06b ]
+
+The result of the writeback, whether it is an ENOSPC or an EIO, or
+anything else, does not inhibit the NFS client from reporting the
+correct file timestamps.
+
+Fixes: 79566ef018f5 ("NFS: Getattr doesn't require data sync semantics")
+Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
+Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/nfs/inode.c | 9 +++------
+ 1 file changed, 3 insertions(+), 6 deletions(-)
+
+diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
+index f7929988b83bb..7e398bca952c9 100644
+--- a/fs/nfs/inode.c
++++ b/fs/nfs/inode.c
+@@ -823,12 +823,9 @@ int nfs_getattr(const struct path *path, struct kstat *stat,
+ }
+
+ /* Flush out writes to the server in order to update c/mtime. */
+- if ((request_mask & (STATX_CTIME|STATX_MTIME)) &&
+- S_ISREG(inode->i_mode)) {
+- err = filemap_write_and_wait(inode->i_mapping);
+- if (err)
+- goto out;
+- }
++ if ((request_mask & (STATX_CTIME | STATX_MTIME)) &&
++ S_ISREG(inode->i_mode))
++ filemap_write_and_wait(inode->i_mapping);
+
+ /*
+ * We may force a getattr if the user cares about atime.
+--
+2.34.1
+
--- /dev/null
+From e495bc8cd3c94022fe3fc91ca6c8f8e6bb7ee274 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 8 Feb 2021 16:45:49 -0500
+Subject: NFS: Don't set NFS_INO_INVALID_XATTR if there is no xattr cache
+
+From: Trond Myklebust <trond.myklebust@hammerspace.com>
+
+[ Upstream commit 848fdd62399c638e65a1512616acaa5de7d5c5e8 ]
+
+Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
+Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/nfs/inode.c | 14 ++++++++++++++
+ 1 file changed, 14 insertions(+)
+
+diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
+index 21addb78523d2..6e7fd73a264af 100644
+--- a/fs/nfs/inode.c
++++ b/fs/nfs/inode.c
+@@ -195,6 +195,18 @@ bool nfs_check_cache_invalid(struct inode *inode, unsigned long flags)
+ }
+ EXPORT_SYMBOL_GPL(nfs_check_cache_invalid);
+
++#ifdef CONFIG_NFS_V4_2
++static bool nfs_has_xattr_cache(const struct nfs_inode *nfsi)
++{
++ return nfsi->xattr_cache != NULL;
++}
++#else
++static bool nfs_has_xattr_cache(const struct nfs_inode *nfsi)
++{
++ return false;
++}
++#endif
++
+ static void nfs_set_cache_invalid(struct inode *inode, unsigned long flags)
+ {
+ struct nfs_inode *nfsi = NFS_I(inode);
+@@ -210,6 +222,8 @@ static void nfs_set_cache_invalid(struct inode *inode, unsigned long flags)
+ } else if (flags & NFS_INO_REVAL_PAGECACHE)
+ flags |= NFS_INO_INVALID_CHANGE | NFS_INO_INVALID_SIZE;
+
++ if (!nfs_has_xattr_cache(nfsi))
++ flags &= ~NFS_INO_INVALID_XATTR;
+ if (inode->i_mapping->nrpages == 0)
+ flags &= ~(NFS_INO_INVALID_DATA|NFS_INO_DATA_INVAL_DEFER);
+ nfsi->cache_validity |= flags;
+--
+2.34.1
+
--- /dev/null
+From b46ff3921099cb7a9a905a772cc0896c64932e98 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 25 Mar 2021 21:20:32 -0400
+Subject: NFS: Don't set NFS_INO_REVAL_PAGECACHE in the inode cache validity
+
+From: Trond Myklebust <trond.myklebust@hammerspace.com>
+
+[ Upstream commit 36a9346c225270262d9f34e66c91aa1723fa903f ]
+
+It is no longer necessary to preserve the NFS_INO_REVAL_PAGECACHE flag.
+
+Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/nfs/inode.c | 6 ++----
+ fs/nfs/nfs4proc.c | 1 -
+ 2 files changed, 2 insertions(+), 5 deletions(-)
+
+diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
+index 1d2c1add7b7a2..0fdc7cf994a0f 100644
+--- a/fs/nfs/inode.c
++++ b/fs/nfs/inode.c
+@@ -217,11 +217,12 @@ static void nfs_set_cache_invalid(struct inode *inode, unsigned long flags)
+ flags &= ~NFS_INO_INVALID_OTHER;
+ flags &= ~(NFS_INO_INVALID_CHANGE
+ | NFS_INO_INVALID_SIZE
+- | NFS_INO_REVAL_PAGECACHE
+ | NFS_INO_INVALID_XATTR);
+ } else if (flags & NFS_INO_REVAL_PAGECACHE)
+ flags |= NFS_INO_INVALID_CHANGE | NFS_INO_INVALID_SIZE;
+
++ flags &= ~NFS_INO_REVAL_PAGECACHE;
++
+ if (!nfs_has_xattr_cache(nfsi))
+ flags &= ~NFS_INO_INVALID_XATTR;
+ if (inode->i_mapping->nrpages == 0)
+@@ -1904,7 +1905,6 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr)
+ nfsi->cache_validity &= ~(NFS_INO_INVALID_ATTR
+ | NFS_INO_INVALID_ATIME
+ | NFS_INO_REVAL_FORCED
+- | NFS_INO_REVAL_PAGECACHE
+ | NFS_INO_INVALID_BLOCKS);
+
+ /* Do atomic weak cache consistency updates */
+@@ -1942,7 +1942,6 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr)
+ } else {
+ nfsi->cache_validity |= save_cache_validity &
+ (NFS_INO_INVALID_CHANGE
+- | NFS_INO_REVAL_PAGECACHE
+ | NFS_INO_REVAL_FORCED);
+ cache_revalidated = false;
+ }
+@@ -1988,7 +1987,6 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr)
+ } else {
+ nfsi->cache_validity |= save_cache_validity &
+ (NFS_INO_INVALID_SIZE
+- | NFS_INO_REVAL_PAGECACHE
+ | NFS_INO_REVAL_FORCED);
+ cache_revalidated = false;
+ }
+diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
+index 916513c3be8d5..48ed61e5ac0f3 100644
+--- a/fs/nfs/nfs4proc.c
++++ b/fs/nfs/nfs4proc.c
+@@ -1197,7 +1197,6 @@ nfs4_update_changeattr_locked(struct inode *inode,
+ cache_validity |= NFS_INO_INVALID_CTIME | NFS_INO_INVALID_MTIME;
+
+ if (cinfo->atomic && cinfo->before == inode_peek_iversion_raw(inode)) {
+- nfsi->cache_validity &= ~NFS_INO_REVAL_PAGECACHE;
+ nfsi->attrtimeo_timestamp = jiffies;
+ } else {
+ if (S_ISDIR(inode->i_mode)) {
+--
+2.34.1
+
--- /dev/null
+From 1794fa7a1a33cc24c9402dce84f7a59fd38d5707 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 8 Mar 2021 14:42:55 -0500
+Subject: NFS: Fix open coded versions of nfs_set_cache_invalid() in NFSv4
+
+From: Trond Myklebust <trond.myklebust@hammerspace.com>
+
+[ Upstream commit b6f80a2ebb97f184c4679518ac83074598bf9bf4 ]
+
+nfs_set_cache_invalid() has code to handle delegations, and other
+optimisations, so let's use it when appropriate.
+
+Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
+Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/nfs/inode.c | 1 +
+ fs/nfs/nfs42proc.c | 12 +++++++-----
+ fs/nfs/nfs4proc.c | 28 ++++++++++++----------------
+ 3 files changed, 20 insertions(+), 21 deletions(-)
+
+diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
+index 6e7fd73a264af..1d2c1add7b7a2 100644
+--- a/fs/nfs/inode.c
++++ b/fs/nfs/inode.c
+@@ -230,6 +230,7 @@ static void nfs_set_cache_invalid(struct inode *inode, unsigned long flags)
+ if (flags & NFS_INO_INVALID_DATA)
+ nfs_fscache_invalidate(inode);
+ }
++EXPORT_SYMBOL_GPL(nfs_set_cache_invalid);
+
+ /*
+ * Invalidate the local caches
+diff --git a/fs/nfs/nfs42proc.c b/fs/nfs/nfs42proc.c
+index 2587b1b8e2ef7..0bebfb3ec3b68 100644
+--- a/fs/nfs/nfs42proc.c
++++ b/fs/nfs/nfs42proc.c
+@@ -366,13 +366,15 @@ static ssize_t _nfs42_proc_copy(struct file *src,
+ pos_dst >> PAGE_SHIFT,
+ (pos_dst + res->write_res.count - 1) >> PAGE_SHIFT));
+ spin_lock(&dst_inode->i_lock);
+- NFS_I(dst_inode)->cache_validity |= (NFS_INO_REVAL_PAGECACHE |
+- NFS_INO_REVAL_FORCED | NFS_INO_INVALID_SIZE |
+- NFS_INO_INVALID_ATTR | NFS_INO_INVALID_DATA);
++ nfs_set_cache_invalid(
++ dst_inode, NFS_INO_REVAL_PAGECACHE | NFS_INO_REVAL_FORCED |
++ NFS_INO_INVALID_SIZE | NFS_INO_INVALID_ATTR |
++ NFS_INO_INVALID_DATA);
+ spin_unlock(&dst_inode->i_lock);
+ spin_lock(&src_inode->i_lock);
+- NFS_I(src_inode)->cache_validity |= (NFS_INO_REVAL_PAGECACHE |
+- NFS_INO_REVAL_FORCED | NFS_INO_INVALID_ATIME);
++ nfs_set_cache_invalid(src_inode, NFS_INO_REVAL_PAGECACHE |
++ NFS_INO_REVAL_FORCED |
++ NFS_INO_INVALID_ATIME);
+ spin_unlock(&src_inode->i_lock);
+ status = res->write_res.count;
+ out:
+diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
+index d222a980164b7..916513c3be8d5 100644
+--- a/fs/nfs/nfs4proc.c
++++ b/fs/nfs/nfs4proc.c
+@@ -1176,14 +1176,14 @@ int nfs4_call_sync(struct rpc_clnt *clnt,
+ static void
+ nfs4_inc_nlink_locked(struct inode *inode)
+ {
+- NFS_I(inode)->cache_validity |= NFS_INO_INVALID_OTHER;
++ nfs_set_cache_invalid(inode, NFS_INO_INVALID_OTHER);
+ inc_nlink(inode);
+ }
+
+ static void
+ nfs4_dec_nlink_locked(struct inode *inode)
+ {
+- NFS_I(inode)->cache_validity |= NFS_INO_INVALID_OTHER;
++ nfs_set_cache_invalid(inode, NFS_INO_INVALID_OTHER);
+ drop_nlink(inode);
+ }
+
+@@ -1194,35 +1194,31 @@ nfs4_update_changeattr_locked(struct inode *inode,
+ {
+ struct nfs_inode *nfsi = NFS_I(inode);
+
+- nfsi->cache_validity |= NFS_INO_INVALID_CTIME
+- | NFS_INO_INVALID_MTIME
+- | cache_validity;
++ cache_validity |= NFS_INO_INVALID_CTIME | NFS_INO_INVALID_MTIME;
+
+ if (cinfo->atomic && cinfo->before == inode_peek_iversion_raw(inode)) {
+ nfsi->cache_validity &= ~NFS_INO_REVAL_PAGECACHE;
+ nfsi->attrtimeo_timestamp = jiffies;
+ } else {
+ if (S_ISDIR(inode->i_mode)) {
+- nfsi->cache_validity |= NFS_INO_INVALID_DATA;
++ cache_validity |= NFS_INO_INVALID_DATA;
+ nfs_force_lookup_revalidate(inode);
+ } else {
+ if (!NFS_PROTO(inode)->have_delegation(inode,
+ FMODE_READ))
+- nfsi->cache_validity |= NFS_INO_REVAL_PAGECACHE;
++ cache_validity |= NFS_INO_REVAL_PAGECACHE;
+ }
+
+ if (cinfo->before != inode_peek_iversion_raw(inode))
+- nfsi->cache_validity |= NFS_INO_INVALID_ACCESS |
+- NFS_INO_INVALID_ACL |
+- NFS_INO_INVALID_XATTR;
++ cache_validity |= NFS_INO_INVALID_ACCESS |
++ NFS_INO_INVALID_ACL |
++ NFS_INO_INVALID_XATTR;
+ }
+ inode_set_iversion_raw(inode, cinfo->after);
+ nfsi->read_cache_jiffies = timestamp;
+ nfsi->attr_gencount = nfs_inc_attr_generation_counter();
++ nfs_set_cache_invalid(inode, cache_validity);
+ nfsi->cache_validity &= ~NFS_INO_INVALID_CHANGE;
+-
+- if (nfsi->cache_validity & NFS_INO_INVALID_DATA)
+- nfs_fscache_invalidate(inode);
+ }
+
+ void
+@@ -5931,9 +5927,9 @@ static int __nfs4_proc_set_acl(struct inode *inode, const void *buf, size_t bufl
+ * so mark the attribute cache invalid.
+ */
+ spin_lock(&inode->i_lock);
+- NFS_I(inode)->cache_validity |= NFS_INO_INVALID_CHANGE
+- | NFS_INO_INVALID_CTIME
+- | NFS_INO_REVAL_FORCED;
++ nfs_set_cache_invalid(inode, NFS_INO_INVALID_CHANGE |
++ NFS_INO_INVALID_CTIME |
++ NFS_INO_REVAL_FORCED);
+ spin_unlock(&inode->i_lock);
+ nfs_access_zap_cache(inode);
+ nfs_zap_acl_cache(inode);
+--
+2.34.1
+
--- /dev/null
+From cf987c44afab63a144400a8aee796a58a13f0a2a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 8 Feb 2022 13:38:23 -0500
+Subject: NFS: LOOKUP_DIRECTORY is also ok with symlinks
+
+From: Trond Myklebust <trond.myklebust@hammerspace.com>
+
+[ Upstream commit e0caaf75d443e02e55e146fd75fe2efc8aed5540 ]
+
+Commit ac795161c936 (NFSv4: Handle case where the lookup of a directory
+fails) [1], part of Linux since 5.17-rc2, introduced a regression, where
+a symbolic link on an NFS mount to a directory on another NFS does not
+resolve(?) the first time it is accessed:
+
+Reported-by: Paul Menzel <pmenzel@molgen.mpg.de>
+Fixes: ac795161c936 ("NFSv4: Handle case where the lookup of a directory fails")
+Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
+Tested-by: Donald Buczek <buczek@molgen.mpg.de>
+Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/nfs/dir.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
+index 682c7b45d8b71..2ad56ff4752c7 100644
+--- a/fs/nfs/dir.c
++++ b/fs/nfs/dir.c
+@@ -1780,14 +1780,14 @@ int nfs_atomic_open(struct inode *dir, struct dentry *dentry,
+ if (!res) {
+ inode = d_inode(dentry);
+ if ((lookup_flags & LOOKUP_DIRECTORY) && inode &&
+- !S_ISDIR(inode->i_mode))
++ !(S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode)))
+ res = ERR_PTR(-ENOTDIR);
+ else if (inode && S_ISREG(inode->i_mode))
+ res = ERR_PTR(-EOPENSTALE);
+ } else if (!IS_ERR(res)) {
+ inode = d_inode(res);
+ if ((lookup_flags & LOOKUP_DIRECTORY) && inode &&
+- !S_ISDIR(inode->i_mode)) {
++ !(S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode))) {
+ dput(res);
+ res = ERR_PTR(-ENOTDIR);
+ } else if (inode && S_ISREG(inode->i_mode)) {
+--
+2.34.1
+
--- /dev/null
+From 0926c5769c40461d69d9d3d1507b793ed9e62b5b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 8 Feb 2022 12:14:44 -0500
+Subject: NFS: Remove an incorrect revalidation in
+ nfs4_update_changeattr_locked()
+
+From: Trond Myklebust <trond.myklebust@hammerspace.com>
+
+[ Upstream commit 9d047bf68fe8cdb4086deaf4edd119731a9481ed ]
+
+In nfs4_update_changeattr_locked(), we don't need to set the
+NFS_INO_REVAL_PAGECACHE flag, because we already know the value of the
+change attribute, and we're already flagging the size. In fact, this
+forces us to revalidate the change attribute a second time for no good
+reason.
+This extra flag appears to have been introduced as part of the xattr
+feature, when update_changeattr_locked() was converted for use by the
+xattr code.
+
+Fixes: 1b523ca972ed ("nfs: modify update_changeattr to deal with regular files")
+Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
+Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/nfs/nfs4proc.c | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
+index 4c80369e0a837..1e91643970a46 100644
+--- a/fs/nfs/nfs4proc.c
++++ b/fs/nfs/nfs4proc.c
+@@ -1219,8 +1219,7 @@ nfs4_update_changeattr_locked(struct inode *inode,
+ NFS_INO_INVALID_ACCESS | NFS_INO_INVALID_ACL |
+ NFS_INO_INVALID_SIZE | NFS_INO_INVALID_OTHER |
+ NFS_INO_INVALID_BLOCKS | NFS_INO_INVALID_NLINK |
+- NFS_INO_INVALID_MODE | NFS_INO_INVALID_XATTR |
+- NFS_INO_REVAL_PAGECACHE;
++ NFS_INO_INVALID_MODE | NFS_INO_INVALID_XATTR;
+ nfsi->attrtimeo = NFS_MINATTRTIMEO(inode);
+ }
+ nfsi->attrtimeo_timestamp = jiffies;
+--
+2.34.1
+
--- /dev/null
+From bd3871990f502faaa518e3683258db2e8c703ad2 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 26 Mar 2021 11:01:19 -0400
+Subject: NFS: Use information about the change attribute to optimise updates
+
+From: Trond Myklebust <trond.myklebust@hammerspace.com>
+
+[ Upstream commit 6f9be83d07615e6af8838a1d489080b399f42a08 ]
+
+If the NFSv4.2 server supports the 'change_attr_type' attribute, then
+allow the client to optimise its attribute cache update strategy.
+
+Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/nfs/inode.c | 111 ++++++++++++++++++++++++++++++++++++++--------
+ fs/nfs/nfs4proc.c | 20 +++++++--
+ 2 files changed, 110 insertions(+), 21 deletions(-)
+
+diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
+index 0fdc7cf994a0f..f7929988b83bb 100644
+--- a/fs/nfs/inode.c
++++ b/fs/nfs/inode.c
+@@ -1643,25 +1643,20 @@ EXPORT_SYMBOL_GPL(_nfs_display_fhandle);
+ #endif
+
+ /**
+- * nfs_inode_attrs_need_update - check if the inode attributes need updating
+- * @inode: pointer to inode
++ * nfs_inode_attrs_cmp_generic - compare attributes
+ * @fattr: attributes
++ * @inode: pointer to inode
+ *
+ * Attempt to divine whether or not an RPC call reply carrying stale
+ * attributes got scheduled after another call carrying updated ones.
+- *
+- * To do so, the function first assumes that a more recent ctime means
+- * that the attributes in fattr are newer, however it also attempt to
+- * catch the case where ctime either didn't change, or went backwards
+- * (if someone reset the clock on the server) by looking at whether
+- * or not this RPC call was started after the inode was last updated.
+ * Note also the check for wraparound of 'attr_gencount'
+ *
+- * The function returns 'true' if it thinks the attributes in 'fattr' are
+- * more recent than the ones cached in the inode.
+- *
++ * The function returns '1' if it thinks the attributes in @fattr are
++ * more recent than the ones cached in @inode. Otherwise it returns
++ * the value '0'.
+ */
+-static int nfs_inode_attrs_need_update(const struct inode *inode, const struct nfs_fattr *fattr)
++static int nfs_inode_attrs_cmp_generic(const struct nfs_fattr *fattr,
++ const struct inode *inode)
+ {
+ unsigned long attr_gencount = NFS_I(inode)->attr_gencount;
+
+@@ -1669,15 +1664,93 @@ static int nfs_inode_attrs_need_update(const struct inode *inode, const struct n
+ (long)(attr_gencount - nfs_read_attr_generation_counter()) > 0;
+ }
+
+-static int nfs_refresh_inode_locked(struct inode *inode, struct nfs_fattr *fattr)
++/**
++ * nfs_inode_attrs_cmp_monotonic - compare attributes
++ * @fattr: attributes
++ * @inode: pointer to inode
++ *
++ * Attempt to divine whether or not an RPC call reply carrying stale
++ * attributes got scheduled after another call carrying updated ones.
++ *
++ * We assume that the server observes monotonic semantics for
++ * the change attribute, so a larger value means that the attributes in
++ * @fattr are more recent, in which case the function returns the
++ * value '1'.
++ * A return value of '0' indicates no measurable change
++ * A return value of '-1' means that the attributes in @inode are
++ * more recent.
++ */
++static int nfs_inode_attrs_cmp_monotonic(const struct nfs_fattr *fattr,
++ const struct inode *inode)
+ {
+- int ret;
++ s64 diff = fattr->change_attr - inode_peek_iversion_raw(inode);
++ if (diff > 0)
++ return 1;
++ return diff == 0 ? 0 : -1;
++}
++
++/**
++ * nfs_inode_attrs_cmp_strict_monotonic - compare attributes
++ * @fattr: attributes
++ * @inode: pointer to inode
++ *
++ * Attempt to divine whether or not an RPC call reply carrying stale
++ * attributes got scheduled after another call carrying updated ones.
++ *
++ * We assume that the server observes strictly monotonic semantics for
++ * the change attribute, so a larger value means that the attributes in
++ * @fattr are more recent, in which case the function returns the
++ * value '1'.
++ * A return value of '-1' means that the attributes in @inode are
++ * more recent or unchanged.
++ */
++static int nfs_inode_attrs_cmp_strict_monotonic(const struct nfs_fattr *fattr,
++ const struct inode *inode)
++{
++ return nfs_inode_attrs_cmp_monotonic(fattr, inode) > 0 ? 1 : -1;
++}
++
++/**
++ * nfs_inode_attrs_cmp - compare attributes
++ * @fattr: attributes
++ * @inode: pointer to inode
++ *
++ * This function returns '1' if it thinks the attributes in @fattr are
++ * more recent than the ones cached in @inode. It returns '-1' if
++ * the attributes in @inode are more recent than the ones in @fattr,
++ * and it returns 0 if not sure.
++ */
++static int nfs_inode_attrs_cmp(const struct nfs_fattr *fattr,
++ const struct inode *inode)
++{
++ if (nfs_inode_attrs_cmp_generic(fattr, inode) > 0)
++ return 1;
++ switch (NFS_SERVER(inode)->change_attr_type) {
++ case NFS4_CHANGE_TYPE_IS_UNDEFINED:
++ break;
++ case NFS4_CHANGE_TYPE_IS_TIME_METADATA:
++ if (!(fattr->valid & NFS_ATTR_FATTR_CHANGE))
++ break;
++ return nfs_inode_attrs_cmp_monotonic(fattr, inode);
++ default:
++ if (!(fattr->valid & NFS_ATTR_FATTR_CHANGE))
++ break;
++ return nfs_inode_attrs_cmp_strict_monotonic(fattr, inode);
++ }
++ return 0;
++}
++
++static int nfs_refresh_inode_locked(struct inode *inode,
++ struct nfs_fattr *fattr)
++{
++ int attr_cmp = nfs_inode_attrs_cmp(fattr, inode);
++ int ret = 0;
+
+ trace_nfs_refresh_inode_enter(inode);
+
+- if (nfs_inode_attrs_need_update(inode, fattr))
++ if (attr_cmp > 0)
+ ret = nfs_update_inode(inode, fattr);
+- else
++ else if (attr_cmp == 0)
+ ret = nfs_check_inode_attributes(inode, fattr);
+
+ trace_nfs_refresh_inode_exit(inode, ret);
+@@ -1762,11 +1835,13 @@ EXPORT_SYMBOL_GPL(nfs_post_op_update_inode);
+ */
+ int nfs_post_op_update_inode_force_wcc_locked(struct inode *inode, struct nfs_fattr *fattr)
+ {
++ int attr_cmp = nfs_inode_attrs_cmp(fattr, inode);
+ int status;
+
+ /* Don't do a WCC update if these attributes are already stale */
+- if ((fattr->valid & NFS_ATTR_FATTR) == 0 ||
+- !nfs_inode_attrs_need_update(inode, fattr)) {
++ if (attr_cmp < 0)
++ return 0;
++ if ((fattr->valid & NFS_ATTR_FATTR) == 0 || !attr_cmp) {
+ fattr->valid &= ~(NFS_ATTR_FATTR_PRECHANGE
+ | NFS_ATTR_FATTR_PRESIZE
+ | NFS_ATTR_FATTR_PREMTIME
+diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
+index 48ed61e5ac0f3..eda7d7fc84ad0 100644
+--- a/fs/nfs/nfs4proc.c
++++ b/fs/nfs/nfs4proc.c
+@@ -1193,10 +1193,23 @@ nfs4_update_changeattr_locked(struct inode *inode,
+ unsigned long timestamp, unsigned long cache_validity)
+ {
+ struct nfs_inode *nfsi = NFS_I(inode);
++ u64 change_attr = inode_peek_iversion_raw(inode);
+
+ cache_validity |= NFS_INO_INVALID_CTIME | NFS_INO_INVALID_MTIME;
+
+- if (cinfo->atomic && cinfo->before == inode_peek_iversion_raw(inode)) {
++ switch (NFS_SERVER(inode)->change_attr_type) {
++ case NFS4_CHANGE_TYPE_IS_UNDEFINED:
++ break;
++ case NFS4_CHANGE_TYPE_IS_TIME_METADATA:
++ if ((s64)(change_attr - cinfo->after) > 0)
++ goto out;
++ break;
++ default:
++ if ((s64)(change_attr - cinfo->after) >= 0)
++ goto out;
++ }
++
++ if (cinfo->atomic && cinfo->before == change_attr) {
+ nfsi->attrtimeo_timestamp = jiffies;
+ } else {
+ if (S_ISDIR(inode->i_mode)) {
+@@ -1208,7 +1221,7 @@ nfs4_update_changeattr_locked(struct inode *inode,
+ cache_validity |= NFS_INO_REVAL_PAGECACHE;
+ }
+
+- if (cinfo->before != inode_peek_iversion_raw(inode))
++ if (cinfo->before != change_attr)
+ cache_validity |= NFS_INO_INVALID_ACCESS |
+ NFS_INO_INVALID_ACL |
+ NFS_INO_INVALID_XATTR;
+@@ -1216,8 +1229,9 @@ nfs4_update_changeattr_locked(struct inode *inode,
+ inode_set_iversion_raw(inode, cinfo->after);
+ nfsi->read_cache_jiffies = timestamp;
+ nfsi->attr_gencount = nfs_inc_attr_generation_counter();
+- nfs_set_cache_invalid(inode, cache_validity);
+ nfsi->cache_validity &= ~NFS_INO_INVALID_CHANGE;
++out:
++ nfs_set_cache_invalid(inode, cache_validity);
+ }
+
+ void
+--
+2.34.1
+
--- /dev/null
+From 9885d62e392ac7eebd6bf99a30ba00278abf54f9 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 25 Jun 2021 15:49:31 -0400
+Subject: NFSv4: Fix handling of non-atomic change attrbute updates
+
+From: Trond Myklebust <trond.myklebust@hammerspace.com>
+
+[ Upstream commit 20cf7d4ea4ad7d9830b01ff7444f6ac64a727a23 ]
+
+If the change attribute update is declared to be non-atomic by the
+server, or our cached value does not match the server's value before the
+operation was performed, then we should declare the inode cache invalid.
+
+On the other hand, if the change to the directory raced with a lookup or
+getattr which already updated the change attribute, then optimise away
+the revalidation.
+
+Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/nfs/nfs4proc.c | 33 +++++++++++++++------------------
+ 1 file changed, 15 insertions(+), 18 deletions(-)
+
+diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
+index eda7d7fc84ad0..4c80369e0a837 100644
+--- a/fs/nfs/nfs4proc.c
++++ b/fs/nfs/nfs4proc.c
+@@ -1196,12 +1196,12 @@ nfs4_update_changeattr_locked(struct inode *inode,
+ u64 change_attr = inode_peek_iversion_raw(inode);
+
+ cache_validity |= NFS_INO_INVALID_CTIME | NFS_INO_INVALID_MTIME;
++ if (S_ISDIR(inode->i_mode))
++ cache_validity |= NFS_INO_INVALID_DATA;
+
+ switch (NFS_SERVER(inode)->change_attr_type) {
+ case NFS4_CHANGE_TYPE_IS_UNDEFINED:
+- break;
+- case NFS4_CHANGE_TYPE_IS_TIME_METADATA:
+- if ((s64)(change_attr - cinfo->after) > 0)
++ if (cinfo->after == change_attr)
+ goto out;
+ break;
+ default:
+@@ -1209,24 +1209,21 @@ nfs4_update_changeattr_locked(struct inode *inode,
+ goto out;
+ }
+
+- if (cinfo->atomic && cinfo->before == change_attr) {
+- nfsi->attrtimeo_timestamp = jiffies;
+- } else {
+- if (S_ISDIR(inode->i_mode)) {
+- cache_validity |= NFS_INO_INVALID_DATA;
++ inode_set_iversion_raw(inode, cinfo->after);
++ if (!cinfo->atomic || cinfo->before != change_attr) {
++ if (S_ISDIR(inode->i_mode))
+ nfs_force_lookup_revalidate(inode);
+- } else {
+- if (!NFS_PROTO(inode)->have_delegation(inode,
+- FMODE_READ))
+- cache_validity |= NFS_INO_REVAL_PAGECACHE;
+- }
+
+- if (cinfo->before != change_attr)
+- cache_validity |= NFS_INO_INVALID_ACCESS |
+- NFS_INO_INVALID_ACL |
+- NFS_INO_INVALID_XATTR;
++ if (!NFS_PROTO(inode)->have_delegation(inode, FMODE_READ))
++ cache_validity |=
++ NFS_INO_INVALID_ACCESS | NFS_INO_INVALID_ACL |
++ NFS_INO_INVALID_SIZE | NFS_INO_INVALID_OTHER |
++ NFS_INO_INVALID_BLOCKS | NFS_INO_INVALID_NLINK |
++ NFS_INO_INVALID_MODE | NFS_INO_INVALID_XATTR |
++ NFS_INO_REVAL_PAGECACHE;
++ nfsi->attrtimeo = NFS_MINATTRTIMEO(inode);
+ }
+- inode_set_iversion_raw(inode, cinfo->after);
++ nfsi->attrtimeo_timestamp = jiffies;
+ nfsi->read_cache_jiffies = timestamp;
+ nfsi->attr_gencount = nfs_inc_attr_generation_counter();
+ nfsi->cache_validity &= ~NFS_INO_INVALID_CHANGE;
+--
+2.34.1
+
kvm-svm-never-reject-emulation-due-to-smap-errata-for-sev-guests.patch
tee-export-teedev_open-and-teedev_close_context.patch
optee-use-driver-internal-tee_context-for-some-rpc.patch
+mtd-rawnand-qcom-fix-clock-sequencing-in-qcom_nandc_.patch
+mtd-rawnand-brcmnand-fixed-incorrect-sub-page-ecc-st.patch
+drivers-hv-vmbus-fix-memory-leak-in-vmbus_add_channe.patch
+asoc-tas2770-insert-post-reset-delay.patch
+kvm-x86-pmu-refactoring-find_arch_event-to-pmc_perf_.patch
+kvm-x86-pmu-don-t-truncate-the-perfevtseln-msr-when-.patch
+kvm-x86-pmu-use-amd64_raw_event_mask-for-perf_type_r.patch
+nfs-don-t-set-nfs_ino_invalid_xattr-if-there-is-no-x.patch
+nfs-fix-open-coded-versions-of-nfs_set_cache_invalid.patch
+nfs-don-t-set-nfs_ino_reval_pagecache-in-the-inode-c.patch
+nfs-use-information-about-the-change-attribute-to-op.patch
+nfsv4-fix-handling-of-non-atomic-change-attrbute-upd.patch
+nfs-remove-an-incorrect-revalidation-in-nfs4_update_.patch
+nfs-lookup_directory-is-also-ok-with-symlinks.patch
+tty-n_tty-do-not-look-ahead-for-eol-character-past-t.patch
+nfs-do-not-report-writeback-errors-in-nfs_getattr.patch
+block-wbt-fix-negative-inflight-counter-when-remove-.patch
--- /dev/null
+From 60c275cf799ebbbf9a4cbac6aaad301946db5676 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 15 Feb 2022 15:28:00 -0800
+Subject: tty: n_tty: do not look ahead for EOL character past the end of the
+ buffer
+
+From: Linus Torvalds <torvalds@linux-foundation.org>
+
+[ Upstream commit 3593030761630e09200072a4bd06468892c27be3 ]
+
+Daniel Gibson reports that the n_tty code gets line termination wrong in
+very specific cases:
+
+ "If you feed a line with exactly 64 chars + terminating newline, and
+ directly afterwards (without reading) another line into a pseudo
+ terminal, the the first read() on the other side will return the 64
+ char line *without* terminating newline, and the next read() will
+ return the missing terminating newline AND the complete next line (if
+ it fits in the buffer)"
+
+and bisected the behavior to commit 3b830a9c34d5 ("tty: convert
+tty_ldisc_ops 'read()' function to take a kernel pointer").
+
+Now, digging deeper, it turns out that the behavior isn't exactly new:
+what changed in commit 3b830a9c34d5 was that the tty line discipline
+.read() function is now passed an intermediate kernel buffer rather than
+the final user space buffer.
+
+And that intermediate kernel buffer is 64 bytes in size - thus that
+special case with exactly 64 bytes plus terminating newline.
+
+The same problem did exist before, but historically the boundary was not
+the 64-byte chunk, but the user-supplied buffer size, which is obviously
+generally bigger (and potentially bigger than N_TTY_BUF_SIZE, which
+would hide the issue entirely).
+
+The reason is that the n_tty canon_copy_from_read_buf() code would look
+ahead for the EOL character one byte further than it would actually
+copy. It would then decide that it had found the terminator, and unmark
+it as an EOL character - which in turn explains why the next read
+wouldn't then be terminated by it.
+
+Now, the reason it did all this in the first place is related to some
+historical and pretty obscure EOF behavior, see commit ac8f3bf8832a
+("n_tty: Fix poll() after buffer-limited eof push read") and commit
+40d5e0905a03 ("n_tty: Fix EOF push handling").
+
+And the reason for the EOL confusion is that we treat EOF as a special
+EOL condition, with the EOL character being NUL (aka "__DISABLED_CHAR"
+in the kernel sources).
+
+So that EOF look-ahead also affects the normal EOL handling.
+
+This patch just removes the look-ahead that causes problems, because EOL
+is much more critical than the historical "EOF in the middle of a line
+that coincides with the end of the buffer" handling ever was.
+
+Now, it is possible that we should indeed re-introduce the "look at next
+character to see if it's a EOF" behavior, but if so, that should be done
+not at the kernel buffer chunk boundary in canon_copy_from_read_buf(),
+but at a higher level, when we run out of the user buffer.
+
+In particular, the place to do that would be at the top of
+'n_tty_read()', where we check if it's a continuation of a previously
+started read, and there is no more buffer space left, we could decide to
+just eat the __DISABLED_CHAR at that point.
+
+But that would be a separate patch, because I suspect nobody actually
+cares, and I'd like to get a report about it before bothering.
+
+Fixes: 3b830a9c34d5 ("tty: convert tty_ldisc_ops 'read()' function to take a kernel pointer")
+Fixes: ac8f3bf8832a ("n_tty: Fix poll() after buffer-limited eof push read")
+Fixes: 40d5e0905a03 ("n_tty: Fix EOF push handling")
+Link: https://bugzilla.kernel.org/show_bug.cgi?id=215611
+Reported-and-tested-by: Daniel Gibson <metalcaedes@gmail.com>
+Cc: Peter Hurley <peter@hurleysoftware.com>
+Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Cc: Jiri Slaby <jirislaby@kernel.org>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/tty/n_tty.c | 6 ++----
+ 1 file changed, 2 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c
+index 128461bd04bb9..58190135efb7d 100644
+--- a/drivers/tty/n_tty.c
++++ b/drivers/tty/n_tty.c
+@@ -2024,7 +2024,7 @@ static bool canon_copy_from_read_buf(struct tty_struct *tty,
+ return false;
+
+ canon_head = smp_load_acquire(&ldata->canon_head);
+- n = min(*nr + 1, canon_head - ldata->read_tail);
++ n = min(*nr, canon_head - ldata->read_tail);
+
+ tail = ldata->read_tail & (N_TTY_BUF_SIZE - 1);
+ size = min_t(size_t, tail + n, N_TTY_BUF_SIZE);
+@@ -2046,10 +2046,8 @@ static bool canon_copy_from_read_buf(struct tty_struct *tty,
+ n += N_TTY_BUF_SIZE;
+ c = n + found;
+
+- if (!found || read_buf(ldata, eol) != __DISABLED_CHAR) {
+- c = min(*nr, c);
++ if (!found || read_buf(ldata, eol) != __DISABLED_CHAR)
+ n = c;
+- }
+
+ n_tty_trace("%s: eol:%zu found:%d n:%zu c:%zu tail:%zu more:%zu\n",
+ __func__, eol, found, n, c, tail, more);
+--
+2.34.1
+