diff options
| author | Florian Fainelli <f.fainelli@gmail.com> | 2014-09-22 14:54:43 -0400 |
|---|---|---|
| committer | David S. Miller <davem@davemloft.net> | 2014-09-22 18:38:40 -0400 |
| commit | 4a0c081eff43a11c65dee3ad6c457f7f58bcebe0 (patch) | |
| tree | 055ff5d64bf6a601eb5165c0820fcb18db998121 | |
| parent | 478a010c9235ca92e66cc5058b42e30e33275ad4 (diff) | |
net: bcmgenet: call bcmgenet_dma_teardown in bcmgenet_fini_dma
We should not be manipulaging the DMA_CTRL registers directly by writing
0 to them to disable DMA. This is an operation that needs to be timed to
make sure the DMA engines have been properly stopped since their state
machine stops on a packet boundary, not immediately.
Make sure that tha bcmgenet_fini_dma() calls bcmgenet_dma_teardown() to
ensure a proper DMA engine state. As a result, we need to reorder the
function bodies to resolve the use dependency.
Fixes: 1c1008c793fa ("net: bcmgenet: add main driver file")
Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
| -rw-r--r-- | drivers/net/ethernet/broadcom/genet/bcmgenet.c | 105 |
1 files changed, 52 insertions, 53 deletions
diff --git a/drivers/net/ethernet/broadcom/genet/bcmgenet.c b/drivers/net/ethernet/broadcom/genet/bcmgenet.c index 11a96437862d..5cc9cae21ed5 100644 --- a/drivers/net/ethernet/broadcom/genet/bcmgenet.c +++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.c | |||
| @@ -1744,13 +1744,63 @@ static void bcmgenet_init_multiq(struct net_device *dev) | |||
| 1744 | bcmgenet_tdma_writel(priv, reg, DMA_CTRL); | 1744 | bcmgenet_tdma_writel(priv, reg, DMA_CTRL); |
| 1745 | } | 1745 | } |
| 1746 | 1746 | ||
| 1747 | static int bcmgenet_dma_teardown(struct bcmgenet_priv *priv) | ||
| 1748 | { | ||
| 1749 | int ret = 0; | ||
| 1750 | int timeout = 0; | ||
| 1751 | u32 reg; | ||
| 1752 | |||
| 1753 | /* Disable TDMA to stop add more frames in TX DMA */ | ||
| 1754 | reg = bcmgenet_tdma_readl(priv, DMA_CTRL); | ||
| 1755 | reg &= ~DMA_EN; | ||
| 1756 | bcmgenet_tdma_writel(priv, reg, DMA_CTRL); | ||
| 1757 | |||
| 1758 | /* Check TDMA status register to confirm TDMA is disabled */ | ||
| 1759 | while (timeout++ < DMA_TIMEOUT_VAL) { | ||
| 1760 | reg = bcmgenet_tdma_readl(priv, DMA_STATUS); | ||
| 1761 | if (reg & DMA_DISABLED) | ||
| 1762 | break; | ||
| 1763 | |||
| 1764 | udelay(1); | ||
| 1765 | } | ||
| 1766 | |||
| 1767 | if (timeout == DMA_TIMEOUT_VAL) { | ||
| 1768 | netdev_warn(priv->dev, "Timed out while disabling TX DMA\n"); | ||
| 1769 | ret = -ETIMEDOUT; | ||
| 1770 | } | ||
| 1771 | |||
| 1772 | /* Wait 10ms for packet drain in both tx and rx dma */ | ||
| 1773 | usleep_range(10000, 20000); | ||
| 1774 | |||
| 1775 | /* Disable RDMA */ | ||
| 1776 | reg = bcmgenet_rdma_readl(priv, DMA_CTRL); | ||
| 1777 | reg &= ~DMA_EN; | ||
| 1778 | bcmgenet_rdma_writel(priv, reg, DMA_CTRL); | ||
| 1779 | |||
| 1780 | timeout = 0; | ||
| 1781 | /* Check RDMA status register to confirm RDMA is disabled */ | ||
| 1782 | while (timeout++ < DMA_TIMEOUT_VAL) { | ||
| 1783 | reg = bcmgenet_rdma_readl(priv, DMA_STATUS); | ||
| 1784 | if (reg & DMA_DISABLED) | ||
| 1785 | break; | ||
| 1786 | |||
| 1787 | udelay(1); | ||
| 1788 | } | ||
| 1789 | |||
| 1790 | if (timeout == DMA_TIMEOUT_VAL) { | ||
| 1791 | netdev_warn(priv->dev, "Timed out while disabling RX DMA\n"); | ||
| 1792 | ret = -ETIMEDOUT; | ||
| 1793 | } | ||
| 1794 | |||
| 1795 | return ret; | ||
| 1796 | } | ||
| 1797 | |||
| 1747 | static void bcmgenet_fini_dma(struct bcmgenet_priv *priv) | 1798 | static void bcmgenet_fini_dma(struct bcmgenet_priv *priv) |
| 1748 | { | 1799 | { |
| 1749 | int i; | 1800 | int i; |
| 1750 | 1801 | ||
| 1751 | /* disable DMA */ | 1802 | /* disable DMA */ |
| 1752 | bcmgenet_rdma_writel(priv, 0, DMA_CTRL); | 1803 | bcmgenet_dma_teardown(priv); |
| 1753 | bcmgenet_tdma_writel(priv, 0, DMA_CTRL); | ||
| 1754 | 1804 | ||
| 1755 | for (i = 0; i < priv->num_tx_bds; i++) { | 1805 | for (i = 0; i < priv->num_tx_bds; i++) { |
| 1756 | if (priv->tx_cbs[i].skb != NULL) { | 1806 | if (priv->tx_cbs[i].skb != NULL) { |
| @@ -2109,57 +2159,6 @@ err_clk_disable: | |||
| 2109 | return ret; | 2159 | return ret; |
| 2110 | } | 2160 | } |
| 2111 | 2161 | ||
| 2112 | static int bcmgenet_dma_teardown(struct bcmgenet_priv *priv) | ||
| 2113 | { | ||
| 2114 | int ret = 0; | ||
| 2115 | int timeout = 0; | ||
| 2116 | u32 reg; | ||
| 2117 | |||
| 2118 | /* Disable TDMA to stop add more frames in TX DMA */ | ||
| 2119 | reg = bcmgenet_tdma_readl(priv, DMA_CTRL); | ||
| 2120 | reg &= ~DMA_EN; | ||
| 2121 | bcmgenet_tdma_writel(priv, reg, DMA_CTRL); | ||
| 2122 | |||
| 2123 | /* Check TDMA status register to confirm TDMA is disabled */ | ||
| 2124 | while (timeout++ < DMA_TIMEOUT_VAL) { | ||
| 2125 | reg = bcmgenet_tdma_readl(priv, DMA_STATUS); | ||
| 2126 | if (reg & DMA_DISABLED) | ||
| 2127 | break; | ||
| 2128 | |||
| 2129 | udelay(1); | ||
| 2130 | } | ||
| 2131 | |||
| 2132 | if (timeout == DMA_TIMEOUT_VAL) { | ||
| 2133 | netdev_warn(priv->dev, "Timed out while disabling TX DMA\n"); | ||
| 2134 | ret = -ETIMEDOUT; | ||
| 2135 | } | ||
| 2136 | |||
| 2137 | /* Wait 10ms for packet drain in both tx and rx dma */ | ||
| 2138 | usleep_range(10000, 20000); | ||
| 2139 | |||
| 2140 | /* Disable RDMA */ | ||
| 2141 | reg = bcmgenet_rdma_readl(priv, DMA_CTRL); | ||
| 2142 | reg &= ~DMA_EN; | ||
| 2143 | bcmgenet_rdma_writel(priv, reg, DMA_CTRL); | ||
| 2144 | |||
| 2145 | timeout = 0; | ||
| 2146 | /* Check RDMA status register to confirm RDMA is disabled */ | ||
| 2147 | while (timeout++ < DMA_TIMEOUT_VAL) { | ||
| 2148 | reg = bcmgenet_rdma_readl(priv, DMA_STATUS); | ||
| 2149 | if (reg & DMA_DISABLED) | ||
| 2150 | break; | ||
| 2151 | |||
| 2152 | udelay(1); | ||
| 2153 | } | ||
| 2154 | |||
| 2155 | if (timeout == DMA_TIMEOUT_VAL) { | ||
| 2156 | netdev_warn(priv->dev, "Timed out while disabling RX DMA\n"); | ||
| 2157 | ret = -ETIMEDOUT; | ||
| 2158 | } | ||
| 2159 | |||
| 2160 | return ret; | ||
| 2161 | } | ||
| 2162 | |||
| 2163 | static void bcmgenet_netif_stop(struct net_device *dev) | 2162 | static void bcmgenet_netif_stop(struct net_device *dev) |
| 2164 | { | 2163 | { |
| 2165 | struct bcmgenet_priv *priv = netdev_priv(dev); | 2164 | struct bcmgenet_priv *priv = netdev_priv(dev); |
