From ed8018ded106c45d36ef9ee5cb660d70bf53e517 Mon Sep 17 00:00:00 2001 From: Sarada Prasanna Garnayak Date: Wed, 8 Feb 2017 21:22:36 +0530 Subject: [PATCH] qcacmn: optimize the usage of runtime PM spinlock Analyze the critical section of the runtime PM feature and replace the spin_lock_irqsave with spin_lock_bh. Disabling the IRQ and usage of spinlock for runtime PM debugging, logging and warning feature Is not required, remove the usage of spinlock from this context. The runtime PM APIs which is used for the prevent/allow runtime PM suspend /resume can be use spin_lock_bh instead of spin_lock_irqsave. For the runtime PM APIs add check point to identify the IRQ context, If the runtime PM APIs calling from IRQ context report WARN_ON for debugging purpose. CRs-Fixed: 1112447 Change-Id: If06970c6ac610a0128344e8c25a9cdd57b2542a3 --- hif/src/pcie/if_pci.c | 62 +++++++++++++++++++++---------------------- 1 file changed, 30 insertions(+), 32 deletions(-) diff --git a/hif/src/pcie/if_pci.c b/hif/src/pcie/if_pci.c index 830b0ba3515c..1df16203b8bb 100644 --- a/hif/src/pcie/if_pci.c +++ b/hif/src/pcie/if_pci.c @@ -977,7 +977,7 @@ static const char *hif_pm_runtime_state_to_string(uint32_t state) * * Return: void */ -void hif_pci_runtime_pm_warn(struct hif_pci_softc *sc, const char *msg) +static void hif_pci_runtime_pm_warn(struct hif_pci_softc *sc, const char *msg) { struct hif_pm_runtime_lock *ctx; @@ -1038,7 +1038,7 @@ static int hif_pci_pm_runtime_debugfs_show(struct seq_file *s, void *data) "SUSPENDED"}; unsigned int msecs_age; int pm_state = atomic_read(&sc->pm_state); - unsigned long timer_expires, flags; + unsigned long timer_expires; struct hif_pm_runtime_lock *ctx; seq_printf(s, "%30s: %s\n", "Runtime PM state", @@ -1078,9 +1078,9 @@ static int hif_pci_pm_runtime_debugfs_show(struct seq_file *s, void *data) msecs_age / 1000, msecs_age % 1000); } - spin_lock_irqsave(&sc->runtime_lock, flags); + spin_lock_bh(&sc->runtime_lock); if (list_empty(&sc->prevent_suspend_list)) { - spin_unlock_irqrestore(&sc->runtime_lock, flags); + spin_unlock_bh(&sc->runtime_lock); return 0; } @@ -1092,7 +1092,7 @@ static int hif_pci_pm_runtime_debugfs_show(struct seq_file *s, void *data) seq_puts(s, " "); } seq_puts(s, "\n"); - spin_unlock_irqrestore(&sc->runtime_lock, flags); + spin_unlock_bh(&sc->runtime_lock); return 0; } @@ -1253,7 +1253,6 @@ static void hif_pm_runtime_open(struct hif_pci_softc *sc) */ static void hif_pm_runtime_sanitize_on_exit(struct hif_pci_softc *sc) { - unsigned long flags; struct hif_pm_runtime_lock *ctx, *tmp; if (atomic_read(&sc->dev->power.usage_count) != 1) @@ -1261,13 +1260,13 @@ static void hif_pm_runtime_sanitize_on_exit(struct hif_pci_softc *sc) else return; - spin_lock_irqsave(&sc->runtime_lock, flags); + spin_lock_bh(&sc->runtime_lock); list_for_each_entry_safe(ctx, tmp, &sc->prevent_suspend_list, list) { - spin_unlock_irqrestore(&sc->runtime_lock, flags); + spin_unlock_bh(&sc->runtime_lock); hif_runtime_lock_deinit(GET_HIF_OPAQUE_HDL(sc), ctx); - spin_lock_irqsave(&sc->runtime_lock, flags); + spin_lock_bh(&sc->runtime_lock); } - spin_unlock_irqrestore(&sc->runtime_lock, flags); + spin_unlock_bh(&sc->runtime_lock); /* ensure 1 and only 1 usage count so that when the wlan * driver is re-insmodded runtime pm won't be @@ -1293,14 +1292,13 @@ static int __hif_pm_runtime_allow_suspend(struct hif_pci_softc *hif_sc, */ static void hif_pm_runtime_sanitize_on_ssr_exit(struct hif_pci_softc *sc) { - unsigned long flags; struct hif_pm_runtime_lock *ctx, *tmp; - spin_lock_irqsave(&sc->runtime_lock, flags); + spin_lock_bh(&sc->runtime_lock); list_for_each_entry_safe(ctx, tmp, &sc->prevent_suspend_list, list) { __hif_pm_runtime_allow_suspend(sc, ctx); } - spin_unlock_irqrestore(&sc->runtime_lock, flags); + spin_unlock_bh(&sc->runtime_lock); } /** @@ -4058,7 +4056,6 @@ int hif_pm_runtime_put(struct hif_opaque_softc *hif_ctx) struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx); struct hif_pci_softc *sc = HIF_GET_PCI_SOFTC(hif_ctx); int pm_state, usage_count; - unsigned long flags; char *error = NULL; if (NULL == scn) { @@ -4079,9 +4076,7 @@ int hif_pm_runtime_put(struct hif_opaque_softc *hif_ctx) } if (error) { - spin_lock_irqsave(&sc->runtime_lock, flags); hif_pci_runtime_pm_warn(sc, error); - spin_unlock_irqrestore(&sc->runtime_lock, flags); return -EINVAL; } @@ -4210,11 +4205,10 @@ static int __hif_pm_runtime_allow_suspend(struct hif_pci_softc *hif_sc, static void hif_pm_runtime_lock_timeout_fn(unsigned long data) { struct hif_pci_softc *hif_sc = (struct hif_pci_softc *)data; - unsigned long flags; unsigned long timer_expires; struct hif_pm_runtime_lock *context, *temp; - spin_lock_irqsave(&hif_sc->runtime_lock, flags); + spin_lock_bh(&hif_sc->runtime_lock); timer_expires = hif_sc->runtime_timer_expires; @@ -4242,7 +4236,7 @@ static void hif_pm_runtime_lock_timeout_fn(unsigned long data) } } - spin_unlock_irqrestore(&hif_sc->runtime_lock, flags); + spin_unlock_bh(&hif_sc->runtime_lock); } int hif_pm_runtime_prevent_suspend(struct hif_opaque_softc *ol_sc, @@ -4251,7 +4245,6 @@ int hif_pm_runtime_prevent_suspend(struct hif_opaque_softc *ol_sc, struct hif_softc *sc = HIF_GET_SOFTC(ol_sc); struct hif_pci_softc *hif_sc = HIF_GET_PCI_SOFTC(ol_sc); struct hif_pm_runtime_lock *context = data; - unsigned long flags; if (!sc->hif_config.enable_runtime_pm) return 0; @@ -4259,10 +4252,13 @@ int hif_pm_runtime_prevent_suspend(struct hif_opaque_softc *ol_sc, if (!context) return -EINVAL; - spin_lock_irqsave(&hif_sc->runtime_lock, flags); + if (in_irq()) + WARN_ON(1); + + spin_lock_bh(&hif_sc->runtime_lock); context->timeout = 0; __hif_pm_runtime_prevent_suspend(hif_sc, context); - spin_unlock_irqrestore(&hif_sc->runtime_lock, flags); + spin_unlock_bh(&hif_sc->runtime_lock); return 0; } @@ -4274,15 +4270,16 @@ int hif_pm_runtime_allow_suspend(struct hif_opaque_softc *ol_sc, struct hif_pci_softc *hif_sc = HIF_GET_PCI_SOFTC(ol_sc); struct hif_pm_runtime_lock *context = data; - unsigned long flags; - if (!sc->hif_config.enable_runtime_pm) return 0; if (!context) return -EINVAL; - spin_lock_irqsave(&hif_sc->runtime_lock, flags); + if (in_irq()) + WARN_ON(1); + + spin_lock_bh(&hif_sc->runtime_lock); __hif_pm_runtime_allow_suspend(hif_sc, context); @@ -4298,7 +4295,7 @@ int hif_pm_runtime_allow_suspend(struct hif_opaque_softc *ol_sc, hif_sc->runtime_timer_expires = 0; } - spin_unlock_irqrestore(&hif_sc->runtime_lock, flags); + spin_unlock_bh(&hif_sc->runtime_lock); return 0; } @@ -4327,7 +4324,6 @@ int hif_pm_runtime_prevent_suspend_timeout(struct hif_opaque_softc *ol_sc, int ret = 0; unsigned long expires; - unsigned long flags; struct hif_pm_runtime_lock *context = lock; if (hif_is_load_or_unload_in_progress(sc)) { @@ -4347,6 +4343,9 @@ int hif_pm_runtime_prevent_suspend_timeout(struct hif_opaque_softc *ol_sc, if (!context) return -EINVAL; + if (in_irq()) + WARN_ON(1); + /* * Don't use internal timer if the timeout is less than auto suspend * delay. @@ -4360,7 +4359,7 @@ int hif_pm_runtime_prevent_suspend_timeout(struct hif_opaque_softc *ol_sc, expires = jiffies + msecs_to_jiffies(delay); expires += !expires; - spin_lock_irqsave(&hif_sc->runtime_lock, flags); + spin_lock_bh(&hif_sc->runtime_lock); context->timeout = delay; ret = __hif_pm_runtime_prevent_suspend(hif_sc, context); @@ -4374,7 +4373,7 @@ int hif_pm_runtime_prevent_suspend_timeout(struct hif_opaque_softc *ol_sc, hif_sc->runtime_timer_expires = expires; } - spin_unlock_irqrestore(&hif_sc->runtime_lock, flags); + spin_unlock_bh(&hif_sc->runtime_lock); HIF_ERROR("%s: pm_state: %s delay: %dms ret: %d\n", __func__, hif_pm_runtime_state_to_string( @@ -4417,7 +4416,6 @@ struct hif_pm_runtime_lock *hif_runtime_lock_init(const char *name) void hif_runtime_lock_deinit(struct hif_opaque_softc *hif_ctx, struct hif_pm_runtime_lock *data) { - unsigned long flags; struct hif_pm_runtime_lock *context = data; struct hif_pci_softc *sc = HIF_GET_PCI_SOFTC(hif_ctx); @@ -4431,9 +4429,9 @@ void hif_runtime_lock_deinit(struct hif_opaque_softc *hif_ctx, * Ensure to delete the context list entry and reduce the usage count * before freeing the context if context is active. */ - spin_lock_irqsave(&sc->runtime_lock, flags); + spin_lock_bh(&sc->runtime_lock); __hif_pm_runtime_allow_suspend(sc, context); - spin_unlock_irqrestore(&sc->runtime_lock, flags); + spin_unlock_bh(&sc->runtime_lock); qdf_mem_free(context); }