diff options
author | Claudiu Manoil <claudiu.manoil@freescale.com> | 2014-02-17 05:53:18 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2014-02-18 15:03:02 -0500 |
commit | c10650b661b6c43c82c8e91b1d0b9b6adcf7f7dc (patch) | |
tree | 7b245d214fd20ccd0e16ea1a586c1a2168744633 | |
parent | efeddce7ea7c75a53b3084d71db15657a00e94dc (diff) |
gianfar: Add missing graceful reset steps and fixes
gfar_halt() and gfar_start() are responsible for stopping
and starting the DMA and the Rx/Tx hw rings. They implement
the support for the "graceful Rx/Tx stop/start" hw procedure,
and also disable/enable eTSEC's hw interrupts in the process.
The GRS/GTS procedure requires however to have the RQUEUE/TQUEUE
registers cleared first and to wait for a period of time for the
current frame to pass through the interface (around ~10ms for a
jumbo frame). Only then may the GTS and GRS bits from DMACTRL be
set to shut down the DMA, and finally the Tx_EN and Rx_EN bits in
MACCFG1 may be cleared to disable the Tx/Rx blocks.
The same register programming order applies to start the Rx/Tx:
enabling the RQUEUE/TQUEUE *before* clearing the GRS/GTS bits.
This is a HW recommendation in order to avoid a possible
controller "lock up" during graceful reset.
Cleanup the gfar_halt()/start() prototypes, to take priv instead
of ndev as their purpose is to operate on HW. Enabling the
RQUEUE/TQUEUE in the hw_init() is not needed anymore since
that's the job of gfar_start().
Signed-off-by: Claudiu Manoil <claudiu.manoil@freescale.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | drivers/net/ethernet/freescale/gianfar.c | 53 | ||||
-rw-r--r-- | drivers/net/ethernet/freescale/gianfar.h | 3 | ||||
-rw-r--r-- | drivers/net/ethernet/freescale/gianfar_ethtool.c | 5 |
3 files changed, 31 insertions, 30 deletions
diff --git a/drivers/net/ethernet/freescale/gianfar.c b/drivers/net/ethernet/freescale/gianfar.c index 385de8064371..a2977a8df645 100644 --- a/drivers/net/ethernet/freescale/gianfar.c +++ b/drivers/net/ethernet/freescale/gianfar.c | |||
@@ -138,9 +138,7 @@ int gfar_clean_rx_ring(struct gfar_priv_rx_q *rx_queue, int rx_work_limit); | |||
138 | static void gfar_clean_tx_ring(struct gfar_priv_tx_q *tx_queue); | 138 | static void gfar_clean_tx_ring(struct gfar_priv_tx_q *tx_queue); |
139 | static void gfar_process_frame(struct net_device *dev, struct sk_buff *skb, | 139 | static void gfar_process_frame(struct net_device *dev, struct sk_buff *skb, |
140 | int amount_pull, struct napi_struct *napi); | 140 | int amount_pull, struct napi_struct *napi); |
141 | void gfar_halt(struct net_device *dev); | 141 | static void gfar_halt_nodisable(struct gfar_private *priv); |
142 | static void gfar_halt_nodisable(struct net_device *dev); | ||
143 | void gfar_start(struct net_device *dev); | ||
144 | static void gfar_clear_exact_match(struct net_device *dev); | 142 | static void gfar_clear_exact_match(struct net_device *dev); |
145 | static void gfar_set_mac_for_addr(struct net_device *dev, int num, | 143 | static void gfar_set_mac_for_addr(struct net_device *dev, int num, |
146 | const u8 *addr); | 144 | const u8 *addr); |
@@ -1070,10 +1068,6 @@ static void gfar_hw_init(struct gfar_private *priv) | |||
1070 | /* Program the interrupt steering regs, only for MG devices */ | 1068 | /* Program the interrupt steering regs, only for MG devices */ |
1071 | if (priv->num_grps > 1) | 1069 | if (priv->num_grps > 1) |
1072 | gfar_write_isrg(priv); | 1070 | gfar_write_isrg(priv); |
1073 | |||
1074 | /* Enable all Rx/Tx queues after MAC reset */ | ||
1075 | gfar_write(®s->rqueue, priv->rqueue); | ||
1076 | gfar_write(®s->tqueue, priv->tqueue); | ||
1077 | } | 1071 | } |
1078 | 1072 | ||
1079 | static void __init gfar_init_addr_hash_table(struct gfar_private *priv) | 1073 | static void __init gfar_init_addr_hash_table(struct gfar_private *priv) |
@@ -1146,7 +1140,7 @@ static int gfar_probe(struct platform_device *ofdev) | |||
1146 | /* Stop the DMA engine now, in case it was running before | 1140 | /* Stop the DMA engine now, in case it was running before |
1147 | * (The firmware could have used it, and left it running). | 1141 | * (The firmware could have used it, and left it running). |
1148 | */ | 1142 | */ |
1149 | gfar_halt(dev); | 1143 | gfar_halt(priv); |
1150 | 1144 | ||
1151 | gfar_hw_init(priv); | 1145 | gfar_hw_init(priv); |
1152 | 1146 | ||
@@ -1314,7 +1308,7 @@ static int gfar_suspend(struct device *dev) | |||
1314 | lock_tx_qs(priv); | 1308 | lock_tx_qs(priv); |
1315 | lock_rx_qs(priv); | 1309 | lock_rx_qs(priv); |
1316 | 1310 | ||
1317 | gfar_halt_nodisable(ndev); | 1311 | gfar_halt_nodisable(priv); |
1318 | 1312 | ||
1319 | /* Disable Tx, and Rx if wake-on-LAN is disabled. */ | 1313 | /* Disable Tx, and Rx if wake-on-LAN is disabled. */ |
1320 | tempval = gfar_read(®s->maccfg1); | 1314 | tempval = gfar_read(®s->maccfg1); |
@@ -1378,7 +1372,7 @@ static int gfar_resume(struct device *dev) | |||
1378 | tempval &= ~MACCFG2_MPEN; | 1372 | tempval &= ~MACCFG2_MPEN; |
1379 | gfar_write(®s->maccfg2, tempval); | 1373 | gfar_write(®s->maccfg2, tempval); |
1380 | 1374 | ||
1381 | gfar_start(ndev); | 1375 | gfar_start(priv); |
1382 | 1376 | ||
1383 | unlock_rx_qs(priv); | 1377 | unlock_rx_qs(priv); |
1384 | unlock_tx_qs(priv); | 1378 | unlock_tx_qs(priv); |
@@ -1410,7 +1404,7 @@ static int gfar_restore(struct device *dev) | |||
1410 | init_registers(ndev); | 1404 | init_registers(ndev); |
1411 | gfar_set_mac_address(ndev); | 1405 | gfar_set_mac_address(ndev); |
1412 | gfar_init_mac(ndev); | 1406 | gfar_init_mac(ndev); |
1413 | gfar_start(ndev); | 1407 | gfar_start(priv); |
1414 | 1408 | ||
1415 | priv->oldlink = 0; | 1409 | priv->oldlink = 0; |
1416 | priv->oldspeed = 0; | 1410 | priv->oldspeed = 0; |
@@ -1633,9 +1627,8 @@ static int __gfar_is_rx_idle(struct gfar_private *priv) | |||
1633 | } | 1627 | } |
1634 | 1628 | ||
1635 | /* Halt the receive and transmit queues */ | 1629 | /* Halt the receive and transmit queues */ |
1636 | static void gfar_halt_nodisable(struct net_device *dev) | 1630 | static void gfar_halt_nodisable(struct gfar_private *priv) |
1637 | { | 1631 | { |
1638 | struct gfar_private *priv = netdev_priv(dev); | ||
1639 | struct gfar __iomem *regs = priv->gfargrp[0].regs; | 1632 | struct gfar __iomem *regs = priv->gfargrp[0].regs; |
1640 | u32 tempval; | 1633 | u32 tempval; |
1641 | 1634 | ||
@@ -1661,15 +1654,20 @@ static void gfar_halt_nodisable(struct net_device *dev) | |||
1661 | } | 1654 | } |
1662 | 1655 | ||
1663 | /* Halt the receive and transmit queues */ | 1656 | /* Halt the receive and transmit queues */ |
1664 | void gfar_halt(struct net_device *dev) | 1657 | void gfar_halt(struct gfar_private *priv) |
1665 | { | 1658 | { |
1666 | struct gfar_private *priv = netdev_priv(dev); | ||
1667 | struct gfar __iomem *regs = priv->gfargrp[0].regs; | 1659 | struct gfar __iomem *regs = priv->gfargrp[0].regs; |
1668 | u32 tempval; | 1660 | u32 tempval; |
1669 | 1661 | ||
1670 | gfar_halt_nodisable(dev); | 1662 | /* Dissable the Rx/Tx hw queues */ |
1663 | gfar_write(®s->rqueue, 0); | ||
1664 | gfar_write(®s->tqueue, 0); | ||
1671 | 1665 | ||
1672 | /* Disable Rx and Tx */ | 1666 | mdelay(10); |
1667 | |||
1668 | gfar_halt_nodisable(priv); | ||
1669 | |||
1670 | /* Disable Rx/Tx DMA */ | ||
1673 | tempval = gfar_read(®s->maccfg1); | 1671 | tempval = gfar_read(®s->maccfg1); |
1674 | tempval &= ~(MACCFG1_RX_EN | MACCFG1_TX_EN); | 1672 | tempval &= ~(MACCFG1_RX_EN | MACCFG1_TX_EN); |
1675 | gfar_write(®s->maccfg1, tempval); | 1673 | gfar_write(®s->maccfg1, tempval); |
@@ -1696,7 +1694,7 @@ void stop_gfar(struct net_device *dev) | |||
1696 | lock_tx_qs(priv); | 1694 | lock_tx_qs(priv); |
1697 | lock_rx_qs(priv); | 1695 | lock_rx_qs(priv); |
1698 | 1696 | ||
1699 | gfar_halt(dev); | 1697 | gfar_halt(priv); |
1700 | 1698 | ||
1701 | unlock_rx_qs(priv); | 1699 | unlock_rx_qs(priv); |
1702 | unlock_tx_qs(priv); | 1700 | unlock_tx_qs(priv); |
@@ -1801,17 +1799,15 @@ static void free_skb_resources(struct gfar_private *priv) | |||
1801 | priv->tx_queue[0]->tx_bd_dma_base); | 1799 | priv->tx_queue[0]->tx_bd_dma_base); |
1802 | } | 1800 | } |
1803 | 1801 | ||
1804 | void gfar_start(struct net_device *dev) | 1802 | void gfar_start(struct gfar_private *priv) |
1805 | { | 1803 | { |
1806 | struct gfar_private *priv = netdev_priv(dev); | ||
1807 | struct gfar __iomem *regs = priv->gfargrp[0].regs; | 1804 | struct gfar __iomem *regs = priv->gfargrp[0].regs; |
1808 | u32 tempval; | 1805 | u32 tempval; |
1809 | int i = 0; | 1806 | int i = 0; |
1810 | 1807 | ||
1811 | /* Enable Rx and Tx in MACCFG1 */ | 1808 | /* Enable Rx/Tx hw queues */ |
1812 | tempval = gfar_read(®s->maccfg1); | 1809 | gfar_write(®s->rqueue, priv->rqueue); |
1813 | tempval |= (MACCFG1_RX_EN | MACCFG1_TX_EN); | 1810 | gfar_write(®s->tqueue, priv->tqueue); |
1814 | gfar_write(®s->maccfg1, tempval); | ||
1815 | 1811 | ||
1816 | /* Initialize DMACTRL to have WWR and WOP */ | 1812 | /* Initialize DMACTRL to have WWR and WOP */ |
1817 | tempval = gfar_read(®s->dmactrl); | 1813 | tempval = gfar_read(®s->dmactrl); |
@@ -1830,9 +1826,14 @@ void gfar_start(struct net_device *dev) | |||
1830 | gfar_write(®s->rstat, priv->gfargrp[i].rstat); | 1826 | gfar_write(®s->rstat, priv->gfargrp[i].rstat); |
1831 | } | 1827 | } |
1832 | 1828 | ||
1829 | /* Enable Rx/Tx DMA */ | ||
1830 | tempval = gfar_read(®s->maccfg1); | ||
1831 | tempval |= (MACCFG1_RX_EN | MACCFG1_TX_EN); | ||
1832 | gfar_write(®s->maccfg1, tempval); | ||
1833 | |||
1833 | gfar_ints_enable(priv); | 1834 | gfar_ints_enable(priv); |
1834 | 1835 | ||
1835 | dev->trans_start = jiffies; /* prevent tx timeout */ | 1836 | priv->ndev->trans_start = jiffies; /* prevent tx timeout */ |
1836 | } | 1837 | } |
1837 | 1838 | ||
1838 | static void gfar_configure_coalescing(struct gfar_private *priv, | 1839 | static void gfar_configure_coalescing(struct gfar_private *priv, |
@@ -1956,7 +1957,7 @@ int startup_gfar(struct net_device *ndev) | |||
1956 | } | 1957 | } |
1957 | 1958 | ||
1958 | /* Start the controller */ | 1959 | /* Start the controller */ |
1959 | gfar_start(ndev); | 1960 | gfar_start(priv); |
1960 | 1961 | ||
1961 | phy_start(priv->phydev); | 1962 | phy_start(priv->phydev); |
1962 | 1963 | ||
diff --git a/drivers/net/ethernet/freescale/gianfar.h b/drivers/net/ethernet/freescale/gianfar.h index 53e34662b90e..2a59398f8cf0 100644 --- a/drivers/net/ethernet/freescale/gianfar.h +++ b/drivers/net/ethernet/freescale/gianfar.h | |||
@@ -1205,7 +1205,8 @@ void unlock_tx_qs(struct gfar_private *priv); | |||
1205 | irqreturn_t gfar_receive(int irq, void *dev_id); | 1205 | irqreturn_t gfar_receive(int irq, void *dev_id); |
1206 | int startup_gfar(struct net_device *dev); | 1206 | int startup_gfar(struct net_device *dev); |
1207 | void stop_gfar(struct net_device *dev); | 1207 | void stop_gfar(struct net_device *dev); |
1208 | void gfar_halt(struct net_device *dev); | 1208 | void gfar_halt(struct gfar_private *priv); |
1209 | void gfar_start(struct gfar_private *priv); | ||
1209 | void gfar_phy_test(struct mii_bus *bus, struct phy_device *phydev, int enable, | 1210 | void gfar_phy_test(struct mii_bus *bus, struct phy_device *phydev, int enable, |
1210 | u32 regnum, u32 read); | 1211 | u32 regnum, u32 read); |
1211 | void gfar_configure_coalescing_all(struct gfar_private *priv); | 1212 | void gfar_configure_coalescing_all(struct gfar_private *priv); |
diff --git a/drivers/net/ethernet/freescale/gianfar_ethtool.c b/drivers/net/ethernet/freescale/gianfar_ethtool.c index 63d234419cc1..69fab72b8a8d 100644 --- a/drivers/net/ethernet/freescale/gianfar_ethtool.c +++ b/drivers/net/ethernet/freescale/gianfar_ethtool.c | |||
@@ -44,7 +44,6 @@ | |||
44 | 44 | ||
45 | #include "gianfar.h" | 45 | #include "gianfar.h" |
46 | 46 | ||
47 | extern void gfar_start(struct net_device *dev); | ||
48 | extern int gfar_clean_rx_ring(struct gfar_priv_rx_q *rx_queue, | 47 | extern int gfar_clean_rx_ring(struct gfar_priv_rx_q *rx_queue, |
49 | int rx_work_limit); | 48 | int rx_work_limit); |
50 | 49 | ||
@@ -504,7 +503,7 @@ static int gfar_sringparam(struct net_device *dev, | |||
504 | lock_tx_qs(priv); | 503 | lock_tx_qs(priv); |
505 | lock_rx_qs(priv); | 504 | lock_rx_qs(priv); |
506 | 505 | ||
507 | gfar_halt(dev); | 506 | gfar_halt(priv); |
508 | 507 | ||
509 | unlock_rx_qs(priv); | 508 | unlock_rx_qs(priv); |
510 | unlock_tx_qs(priv); | 509 | unlock_tx_qs(priv); |
@@ -627,7 +626,7 @@ int gfar_set_features(struct net_device *dev, netdev_features_t features) | |||
627 | lock_tx_qs(priv); | 626 | lock_tx_qs(priv); |
628 | lock_rx_qs(priv); | 627 | lock_rx_qs(priv); |
629 | 628 | ||
630 | gfar_halt(dev); | 629 | gfar_halt(priv); |
631 | 630 | ||
632 | unlock_tx_qs(priv); | 631 | unlock_tx_qs(priv); |
633 | unlock_rx_qs(priv); | 632 | unlock_rx_qs(priv); |