Commit 9b39f05c authored by Sergei Shtylyov's avatar Sergei Shtylyov Committed by David S. Miller

sh_eth: factor out sh_eth_emac_interrupt()

The E-MAC interrupt (EESR.ECI) is not always caused  by an error condition,
so  it really shouldn't be handled by sh_eth_error(). Factor out the E-MAC
interrupt handler, sh_eth_emac_interrupt(),  removing the ECI bit from the
EESR's values throughout the driver...

Update Cogent Embedded's copyright and clean up the whitespace in Renesas'
copyright, while at it...
Signed-off-by: default avatarSergei Shtylyov <sergei.shtylyov@cogentembedded.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 1940f240
/* SuperH Ethernet device driver /* SuperH Ethernet device driver
* *
* Copyright (C) 2014 Renesas Electronics Corporation * Copyright (C) 2014 Renesas Electronics Corporation
* Copyright (C) 2006-2012 Nobuhiro Iwamatsu * Copyright (C) 2006-2012 Nobuhiro Iwamatsu
* Copyright (C) 2008-2014 Renesas Solutions Corp. * Copyright (C) 2008-2014 Renesas Solutions Corp.
* Copyright (C) 2013-2016 Cogent Embedded, Inc. * Copyright (C) 2013-2017 Cogent Embedded, Inc.
* Copyright (C) 2014 Codethink Limited * Copyright (C) 2014 Codethink Limited
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
...@@ -523,7 +523,7 @@ static struct sh_eth_cpu_data r7s72100_data = { ...@@ -523,7 +523,7 @@ static struct sh_eth_cpu_data r7s72100_data = {
.tx_check = EESR_TC1 | EESR_FTC, .tx_check = EESR_TC1 | EESR_FTC,
.eesr_err_check = EESR_TWB1 | EESR_TWB | EESR_TABT | EESR_RABT | .eesr_err_check = EESR_TWB1 | EESR_TWB | EESR_TABT | EESR_RABT |
EESR_RFE | EESR_RDE | EESR_RFRMER | EESR_TFE | EESR_RFE | EESR_RDE | EESR_RFRMER | EESR_TFE |
EESR_TDE | EESR_ECI, EESR_TDE,
.fdr_value = 0x0000070f, .fdr_value = 0x0000070f,
.no_psr = 1, .no_psr = 1,
...@@ -562,7 +562,7 @@ static struct sh_eth_cpu_data r8a7740_data = { ...@@ -562,7 +562,7 @@ static struct sh_eth_cpu_data r8a7740_data = {
.tx_check = EESR_TC1 | EESR_FTC, .tx_check = EESR_TC1 | EESR_FTC,
.eesr_err_check = EESR_TWB1 | EESR_TWB | EESR_TABT | EESR_RABT | .eesr_err_check = EESR_TWB1 | EESR_TWB | EESR_TABT | EESR_RABT |
EESR_RFE | EESR_RDE | EESR_RFRMER | EESR_TFE | EESR_RFE | EESR_RDE | EESR_RFRMER | EESR_TFE |
EESR_TDE | EESR_ECI, EESR_TDE,
.fdr_value = 0x0000070f, .fdr_value = 0x0000070f,
.apr = 1, .apr = 1,
...@@ -607,8 +607,7 @@ static struct sh_eth_cpu_data r8a777x_data = { ...@@ -607,8 +607,7 @@ static struct sh_eth_cpu_data r8a777x_data = {
.tx_check = EESR_FTC | EESR_CND | EESR_DLC | EESR_CD | EESR_RTO, .tx_check = EESR_FTC | EESR_CND | EESR_DLC | EESR_CD | EESR_RTO,
.eesr_err_check = EESR_TWB | EESR_TABT | EESR_RABT | EESR_RFE | .eesr_err_check = EESR_TWB | EESR_TABT | EESR_RABT | EESR_RFE |
EESR_RDE | EESR_RFRMER | EESR_TFE | EESR_TDE | EESR_RDE | EESR_RFRMER | EESR_TFE | EESR_TDE,
EESR_ECI,
.fdr_value = 0x00000f0f, .fdr_value = 0x00000f0f,
.apr = 1, .apr = 1,
...@@ -630,8 +629,7 @@ static struct sh_eth_cpu_data r8a779x_data = { ...@@ -630,8 +629,7 @@ static struct sh_eth_cpu_data r8a779x_data = {
.tx_check = EESR_FTC | EESR_CND | EESR_DLC | EESR_CD | EESR_RTO, .tx_check = EESR_FTC | EESR_CND | EESR_DLC | EESR_CD | EESR_RTO,
.eesr_err_check = EESR_TWB | EESR_TABT | EESR_RABT | EESR_RFE | .eesr_err_check = EESR_TWB | EESR_TABT | EESR_RABT | EESR_RFE |
EESR_RDE | EESR_RFRMER | EESR_TFE | EESR_TDE | EESR_RDE | EESR_RFRMER | EESR_TFE | EESR_TDE,
EESR_ECI,
.fdr_value = 0x00000f0f, .fdr_value = 0x00000f0f,
.trscer_err_mask = DESC_I_RINT8, .trscer_err_mask = DESC_I_RINT8,
...@@ -671,8 +669,7 @@ static struct sh_eth_cpu_data sh7724_data = { ...@@ -671,8 +669,7 @@ static struct sh_eth_cpu_data sh7724_data = {
.tx_check = EESR_FTC | EESR_CND | EESR_DLC | EESR_CD | EESR_RTO, .tx_check = EESR_FTC | EESR_CND | EESR_DLC | EESR_CD | EESR_RTO,
.eesr_err_check = EESR_TWB | EESR_TABT | EESR_RABT | EESR_RFE | .eesr_err_check = EESR_TWB | EESR_TABT | EESR_RABT | EESR_RFE |
EESR_RDE | EESR_RFRMER | EESR_TFE | EESR_TDE | EESR_RDE | EESR_RFRMER | EESR_TFE | EESR_TDE,
EESR_ECI,
.apr = 1, .apr = 1,
.mpr = 1, .mpr = 1,
...@@ -707,8 +704,7 @@ static struct sh_eth_cpu_data sh7757_data = { ...@@ -707,8 +704,7 @@ static struct sh_eth_cpu_data sh7757_data = {
.tx_check = EESR_FTC | EESR_CND | EESR_DLC | EESR_CD | EESR_RTO, .tx_check = EESR_FTC | EESR_CND | EESR_DLC | EESR_CD | EESR_RTO,
.eesr_err_check = EESR_TWB | EESR_TABT | EESR_RABT | EESR_RFE | .eesr_err_check = EESR_TWB | EESR_TABT | EESR_RABT | EESR_RFE |
EESR_RDE | EESR_RFRMER | EESR_TFE | EESR_TDE | EESR_RDE | EESR_RFRMER | EESR_TFE | EESR_TDE,
EESR_ECI,
.irq_flags = IRQF_SHARED, .irq_flags = IRQF_SHARED,
.apr = 1, .apr = 1,
...@@ -776,7 +772,7 @@ static struct sh_eth_cpu_data sh7757_data_giga = { ...@@ -776,7 +772,7 @@ static struct sh_eth_cpu_data sh7757_data_giga = {
.tx_check = EESR_TC1 | EESR_FTC, .tx_check = EESR_TC1 | EESR_FTC,
.eesr_err_check = EESR_TWB1 | EESR_TWB | EESR_TABT | EESR_RABT | .eesr_err_check = EESR_TWB1 | EESR_TWB | EESR_TABT | EESR_RABT |
EESR_RFE | EESR_RDE | EESR_RFRMER | EESR_TFE | EESR_RFE | EESR_RDE | EESR_RFRMER | EESR_TFE |
EESR_TDE | EESR_ECI, EESR_TDE,
.fdr_value = 0x0000072f, .fdr_value = 0x0000072f,
.irq_flags = IRQF_SHARED, .irq_flags = IRQF_SHARED,
...@@ -807,7 +803,7 @@ static struct sh_eth_cpu_data sh7734_data = { ...@@ -807,7 +803,7 @@ static struct sh_eth_cpu_data sh7734_data = {
.tx_check = EESR_TC1 | EESR_FTC, .tx_check = EESR_TC1 | EESR_FTC,
.eesr_err_check = EESR_TWB1 | EESR_TWB | EESR_TABT | EESR_RABT | .eesr_err_check = EESR_TWB1 | EESR_TWB | EESR_TABT | EESR_RABT |
EESR_RFE | EESR_RDE | EESR_RFRMER | EESR_TFE | EESR_RFE | EESR_RDE | EESR_RFRMER | EESR_TFE |
EESR_TDE | EESR_ECI, EESR_TDE,
.apr = 1, .apr = 1,
.mpr = 1, .mpr = 1,
...@@ -835,8 +831,7 @@ static struct sh_eth_cpu_data sh7763_data = { ...@@ -835,8 +831,7 @@ static struct sh_eth_cpu_data sh7763_data = {
.tx_check = EESR_TC1 | EESR_FTC, .tx_check = EESR_TC1 | EESR_FTC,
.eesr_err_check = EESR_TWB1 | EESR_TWB | EESR_TABT | EESR_RABT | .eesr_err_check = EESR_TWB1 | EESR_TWB | EESR_TABT | EESR_RABT |
EESR_RDE | EESR_RFRMER | EESR_TFE | EESR_TDE | EESR_RDE | EESR_RFRMER | EESR_TFE | EESR_TDE,
EESR_ECI,
.apr = 1, .apr = 1,
.mpr = 1, .mpr = 1,
...@@ -1526,43 +1521,44 @@ static void sh_eth_rcv_snd_enable(struct net_device *ndev) ...@@ -1526,43 +1521,44 @@ static void sh_eth_rcv_snd_enable(struct net_device *ndev)
sh_eth_modify(ndev, ECMR, ECMR_RE | ECMR_TE, ECMR_RE | ECMR_TE); sh_eth_modify(ndev, ECMR, ECMR_RE | ECMR_TE, ECMR_RE | ECMR_TE);
} }
/* error control function */ /* E-MAC interrupt handler */
static void sh_eth_error(struct net_device *ndev, u32 intr_status) static void sh_eth_emac_interrupt(struct net_device *ndev)
{ {
struct sh_eth_private *mdp = netdev_priv(ndev); struct sh_eth_private *mdp = netdev_priv(ndev);
u32 felic_stat; u32 felic_stat;
u32 link_stat; u32 link_stat;
u32 mask;
if (intr_status & EESR_ECI) { felic_stat = sh_eth_read(ndev, ECSR) & sh_eth_read(ndev, ECSIPR);
felic_stat = sh_eth_read(ndev, ECSR) & sh_eth_write(ndev, felic_stat, ECSR); /* clear int */
sh_eth_read(ndev, ECSIPR); if (felic_stat & ECSR_ICD)
sh_eth_write(ndev, felic_stat, ECSR); /* clear int */ ndev->stats.tx_carrier_errors++;
if (felic_stat & ECSR_ICD) if (felic_stat & ECSR_LCHNG) {
ndev->stats.tx_carrier_errors++; /* Link Changed */
if (felic_stat & ECSR_LCHNG) { if (mdp->cd->no_psr || mdp->no_ether_link)
/* Link Changed */ return;
if (mdp->cd->no_psr || mdp->no_ether_link) link_stat = sh_eth_read(ndev, PSR);
goto ignore_link; if (mdp->ether_link_active_low)
link_stat = sh_eth_read(ndev, PSR); link_stat = ~link_stat;
if (mdp->ether_link_active_low) if (!(link_stat & PHY_ST_LINK)) {
link_stat = ~link_stat; sh_eth_rcv_snd_disable(ndev);
if (!(link_stat & PHY_ST_LINK)) { } else {
sh_eth_rcv_snd_disable(ndev); /* Link Up */
} else { sh_eth_modify(ndev, EESIPR, DMAC_M_ECI, 0);
/* Link Up */ /* clear int */
sh_eth_modify(ndev, EESIPR, DMAC_M_ECI, 0); sh_eth_modify(ndev, ECSR, 0, 0);
/* clear int */ sh_eth_modify(ndev, EESIPR, DMAC_M_ECI, DMAC_M_ECI);
sh_eth_modify(ndev, ECSR, 0, 0); /* enable tx and rx */
sh_eth_modify(ndev, EESIPR, DMAC_M_ECI, sh_eth_rcv_snd_enable(ndev);
DMAC_M_ECI);
/* enable tx and rx */
sh_eth_rcv_snd_enable(ndev);
}
} }
} }
}
/* error control function */
static void sh_eth_error(struct net_device *ndev, u32 intr_status)
{
struct sh_eth_private *mdp = netdev_priv(ndev);
u32 mask;
ignore_link:
if (intr_status & EESR_TWB) { if (intr_status & EESR_TWB) {
/* Unused write back interrupt */ /* Unused write back interrupt */
if (intr_status & EESR_TABT) { /* Transmit Abort int */ if (intr_status & EESR_TABT) { /* Transmit Abort int */
...@@ -1643,14 +1639,16 @@ static irqreturn_t sh_eth_interrupt(int irq, void *netdev) ...@@ -1643,14 +1639,16 @@ static irqreturn_t sh_eth_interrupt(int irq, void *netdev)
/* Get interrupt status */ /* Get interrupt status */
intr_status = sh_eth_read(ndev, EESR); intr_status = sh_eth_read(ndev, EESR);
/* Mask it with the interrupt mask, forcing ECI interrupt to be always /* Mask it with the interrupt mask, forcing ECI interrupt to be always
* enabled since it's the one that comes thru regardless of the mask, * enabled since it's the one that comes thru regardless of the mask,
* and we need to fully handle it in sh_eth_error() in order to quench * and we need to fully handle it in sh_eth_emac_interrupt() in order
* it as it doesn't get cleared by just writing 1 to the ECI bit... * to quench it as it doesn't get cleared by just writing 1 to the ECI
* bit...
*/ */
intr_enable = sh_eth_read(ndev, EESIPR); intr_enable = sh_eth_read(ndev, EESIPR);
intr_status &= intr_enable | DMAC_M_ECI; intr_status &= intr_enable | DMAC_M_ECI;
if (intr_status & (EESR_RX_CHECK | cd->tx_check | cd->eesr_err_check)) if (intr_status & (EESR_RX_CHECK | cd->tx_check | EESR_ECI |
cd->eesr_err_check))
ret = IRQ_HANDLED; ret = IRQ_HANDLED;
else else
goto out; goto out;
...@@ -1682,6 +1680,10 @@ static irqreturn_t sh_eth_interrupt(int irq, void *netdev) ...@@ -1682,6 +1680,10 @@ static irqreturn_t sh_eth_interrupt(int irq, void *netdev)
netif_wake_queue(ndev); netif_wake_queue(ndev);
} }
/* E-MAC interrupt */
if (intr_status & EESR_ECI)
sh_eth_emac_interrupt(ndev);
if (intr_status & cd->eesr_err_check) { if (intr_status & cd->eesr_err_check) {
/* Clear error interrupts */ /* Clear error interrupts */
sh_eth_write(ndev, intr_status & cd->eesr_err_check, EESR); sh_eth_write(ndev, intr_status & cd->eesr_err_check, EESR);
......
...@@ -265,7 +265,7 @@ enum EESR_BIT { ...@@ -265,7 +265,7 @@ enum EESR_BIT {
EESR_RTO) EESR_RTO)
#define DEFAULT_EESR_ERR_CHECK (EESR_TWB | EESR_TABT | EESR_RABT | EESR_RFE | \ #define DEFAULT_EESR_ERR_CHECK (EESR_TWB | EESR_TABT | EESR_RABT | EESR_RFE | \
EESR_RDE | EESR_RFRMER | EESR_ADE | \ EESR_RDE | EESR_RFRMER | EESR_ADE | \
EESR_TFE | EESR_TDE | EESR_ECI) EESR_TFE | EESR_TDE)
/* EESIPR */ /* EESIPR */
enum DMAC_IM_BIT { enum DMAC_IM_BIT {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment