Skip to content

Commit

Permalink
drivers: net: xgene: XFI PCS reset when link is down
Browse files Browse the repository at this point in the history
This patch fixes the link recovery issue, by doing PCS reset
when the link is down.

Signed-off-by: Fushen Chen <fchen@apm.com>
Signed-off-by: Iyappan Subramanian <isubramanian@apm.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Iyappan Subramanian authored and David S. Miller committed Aug 13, 2016
1 parent 4f1c8d8 commit 3eb7cb9
Show file tree
Hide file tree
Showing 5 changed files with 54 additions and 0 deletions.
6 changes: 6 additions & 0 deletions drivers/net/ethernet/apm/xgene/xgene_enet_hw.h
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,12 @@ enum xgene_enet_rm {
#define MAC_READ_REG_OFFSET 0x0c
#define MAC_COMMAND_DONE_REG_OFFSET 0x10

#define PCS_ADDR_REG_OFFSET 0x00
#define PCS_COMMAND_REG_OFFSET 0x04
#define PCS_WRITE_REG_OFFSET 0x08
#define PCS_READ_REG_OFFSET 0x0c
#define PCS_COMMAND_DONE_REG_OFFSET 0x10

#define MII_MGMT_CONFIG_ADDR 0x20
#define MII_MGMT_COMMAND_ADDR 0x24
#define MII_MGMT_ADDRESS_ADDR 0x28
Expand Down
1 change: 1 addition & 0 deletions drivers/net/ethernet/apm/xgene/xgene_enet_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -1433,6 +1433,7 @@ static int xgene_enet_get_resources(struct xgene_enet_pdata *pdata)
} else {
pdata->mcx_mac_addr = base_addr + BLOCK_AXG_MAC_OFFSET;
pdata->mcx_mac_csr_addr = base_addr + BLOCK_AXG_MAC_CSR_OFFSET;
pdata->pcs_addr = base_addr + BLOCK_PCS_OFFSET;
}
pdata->rx_buff_cnt = NUM_PKT_BUF;

Expand Down
1 change: 1 addition & 0 deletions drivers/net/ethernet/apm/xgene/xgene_enet_main.h
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,7 @@ struct xgene_enet_pdata {
void __iomem *mcx_mac_addr;
void __iomem *mcx_mac_csr_addr;
void __iomem *base_addr;
void __iomem *pcs_addr;
void __iomem *ring_csr_addr;
void __iomem *ring_cmd_addr;
int phy_mode;
Expand Down
42 changes: 42 additions & 0 deletions drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,21 @@ static void xgene_enet_wr_mac(struct xgene_enet_pdata *pdata,
wr_addr);
}

static void xgene_enet_wr_pcs(struct xgene_enet_pdata *pdata,
u32 wr_addr, u32 wr_data)
{
void __iomem *addr, *wr, *cmd, *cmd_done;

addr = pdata->pcs_addr + PCS_ADDR_REG_OFFSET;
wr = pdata->pcs_addr + PCS_WRITE_REG_OFFSET;
cmd = pdata->pcs_addr + PCS_COMMAND_REG_OFFSET;
cmd_done = pdata->pcs_addr + PCS_COMMAND_DONE_REG_OFFSET;

if (!xgene_enet_wr_indirect(addr, wr, cmd, cmd_done, wr_addr, wr_data))
netdev_err(pdata->ndev, "PCS write failed, addr: %04x\n",
wr_addr);
}

static void xgene_enet_rd_csr(struct xgene_enet_pdata *pdata,
u32 offset, u32 *val)
{
Expand Down Expand Up @@ -122,6 +137,7 @@ static bool xgene_enet_rd_indirect(void __iomem *addr, void __iomem *rd,

return true;
}

static void xgene_enet_rd_mac(struct xgene_enet_pdata *pdata,
u32 rd_addr, u32 *rd_data)
{
Expand All @@ -137,6 +153,21 @@ static void xgene_enet_rd_mac(struct xgene_enet_pdata *pdata,
rd_addr);
}

static void xgene_enet_rd_pcs(struct xgene_enet_pdata *pdata,
u32 rd_addr, u32 *rd_data)
{
void __iomem *addr, *rd, *cmd, *cmd_done;

addr = pdata->pcs_addr + PCS_ADDR_REG_OFFSET;
rd = pdata->pcs_addr + PCS_READ_REG_OFFSET;
cmd = pdata->pcs_addr + PCS_COMMAND_REG_OFFSET;
cmd_done = pdata->pcs_addr + PCS_COMMAND_DONE_REG_OFFSET;

if (!xgene_enet_rd_indirect(addr, rd, cmd, cmd_done, rd_addr, rd_data))
netdev_err(pdata->ndev, "PCS read failed, addr: %04x\n",
rd_addr);
}

static int xgene_enet_ecc_init(struct xgene_enet_pdata *pdata)
{
struct net_device *ndev = pdata->ndev;
Expand Down Expand Up @@ -171,6 +202,15 @@ static void xgene_xgmac_reset(struct xgene_enet_pdata *pdata)
xgene_enet_wr_mac(pdata, AXGMAC_CONFIG_0, 0);
}

static void xgene_pcs_reset(struct xgene_enet_pdata *pdata)
{
u32 data;

xgene_enet_rd_pcs(pdata, PCS_CONTROL_1, &data);
xgene_enet_wr_pcs(pdata, PCS_CONTROL_1, data | PCS_CTRL_PCS_RST);
xgene_enet_wr_pcs(pdata, PCS_CONTROL_1, data & ~PCS_CTRL_PCS_RST);
}

static void xgene_xgmac_set_mac_addr(struct xgene_enet_pdata *pdata)
{
u32 addr0, addr1;
Expand Down Expand Up @@ -379,6 +419,8 @@ static void xgene_enet_link_state(struct work_struct *work)
netdev_info(ndev, "Link is Down\n");
}
poll_interval = PHY_POLL_LINK_OFF;

xgene_pcs_reset(pdata);
}

schedule_delayed_work(&pdata->link_work, poll_interval);
Expand Down
4 changes: 4 additions & 0 deletions drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#define X2_BLOCK_ETH_MAC_CSR_OFFSET 0x3000
#define BLOCK_AXG_MAC_OFFSET 0x0800
#define BLOCK_AXG_MAC_CSR_OFFSET 0x2000
#define BLOCK_PCS_OFFSET 0x3800

#define XGENET_CONFIG_REG_ADDR 0x20
#define XGENET_SRST_ADDR 0x00
Expand Down Expand Up @@ -72,6 +73,9 @@
#define XG_MCX_ICM_CONFIG0_REG_0_ADDR 0x00e0
#define XG_MCX_ICM_CONFIG2_REG_0_ADDR 0x00e8

#define PCS_CONTROL_1 0x0000
#define PCS_CTRL_PCS_RST BIT(15)

extern const struct xgene_mac_ops xgene_xgmac_ops;
extern const struct xgene_port_ops xgene_xgport_ops;

Expand Down

0 comments on commit 3eb7cb9

Please sign in to comment.