|
426 | 426 | #define DWC_MMC_RXOCTETCOUNT_GB 0x0784
|
427 | 427 | #define DWC_MMC_RXPACKETCOUNT_GB 0x0780
|
428 | 428 |
|
429 |
| -static int debug = 3; |
| 429 | +static int debug = -1; |
430 | 430 | module_param(debug, int, 0);
|
431 | 431 | MODULE_PARM_DESC(debug, "DWC_eth_qos debug level (0=none,...,16=all)");
|
432 | 432 |
|
@@ -650,6 +650,11 @@ struct net_local {
|
650 | 650 | u32 mmc_tx_counters_mask;
|
651 | 651 |
|
652 | 652 | struct dwceqos_flowcontrol flowcontrol;
|
| 653 | + |
| 654 | + /* Tracks the intermediate state of phy started but hardware |
| 655 | + * init not finished yet. |
| 656 | + */ |
| 657 | + bool phy_defer; |
653 | 658 | };
|
654 | 659 |
|
655 | 660 | static void dwceqos_read_mmc_counters(struct net_local *lp, u32 rx_mask,
|
@@ -901,6 +906,9 @@ static void dwceqos_adjust_link(struct net_device *ndev)
|
901 | 906 | struct phy_device *phydev = lp->phy_dev;
|
902 | 907 | int status_change = 0;
|
903 | 908 |
|
| 909 | + if (lp->phy_defer) |
| 910 | + return; |
| 911 | + |
904 | 912 | if (phydev->link) {
|
905 | 913 | if ((lp->speed != phydev->speed) ||
|
906 | 914 | (lp->duplex != phydev->duplex)) {
|
@@ -1113,15 +1121,15 @@ static int dwceqos_descriptor_init(struct net_local *lp)
|
1113 | 1121 | /* Allocate DMA descriptors */
|
1114 | 1122 | size = DWCEQOS_RX_DCNT * sizeof(struct dwceqos_dma_desc);
|
1115 | 1123 | lp->rx_descs = dma_alloc_coherent(lp->ndev->dev.parent, size,
|
1116 |
| - &lp->rx_descs_addr, 0); |
| 1124 | + &lp->rx_descs_addr, GFP_KERNEL); |
1117 | 1125 | if (!lp->rx_descs)
|
1118 | 1126 | goto err_out;
|
1119 | 1127 | lp->rx_descs_tail_addr = lp->rx_descs_addr +
|
1120 | 1128 | sizeof(struct dwceqos_dma_desc) * DWCEQOS_RX_DCNT;
|
1121 | 1129 |
|
1122 | 1130 | size = DWCEQOS_TX_DCNT * sizeof(struct dwceqos_dma_desc);
|
1123 | 1131 | lp->tx_descs = dma_alloc_coherent(lp->ndev->dev.parent, size,
|
1124 |
| - &lp->tx_descs_addr, 0); |
| 1132 | + &lp->tx_descs_addr, GFP_KERNEL); |
1125 | 1133 | if (!lp->tx_descs)
|
1126 | 1134 | goto err_out;
|
1127 | 1135 | lp->tx_descs_tail_addr = lp->tx_descs_addr +
|
@@ -1635,6 +1643,12 @@ static void dwceqos_init_hw(struct net_local *lp)
|
1635 | 1643 | regval = dwceqos_read(lp, REG_DWCEQOS_MAC_CFG);
|
1636 | 1644 | dwceqos_write(lp, REG_DWCEQOS_MAC_CFG,
|
1637 | 1645 | regval | DWCEQOS_MAC_CFG_TE | DWCEQOS_MAC_CFG_RE);
|
| 1646 | + |
| 1647 | + lp->phy_defer = false; |
| 1648 | + mutex_lock(&lp->phy_dev->lock); |
| 1649 | + phy_read_status(lp->phy_dev); |
| 1650 | + dwceqos_adjust_link(lp->ndev); |
| 1651 | + mutex_unlock(&lp->phy_dev->lock); |
1638 | 1652 | }
|
1639 | 1653 |
|
1640 | 1654 | static void dwceqos_tx_reclaim(unsigned long data)
|
@@ -1880,9 +1894,13 @@ static int dwceqos_open(struct net_device *ndev)
|
1880 | 1894 | }
|
1881 | 1895 | netdev_reset_queue(ndev);
|
1882 | 1896 |
|
| 1897 | + /* The dwceqos reset state machine requires all phy clocks to complete, |
| 1898 | + * hence the unusual init order with phy_start first. |
| 1899 | + */ |
| 1900 | + lp->phy_defer = true; |
| 1901 | + phy_start(lp->phy_dev); |
1883 | 1902 | dwceqos_init_hw(lp);
|
1884 | 1903 | napi_enable(&lp->napi);
|
1885 |
| - phy_start(lp->phy_dev); |
1886 | 1904 |
|
1887 | 1905 | netif_start_queue(ndev);
|
1888 | 1906 | tasklet_enable(&lp->tx_bdreclaim_tasklet);
|
@@ -1915,18 +1933,19 @@ static int dwceqos_stop(struct net_device *ndev)
|
1915 | 1933 | {
|
1916 | 1934 | struct net_local *lp = netdev_priv(ndev);
|
1917 | 1935 |
|
1918 |
| - phy_stop(lp->phy_dev); |
1919 |
| - |
1920 | 1936 | tasklet_disable(&lp->tx_bdreclaim_tasklet);
|
1921 |
| - netif_stop_queue(ndev); |
1922 | 1937 | napi_disable(&lp->napi);
|
1923 | 1938 |
|
1924 |
| - dwceqos_drain_dma(lp); |
| 1939 | + /* Stop all tx before we drain the tx dma. */ |
| 1940 | + netif_tx_lock_bh(lp->ndev); |
| 1941 | + netif_stop_queue(ndev); |
| 1942 | + netif_tx_unlock_bh(lp->ndev); |
1925 | 1943 |
|
1926 |
| - netif_tx_lock(lp->ndev); |
| 1944 | + dwceqos_drain_dma(lp); |
1927 | 1945 | dwceqos_reset_hw(lp);
|
| 1946 | + phy_stop(lp->phy_dev); |
| 1947 | + |
1928 | 1948 | dwceqos_descriptor_free(lp);
|
1929 |
| - netif_tx_unlock(lp->ndev); |
1930 | 1949 |
|
1931 | 1950 | return 0;
|
1932 | 1951 | }
|
@@ -2178,12 +2197,10 @@ static int dwceqos_start_xmit(struct sk_buff *skb, struct net_device *ndev)
|
2178 | 2197 | ((trans.initial_descriptor + trans.nr_descriptors) %
|
2179 | 2198 | DWCEQOS_TX_DCNT));
|
2180 | 2199 |
|
2181 |
| - dwceqos_tx_finalize(skb, lp, &trans); |
2182 |
| - |
2183 |
| - netdev_sent_queue(ndev, skb->len); |
2184 |
| - |
2185 | 2200 | spin_lock_bh(&lp->tx_lock);
|
2186 | 2201 | lp->tx_free -= trans.nr_descriptors;
|
| 2202 | + dwceqos_tx_finalize(skb, lp, &trans); |
| 2203 | + netdev_sent_queue(ndev, skb->len); |
2187 | 2204 | spin_unlock_bh(&lp->tx_lock);
|
2188 | 2205 |
|
2189 | 2206 | ndev->trans_start = jiffies;
|
|
0 commit comments