Skip to content

Commit 60ebd67

Browse files
committed
Merge branch 'ipa-fixes'
Alex Elder says: ==================== net: ipa: prevent shutdown during setup The setup phase of the IPA driver occurs in one of two ways. Normally, it is done directly by the main driver probe function. But some systems (those having a "modem-init" DTS property) don't start setup until an SMP2P interrupt (sent by the modem) arrives. Because it isn't performed by the probe function, setup on "modem-init" systems could be underway at the time a driver remove (or shutdown) request arrives (or vice-versa). This situation can lead to hardware state not being cleaned up properly. This series addresses this problem by having the driver remove function disable the setup interrupt. A consequence of this is that setup will complete if it is underway when the remove function is called. So now, when removing the driver, setup: - will have already completed; - is underway, and will complete before proceeding; or - will not have begun (and will not occur). ==================== Signed-off-by: David S. Miller <[email protected]>
2 parents bd08ee2 + 8afc7e4 commit 60ebd67

File tree

4 files changed

+22
-18
lines changed

4 files changed

+22
-18
lines changed

drivers/net/ipa/ipa_main.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
#include "ipa_reg.h"
2929
#include "ipa_mem.h"
3030
#include "ipa_table.h"
31+
#include "ipa_smp2p.h"
3132
#include "ipa_modem.h"
3233
#include "ipa_uc.h"
3334
#include "ipa_interrupt.h"
@@ -801,6 +802,11 @@ static int ipa_remove(struct platform_device *pdev)
801802
struct device *dev = &pdev->dev;
802803
int ret;
803804

805+
/* Prevent the modem from triggering a call to ipa_setup(). This
806+
* also ensures a modem-initiated setup that's underway completes.
807+
*/
808+
ipa_smp2p_irq_disable_setup(ipa);
809+
804810
ret = pm_runtime_get_sync(dev);
805811
if (WARN_ON(ret < 0))
806812
goto out_power_put;

drivers/net/ipa/ipa_modem.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -339,9 +339,6 @@ int ipa_modem_stop(struct ipa *ipa)
339339
if (state != IPA_MODEM_STATE_RUNNING)
340340
return -EBUSY;
341341

342-
/* Prevent the modem from triggering a call to ipa_setup() */
343-
ipa_smp2p_disable(ipa);
344-
345342
/* Clean up the netdev and endpoints if it was started */
346343
if (netdev) {
347344
struct ipa_priv *priv = netdev_priv(netdev);
@@ -369,6 +366,9 @@ static void ipa_modem_crashed(struct ipa *ipa)
369366
struct device *dev = &ipa->pdev->dev;
370367
int ret;
371368

369+
/* Prevent the modem from triggering a call to ipa_setup() */
370+
ipa_smp2p_irq_disable_setup(ipa);
371+
372372
ret = pm_runtime_get_sync(dev);
373373
if (ret < 0) {
374374
dev_err(dev, "error %d getting power to handle crash\n", ret);

drivers/net/ipa/ipa_smp2p.c

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@
5353
* @setup_ready_irq: IPA interrupt triggered by modem to signal GSI ready
5454
* @power_on: Whether IPA power is on
5555
* @notified: Whether modem has been notified of power state
56-
* @disabled: Whether setup ready interrupt handling is disabled
56+
* @setup_disabled: Whether setup ready interrupt handler is disabled
5757
* @mutex: Mutex protecting ready-interrupt/shutdown interlock
5858
* @panic_notifier: Panic notifier structure
5959
*/
@@ -67,7 +67,7 @@ struct ipa_smp2p {
6767
u32 setup_ready_irq;
6868
bool power_on;
6969
bool notified;
70-
bool disabled;
70+
bool setup_disabled;
7171
struct mutex mutex;
7272
struct notifier_block panic_notifier;
7373
};
@@ -155,11 +155,9 @@ static irqreturn_t ipa_smp2p_modem_setup_ready_isr(int irq, void *dev_id)
155155
struct device *dev;
156156
int ret;
157157

158-
mutex_lock(&smp2p->mutex);
159-
160-
if (smp2p->disabled)
161-
goto out_mutex_unlock;
162-
smp2p->disabled = true; /* If any others arrive, ignore them */
158+
/* Ignore any (spurious) interrupts received after the first */
159+
if (smp2p->ipa->setup_complete)
160+
return IRQ_HANDLED;
163161

164162
/* Power needs to be active for setup */
165163
dev = &smp2p->ipa->pdev->dev;
@@ -176,8 +174,6 @@ static irqreturn_t ipa_smp2p_modem_setup_ready_isr(int irq, void *dev_id)
176174
out_power_put:
177175
pm_runtime_mark_last_busy(dev);
178176
(void)pm_runtime_put_autosuspend(dev);
179-
out_mutex_unlock:
180-
mutex_unlock(&smp2p->mutex);
181177

182178
return IRQ_HANDLED;
183179
}
@@ -313,7 +309,7 @@ void ipa_smp2p_exit(struct ipa *ipa)
313309
kfree(smp2p);
314310
}
315311

316-
void ipa_smp2p_disable(struct ipa *ipa)
312+
void ipa_smp2p_irq_disable_setup(struct ipa *ipa)
317313
{
318314
struct ipa_smp2p *smp2p = ipa->smp2p;
319315

@@ -322,7 +318,10 @@ void ipa_smp2p_disable(struct ipa *ipa)
322318

323319
mutex_lock(&smp2p->mutex);
324320

325-
smp2p->disabled = true;
321+
if (!smp2p->setup_disabled) {
322+
disable_irq(smp2p->setup_ready_irq);
323+
smp2p->setup_disabled = true;
324+
}
326325

327326
mutex_unlock(&smp2p->mutex);
328327
}

drivers/net/ipa/ipa_smp2p.h

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,13 +27,12 @@ int ipa_smp2p_init(struct ipa *ipa, bool modem_init);
2727
void ipa_smp2p_exit(struct ipa *ipa);
2828

2929
/**
30-
* ipa_smp2p_disable() - Prevent "ipa-setup-ready" interrupt handling
30+
* ipa_smp2p_irq_disable_setup() - Disable the "setup ready" interrupt
3131
* @ipa: IPA pointer
3232
*
33-
* Prevent handling of the "setup ready" interrupt from the modem.
34-
* This is used before initiating shutdown of the driver.
33+
* Disable the "ipa-setup-ready" interrupt from the modem.
3534
*/
36-
void ipa_smp2p_disable(struct ipa *ipa);
35+
void ipa_smp2p_irq_disable_setup(struct ipa *ipa);
3736

3837
/**
3938
* ipa_smp2p_notify_reset() - Reset modem notification state

0 commit comments

Comments
 (0)