]> git.baikalelectronics.ru Git - kernel.git/commitdiff
net: ipa: separate disabling setup from modem stop
authorAlex Elder <elder@linaro.org>
Tue, 23 Nov 2021 00:15:55 +0000 (18:15 -0600)
committerDavid S. Miller <davem@davemloft.net>
Tue, 23 Nov 2021 12:06:40 +0000 (12:06 +0000)
The IPA setup_complete flag is set at the end of ipa_setup(), when
the setup phase of initialization has completed successfully.  This
occurs as part of driver probe processing, or (if "modem-init" is
specified in the DTS file) it is triggered by the "ipa-setup-ready"
SMP2P interrupt generated by the modem.

In the latter case, it's possible for driver shutdown (or remove) to
begin while setup processing is underway, and this can't be allowed.
The problem is that the setup_complete flag is not adequate to signal
that setup is underway.

If setup_complete is set, it will never be un-set, so that case is
not a problem.  But if setup_complete is false, there's a chance
setup is underway.

Because setup is triggered by an interrupt on a "modem-init" system,
there is a simple way to ensure the value of setup_complete is safe
to read.  The threaded handler--if it is executing--will complete as
part of a request to disable the "ipa-modem-ready" interrupt.  This
means that ipa_setup() (which is called from the handler) will run
to completion if it was underway, or will never be called otherwise.

The request to disable the "ipa-setup-ready" interrupt is currently
made within ipa_modem_stop().  Instead, disable the interrupt
outside that function in the two places it's called.  In the case of
ipa_remove(), this ensures the setup_complete flag is safe to read
before we read it.

Rename ipa_smp2p_disable() to be ipa_smp2p_irq_disable_setup(), to be
more specific about its effect.

Fixes: 8b29b90afdb0 ("soc: qcom: ipa: AP/modem communications")
Signed-off-by: Alex Elder <elder@linaro.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ipa/ipa_main.c
drivers/net/ipa/ipa_modem.c
drivers/net/ipa/ipa_smp2p.c
drivers/net/ipa/ipa_smp2p.h

index cdfa98a76e1f4a66a030c7fbdbfd9a29606d6eb7..a448ec198bee1862647b96f34f6346ae30fdc067 100644 (file)
@@ -28,6 +28,7 @@
 #include "ipa_reg.h"
 #include "ipa_mem.h"
 #include "ipa_table.h"
+#include "ipa_smp2p.h"
 #include "ipa_modem.h"
 #include "ipa_uc.h"
 #include "ipa_interrupt.h"
@@ -801,6 +802,11 @@ static int ipa_remove(struct platform_device *pdev)
        struct device *dev = &pdev->dev;
        int ret;
 
+       /* Prevent the modem from triggering a call to ipa_setup().  This
+        * also ensures a modem-initiated setup that's underway completes.
+        */
+       ipa_smp2p_irq_disable_setup(ipa);
+
        ret = pm_runtime_get_sync(dev);
        if (WARN_ON(ret < 0))
                goto out_power_put;
index ad116bcc0580e859ac790ee93e4f36f88ace02a2..d0ab4d70c303b098a2de56011c9d87030a181753 100644 (file)
@@ -339,9 +339,6 @@ int ipa_modem_stop(struct ipa *ipa)
        if (state != IPA_MODEM_STATE_RUNNING)
                return -EBUSY;
 
-       /* Prevent the modem from triggering a call to ipa_setup() */
-       ipa_smp2p_disable(ipa);
-
        /* Clean up the netdev and endpoints if it was started */
        if (netdev) {
                struct ipa_priv *priv = netdev_priv(netdev);
@@ -369,6 +366,9 @@ static void ipa_modem_crashed(struct ipa *ipa)
        struct device *dev = &ipa->pdev->dev;
        int ret;
 
+       /* Prevent the modem from triggering a call to ipa_setup() */
+       ipa_smp2p_irq_disable_setup(ipa);
+
        ret = pm_runtime_get_sync(dev);
        if (ret < 0) {
                dev_err(dev, "error %d getting power to handle crash\n", ret);
index 24bc112a072c6084075ae0925c0c66981ce08640..2112336120391c21b26a6bf5df5cf334deee1ee2 100644 (file)
@@ -309,7 +309,7 @@ void ipa_smp2p_exit(struct ipa *ipa)
        kfree(smp2p);
 }
 
-void ipa_smp2p_disable(struct ipa *ipa)
+void ipa_smp2p_irq_disable_setup(struct ipa *ipa)
 {
        struct ipa_smp2p *smp2p = ipa->smp2p;
 
index 99a9567896388b4d6ceb276146014c6b09cef1e6..59cee31a738365dda7c50649a0f70fa892bc40d9 100644 (file)
@@ -27,13 +27,12 @@ int ipa_smp2p_init(struct ipa *ipa, bool modem_init);
 void ipa_smp2p_exit(struct ipa *ipa);
 
 /**
- * ipa_smp2p_disable() - Prevent "ipa-setup-ready" interrupt handling
+ * ipa_smp2p_irq_disable_setup() - Disable the "setup ready" interrupt
  * @ipa:       IPA pointer
  *
- * Prevent handling of the "setup ready" interrupt from the modem.
- * This is used before initiating shutdown of the driver.
+ * Disable the "ipa-setup-ready" interrupt from the modem.
  */
-void ipa_smp2p_disable(struct ipa *ipa);
+void ipa_smp2p_irq_disable_setup(struct ipa *ipa);
 
 /**
  * ipa_smp2p_notify_reset() - Reset modem notification state