diff options
| -rw-r--r-- | drivers/net/ethernet/renesas/sh_eth.c | 39 | ||||
| -rw-r--r-- | drivers/net/ethernet/renesas/sh_eth.h | 1 |
2 files changed, 31 insertions, 9 deletions
diff --git a/drivers/net/ethernet/renesas/sh_eth.c b/drivers/net/ethernet/renesas/sh_eth.c index 7facda1328f8..99a838db032e 100644 --- a/drivers/net/ethernet/renesas/sh_eth.c +++ b/drivers/net/ethernet/renesas/sh_eth.c | |||
| @@ -1316,8 +1316,10 @@ static int sh_eth_dev_init(struct net_device *ndev, bool start) | |||
| 1316 | RFLR); | 1316 | RFLR); |
| 1317 | 1317 | ||
| 1318 | sh_eth_write(ndev, sh_eth_read(ndev, EESR), EESR); | 1318 | sh_eth_write(ndev, sh_eth_read(ndev, EESR), EESR); |
| 1319 | if (start) | 1319 | if (start) { |
| 1320 | mdp->irq_enabled = true; | ||
| 1320 | sh_eth_write(ndev, mdp->cd->eesipr_value, EESIPR); | 1321 | sh_eth_write(ndev, mdp->cd->eesipr_value, EESIPR); |
| 1322 | } | ||
| 1321 | 1323 | ||
| 1322 | /* PAUSE Prohibition */ | 1324 | /* PAUSE Prohibition */ |
| 1323 | val = (sh_eth_read(ndev, ECMR) & ECMR_DM) | | 1325 | val = (sh_eth_read(ndev, ECMR) & ECMR_DM) | |
| @@ -1653,7 +1655,12 @@ static irqreturn_t sh_eth_interrupt(int irq, void *netdev) | |||
| 1653 | if (intr_status & (EESR_RX_CHECK | cd->tx_check | cd->eesr_err_check)) | 1655 | if (intr_status & (EESR_RX_CHECK | cd->tx_check | cd->eesr_err_check)) |
| 1654 | ret = IRQ_HANDLED; | 1656 | ret = IRQ_HANDLED; |
| 1655 | else | 1657 | else |
| 1656 | goto other_irq; | 1658 | goto out; |
| 1659 | |||
| 1660 | if (!likely(mdp->irq_enabled)) { | ||
| 1661 | sh_eth_write(ndev, 0, EESIPR); | ||
| 1662 | goto out; | ||
| 1663 | } | ||
| 1657 | 1664 | ||
| 1658 | if (intr_status & EESR_RX_CHECK) { | 1665 | if (intr_status & EESR_RX_CHECK) { |
| 1659 | if (napi_schedule_prep(&mdp->napi)) { | 1666 | if (napi_schedule_prep(&mdp->napi)) { |
| @@ -1684,7 +1691,7 @@ static irqreturn_t sh_eth_interrupt(int irq, void *netdev) | |||
| 1684 | sh_eth_error(ndev, intr_status); | 1691 | sh_eth_error(ndev, intr_status); |
| 1685 | } | 1692 | } |
| 1686 | 1693 | ||
| 1687 | other_irq: | 1694 | out: |
| 1688 | spin_unlock(&mdp->lock); | 1695 | spin_unlock(&mdp->lock); |
| 1689 | 1696 | ||
| 1690 | return ret; | 1697 | return ret; |
| @@ -1712,7 +1719,8 @@ static int sh_eth_poll(struct napi_struct *napi, int budget) | |||
| 1712 | napi_complete(napi); | 1719 | napi_complete(napi); |
| 1713 | 1720 | ||
| 1714 | /* Reenable Rx interrupts */ | 1721 | /* Reenable Rx interrupts */ |
| 1715 | sh_eth_write(ndev, mdp->cd->eesipr_value, EESIPR); | 1722 | if (mdp->irq_enabled) |
| 1723 | sh_eth_write(ndev, mdp->cd->eesipr_value, EESIPR); | ||
| 1716 | out: | 1724 | out: |
| 1717 | return budget - quota; | 1725 | return budget - quota; |
| 1718 | } | 1726 | } |
| @@ -1970,12 +1978,20 @@ static int sh_eth_set_ringparam(struct net_device *ndev, | |||
| 1970 | if (netif_running(ndev)) { | 1978 | if (netif_running(ndev)) { |
| 1971 | netif_device_detach(ndev); | 1979 | netif_device_detach(ndev); |
| 1972 | netif_tx_disable(ndev); | 1980 | netif_tx_disable(ndev); |
| 1973 | /* Disable interrupts by clearing the interrupt mask. */ | 1981 | |
| 1982 | /* Serialise with the interrupt handler and NAPI, then | ||
| 1983 | * disable interrupts. We have to clear the | ||
| 1984 | * irq_enabled flag first to ensure that interrupts | ||
| 1985 | * won't be re-enabled. | ||
| 1986 | */ | ||
| 1987 | mdp->irq_enabled = false; | ||
| 1988 | synchronize_irq(ndev->irq); | ||
| 1989 | napi_synchronize(&mdp->napi); | ||
| 1974 | sh_eth_write(ndev, 0x0000, EESIPR); | 1990 | sh_eth_write(ndev, 0x0000, EESIPR); |
| 1991 | |||
| 1975 | /* Stop the chip's Tx and Rx processes. */ | 1992 | /* Stop the chip's Tx and Rx processes. */ |
| 1976 | sh_eth_write(ndev, 0, EDTRR); | 1993 | sh_eth_write(ndev, 0, EDTRR); |
| 1977 | sh_eth_write(ndev, 0, EDRRR); | 1994 | sh_eth_write(ndev, 0, EDRRR); |
| 1978 | synchronize_irq(ndev->irq); | ||
| 1979 | 1995 | ||
| 1980 | /* Free all the skbuffs in the Rx queue. */ | 1996 | /* Free all the skbuffs in the Rx queue. */ |
| 1981 | sh_eth_ring_free(ndev); | 1997 | sh_eth_ring_free(ndev); |
| @@ -2001,6 +2017,7 @@ static int sh_eth_set_ringparam(struct net_device *ndev, | |||
| 2001 | return ret; | 2017 | return ret; |
| 2002 | } | 2018 | } |
| 2003 | 2019 | ||
| 2020 | mdp->irq_enabled = true; | ||
| 2004 | sh_eth_write(ndev, mdp->cd->eesipr_value, EESIPR); | 2021 | sh_eth_write(ndev, mdp->cd->eesipr_value, EESIPR); |
| 2005 | /* Setting the Rx mode will start the Rx process. */ | 2022 | /* Setting the Rx mode will start the Rx process. */ |
| 2006 | sh_eth_write(ndev, EDRRR_R, EDRRR); | 2023 | sh_eth_write(ndev, EDRRR_R, EDRRR); |
| @@ -2184,7 +2201,13 @@ static int sh_eth_close(struct net_device *ndev) | |||
| 2184 | 2201 | ||
| 2185 | netif_stop_queue(ndev); | 2202 | netif_stop_queue(ndev); |
| 2186 | 2203 | ||
| 2187 | /* Disable interrupts by clearing the interrupt mask. */ | 2204 | /* Serialise with the interrupt handler and NAPI, then disable |
| 2205 | * interrupts. We have to clear the irq_enabled flag first to | ||
| 2206 | * ensure that interrupts won't be re-enabled. | ||
| 2207 | */ | ||
| 2208 | mdp->irq_enabled = false; | ||
| 2209 | synchronize_irq(ndev->irq); | ||
| 2210 | napi_disable(&mdp->napi); | ||
| 2188 | sh_eth_write(ndev, 0x0000, EESIPR); | 2211 | sh_eth_write(ndev, 0x0000, EESIPR); |
| 2189 | 2212 | ||
| 2190 | /* Stop the chip's Tx and Rx processes. */ | 2213 | /* Stop the chip's Tx and Rx processes. */ |
| @@ -2201,8 +2224,6 @@ static int sh_eth_close(struct net_device *ndev) | |||
| 2201 | 2224 | ||
| 2202 | free_irq(ndev->irq, ndev); | 2225 | free_irq(ndev->irq, ndev); |
| 2203 | 2226 | ||
| 2204 | napi_disable(&mdp->napi); | ||
| 2205 | |||
| 2206 | /* Free all the skbuffs in the Rx queue. */ | 2227 | /* Free all the skbuffs in the Rx queue. */ |
| 2207 | sh_eth_ring_free(ndev); | 2228 | sh_eth_ring_free(ndev); |
| 2208 | 2229 | ||
diff --git a/drivers/net/ethernet/renesas/sh_eth.h b/drivers/net/ethernet/renesas/sh_eth.h index 71f5de1171bd..332d3c16d483 100644 --- a/drivers/net/ethernet/renesas/sh_eth.h +++ b/drivers/net/ethernet/renesas/sh_eth.h | |||
| @@ -513,6 +513,7 @@ struct sh_eth_private { | |||
| 513 | u32 rx_buf_sz; /* Based on MTU+slack. */ | 513 | u32 rx_buf_sz; /* Based on MTU+slack. */ |
| 514 | int edmac_endian; | 514 | int edmac_endian; |
| 515 | struct napi_struct napi; | 515 | struct napi_struct napi; |
| 516 | bool irq_enabled; | ||
| 516 | /* MII transceiver section. */ | 517 | /* MII transceiver section. */ |
| 517 | u32 phy_id; /* PHY ID */ | 518 | u32 phy_id; /* PHY ID */ |
| 518 | struct mii_bus *mii_bus; /* MDIO bus control */ | 519 | struct mii_bus *mii_bus; /* MDIO bus control */ |
