Skip to content

Commit ebc9780

Browse files
committed
Merge branch 'dwc_eth_qos'
Lars Persson says: ==================== dwc_eth_qos: stability fixes and support for CMA This series has bug fixes for the dwc_eth_qos ethernet driver. Mainly two stability fixes for problems found by Rabin Vincent: - Successive starts and stops of the interface would trigger a DMA reset timeout. - A race condition in the TX DMA handling could trigger a netdev watchdog timeout. The memory allocation was improved to support use of the CMA as DMA allocator backend. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
2 parents 11351bf + cd5e412 commit ebc9780

File tree

1 file changed

+31
-14
lines changed

1 file changed

+31
-14
lines changed

drivers/net/ethernet/synopsys/dwc_eth_qos.c

Lines changed: 31 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -426,7 +426,7 @@
426426
#define DWC_MMC_RXOCTETCOUNT_GB 0x0784
427427
#define DWC_MMC_RXPACKETCOUNT_GB 0x0780
428428

429-
static int debug = 3;
429+
static int debug = -1;
430430
module_param(debug, int, 0);
431431
MODULE_PARM_DESC(debug, "DWC_eth_qos debug level (0=none,...,16=all)");
432432

@@ -650,6 +650,11 @@ struct net_local {
650650
u32 mmc_tx_counters_mask;
651651

652652
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;
653658
};
654659

655660
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)
901906
struct phy_device *phydev = lp->phy_dev;
902907
int status_change = 0;
903908

909+
if (lp->phy_defer)
910+
return;
911+
904912
if (phydev->link) {
905913
if ((lp->speed != phydev->speed) ||
906914
(lp->duplex != phydev->duplex)) {
@@ -1113,15 +1121,15 @@ static int dwceqos_descriptor_init(struct net_local *lp)
11131121
/* Allocate DMA descriptors */
11141122
size = DWCEQOS_RX_DCNT * sizeof(struct dwceqos_dma_desc);
11151123
lp->rx_descs = dma_alloc_coherent(lp->ndev->dev.parent, size,
1116-
&lp->rx_descs_addr, 0);
1124+
&lp->rx_descs_addr, GFP_KERNEL);
11171125
if (!lp->rx_descs)
11181126
goto err_out;
11191127
lp->rx_descs_tail_addr = lp->rx_descs_addr +
11201128
sizeof(struct dwceqos_dma_desc) * DWCEQOS_RX_DCNT;
11211129

11221130
size = DWCEQOS_TX_DCNT * sizeof(struct dwceqos_dma_desc);
11231131
lp->tx_descs = dma_alloc_coherent(lp->ndev->dev.parent, size,
1124-
&lp->tx_descs_addr, 0);
1132+
&lp->tx_descs_addr, GFP_KERNEL);
11251133
if (!lp->tx_descs)
11261134
goto err_out;
11271135
lp->tx_descs_tail_addr = lp->tx_descs_addr +
@@ -1635,6 +1643,12 @@ static void dwceqos_init_hw(struct net_local *lp)
16351643
regval = dwceqos_read(lp, REG_DWCEQOS_MAC_CFG);
16361644
dwceqos_write(lp, REG_DWCEQOS_MAC_CFG,
16371645
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);
16381652
}
16391653

16401654
static void dwceqos_tx_reclaim(unsigned long data)
@@ -1880,9 +1894,13 @@ static int dwceqos_open(struct net_device *ndev)
18801894
}
18811895
netdev_reset_queue(ndev);
18821896

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);
18831902
dwceqos_init_hw(lp);
18841903
napi_enable(&lp->napi);
1885-
phy_start(lp->phy_dev);
18861904

18871905
netif_start_queue(ndev);
18881906
tasklet_enable(&lp->tx_bdreclaim_tasklet);
@@ -1915,18 +1933,19 @@ static int dwceqos_stop(struct net_device *ndev)
19151933
{
19161934
struct net_local *lp = netdev_priv(ndev);
19171935

1918-
phy_stop(lp->phy_dev);
1919-
19201936
tasklet_disable(&lp->tx_bdreclaim_tasklet);
1921-
netif_stop_queue(ndev);
19221937
napi_disable(&lp->napi);
19231938

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);
19251943

1926-
netif_tx_lock(lp->ndev);
1944+
dwceqos_drain_dma(lp);
19271945
dwceqos_reset_hw(lp);
1946+
phy_stop(lp->phy_dev);
1947+
19281948
dwceqos_descriptor_free(lp);
1929-
netif_tx_unlock(lp->ndev);
19301949

19311950
return 0;
19321951
}
@@ -2178,12 +2197,10 @@ static int dwceqos_start_xmit(struct sk_buff *skb, struct net_device *ndev)
21782197
((trans.initial_descriptor + trans.nr_descriptors) %
21792198
DWCEQOS_TX_DCNT));
21802199

2181-
dwceqos_tx_finalize(skb, lp, &trans);
2182-
2183-
netdev_sent_queue(ndev, skb->len);
2184-
21852200
spin_lock_bh(&lp->tx_lock);
21862201
lp->tx_free -= trans.nr_descriptors;
2202+
dwceqos_tx_finalize(skb, lp, &trans);
2203+
netdev_sent_queue(ndev, skb->len);
21872204
spin_unlock_bh(&lp->tx_lock);
21882205

21892206
ndev->trans_start = jiffies;

0 commit comments

Comments
 (0)