diff options
author | Sebastien Griffoul <sebastien.griffoul@intel.com> | 2016-05-24 16:29:39 +0200 |
---|---|---|
committer | Anas Nashif <nashif@linux.intel.com> | 2016-05-26 15:12:25 +0000 |
commit | 8237d0f882124d9aa9e9e79336de79b8f71deabb (patch) | |
tree | 9e60741fea086f8031710983f80bc020ce5ed4c4 | |
parent | 0595c47e170a92b25a29e08865fea63d3d5710d0 (diff) |
eth: Fix spurious interrupt issues
The ethernet driver generates a lot of spurious interrupts.
These spurious interrupts have two sources:
1) The Mac Management Counter (MMC) module generates a lot of interrupts
(GMI - bit 27 of the status register). Unfortunately the Interrupt
enable register doesn't allow us to enable/disable it (bit 27 is
reserved). Therefore the only way to mask this interrupt is to mask
all the MMC interrupts (register REG_MMC_RX_INTR_MASK,
REG_MMC_TX_INTR_MASK and REG_MMC_RX_IPC_INTR_MASK). By default
these interrupts are not masked.
2) The RX interrupt is not correctly acknowledged. According to the
datasheet, NIS is a sticky bit and must be cleared (by writing 1
to this bit) each time a corresponding bit, which causes NIS to
be set, is cleared.
Change-Id: I2033973849d87cddc328c65d0d4ad36b5a0c934e
Signed-off-by: Sebastien Griffoul <sebastien.griffoul@intel.com>
-rw-r--r-- | drivers/ethernet/eth_dw.c | 7 | ||||
-rw-r--r-- | drivers/ethernet/eth_dw_priv.h | 8 |
2 files changed, 14 insertions, 1 deletions
diff --git a/drivers/ethernet/eth_dw.c b/drivers/ethernet/eth_dw.c index 921bfa66b..366cc1ac0 100644 --- a/drivers/ethernet/eth_dw.c +++ b/drivers/ethernet/eth_dw.c @@ -165,7 +165,7 @@ void eth_dw_isr(struct device *port) eth_rx(port); /* Acknowledge the interrupt. */ - eth_write(base_addr, REG_ADDR_STATUS, STATUS_RX_INT); + eth_write(base_addr, REG_ADDR_STATUS, STATUS_NORMAL_INT | STATUS_RX_INT); } #ifdef CONFIG_PCI @@ -260,6 +260,11 @@ static int eth_initialize(struct device *port) /* Enable receive interrupts */ INT_ENABLE_RX); + /* Mask all the MMC interrupts */ + eth_write(base_addr, REG_MMC_RX_INTR_MASK, MMC_DEFAULT_MASK); + eth_write(base_addr, REG_MMC_TX_INTR_MASK, MMC_DEFAULT_MASK); + eth_write(base_addr, REG_MMC_RX_IPC_INTR_MASK, MMC_DEFAULT_MASK); + eth_write(base_addr, REG_ADDR_DMA_OPERATION, /* Enable receive store-and-forward mode for simplicity. */ OP_MODE_25_RX_STORE_N_FORWARD | diff --git a/drivers/ethernet/eth_dw_priv.h b/drivers/ethernet/eth_dw_priv.h index caaaf5999..f5dfdedb5 100644 --- a/drivers/ethernet/eth_dw_priv.h +++ b/drivers/ethernet/eth_dw_priv.h @@ -170,11 +170,14 @@ struct eth_runtime { volatile uint8_t rx_buf[UIP_BUFSIZE]; }; +#define MMC_DEFAULT_MASK 0xffffffff + #define MAC_CONF_14_RMII_100M BIT(14) #define MAC_CONF_11_DUPLEX BIT(11) #define MAC_CONF_3_TX_EN BIT(3) #define MAC_CONF_2_RX_EN BIT(2) +#define STATUS_NORMAL_INT BIT(16) #define STATUS_RX_INT BIT(6) #define OP_MODE_25_RX_STORE_N_FORWARD BIT(25) @@ -188,6 +191,11 @@ struct eth_runtime { #define REG_ADDR_MAC_CONF 0x0000 #define REG_ADDR_MACADDR_HI 0x0040 #define REG_ADDR_MACADDR_LO 0x0044 + +#define REG_MMC_RX_INTR_MASK 0x010c +#define REG_MMC_TX_INTR_MASK 0x0110 +#define REG_MMC_RX_IPC_INTR_MASK 0x0200 + #define REG_ADDR_TX_POLL_DEMAND 0x1004 #define REG_ADDR_RX_POLL_DEMAND 0x1008 #define REG_ADDR_RX_DESC_LIST 0x100C |