From a4f48458ca1c02eeedf914ef6a892e047d6b65cc Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Fri, 15 May 2020 15:07:30 -0500 Subject: [PATCH 1/2] net: ipa: don't use noirq suspend/resume callbacks Use the suspend and resume callbacks rather than suspend_noirq and resume_noirq. With IPA v4.2, we use the CHANNEL_STOP command to implement a suspend, and without interrupts enabled, that command won't complete. Signed-off-by: Alex Elder Signed-off-by: David S. Miller --- drivers/net/ipa/ipa_main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/ipa/ipa_main.c b/drivers/net/ipa/ipa_main.c index e0b1fe3c34f9..76d5108b8403 100644 --- a/drivers/net/ipa/ipa_main.c +++ b/drivers/net/ipa/ipa_main.c @@ -933,8 +933,8 @@ static int ipa_resume(struct device *dev) } static const struct dev_pm_ops ipa_pm_ops = { - .suspend_noirq = ipa_suspend, - .resume_noirq = ipa_resume, + .suspend = ipa_suspend, + .resume = ipa_resume, }; static struct platform_driver ipa_driver = { From 195ef57f870070cb02f2f3b99a63d69e8e8f798e Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Fri, 15 May 2020 15:07:31 -0500 Subject: [PATCH 2/2] net: ipa: do not clear interrupt in gsi_channel_start() In gsi_channel_start() there is harmless-looking comment "Clear the channel's event ring interrupt in case it's pending". The intent was to avoid getting spurious interrupts when first bringing up a channel. However we now use channel stop/start to implement suspend and resume, and an interrupt pending at the time we resume is actually something we don't want to ignore. The very first time we bring up the channel we do not expect an interrupt to be pending, and even if it were, the effect would simply be to schedule NAPI on that channel, which would find nothing to do, which is not a problem. Stop clearing any pending IEOB interrupt in gsi_channel_start(). That leaves one caller of the trivial function gsi_isr_ieob_clear(). Get rid of that function and just open-code it in gsi_isr_ieob() instead. This fixes a problem where suspend/resume IPA v4.2 would get stuck when resuming after a suspend. Signed-off-by: Alex Elder Signed-off-by: David S. Miller --- drivers/net/ipa/gsi.c | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/drivers/net/ipa/gsi.c b/drivers/net/ipa/gsi.c index 66570609c845..d343dc94cb48 100644 --- a/drivers/net/ipa/gsi.c +++ b/drivers/net/ipa/gsi.c @@ -238,11 +238,6 @@ static void gsi_irq_ieob_enable(struct gsi *gsi, u32 evt_ring_id) iowrite32(val, gsi->virt + GSI_CNTXT_SRC_IEOB_IRQ_MSK_OFFSET); } -static void gsi_isr_ieob_clear(struct gsi *gsi, u32 mask) -{ - iowrite32(mask, gsi->virt + GSI_CNTXT_SRC_IEOB_IRQ_CLR_OFFSET); -} - static void gsi_irq_ieob_disable(struct gsi *gsi, u32 evt_ring_id) { u32 val; @@ -777,7 +772,6 @@ static void gsi_channel_deprogram(struct gsi_channel *channel) int gsi_channel_start(struct gsi *gsi, u32 channel_id) { struct gsi_channel *channel = &gsi->channel[channel_id]; - u32 evt_ring_id = channel->evt_ring_id; int ret; mutex_lock(&gsi->mutex); @@ -786,9 +780,6 @@ int gsi_channel_start(struct gsi *gsi, u32 channel_id) mutex_unlock(&gsi->mutex); - /* Clear the channel's event ring interrupt in case it's pending */ - gsi_isr_ieob_clear(gsi, BIT(evt_ring_id)); - gsi_channel_thaw(channel); return ret; @@ -1093,7 +1084,7 @@ static void gsi_isr_ieob(struct gsi *gsi) u32 event_mask; event_mask = ioread32(gsi->virt + GSI_CNTXT_SRC_IEOB_IRQ_OFFSET); - gsi_isr_ieob_clear(gsi, event_mask); + iowrite32(event_mask, gsi->virt + GSI_CNTXT_SRC_IEOB_IRQ_CLR_OFFSET); while (event_mask) { u32 evt_ring_id = __ffs(event_mask);