Commit 36cfd3a6 authored by Russell King's avatar Russell King Committed by David S. Miller

net: mvpp2: restructure "link status" interrupt handling

The "link status" interrupt is used for more than just link status.
Restructure mvpp2_link_status_isr() so we can add additional handling.
Reviewed-by: default avatarAndrew Lunn <andrew@lunn.ch>
Signed-off-by: default avatarRussell King <rmk+kernel@armlinux.org.uk>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent b599a5b9
...@@ -2974,62 +2974,81 @@ static irqreturn_t mvpp2_isr(int irq, void *dev_id) ...@@ -2974,62 +2974,81 @@ static irqreturn_t mvpp2_isr(int irq, void *dev_id)
return IRQ_HANDLED; return IRQ_HANDLED;
} }
/* Per-port interrupt for link status changes */ static void mvpp2_isr_handle_link(struct mvpp2_port *port, bool link)
static irqreturn_t mvpp2_link_status_isr(int irq, void *dev_id)
{ {
struct mvpp2_port *port = (struct mvpp2_port *)dev_id;
struct net_device *dev = port->dev; struct net_device *dev = port->dev;
bool event = false, link = false;
u32 val;
mvpp22_gop_mask_irq(port); if (port->phylink) {
phylink_mac_change(port->phylink, link);
return;
}
if (!netif_running(dev))
return;
if (link) {
mvpp2_interrupts_enable(port);
mvpp2_egress_enable(port);
mvpp2_ingress_enable(port);
netif_carrier_on(dev);
netif_tx_wake_all_queues(dev);
} else {
netif_tx_stop_all_queues(dev);
netif_carrier_off(dev);
mvpp2_ingress_disable(port);
mvpp2_egress_disable(port);
mvpp2_interrupts_disable(port);
}
}
static void mvpp2_isr_handle_xlg(struct mvpp2_port *port)
{
bool link;
u32 val;
if (mvpp2_port_supports_xlg(port) &&
mvpp2_is_xlg(port->phy_interface)) {
val = readl(port->base + MVPP22_XLG_INT_STAT); val = readl(port->base + MVPP22_XLG_INT_STAT);
if (val & MVPP22_XLG_INT_STAT_LINK) { if (val & MVPP22_XLG_INT_STAT_LINK) {
event = true;
val = readl(port->base + MVPP22_XLG_STATUS); val = readl(port->base + MVPP22_XLG_STATUS);
if (val & MVPP22_XLG_STATUS_LINK_UP) if (val & MVPP22_XLG_STATUS_LINK_UP)
link = true; link = true;
mvpp2_isr_handle_link(port, link);
} }
} else if (phy_interface_mode_is_rgmii(port->phy_interface) || }
static void mvpp2_isr_handle_gmac_internal(struct mvpp2_port *port)
{
bool link;
u32 val;
if (phy_interface_mode_is_rgmii(port->phy_interface) ||
phy_interface_mode_is_8023z(port->phy_interface) || phy_interface_mode_is_8023z(port->phy_interface) ||
port->phy_interface == PHY_INTERFACE_MODE_SGMII) { port->phy_interface == PHY_INTERFACE_MODE_SGMII) {
val = readl(port->base + MVPP22_GMAC_INT_STAT); val = readl(port->base + MVPP22_GMAC_INT_STAT);
if (val & MVPP22_GMAC_INT_STAT_LINK) { if (val & MVPP22_GMAC_INT_STAT_LINK) {
event = true;
val = readl(port->base + MVPP2_GMAC_STATUS0); val = readl(port->base + MVPP2_GMAC_STATUS0);
if (val & MVPP2_GMAC_STATUS0_LINK_UP) if (val & MVPP2_GMAC_STATUS0_LINK_UP)
link = true; link = true;
mvpp2_isr_handle_link(port, link);
} }
} }
}
if (port->phylink) { /* Per-port interrupt for link status changes */
phylink_mac_change(port->phylink, link); static irqreturn_t mvpp2_link_status_isr(int irq, void *dev_id)
goto handled; {
} struct mvpp2_port *port = (struct mvpp2_port *)dev_id;
if (!netif_running(dev) || !event)
goto handled;
if (link) { mvpp22_gop_mask_irq(port);
mvpp2_interrupts_enable(port);
mvpp2_egress_enable(port); if (mvpp2_port_supports_xlg(port) &&
mvpp2_ingress_enable(port); mvpp2_is_xlg(port->phy_interface)) {
netif_carrier_on(dev); mvpp2_isr_handle_xlg(port);
netif_tx_wake_all_queues(dev);
} else { } else {
netif_tx_stop_all_queues(dev); mvpp2_isr_handle_gmac_internal(port);
netif_carrier_off(dev);
mvpp2_ingress_disable(port);
mvpp2_egress_disable(port);
mvpp2_interrupts_disable(port);
} }
handled:
mvpp22_gop_unmask_irq(port); mvpp22_gop_unmask_irq(port);
return IRQ_HANDLED; return IRQ_HANDLED;
} }
......
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