Skip to content

Commit 45a42a3

Browse files
Alex Elderdavem330
authored andcommitted
net: ipa: disable GSI interrupts while suspended
Introduce new functions gsi_suspend() and gsi_resume(), which will disable the GSI interrupt handler after all endpoints are suspended and re-enable it before endpoints are resumed. This will ensure no GSI interrupt handler will fire when the hardware is suspended. Here's a little further explanation. There are seven GSI interrupt types, and most are disabled except when needed. - These two are not used (never enabled): GSI_INTER_EE_CH_CTRL GSI_INTER_EE_EV_CTRL - These two are only used to implement channel and event ring commands, and are only enabled while a command is underway: GSI_CH_CTRL GSI_EV_CTRL - The IEOB interrupt signals I/O completion. It will not fire when a channel is stopped (or "suspended"). GSI_IEOB - This interrupt is used to allocate or halt modem channels, and is only enabled while such a command is underway. GSI_GLOB_EE However it also is used to signal certain errors, and this could occur at any time. - The general interrupt signals general errors, and could occur at any time. GSI_GENERAL The purpose for this change is to ensure no global or general interrupts fire due to errors while the hardware is suspended. We enable the clock on resume, and at that time we can "handle" (at least report) these error conditions. Signed-off-by: Alex Elder <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent b176f95 commit 45a42a3

File tree

3 files changed

+28
-1
lines changed

3 files changed

+28
-1
lines changed

drivers/net/ipa/gsi.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -981,6 +981,18 @@ int gsi_channel_resume(struct gsi *gsi, u32 channel_id)
981981
return __gsi_channel_start(channel, true);
982982
}
983983

984+
/* Prevent all GSI interrupts while suspended */
985+
void gsi_suspend(struct gsi *gsi)
986+
{
987+
disable_irq(gsi->irq);
988+
}
989+
990+
/* Allow all GSI interrupts again when resuming */
991+
void gsi_resume(struct gsi *gsi)
992+
{
993+
enable_irq(gsi->irq);
994+
}
995+
984996
/**
985997
* gsi_channel_tx_queued() - Report queued TX transfers for a channel
986998
* @channel: Channel for which to report

drivers/net/ipa/gsi.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,18 @@ int gsi_channel_stop(struct gsi *gsi, u32 channel_id);
232232
*/
233233
void gsi_channel_reset(struct gsi *gsi, u32 channel_id, bool doorbell);
234234

235+
/**
236+
* gsi_suspend() - Prepare the GSI subsystem for suspend
237+
* @gsi: GSI pointer
238+
*/
239+
void gsi_suspend(struct gsi *gsi);
240+
241+
/**
242+
* gsi_resume() - Resume the GSI subsystem following suspend
243+
* @gsi: GSI pointer
244+
*/
245+
void gsi_resume(struct gsi *gsi);
246+
235247
/**
236248
* gsi_channel_suspend() - Suspend a GSI channel
237249
* @gsi: GSI pointer

drivers/net/ipa/ipa_main.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -892,6 +892,7 @@ static int ipa_suspend(struct device *dev)
892892
if (ipa->setup_complete) {
893893
__clear_bit(IPA_FLAG_RESUMED, ipa->flags);
894894
ipa_endpoint_suspend(ipa);
895+
gsi_suspend(&ipa->gsi);
895896
}
896897

897898
ipa_clock_put(ipa);
@@ -919,8 +920,10 @@ static int ipa_resume(struct device *dev)
919920
ipa_clock_get(ipa);
920921

921922
/* Endpoints aren't usable until setup is complete */
922-
if (ipa->setup_complete)
923+
if (ipa->setup_complete) {
924+
gsi_resume(&ipa->gsi);
923925
ipa_endpoint_resume(ipa);
926+
}
924927

925928
return 0;
926929
}

0 commit comments

Comments
 (0)