From c5f0e9f9593602515112ab5c129affa18e2ce501 Mon Sep 17 00:00:00 2001 From: Zhuo Wang Date: Mon, 22 Apr 2019 12:49:34 +0800 Subject: [PATCH] ethernet: fix suspend resume crash [1/1] PD#SWPL-7166 Problem: suspend resume test failed Solution: cancel work queue first Verify: verify on u200 board Change-Id: Ibd1a9587a32edf5583db564d2efe0ff0279d4d10 Signed-off-by: Zhuo Wang Conflicts: drivers/net/ethernet/stmicro/stmmac/stmmac_main.c --- drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 43 ++++++++++++++++++----- 1 file changed, 34 insertions(+), 9 deletions(-) diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index d101263..fea8794 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -58,7 +58,11 @@ #ifdef CONFIG_DWMAC_MESON #include #endif -#define STMMAC_ALIGN(x) __ALIGN_KERNEL(x, SMP_CACHE_BYTES) + +#include +#define PM_SUSPEND_PREPARE 0x0003 /* Going to suspend the system */ + +#define STMMAC_ALIGN(x) __ALIGN_KERNEL(x, SMP_CACHE_BYTES) #define TSO_MAX_BUFF_SIZE (SZ_16K - 1) /* Module parameters */ @@ -126,7 +130,7 @@ static void stmmac_exit_fs(struct net_device *dev); /*won't be valid unless enable amlogic priv code*/ #ifdef CONFIG_AMLOGIC_ETH_PRIVE -#undef TX_MONITOR +#define TX_MONITOR #endif #ifdef TX_MONITOR @@ -1794,6 +1798,26 @@ static int stmmac_hw_setup(struct net_device *dev, bool init_ptp) return 0; } +#ifdef TX_MONITOR +static int suspend_pm_notify(struct notifier_block *nb, + unsigned long mode, void *_unused) +{ + switch (mode) { + case PM_SUSPEND_PREPARE: + cancel_delayed_work_sync(&moniter_tx_worker); + flush_scheduled_work(); + pr_info("receive suspend notify\n"); + break; + default: + break; + } + return 0; +} + +static struct notifier_block suspend_pm_nb = { + .notifier_call = suspend_pm_notify, +}; +#endif /** * stmmac_open - open entry point of the driver * @dev : pointer to the device structure. @@ -2737,9 +2761,6 @@ static void stmmac_tx_timeout(struct net_device *dev) /* Clear Tx resources and restart transmitting again */ stmmac_tx_err(priv); -#ifdef TX_MONITOR - timeout_err = 1; -#endif } /** @@ -3291,7 +3312,7 @@ static void moniter_tx_handler(struct work_struct *work) } else { pr_info("device not init yet!\n"); } - queue_delayed_work(moniter_tx_wq, &moniter_tx_worker, HZ); +// queue_delayed_work(moniter_tx_wq, &moniter_tx_worker, HZ); } #endif /** @@ -3313,8 +3334,15 @@ int stmmac_dvr_probe(struct device *device, struct stmmac_priv *priv; #ifdef TX_MONITOR + int result = 0; moniter_tx_wq = create_singlethread_workqueue("eth_moniter_tx_wq"); INIT_DELAYED_WORK(&moniter_tx_worker, moniter_tx_handler); + /*register pm notify callback*/ + result = register_pm_notifier(&suspend_pm_nb); + if (result) { + unregister_pm_notifier(&suspend_pm_nb); + pr_info("register suspend notifier failed return %d\n", result); + } #endif ndev = alloc_etherdev(sizeof(struct stmmac_priv)); if (!ndev) @@ -3540,9 +3568,6 @@ int stmmac_suspend(struct device *dev) struct stmmac_priv *priv = netdev_priv(ndev); unsigned long flags; -#ifdef TX_MONITOR - cancel_delayed_work_sync(&moniter_tx_worker); -#endif if (!ndev || !netif_running(ndev)) return 0; -- 2.7.4