Skip to content

Commit

Permalink
drivers: net: stmmac: rework core ISR to better manage PCS and PMT
Browse files Browse the repository at this point in the history
By default, all gmac cores disable the PCS block and always
enable the PMT.

Note that this is done in a different way by 3.x and 4.x cores.

With this rework, PCS and PMT interrupt masks can be driven by
parameters now moved inside the mac_device_info structure
and the settings follow what the HW capability register reports.

Signed-off-by: Giuseppe Cavallaro <peppe.cavallaro@st.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Giuseppe CAVALLARO authored and David S. Miller committed Jun 28, 2016
1 parent 70523e6 commit 3fe5cad
Show file tree
Hide file tree
Showing 8 changed files with 79 additions and 35 deletions.
2 changes: 2 additions & 0 deletions drivers/net/ethernet/stmicro/stmmac/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -529,6 +529,8 @@ struct mac_device_info {
int unicast_filter_entries;
int mcast_bits_log2;
unsigned int rx_csum;
unsigned int pcs;
unsigned int pmt;
};

struct mac_device_info *dwmac1000_setup(void __iomem *ioaddr, int mcbins,
Expand Down
30 changes: 20 additions & 10 deletions drivers/net/ethernet/stmicro/stmmac/dwmac1000.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,16 +38,26 @@
#define GMAC_WAKEUP_FILTER 0x00000028 /* Wake-up Frame Filter */

#define GMAC_INT_STATUS 0x00000038 /* interrupt status register */
enum dwmac1000_irq_status {
lpiis_irq = 0x400,
time_stamp_irq = 0x0200,
mmc_rx_csum_offload_irq = 0x0080,
mmc_tx_irq = 0x0040,
mmc_rx_irq = 0x0020,
mmc_irq = 0x0010,
pmt_irq = 0x0008,
};
#define GMAC_INT_MASK 0x0000003c /* interrupt mask register */
#define GMAC_INT_STATUS_PMT BIT(3)
#define GMAC_INT_STATUS_MMCIS BIT(4)
#define GMAC_INT_STATUS_MMCRIS BIT(5)
#define GMAC_INT_STATUS_MMCTIS BIT(6)
#define GMAC_INT_STATUS_MMCCSUM BIT(7)
#define GMAC_INT_STATUS_TSTAMP BIT(9)
#define GMAC_INT_STATUS_LPIIS BIT(10)

/* interrupt mask register */
#define GMAC_INT_MASK 0x0000003c
#define GMAC_INT_DISABLE_RGMII BIT(0)
#define GMAC_INT_DISABLE_PCSLINK BIT(1)
#define GMAC_INT_DISABLE_PCSAN BIT(2)
#define GMAC_INT_DISABLE_PMT BIT(3)
#define GMAC_INT_DISABLE_TIMESTAMP BIT(9)
#define GMAC_INT_DISABLE_PCS (GMAC_INT_DISABLE_RGMII | \
GMAC_INT_DISABLE_PCSLINK | \
GMAC_INT_DISABLE_PCSAN)
#define GMAC_INT_DEFAULT_MASK (GMAC_INT_DISABLE_TIMESTAMP | \
GMAC_INT_DISABLE_PCS)

