Merge tag 'v4.9.209' of git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux...
[platform/kernel/linux-amlogic.git] / drivers / net / ethernet / stmicro / stmmac / stmmac_main.c
index a2b7c68..12ced97 100644 (file)
 #include <linux/reset.h>
 #include <linux/of_mdio.h>
 #include "dwmac1000.h"
+#ifdef CONFIG_AMLOGIC_ETH_PRIVE
+#include "stmmac_platform.h"
+#endif
+#ifdef CONFIG_DWMAC_MESON
+#include <phy_debug.h>
+#endif
+
+#include <linux/suspend.h>
+#define PM_SUSPEND_PREPARE      0x0003 /* Going to suspend the system */
 
 #define        STMMAC_ALIGN(x)         ALIGN(ALIGN(x, SMP_CACHE_BYTES), 16)
 #define        TSO_MAX_BUFF_SIZE       (SZ_16K - 1)
@@ -121,6 +130,15 @@ static void stmmac_exit_fs(struct net_device *dev);
 
 #define STMMAC_COAL_TIMER(x) (jiffies + usecs_to_jiffies(x))
 
+/*won't be valid unless enable amlogic priv code*/
+#ifdef CONFIG_AMLOGIC_ETH_PRIVE
+#define TX_MONITOR
+#endif
+
+#ifdef TX_MONITOR
+static struct workqueue_struct *moniter_tx_wq;
+static struct delayed_work moniter_tx_worker;
+#endif
 /**
  * stmmac_verify_args - verify the driver parameters.
  * Description: it checks the driver parameters and set a default in case of
@@ -1782,6 +1800,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.
@@ -1871,7 +1909,9 @@ static int stmmac_open(struct net_device *dev)
 
        napi_enable(&priv->napi);
        netif_start_queue(dev);
-
+#ifdef TX_MONITOR
+       queue_delayed_work(moniter_tx_wq, &moniter_tx_worker, HZ);
+#endif
        return 0;
 
 lpiirq_error:
@@ -2714,6 +2754,9 @@ static int stmmac_poll(struct napi_struct *napi, int budget)
  *   netdev structure and arrange for the device to be reset to a sane state
  *   in order to transmit a new packet.
  */
+#ifdef TX_MONITOR
+unsigned int timeout_err;
+#endif
 static void stmmac_tx_timeout(struct net_device *dev)
 {
        struct stmmac_priv *priv = netdev_priv(dev);
@@ -3257,6 +3300,23 @@ static int stmmac_hw_init(struct stmmac_priv *priv)
        return 0;
 }
 
+#ifdef TX_MONITOR
+struct stmmac_priv *priv_monitor;
+static void moniter_tx_handler(struct work_struct *work)
+{
+       if (priv_monitor) {
+               if (timeout_err) {
+                       pr_info("reset eth\n");
+                       stmmac_release(priv_monitor->dev);
+                       stmmac_open(priv_monitor->dev);
+                       timeout_err = 0;
+               }
+       } else {
+               pr_info("device not init yet!\n");
+       }
+//     queue_delayed_work(moniter_tx_wq, &moniter_tx_worker, HZ);
+}
+#endif
 /**
  * stmmac_dvr_probe
  * @device: device pointer
@@ -3275,6 +3335,17 @@ int stmmac_dvr_probe(struct device *device,
        struct net_device *ndev = NULL;
        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)
                return -ENOMEM;
@@ -3422,6 +3493,13 @@ int stmmac_dvr_probe(struct device *device,
                goto error_netdev_register;
        }
 
+#ifdef CONFIG_DWMAC_MESON
+       ret = gmac_create_sysfs(
+               mdiobus_get_phy(priv->mii, priv->plat->phy_addr), priv->ioaddr);
+#endif
+#ifdef TX_MONITOR
+       priv_monitor = priv;
+#endif
        return ret;
 
 error_netdev_register:
@@ -3458,6 +3536,10 @@ int stmmac_dvr_remove(struct device *dev)
        priv->hw->dma->stop_rx(priv->ioaddr);
        priv->hw->dma->stop_tx(priv->ioaddr);
 
+#ifdef CONFIG_DWMAC_MESON
+       gmac_remove_sysfs(priv->phydev);
+#endif
+
        stmmac_set_mac(priv->ioaddr, false);
        netif_carrier_off(ndev);
        unregister_netdev(ndev);
@@ -3499,15 +3581,25 @@ int stmmac_suspend(struct device *dev)
        netif_device_detach(ndev);
        netif_stop_queue(ndev);
 
+       /**
+        *napi_disable call might_sleep,if not irq restore
+        *It will warning bug
+        */
+       spin_unlock_irqrestore(&priv->lock, flags);
        napi_disable(&priv->napi);
+       spin_lock_irqsave(&priv->lock, flags);
 
+#ifdef CONFIG_AMLOGIC_ETH_PRIVE
+       del_timer_sync(&priv->txtimer);
+#endif
        /* Stop TX/RX DMA */
        priv->hw->dma->stop_tx(priv->ioaddr);
        priv->hw->dma->stop_rx(priv->ioaddr);
 
        /* Enable Power down mode by programming the PMT regs */
        if (device_may_wakeup(priv->device)) {
-               priv->hw->mac->pmt(priv->hw, priv->wolopts);
+               //priv->hw->mac->pmt(priv->hw, priv->wolopts);
+               priv->hw->mac->pmt(priv->hw, 0x1 << 5);
                priv->irq_wake = 1;
        } else {
                stmmac_set_mac(priv->ioaddr, false);
@@ -3561,8 +3653,9 @@ int stmmac_resume(struct device *dev)
                        stmmac_mdio_reset(priv->mii);
        }
 
+#ifndef CONFIG_AMLOGIC_ETH_PRIVE
        netif_device_attach(ndev);
-
+#endif
        spin_lock_irqsave(&priv->lock, flags);
 
        priv->cur_rx = 0;
@@ -3576,10 +3669,15 @@ int stmmac_resume(struct device *dev)
 
        stmmac_clear_descriptors(priv);
 
+       spin_unlock_irqrestore(&priv->lock, flags);
        stmmac_hw_setup(ndev, false);
+       spin_lock_irqsave(&priv->lock, flags);
+
        stmmac_init_tx_coalesce(priv);
        stmmac_set_rx_mode(ndev);
-
+#ifdef CONFIG_AMLOGIC_ETH_PRIVE
+       netif_device_attach(ndev);
+#endif
        napi_enable(&priv->napi);
 
        netif_start_queue(ndev);