net: stmmac: Use mutex instead of spinlock
authorThierry Reding <treding@nvidia.com>
Thu, 24 May 2018 14:09:07 +0000 (16:09 +0200)
committerDavid S. Miller <davem@davemloft.net>
Tue, 29 May 2018 02:54:15 +0000 (22:54 -0400)
Some drivers, such as DWC EQOS on Tegra, need to perform operations that
can sleep under this lock (clk_set_rate() in tegra_eqos_fix_speed()) for
proper operation. Since there is no need for this lock to be a spinlock,
convert it to a mutex instead.

Fixes: e6ea2d16fc61 ("net: stmmac: dwc-qos: Add Tegra186 support")
Reported-by: Jon Hunter <jonathanh@nvidia.com>
Signed-off-by: Thierry Reding <treding@nvidia.com>
Tested-by: Bhadram Varka <vbhadram@nvidia.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/stmicro/stmmac/stmmac.h
drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c

index 4d425b1a0c5934dcb1cbba1dd30273beb49fff98..fbfe5dcefa87fe9b17a8896c3e2800d354c12d8e 100644 (file)
@@ -122,7 +122,7 @@ struct stmmac_priv {
        struct net_device *dev;
        struct device *device;
        struct mac_device_info *hw;
-       spinlock_t lock;
+       struct mutex lock;
 
        /* RX Queue */
        struct stmmac_rx_queue rx_queue[MTL_MAX_RX_QUEUES];
index 6d82b3ef5c3b842578fc8d5150a5a7c8008d74ed..5710864fa80903102a82115aaa2bec9ac6d31aba 100644 (file)
@@ -390,9 +390,9 @@ stmmac_ethtool_set_link_ksettings(struct net_device *dev,
                        ADVERTISED_10baseT_Half |
                        ADVERTISED_10baseT_Full);
 
-               spin_lock(&priv->lock);
+               mutex_lock(&priv->lock);
                stmmac_pcs_ctrl_ane(priv, priv->ioaddr, 1, priv->hw->ps, 0);
-               spin_unlock(&priv->lock);
+               mutex_unlock(&priv->lock);
 
                return 0;
        }
@@ -632,12 +632,12 @@ static void stmmac_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
 {
        struct stmmac_priv *priv = netdev_priv(dev);
 
-       spin_lock_irq(&priv->lock);
+       mutex_lock(&priv->lock);
        if (device_can_wakeup(priv->device)) {
                wol->supported = WAKE_MAGIC | WAKE_UCAST;
                wol->wolopts = priv->wolopts;
        }
-       spin_unlock_irq(&priv->lock);
+       mutex_unlock(&priv->lock);
 }
 
 static int stmmac_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
@@ -666,9 +666,9 @@ static int stmmac_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
                disable_irq_wake(priv->wol_irq);
        }
 
-       spin_lock_irq(&priv->lock);
+       mutex_lock(&priv->lock);
        priv->wolopts = wol->wolopts;
-       spin_unlock_irq(&priv->lock);
+       mutex_unlock(&priv->lock);
 
        return 0;
 }
index c32de53a00d3eb26bd436165b2e3eb7c1a40959c..77af85c981db1e8690adf56d14c55ba4e43fc9a6 100644 (file)
@@ -381,7 +381,6 @@ bool stmmac_eee_init(struct stmmac_priv *priv)
 {
        struct net_device *ndev = priv->dev;
        int interface = priv->plat->interface;
-       unsigned long flags;
        bool ret = false;
 
        if ((interface != PHY_INTERFACE_MODE_MII) &&
@@ -408,7 +407,7 @@ bool stmmac_eee_init(struct stmmac_priv *priv)
                         * changed).
                         * In that case the driver disable own timers.
                         */
-                       spin_lock_irqsave(&priv->lock, flags);
+                       mutex_lock(&priv->lock);
                        if (priv->eee_active) {
                                netdev_dbg(priv->dev, "disable EEE\n");
                                del_timer_sync(&priv->eee_ctrl_timer);
@@ -416,11 +415,11 @@ bool stmmac_eee_init(struct stmmac_priv *priv)
                                                tx_lpi_timer);
                        }
                        priv->eee_active = 0;
-                       spin_unlock_irqrestore(&priv->lock, flags);
+                       mutex_unlock(&priv->lock);
                        goto out;
                }
                /* Activate the EEE and start timers */