/* PMT Control and Status */
#define GMAC_PMT 0x0000002c
Expand Down
24 changes: 17 additions & 7 deletions drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,10 @@ static void dwmac1000_core_init(struct mac_device_info *hw, int mtu)
{
void __iomem *ioaddr = hw->pcsr;
u32 value = readl(ioaddr + GMAC_CONTROL);

/* Configure GMAC core */
value |= GMAC_CORE_INIT;

if (mtu > 1500)
value |= GMAC_CONTROL_2K;
if (mtu > 2000)
Expand All @@ -46,7 +49,14 @@ static void dwmac1000_core_init(struct mac_device_info *hw, int mtu)
writel(value, ioaddr + GMAC_CONTROL);

/* Mask GMAC interrupts */
writel(0x207, ioaddr + GMAC_INT_MASK);
value = GMAC_INT_DEFAULT_MASK;

if (hw->pmt)
value &= ~GMAC_INT_DISABLE_PMT;
if (hw->pcs)
value &= ~GMAC_INT_DISABLE_PCS;

writel(value, ioaddr + GMAC_INT_MASK);

#ifdef STMMAC_VLAN_TAG_USED
/* Tag detection without filtering */
Expand Down Expand Up @@ -283,20 +293,20 @@ static int dwmac1000_irq_status(struct mac_device_info *hw,
int ret = 0;

/* Not used events (e.g. MMC interrupts) are not handled. */
if ((intr_status & mmc_tx_irq))
if ((intr_status & GMAC_INT_STATUS_MMCTIS))
x->mmc_tx_irq_n++;
if (unlikely(intr_status & mmc_rx_irq))
if (unlikely(intr_status & GMAC_INT_STATUS_MMCRIS))
x->mmc_rx_irq_n++;
if (unlikely(intr_status & mmc_rx_csum_offload_irq))
if (unlikely(intr_status & GMAC_INT_STATUS_MMCCSUM))
x->mmc_rx_csum_offload_irq_n++;
if (unlikely(intr_status & pmt_irq)) {
if (unlikely(intr_status & GMAC_INT_DISABLE_PMT)) {
/* clear the PMT bits 5 and 6 by reading the PMT status reg */
readl(ioaddr + GMAC_PMT);
x->irq_receive_pmt_irq_n++;
}

/* MAC trx/rx EEE LPI entry/exit interrupts */
if (intr_status & lpiis_irq) {
/* MAC tx/rx EEE LPI entry/exit interrupts */
if (intr_status & GMAC_INT_STATUS_LPIIS) {
/* Clean LPI interrupt by reading the Reg 12 */
ret = readl(ioaddr + LPI_CTRL_STATUS);

Expand Down
9 changes: 9 additions & 0 deletions drivers/net/ethernet/stmicro/stmmac/dwmac4.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,18 @@
#define GMAC_TX_FLOW_CTRL_PT_SHIFT 16

/* MAC Interrupt bitmap*/
#define GMAC_INT_RGSMIIS BIT(0)
#define GMAC_INT_PCS_LINK BIT(1)
#define GMAC_INT_PCS_ANE BIT(2)
#define GMAC_INT_PCS_PHYIS BIT(3)
#define GMAC_INT_PMT_EN BIT(4)
#define GMAC_INT_LPI_EN BIT(5)

#define GMAC_PCS_IRQ_DEFAULT (GMAC_INT_RGSMIIS | GMAC_INT_PCS_LINK | \
GMAC_INT_PCS_ANE)

#define GMAC_INT_DEFAULT_MASK GMAC_INT_PMT_EN

enum dwmac4_irq_status {
time_stamp_irq = 0x00001000,
mmc_rx_csum_offload_irq = 0x00000800,
Expand Down
8 changes: 7 additions & 1 deletion drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,13 @@ static void dwmac4_core_init(struct mac_device_info *hw, int mtu)
writel(value, ioaddr + GMAC_CONFIG);

/* Mask GMAC interrupts */
writel(GMAC_INT_PMT_EN, ioaddr + GMAC_INT_EN);
value = GMAC_INT_DEFAULT_MASK;
if (hw->pmt)
value |= GMAC_INT_PMT_EN;
if (hw->pcs)
value |= GMAC_PCS_IRQ_DEFAULT;

writel(value, ioaddr + GMAC_INT_EN);
}

static void dwmac4_dump_regs(struct mac_device_info *hw)
Expand Down
1 change: 0 additions & 1 deletion drivers/net/ethernet/stmicro/stmmac/stmmac.h
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,6 @@ struct stmmac_priv {
int eee_enabled;
int eee_active;
int tx_lpi_timer;
int pcs;
unsigned int mode;
int extend_desc;
struct ptp_clock *ptp_clock;
Expand Down
11 changes: 7 additions & 4 deletions drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
Original file line number Diff line number Diff line change
Expand Up @@ -276,7 +276,8 @@ static int stmmac_ethtool_getsettings(struct net_device *dev,
struct phy_device *phy = priv->phydev;
int rc;

if ((priv->pcs & STMMAC_PCS_RGMII) || (priv->pcs & STMMAC_PCS_SGMII)) {
if (priv->hw->pcs & STMMAC_PCS_RGMII ||
priv->hw->pcs & STMMAC_PCS_SGMII) {
struct rgmii_adv adv;

if (!priv->xstats.pcs_link) {
Expand Down Expand Up @@ -361,7 +362,8 @@ static int stmmac_ethtool_setsettings(struct net_device *dev,
struct phy_device *phy = priv->phydev;
int rc;

if ((priv->pcs & STMMAC_PCS_RGMII) || (priv->pcs & STMMAC_PCS_SGMII)) {
if (priv->hw->pcs & STMMAC_PCS_RGMII ||
priv->hw->pcs & STMMAC_PCS_SGMII) {
u32 mask = ADVERTISED_Autoneg | ADVERTISED_Pause;

/* Only support ANE */
Expand Down Expand Up @@ -457,7 +459,7 @@ stmmac_get_pauseparam(struct net_device *netdev,
pause->rx_pause = 0;
pause->tx_pause = 0;

if (priv->pcs && priv->hw->mac->pcs_get_adv_lp) {
if (priv->hw->pcs && priv->hw->mac->pcs_get_adv_lp) {
struct rgmii_adv adv_lp;

pause->autoneg = 1;
Expand Down Expand Up @@ -487,7 +489,7 @@ stmmac_set_pauseparam(struct net_device *netdev,
struct phy_device *phy = priv->phydev;
int new_pause = FLOW_OFF;

if (priv->pcs && priv->hw->mac->pcs_get_adv_lp) {
if (priv->hw->pcs && priv->hw->mac->pcs_get_adv_lp) {
struct rgmii_adv adv_lp;

pause->autoneg = 1;
Expand All @@ -507,6 +509,7 @@ stmmac_set_pauseparam(struct net_device *netdev,

priv->flow_ctrl = new_pause;
phy->autoneg = pause->autoneg;

if (phy->autoneg) {
if (netif_running(netdev))
return phy_start_aneg(phy);
Expand Down
29 changes: 17 additions & 12 deletions drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -285,8 +285,9 @@ bool stmmac_eee_init(struct stmmac_priv *priv)
/* Using PCS we cannot dial with the phy registers at this stage
* so we do not support extra feature like EEE.
*/
if ((priv->pcs == STMMAC_PCS_RGMII) || (priv->pcs == STMMAC_PCS_TBI) ||
(priv->pcs == STMMAC_PCS_RTBI))
if ((priv->hw->pcs == STMMAC_PCS_RGMII) ||
(priv->hw->pcs == STMMAC_PCS_TBI) ||
(priv->hw->pcs == STMMAC_PCS_RTBI))
goto out;

/* MAC core supports the EEE feature. */
Expand Down Expand Up @@ -799,10 +800,10 @@ static void stmmac_check_pcs_mode(struct stmmac_priv *priv)
(interface == PHY_INTERFACE_MODE_RGMII_RXID) ||
(interface == PHY_INTERFACE_MODE_RGMII_TXID)) {
pr_debug("STMMAC: PCS RGMII support enable\n");
priv->pcs = STMMAC_PCS_RGMII;
priv->hw->pcs = STMMAC_PCS_RGMII;
} else if (interface == PHY_INTERFACE_MODE_SGMII) {
pr_debug("STMMAC: PCS SGMII support enable\n");
priv->pcs = STMMAC_PCS_SGMII;
priv->hw->pcs = STMMAC_PCS_SGMII;
}
}
}
Expand Down Expand Up @@ -1714,7 +1715,7 @@ static int stmmac_hw_setup(struct net_device *dev, bool init_ptp)
priv->hw->dma->rx_watchdog(priv->ioaddr, MAX_DMA_RIWT);
}

if (priv->pcs && priv->hw->mac->pcs_ctrl_ane)
if (priv->hw->pcs && priv->hw->mac->pcs_ctrl_ane)
priv->hw->mac->pcs_ctrl_ane(priv->hw, 1, 0, 0);

/* set TX ring length */
Expand Down Expand Up @@ -1748,8 +1749,9 @@ static int stmmac_open(struct net_device *dev)

stmmac_check_ether_addr(priv);

if (priv->pcs != STMMAC_PCS_RGMII && priv->pcs != STMMAC_PCS_TBI &&
priv->pcs != STMMAC_PCS_RTBI) {
if (priv->hw->pcs != STMMAC_PCS_RGMII &&
priv->hw->pcs != STMMAC_PCS_TBI &&
priv->hw->pcs != STMMAC_PCS_RTBI) {
ret = stmmac_init_phy(dev);
if (ret) {
pr_err("%s: Cannot attach to PHY (error: %d)\n",
Expand Down Expand Up @@ -2811,7 +2813,7 @@ static irqreturn_t stmmac_interrupt(int irq, void *dev_id)
}

/* PCS link status */
if (priv->pcs) {
if (priv->hw->pcs) {
if (priv->xstats.pcs_link)
netif_carrier_on(dev);
else
Expand Down Expand Up @@ -3138,6 +3140,7 @@ static int stmmac_hw_init(struct stmmac_priv *priv)
*/
priv->plat->enh_desc = priv->dma_cap.enh_desc;
priv->plat->pmt = priv->dma_cap.pmt_remote_wake_up;
priv->hw->pmt = priv->plat->pmt;

/* TXCOE doesn't work in thresh DMA mode */
if (priv->plat->force_thresh_dma_mode)
Expand Down Expand Up @@ -3333,8 +3336,9 @@ int stmmac_dvr_probe(struct device *device,

stmmac_check_pcs_mode(priv);

if (priv->pcs != STMMAC_PCS_RGMII && priv->pcs != STMMAC_PCS_TBI &&
priv->pcs != STMMAC_PCS_RTBI) {
if (priv->hw->pcs != STMMAC_PCS_RGMII &&
priv->hw->pcs != STMMAC_PCS_TBI &&
priv->hw->pcs != STMMAC_PCS_RTBI) {
/* MDIO bus Registration */
ret = stmmac_mdio_register(ndev);
if (ret < 0) {
Expand Down Expand Up @@ -3384,8 +3388,9 @@ int stmmac_dvr_remove(struct device *dev)
reset_control_assert(priv->stmmac_rst);
clk_disable_unprepare(priv->pclk);
clk_disable_unprepare(priv->stmmac_clk);
if (priv->pcs != STMMAC_PCS_RGMII && priv->pcs != STMMAC_PCS_TBI &&
priv->pcs != STMMAC_PCS_RTBI)
if (priv->hw->pcs != STMMAC_PCS_RGMII &&
priv->hw->pcs != STMMAC_PCS_TBI &&
priv->hw->pcs != STMMAC_PCS_RTBI)
stmmac_mdio_unregister(ndev);
free_netdev(ndev);

Expand Down

0 comments on commit 3fe5cad

Please sign in to comment.