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: Giuseppe Cavallaro <peppe.cavallaro@st.com> Tested-by: Byungho An <bh74.an@samsung.com> Cc: Udit Kumar <udit-dlh.kumar@st.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
c24602ef86
commit
0982a0f6d1
6 changed files with 55 additions and 50 deletions
|
@ -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 {
|
||||||
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 {
|
||||||
/* 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 {
|
||||||
(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)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
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)
|
||||||
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[] = {
|
||||||
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,30 +1780,14 @@ 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++;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue