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 {
unsigned long l3_filter_match;
unsigned long l4_filter_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*/
......@@ -217,16 +221,14 @@ enum dma_irq_status {
handle_tx = 0x8,
};
enum core_specific_irq_mask {
core_mmc_tx_irq = 1,
core_mmc_rx_irq = 2,
core_mmc_rx_csum_offload_irq = 4,
core_irq_receive_pmt_irq = 8,
core_irq_tx_path_in_lpi_mode = 16,
core_irq_tx_path_exit_lpi_mode = 32,
core_irq_rx_path_in_lpi_mode = 64,
core_irq_rx_path_exit_lpi_mode = 128,
};
#define CORE_IRQ_TX_PATH_IN_LPI_MODE (1 << 1)
#define CORE_IRQ_TX_PATH_EXIT_LPI_MODE (1 << 2)
#define CORE_IRQ_RX_PATH_IN_LPI_MODE (1 << 3)
#define CORE_IRQ_RX_PATH_EXIT_LPI_MODE (1 << 4)
#define CORE_PCS_ANE_COMPLETE (1 << 5)
#define CORE_PCS_LINK_STATUS (1 << 6)
#define CORE_RGMII_IRQ (1 << 7)
/* DMA HW capabilities */
struct dma_features {
......@@ -355,7 +357,8 @@ struct stmmac_ops {
/* Dump MAC registers */
void (*dump_regs) (void __iomem *ioaddr);
/* 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 */
void (*set_filter) (struct net_device *dev, int id);
/* Flow control setting */
......
......@@ -89,13 +89,14 @@ enum power_event {
(reg * 8))
#define GMAC_MAX_PERFECT_ADDRESSES 32
/* PCS registers (AN/TBI/SGMII/RGMII) offset */
#define GMAC_AN_CTRL 0x000000c0 /* AN control */
#define GMAC_AN_STATUS 0x000000c4 /* AN status */
#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_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 */
#define GMAC_CONTROL_TC 0x01000000 /* Transmit Conf. in RGMII/SGMII */
......
......@@ -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);
int status = 0;
int ret = 0;
/* Not used events (e.g. MMC interrupts) are not handled. */
if ((intr_status & mmc_tx_irq)) {
CHIP_DBG(KERN_INFO "GMAC: MMC tx interrupt: 0x%08x\n",
readl(ioaddr + GMAC_MMC_TX_INTR));
status |= core_mmc_tx_irq;
x->mmc_tx_irq_n++;
}
if (unlikely(intr_status & mmc_rx_irq)) {
CHIP_DBG(KERN_INFO "GMAC: MMC rx interrupt: 0x%08x\n",
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)) {
CHIP_DBG(KERN_INFO "GMAC: MMC rx csum offload: 0x%08x\n",
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)) {
CHIP_DBG(KERN_INFO "GMAC: received Magic frame\n");
/* clear the PMT bits 5 and 6 by reading the PMT
* status register. */
readl(ioaddr + GMAC_PMT);
status |= core_irq_receive_pmt_irq;
x->irq_receive_pmt_irq_n++;
}
/* MAC trx/rx EEE LPI entry/exit interrupts */
if (intr_status & lpiis_irq) {
/* 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");
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");
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");
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");
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)
......
......@@ -72,7 +72,8 @@ static int dwmac100_rx_ipc_enable(void __iomem *ioaddr)
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;
}
......
......@@ -131,6 +131,10 @@ static const struct stmmac_stats stmmac_gstrings_stats[] = {
STMMAC_STAT(l3_filter_match),
STMMAC_STAT(l4_filter_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)
......
......@@ -1780,30 +1780,14 @@ static irqreturn_t stmmac_interrupt(int irq, void *dev_id)
/* To handle GMAC own interrupts */
if (priv->plat->has_gmac) {
int status = priv->hw->mac->host_irq_status((void __iomem *)
dev->base_addr);
dev->base_addr,
&priv->xstats);
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 */
if (status & core_irq_tx_path_in_lpi_mode) {
priv->xstats.irq_tx_path_in_lpi_mode_n++;
if (status & CORE_IRQ_TX_PATH_IN_LPI_MODE)
priv->tx_path_in_lpi_mode = true;
}
if (status & core_irq_tx_path_exit_lpi_mode) {
priv->xstats.irq_tx_path_exit_lpi_mode_n++;
if (status & CORE_IRQ_TX_PATH_EXIT_LPI_MODE)
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++;
}
}
......
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