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:
Родитель
c24602ef86
Коммит
0982a0f6d1
|
@ -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++;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче