--- /dev/null
+From 998c0bd2b3715244da7639cc4e6a2062cb79c3f4 Mon Sep 17 00:00:00 2001
+From: Alex Elder <elder@linaro.org>
+Date: Wed, 12 Jan 2022 07:30:12 -0600
+Subject: net: ipa: prevent concurrent replenish
+
+From: Alex Elder <elder@linaro.org>
+
+commit 998c0bd2b3715244da7639cc4e6a2062cb79c3f4 upstream.
+
+We have seen cases where an endpoint RX completion interrupt arrives
+while replenishing for the endpoint is underway. This causes another
+instance of replenishing to begin as part of completing the receive
+transaction. If this occurs it can lead to transaction corruption.
+
+Use a new flag to ensure only one replenish instance for an endpoint
+executes at a time.
+
+Fixes: 84f9bd12d46db ("soc: qcom: ipa: IPA endpoints")
+Signed-off-by: Alex Elder <elder@linaro.org>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/net/ipa/ipa_endpoint.c | 13 +++++++++++++
+ drivers/net/ipa/ipa_endpoint.h | 2 ++
+ 2 files changed, 15 insertions(+)
+
+--- a/drivers/net/ipa/ipa_endpoint.c
++++ b/drivers/net/ipa/ipa_endpoint.c
+@@ -1075,15 +1075,27 @@ static void ipa_endpoint_replenish(struc
+ return;
+ }
+
++ /* If already active, just update the backlog */
++ if (test_and_set_bit(IPA_REPLENISH_ACTIVE, endpoint->replenish_flags)) {
++ if (add_one)
++ atomic_inc(&endpoint->replenish_backlog);
++ return;
++ }
++
+ while (atomic_dec_not_zero(&endpoint->replenish_backlog))
+ if (ipa_endpoint_replenish_one(endpoint))
+ goto try_again_later;
++
++ clear_bit(IPA_REPLENISH_ACTIVE, endpoint->replenish_flags);
++
+ if (add_one)
+ atomic_inc(&endpoint->replenish_backlog);
+
+ return;
+
+ try_again_later:
++ clear_bit(IPA_REPLENISH_ACTIVE, endpoint->replenish_flags);
++
+ /* The last one didn't succeed, so fix the backlog */
+ delta = add_one ? 2 : 1;
+ backlog = atomic_add_return(delta, &endpoint->replenish_backlog);
+@@ -1666,6 +1678,7 @@ static void ipa_endpoint_setup_one(struc
+ * backlog is the same as the maximum outstanding TREs.
+ */
+ clear_bit(IPA_REPLENISH_ENABLED, endpoint->replenish_flags);
++ clear_bit(IPA_REPLENISH_ACTIVE, endpoint->replenish_flags);
+ atomic_set(&endpoint->replenish_saved,
+ gsi_channel_tre_max(gsi, endpoint->channel_id));
+ atomic_set(&endpoint->replenish_backlog, 0);
+--- a/drivers/net/ipa/ipa_endpoint.h
++++ b/drivers/net/ipa/ipa_endpoint.h
+@@ -44,10 +44,12 @@ enum ipa_endpoint_name {
+ * enum ipa_replenish_flag: RX buffer replenish flags
+ *
+ * @IPA_REPLENISH_ENABLED: Whether receive buffer replenishing is enabled
++ * @IPA_REPLENISH_ACTIVE: Whether replenishing is underway
+ * @IPA_REPLENISH_COUNT: Number of defined replenish flags
+ */
+ enum ipa_replenish_flag {
+ IPA_REPLENISH_ENABLED,
++ IPA_REPLENISH_ACTIVE,
+ IPA_REPLENISH_COUNT, /* Number of flags (must be last) */
+ };
+
--- /dev/null
+From c1aaa01dbf4cef95af3e04a5a43986c290e06ea3 Mon Sep 17 00:00:00 2001
+From: Alex Elder <elder@linaro.org>
+Date: Wed, 12 Jan 2022 07:30:11 -0600
+Subject: net: ipa: use a bitmap for endpoint replenish_enabled
+
+From: Alex Elder <elder@linaro.org>
+
+commit c1aaa01dbf4cef95af3e04a5a43986c290e06ea3 upstream.
+
+Define a new replenish_flags bitmap to contain Boolean flags
+associated with an endpoint's replenishing state. Replace the
+replenish_enabled field with a flag in that bitmap. This is to
+prepare for the next patch, which adds another flag.
+
+Signed-off-by: Alex Elder <elder@linaro.org>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/net/ipa/ipa_endpoint.c | 8 ++++----
+ drivers/net/ipa/ipa_endpoint.h | 15 +++++++++++++--
+ 2 files changed, 17 insertions(+), 6 deletions(-)
+
+--- a/drivers/net/ipa/ipa_endpoint.c
++++ b/drivers/net/ipa/ipa_endpoint.c
+@@ -1069,7 +1069,7 @@ static void ipa_endpoint_replenish(struc
+ u32 backlog;
+ int delta;
+
+- if (!endpoint->replenish_enabled) {
++ if (!test_bit(IPA_REPLENISH_ENABLED, endpoint->replenish_flags)) {
+ if (add_one)
+ atomic_inc(&endpoint->replenish_saved);
+ return;
+@@ -1106,7 +1106,7 @@ static void ipa_endpoint_replenish_enabl
+ u32 max_backlog;
+ u32 saved;
+
+- endpoint->replenish_enabled = true;
++ set_bit(IPA_REPLENISH_ENABLED, endpoint->replenish_flags);
+ while ((saved = atomic_xchg(&endpoint->replenish_saved, 0)))
+ atomic_add(saved, &endpoint->replenish_backlog);
+
+@@ -1120,7 +1120,7 @@ static void ipa_endpoint_replenish_disab
+ {
+ u32 backlog;
+
+- endpoint->replenish_enabled = false;
++ clear_bit(IPA_REPLENISH_ENABLED, endpoint->replenish_flags);
+ while ((backlog = atomic_xchg(&endpoint->replenish_backlog, 0)))
+ atomic_add(backlog, &endpoint->replenish_saved);
+ }
+@@ -1665,7 +1665,7 @@ static void ipa_endpoint_setup_one(struc
+ /* RX transactions require a single TRE, so the maximum
+ * backlog is the same as the maximum outstanding TREs.
+ */
+- endpoint->replenish_enabled = false;
++ clear_bit(IPA_REPLENISH_ENABLED, endpoint->replenish_flags);
+ atomic_set(&endpoint->replenish_saved,
+ gsi_channel_tre_max(gsi, endpoint->channel_id));
+ atomic_set(&endpoint->replenish_backlog, 0);
+--- a/drivers/net/ipa/ipa_endpoint.h
++++ b/drivers/net/ipa/ipa_endpoint.h
+@@ -41,6 +41,17 @@ enum ipa_endpoint_name {
+ #define IPA_ENDPOINT_MAX 32 /* Max supported by driver */
+
+ /**
++ * enum ipa_replenish_flag: RX buffer replenish flags
++ *
++ * @IPA_REPLENISH_ENABLED: Whether receive buffer replenishing is enabled
++ * @IPA_REPLENISH_COUNT: Number of defined replenish flags
++ */
++enum ipa_replenish_flag {
++ IPA_REPLENISH_ENABLED,
++ IPA_REPLENISH_COUNT, /* Number of flags (must be last) */
++};
++
++/**
+ * struct ipa_endpoint - IPA endpoint information
+ * @ipa: IPA pointer
+ * @ee_id: Execution environmnent endpoint is associated with
+@@ -51,7 +62,7 @@ enum ipa_endpoint_name {
+ * @trans_tre_max: Maximum number of TRE descriptors per transaction
+ * @evt_ring_id: GSI event ring used by the endpoint
+ * @netdev: Network device pointer, if endpoint uses one
+- * @replenish_enabled: Whether receive buffer replenishing is enabled
++ * @replenish_flags: Replenishing state flags
+ * @replenish_ready: Number of replenish transactions without doorbell
+ * @replenish_saved: Replenish requests held while disabled
+ * @replenish_backlog: Number of buffers needed to fill hardware queue
+@@ -72,7 +83,7 @@ struct ipa_endpoint {
+ struct net_device *netdev;
+
+ /* Receive buffer replenishing for RX endpoints */
+- bool replenish_enabled;
++ DECLARE_BITMAP(replenish_flags, IPA_REPLENISH_COUNT);
+ u32 replenish_ready;
+ atomic_t replenish_saved;
+ atomic_t replenish_backlog;