Loading drivers/net/wireless/ath/wil6210/debug.c +20 −26 Original line number Diff line number Diff line /* * Copyright (c) 2013 Qualcomm Atheros, Inc. * Copyright (c) 2013,2016 Qualcomm Atheros, Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above Loading @@ -19,50 +19,45 @@ void __wil_err(struct wil6210_priv *wil, const char *fmt, ...) { struct net_device *ndev = wil_to_ndev(wil); struct va_format vaf = { .fmt = fmt, }; struct va_format vaf; va_list args; va_start(args, fmt); vaf.fmt = fmt; vaf.va = &args; netdev_err(ndev, "%pV", &vaf); netdev_err(wil_to_ndev(wil), "%pV", &vaf); trace_wil6210_log_err(&vaf); va_end(args); } void __wil_info(struct wil6210_priv *wil, const char *fmt, ...) { struct net_device *ndev = wil_to_ndev(wil); struct va_format vaf = { .fmt = fmt, }; struct va_format vaf; va_list args; va_start(args, fmt); vaf.fmt = fmt; vaf.va = &args; netdev_info(ndev, "%pV", &vaf); netdev_info(wil_to_ndev(wil), "%pV", &vaf); trace_wil6210_log_info(&vaf); va_end(args); } void __wil_err_ratelimited(struct wil6210_priv *wil, const char *fmt, ...) { if (net_ratelimit()) { struct net_device *ndev = wil_to_ndev(wil); struct va_format vaf = { .fmt = fmt, }; struct va_format vaf; va_list args; if (!net_ratelimit()) return; va_start(args, fmt); vaf.fmt = fmt; vaf.va = &args; netdev_err(ndev, "%pV", &vaf); netdev_err(wil_to_ndev(wil), "%pV", &vaf); trace_wil6210_log_err(&vaf); va_end(args); } } void wil_dbg_ratelimited(const struct wil6210_priv *wil, const char *fmt, ...) { Loading @@ -82,12 +77,11 @@ void wil_dbg_ratelimited(const struct wil6210_priv *wil, const char *fmt, ...) void wil_dbg_trace(struct wil6210_priv *wil, const char *fmt, ...) { struct va_format vaf = { .fmt = fmt, }; struct va_format vaf; va_list args; va_start(args, fmt); vaf.fmt = fmt; vaf.va = &args; trace_wil6210_log_dbg(&vaf); va_end(args); Loading drivers/net/wireless/ath/wil6210/pcie_bus.c +66 −2 Original line number Diff line number Diff line /* * Copyright (c) 2012-2015 Qualcomm Atheros, Inc. * Copyright (c) 2012-2016 Qualcomm Atheros, Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above Loading @@ -18,13 +18,20 @@ #include <linux/pci.h> #include <linux/moduleparam.h> #include <linux/interrupt.h> #include <linux/suspend.h> #include "wil6210.h" static bool use_msi = true; module_param(use_msi, bool, S_IRUGO); MODULE_PARM_DESC(use_msi, " Use MSI interrupt, default - true"); #ifdef CONFIG_PM #ifdef CONFIG_PM_SLEEP static int wil6210_pm_notify(struct notifier_block *notify_block, unsigned long mode, void *unused); #endif /* CONFIG_PM_SLEEP */ #endif /* CONFIG_PM */ static void wil_set_capabilities(struct wil6210_priv *wil) { Loading Loading @@ -238,6 +245,18 @@ static int wil_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *id) goto bus_disable; } #ifdef CONFIG_PM #ifdef CONFIG_PM_SLEEP wil->pm_notify.notifier_call = wil6210_pm_notify; rc = register_pm_notifier(&wil->pm_notify); if (rc) /* Do not fail the driver initialization, as suspend can * be prevented in a later phase if needed */ wil_err(wil, "register_pm_notifier failed: %d\n", rc); #endif /* CONFIG_PM_SLEEP */ #endif /* CONFIG_PM */ wil6210_debugfs_init(wil); Loading Loading @@ -267,6 +286,12 @@ static void wil_pcie_remove(struct pci_dev *pdev) wil_dbg_misc(wil, "%s()\n", __func__); #ifdef CONFIG_PM #ifdef CONFIG_PM_SLEEP unregister_pm_notifier(&wil->pm_notify); #endif /* CONFIG_PM_SLEEP */ #endif /* CONFIG_PM */ wil6210_debugfs_remove(wil); wil_if_remove(wil); wil_if_pcie_disable(wil); Loading Loading @@ -335,6 +360,45 @@ static int wil6210_resume(struct device *dev, bool is_runtime) return rc; } static int wil6210_pm_notify(struct notifier_block *notify_block, unsigned long mode, void *unused) { struct wil6210_priv *wil = container_of( notify_block, struct wil6210_priv, pm_notify); int rc = 0; enum wil_platform_event evt; wil_dbg_pm(wil, "%s: mode (%ld)\n", __func__, mode); switch (mode) { case PM_HIBERNATION_PREPARE: case PM_SUSPEND_PREPARE: case PM_RESTORE_PREPARE: rc = wil_can_suspend(wil, false); if (rc) break; evt = WIL_PLATFORM_EVT_PRE_SUSPEND; if (wil->platform_ops.notify) rc = wil->platform_ops.notify(wil->platform_handle, evt); break; case PM_POST_SUSPEND: case PM_POST_HIBERNATION: case PM_POST_RESTORE: evt = WIL_PLATFORM_EVT_POST_SUSPEND; if (wil->platform_ops.notify) rc = wil->platform_ops.notify(wil->platform_handle, evt); break; default: wil_dbg_pm(wil, "unhandled notify mode %ld\n", mode); break; } wil_dbg_pm(wil, "notification mode %ld: rc (%d)\n", mode, rc); return rc; } static int wil6210_pm_suspend(struct device *dev) { return wil6210_suspend(dev, false); Loading drivers/net/wireless/ath/wil6210/pm.c +24 −1 Original line number Diff line number Diff line /* * Copyright (c) 2014 Qualcomm Atheros, Inc. * Copyright (c) 2014,2016 Qualcomm Atheros, Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above Loading @@ -24,10 +24,32 @@ int wil_can_suspend(struct wil6210_priv *wil, bool is_runtime) wil_dbg_pm(wil, "%s(%s)\n", __func__, is_runtime ? "runtime" : "system"); if (!netif_running(wil_to_ndev(wil))) { /* can always sleep when down */ wil_dbg_pm(wil, "Interface is down\n"); goto out; } if (test_bit(wil_status_resetting, wil->status)) { wil_dbg_pm(wil, "Delay suspend when resetting\n"); rc = -EBUSY; goto out; } if (wil->recovery_state != fw_recovery_idle) { wil_dbg_pm(wil, "Delay suspend during recovery\n"); rc = -EBUSY; goto out; } /* interface is running */ switch (wdev->iftype) { case NL80211_IFTYPE_MONITOR: case NL80211_IFTYPE_STATION: case NL80211_IFTYPE_P2P_CLIENT: if (test_bit(wil_status_fwconnecting, wil->status)) { wil_dbg_pm(wil, "Delay suspend when connecting\n"); rc = -EBUSY; goto out; } break; /* AP-like interface - can't suspend */ default: Loading @@ -36,6 +58,7 @@ int wil_can_suspend(struct wil6210_priv *wil, bool is_runtime) break; } out: wil_dbg_pm(wil, "%s(%s) => %s (%d)\n", __func__, is_runtime ? "runtime" : "system", rc ? "No" : "Yes", rc); Loading drivers/net/wireless/ath/wil6210/txrx.c +41 −1 Original line number Diff line number Diff line Loading @@ -184,6 +184,13 @@ static void wil_vring_free(struct wil6210_priv *wil, struct vring *vring, &vring->va[vring->swtail].tx; ctx = &vring->ctx[vring->swtail]; if (!ctx) { wil_dbg_txrx(wil, "ctx(%d) was already completed\n", vring->swtail); vring->swtail = wil_vring_next_tail(vring); continue; } *d = *_d; wil_txdesc_unmap(dev, d, ctx); if (ctx->skb) Loading Loading @@ -544,6 +551,12 @@ static int wil_rx_refill(struct wil6210_priv *wil, int count) break; } } /* make sure all writes to descriptors (shared memory) are done before * committing them to HW */ wmb(); wil_w(wil, v->hwtail, v->swtail); return rc; Loading Loading @@ -969,6 +982,13 @@ void wil_vring_fini_tx(struct wil6210_priv *wil, int id) txdata->dot1x_open = false; txdata->enabled = 0; /* no Tx can be in progress or start anew */ spin_unlock_bh(&txdata->lock); /* napi_synchronize waits for completion of the current NAPI but will * not prevent the next NAPI run. * Add a memory barrier to guarantee that txdata->enabled is zeroed * before napi_synchronize so that the next scheduled NAPI will not * handle this vring */ wmb(); /* make sure NAPI won't touch this vring */ if (test_bit(wil_status_napi_en, wil->status)) napi_synchronize(&wil->napi_tx); Loading Loading @@ -1551,6 +1571,13 @@ static int __wil_tx_vring_tso(struct wil6210_priv *wil, struct vring *vring, vring_index, used, used + descs_used); } /* Make sure to advance the head only after descriptor update is done. * This will prevent a race condition where the completion thread * will see the DU bit set from previous run and will handle the * skb before it was completed. */ wmb(); /* advance swhead */ wil_vring_advance_head(vring, descs_used); wil_dbg_txrx(wil, "TSO: Tx swhead %d -> %d\n", swhead, vring->swhead); Loading @@ -1567,7 +1594,7 @@ mem_error: while (descs_used > 0) { struct wil_ctx *ctx; i = (swhead + descs_used) % vring->size; i = (swhead + descs_used - 1) % vring->size; d = (struct vring_tx_desc *)&vring->va[i].tx; _desc = &vring->va[i].tx; *d = *_desc; Loading Loading @@ -1691,6 +1718,13 @@ static int __wil_tx_vring(struct wil6210_priv *wil, struct vring *vring, vring_index, used, used + nr_frags + 1); } /* Make sure to advance the head only after descriptor update is done. * This will prevent a race condition where the completion thread * will see the DU bit set from previous run and will handle the * skb before it was completed. */ wmb(); /* advance swhead */ wil_vring_advance_head(vring, nr_frags + 1); wil_dbg_txrx(wil, "Tx[%2d] swhead %d -> %d\n", vring_index, swhead, Loading Loading @@ -1914,6 +1948,12 @@ int wil_tx_complete(struct wil6210_priv *wil, int ringid) wil_consume_skb(skb, d->dma.error == 0); } memset(ctx, 0, sizeof(*ctx)); /* Make sure the ctx is zeroed before updating the tail * to prevent a case where wil_tx_vring will see * this descriptor as used and handle it before ctx zero * is completed. */ wmb(); /* There is no need to touch HW descriptor: * - ststus bit TX_DMA_STATUS_DU is set by design, * so hardware will not try to process this desc., Loading drivers/net/wireless/ath/wil6210/wil6210.h +5 −0 Original line number Diff line number Diff line Loading @@ -662,6 +662,11 @@ struct wil6210_priv { /* High Access Latency Policy voting */ struct wil_halp halp; #ifdef CONFIG_PM #ifdef CONFIG_PM_SLEEP struct notifier_block pm_notify; #endif /* CONFIG_PM_SLEEP */ #endif /* CONFIG_PM */ }; #define wil_to_wiphy(i) (i->wdev->wiphy) Loading Loading
drivers/net/wireless/ath/wil6210/debug.c +20 −26 Original line number Diff line number Diff line /* * Copyright (c) 2013 Qualcomm Atheros, Inc. * Copyright (c) 2013,2016 Qualcomm Atheros, Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above Loading @@ -19,50 +19,45 @@ void __wil_err(struct wil6210_priv *wil, const char *fmt, ...) { struct net_device *ndev = wil_to_ndev(wil); struct va_format vaf = { .fmt = fmt, }; struct va_format vaf; va_list args; va_start(args, fmt); vaf.fmt = fmt; vaf.va = &args; netdev_err(ndev, "%pV", &vaf); netdev_err(wil_to_ndev(wil), "%pV", &vaf); trace_wil6210_log_err(&vaf); va_end(args); } void __wil_info(struct wil6210_priv *wil, const char *fmt, ...) { struct net_device *ndev = wil_to_ndev(wil); struct va_format vaf = { .fmt = fmt, }; struct va_format vaf; va_list args; va_start(args, fmt); vaf.fmt = fmt; vaf.va = &args; netdev_info(ndev, "%pV", &vaf); netdev_info(wil_to_ndev(wil), "%pV", &vaf); trace_wil6210_log_info(&vaf); va_end(args); } void __wil_err_ratelimited(struct wil6210_priv *wil, const char *fmt, ...) { if (net_ratelimit()) { struct net_device *ndev = wil_to_ndev(wil); struct va_format vaf = { .fmt = fmt, }; struct va_format vaf; va_list args; if (!net_ratelimit()) return; va_start(args, fmt); vaf.fmt = fmt; vaf.va = &args; netdev_err(ndev, "%pV", &vaf); netdev_err(wil_to_ndev(wil), "%pV", &vaf); trace_wil6210_log_err(&vaf); va_end(args); } } void wil_dbg_ratelimited(const struct wil6210_priv *wil, const char *fmt, ...) { Loading @@ -82,12 +77,11 @@ void wil_dbg_ratelimited(const struct wil6210_priv *wil, const char *fmt, ...) void wil_dbg_trace(struct wil6210_priv *wil, const char *fmt, ...) { struct va_format vaf = { .fmt = fmt, }; struct va_format vaf; va_list args; va_start(args, fmt); vaf.fmt = fmt; vaf.va = &args; trace_wil6210_log_dbg(&vaf); va_end(args); Loading
drivers/net/wireless/ath/wil6210/pcie_bus.c +66 −2 Original line number Diff line number Diff line /* * Copyright (c) 2012-2015 Qualcomm Atheros, Inc. * Copyright (c) 2012-2016 Qualcomm Atheros, Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above Loading @@ -18,13 +18,20 @@ #include <linux/pci.h> #include <linux/moduleparam.h> #include <linux/interrupt.h> #include <linux/suspend.h> #include "wil6210.h" static bool use_msi = true; module_param(use_msi, bool, S_IRUGO); MODULE_PARM_DESC(use_msi, " Use MSI interrupt, default - true"); #ifdef CONFIG_PM #ifdef CONFIG_PM_SLEEP static int wil6210_pm_notify(struct notifier_block *notify_block, unsigned long mode, void *unused); #endif /* CONFIG_PM_SLEEP */ #endif /* CONFIG_PM */ static void wil_set_capabilities(struct wil6210_priv *wil) { Loading Loading @@ -238,6 +245,18 @@ static int wil_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *id) goto bus_disable; } #ifdef CONFIG_PM #ifdef CONFIG_PM_SLEEP wil->pm_notify.notifier_call = wil6210_pm_notify; rc = register_pm_notifier(&wil->pm_notify); if (rc) /* Do not fail the driver initialization, as suspend can * be prevented in a later phase if needed */ wil_err(wil, "register_pm_notifier failed: %d\n", rc); #endif /* CONFIG_PM_SLEEP */ #endif /* CONFIG_PM */ wil6210_debugfs_init(wil); Loading Loading @@ -267,6 +286,12 @@ static void wil_pcie_remove(struct pci_dev *pdev) wil_dbg_misc(wil, "%s()\n", __func__); #ifdef CONFIG_PM #ifdef CONFIG_PM_SLEEP unregister_pm_notifier(&wil->pm_notify); #endif /* CONFIG_PM_SLEEP */ #endif /* CONFIG_PM */ wil6210_debugfs_remove(wil); wil_if_remove(wil); wil_if_pcie_disable(wil); Loading Loading @@ -335,6 +360,45 @@ static int wil6210_resume(struct device *dev, bool is_runtime) return rc; } static int wil6210_pm_notify(struct notifier_block *notify_block, unsigned long mode, void *unused) { struct wil6210_priv *wil = container_of( notify_block, struct wil6210_priv, pm_notify); int rc = 0; enum wil_platform_event evt; wil_dbg_pm(wil, "%s: mode (%ld)\n", __func__, mode); switch (mode) { case PM_HIBERNATION_PREPARE: case PM_SUSPEND_PREPARE: case PM_RESTORE_PREPARE: rc = wil_can_suspend(wil, false); if (rc) break; evt = WIL_PLATFORM_EVT_PRE_SUSPEND; if (wil->platform_ops.notify) rc = wil->platform_ops.notify(wil->platform_handle, evt); break; case PM_POST_SUSPEND: case PM_POST_HIBERNATION: case PM_POST_RESTORE: evt = WIL_PLATFORM_EVT_POST_SUSPEND; if (wil->platform_ops.notify) rc = wil->platform_ops.notify(wil->platform_handle, evt); break; default: wil_dbg_pm(wil, "unhandled notify mode %ld\n", mode); break; } wil_dbg_pm(wil, "notification mode %ld: rc (%d)\n", mode, rc); return rc; } static int wil6210_pm_suspend(struct device *dev) { return wil6210_suspend(dev, false); Loading
drivers/net/wireless/ath/wil6210/pm.c +24 −1 Original line number Diff line number Diff line /* * Copyright (c) 2014 Qualcomm Atheros, Inc. * Copyright (c) 2014,2016 Qualcomm Atheros, Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above Loading @@ -24,10 +24,32 @@ int wil_can_suspend(struct wil6210_priv *wil, bool is_runtime) wil_dbg_pm(wil, "%s(%s)\n", __func__, is_runtime ? "runtime" : "system"); if (!netif_running(wil_to_ndev(wil))) { /* can always sleep when down */ wil_dbg_pm(wil, "Interface is down\n"); goto out; } if (test_bit(wil_status_resetting, wil->status)) { wil_dbg_pm(wil, "Delay suspend when resetting\n"); rc = -EBUSY; goto out; } if (wil->recovery_state != fw_recovery_idle) { wil_dbg_pm(wil, "Delay suspend during recovery\n"); rc = -EBUSY; goto out; } /* interface is running */ switch (wdev->iftype) { case NL80211_IFTYPE_MONITOR: case NL80211_IFTYPE_STATION: case NL80211_IFTYPE_P2P_CLIENT: if (test_bit(wil_status_fwconnecting, wil->status)) { wil_dbg_pm(wil, "Delay suspend when connecting\n"); rc = -EBUSY; goto out; } break; /* AP-like interface - can't suspend */ default: Loading @@ -36,6 +58,7 @@ int wil_can_suspend(struct wil6210_priv *wil, bool is_runtime) break; } out: wil_dbg_pm(wil, "%s(%s) => %s (%d)\n", __func__, is_runtime ? "runtime" : "system", rc ? "No" : "Yes", rc); Loading
drivers/net/wireless/ath/wil6210/txrx.c +41 −1 Original line number Diff line number Diff line Loading @@ -184,6 +184,13 @@ static void wil_vring_free(struct wil6210_priv *wil, struct vring *vring, &vring->va[vring->swtail].tx; ctx = &vring->ctx[vring->swtail]; if (!ctx) { wil_dbg_txrx(wil, "ctx(%d) was already completed\n", vring->swtail); vring->swtail = wil_vring_next_tail(vring); continue; } *d = *_d; wil_txdesc_unmap(dev, d, ctx); if (ctx->skb) Loading Loading @@ -544,6 +551,12 @@ static int wil_rx_refill(struct wil6210_priv *wil, int count) break; } } /* make sure all writes to descriptors (shared memory) are done before * committing them to HW */ wmb(); wil_w(wil, v->hwtail, v->swtail); return rc; Loading Loading @@ -969,6 +982,13 @@ void wil_vring_fini_tx(struct wil6210_priv *wil, int id) txdata->dot1x_open = false; txdata->enabled = 0; /* no Tx can be in progress or start anew */ spin_unlock_bh(&txdata->lock); /* napi_synchronize waits for completion of the current NAPI but will * not prevent the next NAPI run. * Add a memory barrier to guarantee that txdata->enabled is zeroed * before napi_synchronize so that the next scheduled NAPI will not * handle this vring */ wmb(); /* make sure NAPI won't touch this vring */ if (test_bit(wil_status_napi_en, wil->status)) napi_synchronize(&wil->napi_tx); Loading Loading @@ -1551,6 +1571,13 @@ static int __wil_tx_vring_tso(struct wil6210_priv *wil, struct vring *vring, vring_index, used, used + descs_used); } /* Make sure to advance the head only after descriptor update is done. * This will prevent a race condition where the completion thread * will see the DU bit set from previous run and will handle the * skb before it was completed. */ wmb(); /* advance swhead */ wil_vring_advance_head(vring, descs_used); wil_dbg_txrx(wil, "TSO: Tx swhead %d -> %d\n", swhead, vring->swhead); Loading @@ -1567,7 +1594,7 @@ mem_error: while (descs_used > 0) { struct wil_ctx *ctx; i = (swhead + descs_used) % vring->size; i = (swhead + descs_used - 1) % vring->size; d = (struct vring_tx_desc *)&vring->va[i].tx; _desc = &vring->va[i].tx; *d = *_desc; Loading Loading @@ -1691,6 +1718,13 @@ static int __wil_tx_vring(struct wil6210_priv *wil, struct vring *vring, vring_index, used, used + nr_frags + 1); } /* Make sure to advance the head only after descriptor update is done. * This will prevent a race condition where the completion thread * will see the DU bit set from previous run and will handle the * skb before it was completed. */ wmb(); /* advance swhead */ wil_vring_advance_head(vring, nr_frags + 1); wil_dbg_txrx(wil, "Tx[%2d] swhead %d -> %d\n", vring_index, swhead, Loading Loading @@ -1914,6 +1948,12 @@ int wil_tx_complete(struct wil6210_priv *wil, int ringid) wil_consume_skb(skb, d->dma.error == 0); } memset(ctx, 0, sizeof(*ctx)); /* Make sure the ctx is zeroed before updating the tail * to prevent a case where wil_tx_vring will see * this descriptor as used and handle it before ctx zero * is completed. */ wmb(); /* There is no need to touch HW descriptor: * - ststus bit TX_DMA_STATUS_DU is set by design, * so hardware will not try to process this desc., Loading
drivers/net/wireless/ath/wil6210/wil6210.h +5 −0 Original line number Diff line number Diff line Loading @@ -662,6 +662,11 @@ struct wil6210_priv { /* High Access Latency Policy voting */ struct wil_halp halp; #ifdef CONFIG_PM #ifdef CONFIG_PM_SLEEP struct notifier_block pm_notify; #endif /* CONFIG_PM_SLEEP */ #endif /* CONFIG_PM */ }; #define wil_to_wiphy(i) (i->wdev->wiphy) Loading