-               spin_lock_irqsave(&priv->lock, flags);
+               mutex_lock(&priv->lock);
                if (!priv->eee_active) {
                        priv->eee_active = 1;
                        timer_setup(&priv->eee_ctrl_timer,
@@ -435,7 +434,7 @@ bool stmmac_eee_init(struct stmmac_priv *priv)
                stmmac_set_eee_pls(priv, priv->hw, ndev->phydev->link);
 
                ret = true;
-               spin_unlock_irqrestore(&priv->lock, flags);
+               mutex_unlock(&priv->lock);
 
                netdev_dbg(priv->dev, "Energy-Efficient Ethernet initialized\n");
        }
@@ -811,13 +810,12 @@ static void stmmac_adjust_link(struct net_device *dev)
 {
        struct stmmac_priv *priv = netdev_priv(dev);
        struct phy_device *phydev = dev->phydev;
-       unsigned long flags;
        bool new_state = false;
 
        if (!phydev)
                return;
 
-       spin_lock_irqsave(&priv->lock, flags);
+       mutex_lock(&priv->lock);
 
        if (phydev->link) {
                u32 ctrl = readl(priv->ioaddr + MAC_CTRL_REG);
@@ -876,7 +874,7 @@ static void stmmac_adjust_link(struct net_device *dev)
        if (new_state && netif_msg_link(priv))
                phy_print_status(phydev);
 
-       spin_unlock_irqrestore(&priv->lock, flags);
+       mutex_unlock(&priv->lock);
 
        if (phydev->is_pseudo_fixed_link)
                /* Stop PHY layer to call the hook to adjust the link in case
@@ -4275,7 +4273,7 @@ int stmmac_dvr_probe(struct device *device,
                               (8 * priv->plat->rx_queues_to_use));
        }
 
-       spin_lock_init(&priv->lock);
+       mutex_init(&priv->lock);
 
        /* If a specific clk_csr value is passed from the platform
         * this means that the CSR Clock Range selection cannot be
@@ -4359,6 +4357,7 @@ int stmmac_dvr_remove(struct device *dev)
            priv->hw->pcs != STMMAC_PCS_RTBI)
                stmmac_mdio_unregister(ndev);
        destroy_workqueue(priv->wq);
+       mutex_destroy(&priv->lock);
        free_netdev(ndev);
 
        return 0;
@@ -4376,7 +4375,6 @@ int stmmac_suspend(struct device *dev)
 {
        struct net_device *ndev = dev_get_drvdata(dev);
        struct stmmac_priv *priv = netdev_priv(ndev);
-       unsigned long flags;
 
        if (!ndev || !netif_running(ndev))
                return 0;
@@ -4384,7 +4382,7 @@ int stmmac_suspend(struct device *dev)
        if (ndev->phydev)
                phy_stop(ndev->phydev);
 
-       spin_lock_irqsave(&priv->lock, flags);
+       mutex_lock(&priv->lock);
 
        netif_device_detach(ndev);
        stmmac_stop_all_queues(priv);
@@ -4405,7 +4403,7 @@ int stmmac_suspend(struct device *dev)
                clk_disable(priv->plat->pclk);
                clk_disable(priv->plat->stmmac_clk);
        }
-       spin_unlock_irqrestore(&priv->lock, flags);
+       mutex_unlock(&priv->lock);
 
        priv->oldlink = false;
        priv->speed = SPEED_UNKNOWN;
@@ -4450,7 +4448,6 @@ int stmmac_resume(struct device *dev)
 {
        struct net_device *ndev = dev_get_drvdata(dev);
        struct stmmac_priv *priv = netdev_priv(ndev);
-       unsigned long flags;
 
        if (!netif_running(ndev))
                return 0;
@@ -4462,9 +4459,9 @@ int stmmac_resume(struct device *dev)
         * from another devices (e.g. serial console).
         */
        if (device_may_wakeup(priv->device)) {
-               spin_lock_irqsave(&priv->lock, flags);
+               mutex_lock(&priv->lock);
                stmmac_pmt(priv, priv->hw, 0);
-               spin_unlock_irqrestore(&priv->lock, flags);
+               mutex_unlock(&priv->lock);
                priv->irq_wake = 0;
        } else {
                pinctrl_pm_select_default_state(priv->device);
@@ -4478,7 +4475,7 @@ int stmmac_resume(struct device *dev)
 
        netif_device_attach(ndev);
 
-       spin_lock_irqsave(&priv->lock, flags);
+       mutex_lock(&priv->lock);
 
        stmmac_reset_queues_param(priv);
 
@@ -4492,7 +4489,7 @@ int stmmac_resume(struct device *dev)
 
        stmmac_start_all_queues(priv);
 
-       spin_unlock_irqrestore(&priv->lock, flags);
+       mutex_unlock(&priv->lock);
 
        if (ndev->phydev)
                phy_start(ndev->phydev);