Skip to content

Commit

Permalink
net: netcp: Fixes SGMII reset on network interface shutdown
Browse files Browse the repository at this point in the history
This patch asserts SGMII RTRESET, i.e. resetting the SGMII Tx/Rx
logic,  during network interface shutdown to avoid having the
hardware wedge when shutting down with high incoming traffic rates.
This is cleared (brought out of RTRESET) when the interface is
brought back up.

Signed-off-by: WingMan Kwok <w-kwok2@ti.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
WingMan Kwok authored and David S. Miller committed Jul 27, 2015
1 parent 54109da commit 7025e88
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 2 deletions.
1 change: 1 addition & 0 deletions drivers/net/ethernet/ti/netcp.h
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,7 @@ void *netcp_device_find_module(struct netcp_device *netcp_device,

/* SGMII functions */
int netcp_sgmii_reset(void __iomem *sgmii_ofs, int port);
bool netcp_sgmii_rtreset(void __iomem *sgmii_ofs, int port, bool set);
int netcp_sgmii_get_port_link(void __iomem *sgmii_ofs, int port);
int netcp_sgmii_config(void __iomem *sgmii_ofs, int port, u32 interface);

Expand Down
18 changes: 18 additions & 0 deletions drivers/net/ethernet/ti/netcp_ethss.c
Original file line number Diff line number Diff line change
Expand Up @@ -1901,11 +1901,28 @@ static void gbe_port_config(struct gbe_priv *gbe_dev, struct gbe_slave *slave,
writel(slave->mac_control, GBE_REG_ADDR(slave, emac_regs, mac_control));
}

static void gbe_sgmii_rtreset(struct gbe_priv *priv,
struct gbe_slave *slave, bool set)
{
void __iomem *sgmii_port_regs;

if (SLAVE_LINK_IS_XGMII(slave))
return;

if ((priv->ss_version == GBE_SS_VERSION_14) && (slave->slave_num >= 2))
sgmii_port_regs = priv->sgmii_port34_regs;
else
sgmii_port_regs = priv->sgmii_port_regs;

netcp_sgmii_rtreset(sgmii_port_regs, slave->slave_num, set);
}

static void gbe_slave_stop(struct gbe_intf *intf)
{
struct gbe_priv *gbe_dev = intf->gbe_dev;
struct gbe_slave *slave = intf->slave;

gbe_sgmii_rtreset(gbe_dev, slave, true);
gbe_port_reset(slave);
/* Disable forwarding */
cpsw_ale_control_set(gbe_dev->ale, slave->port_num,
Expand Down Expand Up @@ -1947,6 +1964,7 @@ static int gbe_slave_open(struct gbe_intf *gbe_intf)

gbe_sgmii_config(priv, slave);
gbe_port_reset(slave);
gbe_sgmii_rtreset(priv, slave, false);
gbe_port_config(priv, slave, priv->rx_packet_max);
gbe_set_slave_mac(slave, gbe_intf);
/* enable forwarding */
Expand Down
30 changes: 28 additions & 2 deletions drivers/net/ethernet/ti/netcp_sgmii.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@

#include "netcp.h"

#define SGMII_SRESET_RESET BIT(0)
#define SGMII_SRESET_RTRESET BIT(1)

#define SGMII_REG_STATUS_LOCK BIT(4)
#define SGMII_REG_STATUS_LINK BIT(0)
#define SGMII_REG_STATUS_AUTONEG BIT(2)
Expand Down Expand Up @@ -51,12 +54,35 @@ static void sgmii_write_reg_bit(void __iomem *base, int reg, u32 val)
int netcp_sgmii_reset(void __iomem *sgmii_ofs, int port)
{
/* Soft reset */
sgmii_write_reg_bit(sgmii_ofs, SGMII_SRESET_REG(port), 0x1);
while (sgmii_read_reg(sgmii_ofs, SGMII_SRESET_REG(port)) != 0x0)
sgmii_write_reg_bit(sgmii_ofs, SGMII_SRESET_REG(port),
SGMII_SRESET_RESET);

while ((sgmii_read_reg(sgmii_ofs, SGMII_SRESET_REG(port)) &
SGMII_SRESET_RESET) != 0x0)
;

return 0;
}

/* port is 0 based */
bool netcp_sgmii_rtreset(void __iomem *sgmii_ofs, int port, bool set)
{
u32 reg;
bool oldval;

/* Initiate a soft reset */
reg = sgmii_read_reg(sgmii_ofs, SGMII_SRESET_REG(port));
oldval = (reg & SGMII_SRESET_RTRESET) != 0x0;
if (set)
reg |= SGMII_SRESET_RTRESET;
else
reg &= ~SGMII_SRESET_RTRESET;
sgmii_write_reg(sgmii_ofs, SGMII_SRESET_REG(port), reg);
wmb();

return oldval;
}

int netcp_sgmii_get_port_link(void __iomem *sgmii_ofs, int port)
{
u32 status = 0, link = 0;
Expand Down

0 comments on commit 7025e88

Please sign in to comment.