Commit 0982a0f6 authored by Giuseppe CAVALLARO's avatar Giuseppe CAVALLARO Committed by David S. Miller

stmmac: start adding pcs and rgmii core irq

This patch starts adding in the main ISR the management of the PCS and
RGMII/SGMII core interrupts. This is to help further development
on this area. Currently the core irq handler only clears the
PCS and S-R_MII interrupts and reports the event in the ethtool stats.
Signed-off-by: default avatarGiuseppe Cavallaro <peppe.cavallaro@st.com>
Tested-by: default avatarByungho An <bh74.an@samsung.com>
Cc: Udit Kumar <udit-dlh.kumar@st.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent c24602ef
...@@ -140,6 +140,10 @@ struct stmmac_extra_stats { ...@@ -140,6 +140,10 @@ struct stmmac_extra_stats {
unsigned long l3_filter_match; unsigned long l3_filter_match;
unsigned long l4_filter_match; unsigned long l4_filter_match;
unsigned long l3_l4_filter_no_match; unsigned long l3_l4_filter_no_match;
/* PCS */
unsigned long irq_pcs_ane_n;
unsigned long irq_pcs_link_n;
unsigned long irq_rgmii_n;
}; };
/* CSR Frequency Access Defines*/ /* CSR Frequency Access Defines*/
...@@ -217,16 +221,14 @@ enum dma_irq_status { ...@@ -217,16 +221,14 @@ enum dma_irq_status {
handle_tx = 0x8, handle_tx = 0x8,
}; };
enum core_specific_irq_mask { #define CORE_IRQ_TX_PATH_IN_LPI_MODE (1 << 1)
core_mmc_tx_irq = 1, #define CORE_IRQ_TX_PATH_EXIT_LPI_MODE (1 << 2)
core_mmc_rx_irq = 2, #define CORE_IRQ_RX_PATH_IN_LPI_MODE (1 << 3)
core_mmc_rx_csum_offload_irq = 4, #define CORE_IRQ_RX_PATH_EXIT_LPI_MODE (1 << 4)
core_irq_receive_pmt_irq = 8,
core_irq_tx_path_in_lpi_mode = 16, #define CORE_PCS_ANE_COMPLETE (1 << 5)
core_irq_tx_path_exit_lpi_mode = 32, #define CORE_PCS_LINK_STATUS (1 << 6)
core_irq_rx_path_in_lpi_mode = 64, #define CORE_RGMII_IRQ (1 << 7)
core_irq_rx_path_exit_lpi_mode = 128,
};
/* DMA HW capabilities */ /* DMA HW capabilities */
struct dma_features { struct dma_features {
...@@ -355,7 +357,8 @@ struct stmmac_ops { ...@@ -355,7 +357,8 @@ struct stmmac_ops {
/* Dump MAC registers */ /* Dump MAC registers */
void (*dump_regs) (void __iomem *ioaddr); void (*dump_regs) (void __iomem *ioaddr);
/* Handle extra events on specific interrupts hw dependent */ /* Handle extra events on specific interrupts hw dependent */
int (*host_irq_status) (void __iomem *ioaddr); int (*host_irq_status) (void __iomem *ioaddr,
struct stmmac_extra_stats *x);
/* Multicast filter setting */ /* Multicast filter setting */
void (*set_filter) (struct net_device *dev, int id); void (*set_filter) (struct net_device *dev, int id);
/* Flow control setting */ /* Flow control setting */
......
...@@ -89,13 +89,14 @@ enum power_event { ...@@ -89,13 +89,14 @@ enum power_event {
(reg * 8)) (reg * 8))
#define GMAC_MAX_PERFECT_ADDRESSES 32 #define GMAC_MAX_PERFECT_ADDRESSES 32
/* PCS registers (AN/TBI/SGMII/RGMII) offset */
#define GMAC_AN_CTRL 0x000000c0 /* AN control */ #define GMAC_AN_CTRL 0x000000c0 /* AN control */
#define GMAC_AN_STATUS 0x000000c4 /* AN status */ #define GMAC_AN_STATUS 0x000000c4 /* AN status */
#define GMAC_ANE_ADV 0x000000c8 /* Auto-Neg. Advertisement */ #define GMAC_ANE_ADV 0x000000c8 /* Auto-Neg. Advertisement */
#define GMAC_ANE_LINK 0x000000cc /* Auto-Neg. link partener ability */ #define GMAC_ANE_LPA 0x000000cc /* Auto-Neg. link partener ability */
#define GMAC_ANE_EXP 0x000000d0 /* ANE expansion */ #define GMAC_ANE_EXP 0x000000d0 /* ANE expansion */
#define GMAC_TBI 0x000000d4 /* TBI extend status */ #define GMAC_TBI 0x000000d4 /* TBI extend status */
#define GMAC_GMII_STATUS 0x000000d8 /* S/R-GMII status */ #define GMAC_S_R_GMII 0x000000d8 /* SGMII RGMII status */
/* GMAC Configuration defines */ /* GMAC Configuration defines */
#define GMAC_CONTROL_TC 0x01000000 /* Transmit Conf. in RGMII/SGMII */ #define GMAC_CONTROL_TC 0x01000000 /* Transmit Conf. in RGMII/SGMII */
......
...@@ -194,58 +194,70 @@ static void dwmac1000_pmt(void __iomem *ioaddr, unsigned long mode) ...@@ -194,58 +194,70 @@ static void dwmac1000_pmt(void __iomem *ioaddr, unsigned long mode)
} }
static int dwmac1000_irq_status(void __iomem *ioaddr) static int dwmac1000_irq_status(void __iomem *ioaddr,
struct stmmac_extra_stats *x)
{ {
u32 intr_status = readl(ioaddr + GMAC_INT_STATUS); u32 intr_status = readl(ioaddr + GMAC_INT_STATUS);
int status = 0; int ret = 0;
/* Not used events (e.g. MMC interrupts) are not handled. */ /* Not used events (e.g. MMC interrupts) are not handled. */
if ((intr_status & mmc_tx_irq)) { if ((intr_status & mmc_tx_irq)) {
CHIP_DBG(KERN_INFO "GMAC: MMC tx interrupt: 0x%08x\n", CHIP_DBG(KERN_INFO "GMAC: MMC tx interrupt: 0x%08x\n",
readl(ioaddr + GMAC_MMC_TX_INTR)); readl(ioaddr + GMAC_MMC_TX_INTR));
status |= core_mmc_tx_irq; x->mmc_tx_irq_n++;
} }
if (unlikely(intr_status & mmc_rx_irq)) { if (unlikely(intr_status & mmc_rx_irq)) {
CHIP_DBG(KERN_INFO "GMAC: MMC rx interrupt: 0x%08x\n", CHIP_DBG(KERN_INFO "GMAC: MMC rx interrupt: 0x%08x\n",
readl(ioaddr + GMAC_MMC_RX_INTR)); readl(ioaddr + GMAC_MMC_RX_INTR));
status |= core_mmc_rx_irq; x->mmc_rx_irq_n++;
} }
if (unlikely(intr_status & mmc_rx_csum_offload_irq)) { if (unlikely(intr_status & mmc_rx_csum_offload_irq)) {
CHIP_DBG(KERN_INFO "GMAC: MMC rx csum offload: 0x%08x\n", CHIP_DBG(KERN_INFO "GMAC: MMC rx csum offload: 0x%08x\n",
readl(ioaddr + GMAC_MMC_RX_CSUM_OFFLOAD)); readl(ioaddr + GMAC_MMC_RX_CSUM_OFFLOAD));
status |= core_mmc_rx_csum_offload_irq; x->mmc_rx_csum_offload_irq_n++;
} }
if (unlikely(intr_status & pmt_irq)) { if (unlikely(intr_status & pmt_irq)) {
CHIP_DBG(KERN_INFO "GMAC: received Magic frame\n"); CHIP_DBG(KERN_INFO "GMAC: received Magic frame\n");
/* clear the PMT bits 5 and 6 by reading the PMT /* clear the PMT bits 5 and 6 by reading the PMT
* status register. */ * status register. */
readl(ioaddr + GMAC_PMT); readl(ioaddr + GMAC_PMT);
status |= core_irq_receive_pmt_irq; x->irq_receive_pmt_irq_n++;
} }
/* MAC trx/rx EEE LPI entry/exit interrupts */ /* MAC trx/rx EEE LPI entry/exit interrupts */
if (intr_status & lpiis_irq) { if (intr_status & lpiis_irq) {
/* Clean LPI interrupt by reading the Reg 12 */ /* Clean LPI interrupt by reading the Reg 12 */
u32 lpi_status = readl(ioaddr + LPI_CTRL_STATUS); ret = readl(ioaddr + LPI_CTRL_STATUS);
if (lpi_status & LPI_CTRL_STATUS_TLPIEN) { if (ret & LPI_CTRL_STATUS_TLPIEN) {
CHIP_DBG(KERN_INFO "GMAC TX entered in LPI\n"); CHIP_DBG(KERN_INFO "GMAC TX entered in LPI\n");
status |= core_irq_tx_path_in_lpi_mode; x->irq_tx_path_in_lpi_mode_n++;
} }
if (lpi_status & LPI_CTRL_STATUS_TLPIEX) { if (ret & LPI_CTRL_STATUS_TLPIEX) {
CHIP_DBG(KERN_INFO "GMAC TX exit from LPI\n"); CHIP_DBG(KERN_INFO "GMAC TX exit from LPI\n");
status |= core_irq_tx_path_exit_lpi_mode; x->irq_tx_path_exit_lpi_mode_n++;
} }
if (lpi_status & LPI_CTRL_STATUS_RLPIEN) { if (ret & LPI_CTRL_STATUS_RLPIEN) {
CHIP_DBG(KERN_INFO "GMAC RX entered in LPI\n"); CHIP_DBG(KERN_INFO "GMAC RX entered in LPI\n");
status |= core_irq_rx_path_in_lpi_mode; x->irq_rx_path_in_lpi_mode_n++;
} }
if (lpi_status & LPI_CTRL_STATUS_RLPIEX) { if (ret & LPI_CTRL_STATUS_RLPIEX) {
CHIP_DBG(KERN_INFO "GMAC RX exit from LPI\n"); CHIP_DBG(KERN_INFO "GMAC RX exit from LPI\n");
status |= core_irq_rx_path_exit_lpi_mode; x->irq_rx_path_exit_lpi_mode_n++;
} }
} }
return status; if ((intr_status & pcs_ane_irq) || (intr_status & pcs_link_irq)) {
CHIP_DBG(KERN_INFO "GMAC PCS ANE IRQ\n");
readl(ioaddr + GMAC_AN_STATUS);
x->irq_pcs_ane_n++;
}
if (intr_status & rgmii_irq) {
CHIP_DBG(KERN_INFO "GMAC RGMII IRQ status\n");
readl(ioaddr + GMAC_S_R_GMII);
x->irq_rgmii_n++;
}
return ret;
} }
static void dwmac1000_set_eee_mode(void __iomem *ioaddr) static void dwmac1000_set_eee_mode(void __iomem *ioaddr)
......
...@@ -72,7 +72,8 @@ static int dwmac100_rx_ipc_enable(void __iomem *ioaddr) ...@@ -72,7 +72,8 @@ static int dwmac100_rx_ipc_enable(void __iomem *ioaddr)
return 0; return 0;
} }
static int dwmac100_irq_status(void __iomem *ioaddr) static int dwmac100_irq_status(void __iomem *ioaddr,
struct stmmac_extra_stats *x)
{ {
return 0; return 0;
} }
......
...@@ -131,6 +131,10 @@ static const struct stmmac_stats stmmac_gstrings_stats[] = { ...@@ -131,6 +131,10 @@ static const struct stmmac_stats stmmac_gstrings_stats[] = {
STMMAC_STAT(l3_filter_match), STMMAC_STAT(l3_filter_match),
STMMAC_STAT(l4_filter_match), STMMAC_STAT(l4_filter_match),
STMMAC_STAT(l3_l4_filter_no_match), STMMAC_STAT(l3_l4_filter_no_match),
/* PCS */
STMMAC_STAT(irq_pcs_ane_n),
STMMAC_STAT(irq_pcs_link_n),
STMMAC_STAT(irq_rgmii_n),
}; };
#define STMMAC_STATS_LEN ARRAY_SIZE(stmmac_gstrings_stats) #define STMMAC_STATS_LEN ARRAY_SIZE(stmmac_gstrings_stats)
......
...@@ -1780,31 +1780,15 @@ static irqreturn_t stmmac_interrupt(int irq, void *dev_id) ...@@ -1780,31 +1780,15 @@ static irqreturn_t stmmac_interrupt(int irq, void *dev_id)
/* To handle GMAC own interrupts */ /* To handle GMAC own interrupts */
if (priv->plat->has_gmac) { if (priv->plat->has_gmac) {
int status = priv->hw->mac->host_irq_status((void __iomem *) int status = priv->hw->mac->host_irq_status((void __iomem *)
dev->base_addr); dev->base_addr,
&priv->xstats);
if (unlikely(status)) { if (unlikely(status)) {
if (status & core_mmc_tx_irq)
priv->xstats.mmc_tx_irq_n++;
if (status & core_mmc_rx_irq)
priv->xstats.mmc_rx_irq_n++;
if (status & core_mmc_rx_csum_offload_irq)
priv->xstats.mmc_rx_csum_offload_irq_n++;
if (status & core_irq_receive_pmt_irq)
priv->xstats.irq_receive_pmt_irq_n++;
/* For LPI we need to save the tx status */ /* For LPI we need to save the tx status */
if (status & core_irq_tx_path_in_lpi_mode) { if (status & CORE_IRQ_TX_PATH_IN_LPI_MODE)
priv->xstats.irq_tx_path_in_lpi_mode_n++;
priv->tx_path_in_lpi_mode = true; priv->tx_path_in_lpi_mode = true;
} if (status & CORE_IRQ_TX_PATH_EXIT_LPI_MODE)
if (status & core_irq_tx_path_exit_lpi_mode) {
priv->xstats.irq_tx_path_exit_lpi_mode_n++;
priv->tx_path_in_lpi_mode = false; priv->tx_path_in_lpi_mode = false;
} }
if (status & core_irq_rx_path_in_lpi_mode)
priv->xstats.irq_rx_path_in_lpi_mode_n++;
if (status & core_irq_rx_path_exit_lpi_mode)
priv->xstats.irq_rx_path_exit_lpi_mode_n++;
}
} }
/* To handle DMA interrupts */ /* To handle DMA interrupts */
......
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