aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/ethernet/stmicro/stmmac/stmmac_main.c')
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/stmmac_main.c166
1 files changed, 159 insertions, 7 deletions
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index eba49cb810f9..ea3bc0963bd7 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -133,6 +133,12 @@ static const u32 default_msg_level = (NETIF_MSG_DRV | NETIF_MSG_PROBE |
133 NETIF_MSG_LINK | NETIF_MSG_IFUP | 133 NETIF_MSG_LINK | NETIF_MSG_IFUP |
134 NETIF_MSG_IFDOWN | NETIF_MSG_TIMER); 134 NETIF_MSG_IFDOWN | NETIF_MSG_TIMER);
135 135
136#define STMMAC_DEFAULT_LPI_TIMER 1000
137static int eee_timer = STMMAC_DEFAULT_LPI_TIMER;
138module_param(eee_timer, int, S_IRUGO | S_IWUSR);
139MODULE_PARM_DESC(eee_timer, "LPI tx expiration time in msec");
140#define STMMAC_LPI_TIMER(x) (jiffies + msecs_to_jiffies(x))
141
136static irqreturn_t stmmac_interrupt(int irq, void *dev_id); 142static irqreturn_t stmmac_interrupt(int irq, void *dev_id);
137 143
138#ifdef CONFIG_STMMAC_DEBUG_FS 144#ifdef CONFIG_STMMAC_DEBUG_FS
@@ -161,6 +167,8 @@ static void stmmac_verify_args(void)
161 flow_ctrl = FLOW_OFF; 167 flow_ctrl = FLOW_OFF;
162 if (unlikely((pause < 0) || (pause > 0xffff))) 168 if (unlikely((pause < 0) || (pause > 0xffff)))
163 pause = PAUSE_TIME; 169 pause = PAUSE_TIME;
170 if (eee_timer < 0)
171 eee_timer = STMMAC_DEFAULT_LPI_TIMER;
164} 172}
165 173
166static void stmmac_clk_csr_set(struct stmmac_priv *priv) 174static void stmmac_clk_csr_set(struct stmmac_priv *priv)
@@ -229,6 +237,85 @@ static inline void stmmac_hw_fix_mac_speed(struct stmmac_priv *priv)
229 phydev->speed); 237 phydev->speed);
230} 238}
231 239
240static void stmmac_enable_eee_mode(struct stmmac_priv *priv)
241{
242 /* Check and enter in LPI mode */
243 if ((priv->dirty_tx == priv->cur_tx) &&
244 (priv->tx_path_in_lpi_mode == false))
245 priv->hw->mac->set_eee_mode(priv->ioaddr);
246}
247
248void stmmac_disable_eee_mode(struct stmmac_priv *priv)
249{
250 /* Exit and disable EEE in case of we are are in LPI state. */
251 priv->hw->mac->reset_eee_mode(priv->ioaddr);
252 del_timer_sync(&priv->eee_ctrl_timer);
253 priv->tx_path_in_lpi_mode = false;
254}
255
256/**
257 * stmmac_eee_ctrl_timer
258 * @arg : data hook
259 * Description:
260 * If there is no data transfer and if we are not in LPI state,
261 * then MAC Transmitter can be moved to LPI state.
262 */
263static void stmmac_eee_ctrl_timer(unsigned long arg)
264{
265 struct stmmac_priv *priv = (struct stmmac_priv *)arg;
266
267 stmmac_enable_eee_mode(priv);
268 mod_timer(&priv->eee_ctrl_timer, STMMAC_LPI_TIMER(eee_timer));
269}
270
271/**
272 * stmmac_eee_init
273 * @priv: private device pointer
274 * Description:
275 * If the EEE support has been enabled while configuring the driver,
276 * if the GMAC actually supports the EEE (from the HW cap reg) and the
277 * phy can also manage EEE, so enable the LPI state and start the timer
278 * to verify if the tx path can enter in LPI state.
279 */
280bool stmmac_eee_init(struct stmmac_priv *priv)
281{
282 bool ret = false;
283
284 /* MAC core supports the EEE feature. */
285 if (priv->dma_cap.eee) {
286 /* Check if the PHY supports EEE */
287 if (phy_init_eee(priv->phydev, 1))
288 goto out;
289
290 priv->eee_active = 1;
291 init_timer(&priv->eee_ctrl_timer);
292 priv->eee_ctrl_timer.function = stmmac_eee_ctrl_timer;
293 priv->eee_ctrl_timer.data = (unsigned long)priv;
294 priv->eee_ctrl_timer.expires = STMMAC_LPI_TIMER(eee_timer);
295 add_timer(&priv->eee_ctrl_timer);
296
297 priv->hw->mac->set_eee_timer(priv->ioaddr,
298 STMMAC_DEFAULT_LIT_LS_TIMER,
299 priv->tx_lpi_timer);
300
301 pr_info("stmmac: Energy-Efficient Ethernet initialized\n");
302
303 ret = true;
304 }
305out:
306 return ret;
307}
308
309static void stmmac_eee_adjust(struct stmmac_priv *priv)
310{
311 /* When the EEE has been already initialised we have to
312 * modify the PLS bit in the LPI ctrl & status reg according
313 * to the PHY link status. For this reason.
314 */
315 if (priv->eee_enabled)
316 priv->hw->mac->set_eee_pls(priv->ioaddr, priv->phydev->link);
317}
318
232/** 319/**
233 * stmmac_adjust_link 320 * stmmac_adjust_link
234 * @dev: net device structure 321 * @dev: net device structure
@@ -249,6 +336,7 @@ static void stmmac_adjust_link(struct net_device *dev)
249 phydev->addr, phydev->link); 336 phydev->addr, phydev->link);
250 337
251 spin_lock_irqsave(&priv->lock, flags); 338 spin_lock_irqsave(&priv->lock, flags);
339
252 if (phydev->link) { 340 if (phydev->link) {
253 u32 ctrl = readl(priv->ioaddr + MAC_CTRL_REG); 341 u32 ctrl = readl(priv->ioaddr + MAC_CTRL_REG);
254 342
@@ -315,6 +403,8 @@ static void stmmac_adjust_link(struct net_device *dev)
315 if (new_state && netif_msg_link(priv)) 403 if (new_state && netif_msg_link(priv))
316 phy_print_status(phydev); 404 phy_print_status(phydev);
317 405
406 stmmac_eee_adjust(priv);
407
318 spin_unlock_irqrestore(&priv->lock, flags); 408 spin_unlock_irqrestore(&priv->lock, flags);
319 409
320 DBG(probe, DEBUG, "stmmac_adjust_link: exiting\n"); 410 DBG(probe, DEBUG, "stmmac_adjust_link: exiting\n");
@@ -332,7 +422,7 @@ static int stmmac_init_phy(struct net_device *dev)
332{ 422{
333 struct stmmac_priv *priv = netdev_priv(dev); 423 struct stmmac_priv *priv = netdev_priv(dev);
334 struct phy_device *phydev; 424 struct phy_device *phydev;
335 char phy_id[MII_BUS_ID_SIZE + 3]; 425 char phy_id_fmt[MII_BUS_ID_SIZE + 3];
336 char bus_id[MII_BUS_ID_SIZE]; 426 char bus_id[MII_BUS_ID_SIZE];
337 int interface = priv->plat->interface; 427 int interface = priv->plat->interface;
338 priv->oldlink = 0; 428 priv->oldlink = 0;
@@ -346,11 +436,12 @@ static int stmmac_init_phy(struct net_device *dev)
346 snprintf(bus_id, MII_BUS_ID_SIZE, "stmmac-%x", 436 snprintf(bus_id, MII_BUS_ID_SIZE, "stmmac-%x",
347 priv->plat->bus_id); 437 priv->plat->bus_id);
348 438
349 snprintf(phy_id, MII_BUS_ID_SIZE + 3, PHY_ID_FMT, bus_id, 439 snprintf(phy_id_fmt, MII_BUS_ID_SIZE + 3, PHY_ID_FMT, bus_id,
350 priv->plat->phy_addr); 440 priv->plat->phy_addr);
351 pr_debug("stmmac_init_phy: trying to attach to %s\n", phy_id); 441 pr_debug("stmmac_init_phy: trying to attach to %s\n", phy_id_fmt);
352 442
353 phydev = phy_connect(dev, phy_id, &stmmac_adjust_link, 0, interface); 443 phydev = phy_connect(dev, phy_id_fmt, &stmmac_adjust_link, 0,
444 interface);
354 445
355 if (IS_ERR(phydev)) { 446 if (IS_ERR(phydev)) {
356 pr_err("%s: Could not attach to PHY\n", dev->name); 447 pr_err("%s: Could not attach to PHY\n", dev->name);
@@ -689,6 +780,11 @@ static void stmmac_tx(struct stmmac_priv *priv)
689 } 780 }
690 netif_tx_unlock(priv->dev); 781 netif_tx_unlock(priv->dev);
691 } 782 }
783
784 if ((priv->eee_enabled) && (!priv->tx_path_in_lpi_mode)) {
785 stmmac_enable_eee_mode(priv);
786 mod_timer(&priv->eee_ctrl_timer, STMMAC_LPI_TIMER(eee_timer));
787 }
692 spin_unlock(&priv->tx_lock); 788 spin_unlock(&priv->tx_lock);
693} 789}
694 790
@@ -1027,6 +1123,17 @@ static int stmmac_open(struct net_device *dev)
1027 } 1123 }
1028 } 1124 }
1029 1125
1126 /* Request the IRQ lines */
1127 if (priv->lpi_irq != -ENXIO) {
1128 ret = request_irq(priv->lpi_irq, stmmac_interrupt, IRQF_SHARED,
1129 dev->name, dev);
1130 if (unlikely(ret < 0)) {
1131 pr_err("%s: ERROR: allocating the LPI IRQ %d (%d)\n",
1132 __func__, priv->lpi_irq, ret);
1133 goto open_error_lpiirq;
1134 }
1135 }
1136
1030 /* Enable the MAC Rx/Tx */ 1137 /* Enable the MAC Rx/Tx */
1031 stmmac_set_mac(priv->ioaddr, true); 1138 stmmac_set_mac(priv->ioaddr, true);
1032 1139
@@ -1062,12 +1169,19 @@ static int stmmac_open(struct net_device *dev)
1062 if (priv->phydev) 1169 if (priv->phydev)
1063 phy_start(priv->phydev); 1170 phy_start(priv->phydev);
1064 1171
1172 priv->tx_lpi_timer = STMMAC_DEFAULT_TWT_LS_TIMER;
1173 priv->eee_enabled = stmmac_eee_init(priv);
1174
1065 napi_enable(&priv->napi); 1175 napi_enable(&priv->napi);
1066 skb_queue_head_init(&priv->rx_recycle); 1176 skb_queue_head_init(&priv->rx_recycle);
1067 netif_start_queue(dev); 1177 netif_start_queue(dev);
1068 1178
1069 return 0; 1179 return 0;
1070 1180
1181open_error_lpiirq:
1182 if (priv->wol_irq != dev->irq)
1183 free_irq(priv->wol_irq, dev);
1184
1071open_error_wolirq: 1185open_error_wolirq:
1072 free_irq(dev->irq, dev); 1186 free_irq(dev->irq, dev);
1073 1187
@@ -1093,6 +1207,9 @@ static int stmmac_release(struct net_device *dev)
1093{ 1207{
1094 struct stmmac_priv *priv = netdev_priv(dev); 1208 struct stmmac_priv *priv = netdev_priv(dev);
1095 1209
1210 if (priv->eee_enabled)
1211 del_timer_sync(&priv->eee_ctrl_timer);
1212
1096 /* Stop and disconnect the PHY */ 1213 /* Stop and disconnect the PHY */
1097 if (priv->phydev) { 1214 if (priv->phydev) {
1098 phy_stop(priv->phydev); 1215 phy_stop(priv->phydev);
@@ -1115,6 +1232,8 @@ static int stmmac_release(struct net_device *dev)
1115 free_irq(dev->irq, dev); 1232 free_irq(dev->irq, dev);
1116 if (priv->wol_irq != dev->irq) 1233 if (priv->wol_irq != dev->irq)
1117 free_irq(priv->wol_irq, dev); 1234 free_irq(priv->wol_irq, dev);
1235 if (priv->lpi_irq != -ENXIO)
1236 free_irq(priv->lpi_irq, dev);
1118 1237
1119 /* Stop TX/RX DMA and clear the descriptors */ 1238 /* Stop TX/RX DMA and clear the descriptors */
1120 priv->hw->dma->stop_tx(priv->ioaddr); 1239 priv->hw->dma->stop_tx(priv->ioaddr);
@@ -1164,6 +1283,9 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev)
1164 1283
1165 spin_lock(&priv->tx_lock); 1284 spin_lock(&priv->tx_lock);
1166 1285
1286 if (priv->tx_path_in_lpi_mode)
1287 stmmac_disable_eee_mode(priv);
1288
1167 entry = priv->cur_tx % txsize; 1289 entry = priv->cur_tx % txsize;
1168 1290
1169#ifdef STMMAC_XMIT_DEBUG 1291#ifdef STMMAC_XMIT_DEBUG
@@ -1540,10 +1662,37 @@ static irqreturn_t stmmac_interrupt(int irq, void *dev_id)
1540 return IRQ_NONE; 1662 return IRQ_NONE;
1541 } 1663 }
1542 1664
1543 if (priv->plat->has_gmac) 1665 /* To handle GMAC own interrupts */
1544 /* To handle GMAC own interrupts */ 1666 if (priv->plat->has_gmac) {
1545 priv->hw->mac->host_irq_status((void __iomem *) dev->base_addr); 1667 int status = priv->hw->mac->host_irq_status((void __iomem *)
1668 dev->base_addr);
1669 if (unlikely(status)) {
1670 if (status & core_mmc_tx_irq)
1671 priv->xstats.mmc_tx_irq_n++;
1672 if (status & core_mmc_rx_irq)
1673 priv->xstats.mmc_rx_irq_n++;
1674 if (status & core_mmc_rx_csum_offload_irq)
1675 priv->xstats.mmc_rx_csum_offload_irq_n++;
1676 if (status & core_irq_receive_pmt_irq)
1677 priv->xstats.irq_receive_pmt_irq_n++;
1678
1679 /* For LPI we need to save the tx status */
1680 if (status & core_irq_tx_path_in_lpi_mode) {
1681 priv->xstats.irq_tx_path_in_lpi_mode_n++;
1682 priv->tx_path_in_lpi_mode = true;
1683 }
1684 if (status & core_irq_tx_path_exit_lpi_mode) {
1685 priv->xstats.irq_tx_path_exit_lpi_mode_n++;
1686 priv->tx_path_in_lpi_mode = false;
1687 }
1688 if (status & core_irq_rx_path_in_lpi_mode)
1689 priv->xstats.irq_rx_path_in_lpi_mode_n++;
1690 if (status & core_irq_rx_path_exit_lpi_mode)
1691 priv->xstats.irq_rx_path_exit_lpi_mode_n++;
1692 }
1693 }
1546 1694
1695 /* To handle DMA interrupts */
1547 stmmac_dma_interrupt(priv); 1696 stmmac_dma_interrupt(priv);
1548 1697
1549 return IRQ_HANDLED; 1698 return IRQ_HANDLED;
@@ -2155,6 +2304,9 @@ static int __init stmmac_cmdline_opt(char *str)
2155 } else if (!strncmp(opt, "pause:", 6)) { 2304 } else if (!strncmp(opt, "pause:", 6)) {
2156 if (kstrtoint(opt + 6, 0, &pause)) 2305 if (kstrtoint(opt + 6, 0, &pause))
2157 goto err; 2306 goto err;
2307 } else if (!strncmp(opt, "eee_timer:", 6)) {
2308 if (kstrtoint(opt + 10, 0, &eee_timer))
2309 goto err;
2158#ifdef CONFIG_STMMAC_TIMER 2310#ifdef CONFIG_STMMAC_TIMER
2159 } else if (!strncmp(opt, "tmrate:", 7)) { 2311 } else if (!strncmp(opt, "tmrate:", 7)) {
2160 if (kstrtoint(opt + 7, 0, &tmrate)) 2312 if (kstrtoint(opt + 7, 0, &tmrate))