|
@@ -205,30 +205,24 @@ static u32 xgene_enet_ring_len(struct xgene_enet_desc_ring *ring)
|
|
|
}
|
|
|
|
|
|
void xgene_enet_parse_error(struct xgene_enet_desc_ring *ring,
|
|
|
- struct xgene_enet_pdata *pdata,
|
|
|
enum xgene_enet_err_code status)
|
|
|
{
|
|
|
switch (status) {
|
|
|
case INGRESS_CRC:
|
|
|
ring->rx_crc_errors++;
|
|
|
- ring->rx_dropped++;
|
|
|
break;
|
|
|
case INGRESS_CHECKSUM:
|
|
|
case INGRESS_CHECKSUM_COMPUTE:
|
|
|
ring->rx_errors++;
|
|
|
- ring->rx_dropped++;
|
|
|
break;
|
|
|
case INGRESS_TRUNC_FRAME:
|
|
|
ring->rx_frame_errors++;
|
|
|
- ring->rx_dropped++;
|
|
|
break;
|
|
|
case INGRESS_PKT_LEN:
|
|
|
ring->rx_length_errors++;
|
|
|
- ring->rx_dropped++;
|
|
|
break;
|
|
|
case INGRESS_PKT_UNDER:
|
|
|
ring->rx_frame_errors++;
|
|
|
- ring->rx_dropped++;
|
|
|
break;
|
|
|
case INGRESS_FIFO_OVERRUN:
|
|
|
ring->rx_fifo_errors++;
|
|
@@ -270,42 +264,39 @@ static void xgene_enet_wr_mcx_csr(struct xgene_enet_pdata *pdata,
|
|
|
iowrite32(val, addr);
|
|
|
}
|
|
|
|
|
|
-static bool xgene_enet_wr_indirect(void __iomem *addr, void __iomem *wr,
|
|
|
- void __iomem *cmd, void __iomem *cmd_done,
|
|
|
- u32 wr_addr, u32 wr_data)
|
|
|
+void xgene_enet_wr_mac(struct xgene_enet_pdata *pdata, u32 wr_addr, u32 wr_data)
|
|
|
{
|
|
|
- u32 done;
|
|
|
+ void __iomem *addr, *wr, *cmd, *cmd_done;
|
|
|
+ struct net_device *ndev = pdata->ndev;
|
|
|
u8 wait = 10;
|
|
|
+ u32 done;
|
|
|
+
|
|
|
+ if (pdata->mdio_driver && ndev->phydev &&
|
|
|
+ pdata->phy_mode == PHY_INTERFACE_MODE_RGMII) {
|
|
|
+ struct mii_bus *bus = ndev->phydev->mdio.bus;
|
|
|
+
|
|
|
+ return xgene_mdio_wr_mac(bus->priv, wr_addr, wr_data);
|
|
|
+ }
|
|
|
+
|
|
|
+ addr = pdata->mcx_mac_addr + MAC_ADDR_REG_OFFSET;
|
|
|
+ wr = pdata->mcx_mac_addr + MAC_WRITE_REG_OFFSET;
|
|
|
+ cmd = pdata->mcx_mac_addr + MAC_COMMAND_REG_OFFSET;
|
|
|
+ cmd_done = pdata->mcx_mac_addr + MAC_COMMAND_DONE_REG_OFFSET;
|
|
|
|
|
|
+ spin_lock(&pdata->mac_lock);
|
|
|
iowrite32(wr_addr, addr);
|
|
|
iowrite32(wr_data, wr);
|
|
|
iowrite32(XGENE_ENET_WR_CMD, cmd);
|
|
|
|
|
|
- /* wait for write command to complete */
|
|
|
while (!(done = ioread32(cmd_done)) && wait--)
|
|
|
udelay(1);
|
|
|
|
|
|
if (!done)
|
|
|
- return false;
|
|
|
+ netdev_err(ndev, "mac write failed, addr: %04x data: %08x\n",
|
|
|
+ wr_addr, wr_data);
|
|
|
|
|
|
iowrite32(0, cmd);
|
|
|
-
|
|
|
- return true;
|
|
|
-}
|
|
|
-
|
|
|
-static void xgene_enet_wr_mcx_mac(struct xgene_enet_pdata *pdata,
|
|
|
- u32 wr_addr, u32 wr_data)
|
|
|
-{
|
|
|
- void __iomem *addr, *wr, *cmd, *cmd_done;
|
|
|
-
|
|
|
- addr = pdata->mcx_mac_addr + MAC_ADDR_REG_OFFSET;
|
|
|
- wr = pdata->mcx_mac_addr + MAC_WRITE_REG_OFFSET;
|
|
|
- cmd = pdata->mcx_mac_addr + MAC_COMMAND_REG_OFFSET;
|
|
|
- cmd_done = pdata->mcx_mac_addr + MAC_COMMAND_DONE_REG_OFFSET;
|
|
|
-
|
|
|
- if (!xgene_enet_wr_indirect(addr, wr, cmd, cmd_done, wr_addr, wr_data))
|
|
|
- netdev_err(pdata->ndev, "MCX mac write failed, addr: %04x\n",
|
|
|
- wr_addr);
|
|
|
+ spin_unlock(&pdata->mac_lock);
|
|
|
}
|
|
|
|
|
|
static void xgene_enet_rd_csr(struct xgene_enet_pdata *pdata,
|
|
@@ -332,42 +323,69 @@ static void xgene_enet_rd_mcx_csr(struct xgene_enet_pdata *pdata,
|
|
|
*val = ioread32(addr);
|
|
|
}
|
|
|
|
|
|
-static bool xgene_enet_rd_indirect(void __iomem *addr, void __iomem *rd,
|
|
|
- void __iomem *cmd, void __iomem *cmd_done,
|
|
|
- u32 rd_addr, u32 *rd_data)
|
|
|
+u32 xgene_enet_rd_mac(struct xgene_enet_pdata *pdata, u32 rd_addr)
|
|
|
{
|
|
|
- u32 done;
|
|
|
+ void __iomem *addr, *rd, *cmd, *cmd_done;
|
|
|
+ u32 done, rd_data;
|
|
|
u8 wait = 10;
|
|
|
|
|
|
+ if (pdata->mdio_driver && pdata->ndev->phydev &&
|
|
|
+ pdata->phy_mode == PHY_INTERFACE_MODE_RGMII) {
|
|
|
+ struct mii_bus *bus = pdata->ndev->phydev->mdio.bus;
|
|
|
+
|
|
|
+ return xgene_mdio_rd_mac(bus->priv, rd_addr);
|
|
|
+ }
|
|
|
+
|
|
|
+ addr = pdata->mcx_mac_addr + MAC_ADDR_REG_OFFSET;
|
|
|
+ rd = pdata->mcx_mac_addr + MAC_READ_REG_OFFSET;
|
|
|
+ cmd = pdata->mcx_mac_addr + MAC_COMMAND_REG_OFFSET;
|
|
|
+ cmd_done = pdata->mcx_mac_addr + MAC_COMMAND_DONE_REG_OFFSET;
|
|
|
+
|
|
|
+ spin_lock(&pdata->mac_lock);
|
|
|
iowrite32(rd_addr, addr);
|
|
|
iowrite32(XGENE_ENET_RD_CMD, cmd);
|
|
|
|
|
|
- /* wait for read command to complete */
|
|
|
while (!(done = ioread32(cmd_done)) && wait--)
|
|
|
udelay(1);
|
|
|
|
|
|
if (!done)
|
|
|
- return false;
|
|
|
+ netdev_err(pdata->ndev, "mac read failed, addr: %04x\n",
|
|
|
+ rd_addr);
|
|
|
|
|
|
- *rd_data = ioread32(rd);
|
|
|
+ rd_data = ioread32(rd);
|
|
|
iowrite32(0, cmd);
|
|
|
+ spin_unlock(&pdata->mac_lock);
|
|
|
|
|
|
- return true;
|
|
|
+ return rd_data;
|
|
|
}
|
|
|
|
|
|
-static void xgene_enet_rd_mcx_mac(struct xgene_enet_pdata *pdata,
|
|
|
- u32 rd_addr, u32 *rd_data)
|
|
|
+u32 xgene_enet_rd_stat(struct xgene_enet_pdata *pdata, u32 rd_addr)
|
|
|
{
|
|
|
void __iomem *addr, *rd, *cmd, *cmd_done;
|
|
|
+ u32 done, rd_data;
|
|
|
+ u8 wait = 10;
|
|
|
|
|
|
- addr = pdata->mcx_mac_addr + MAC_ADDR_REG_OFFSET;
|
|
|
- rd = pdata->mcx_mac_addr + MAC_READ_REG_OFFSET;
|
|
|
- cmd = pdata->mcx_mac_addr + MAC_COMMAND_REG_OFFSET;
|
|
|
- cmd_done = pdata->mcx_mac_addr + MAC_COMMAND_DONE_REG_OFFSET;
|
|
|
+ addr = pdata->mcx_stats_addr + STAT_ADDR_REG_OFFSET;
|
|
|
+ rd = pdata->mcx_stats_addr + STAT_READ_REG_OFFSET;
|
|
|
+ cmd = pdata->mcx_stats_addr + STAT_COMMAND_REG_OFFSET;
|
|
|
+ cmd_done = pdata->mcx_stats_addr + STAT_COMMAND_DONE_REG_OFFSET;
|
|
|
+
|
|
|
+ spin_lock(&pdata->stats_lock);
|
|
|
+ iowrite32(rd_addr, addr);
|
|
|
+ iowrite32(XGENE_ENET_RD_CMD, cmd);
|
|
|
|
|
|
- if (!xgene_enet_rd_indirect(addr, rd, cmd, cmd_done, rd_addr, rd_data))
|
|
|
- netdev_err(pdata->ndev, "MCX mac read failed, addr: %04x\n",
|
|
|
+ while (!(done = ioread32(cmd_done)) && wait--)
|
|
|
+ udelay(1);
|
|
|
+
|
|
|
+ if (!done)
|
|
|
+ netdev_err(pdata->ndev, "mac stats read failed, addr: %04x\n",
|
|
|
rd_addr);
|
|
|
+
|
|
|
+ rd_data = ioread32(rd);
|
|
|
+ iowrite32(0, cmd);
|
|
|
+ spin_unlock(&pdata->stats_lock);
|
|
|
+
|
|
|
+ return rd_data;
|
|
|
}
|
|
|
|
|
|
static void xgene_gmac_set_mac_addr(struct xgene_enet_pdata *pdata)
|
|
@@ -379,8 +397,8 @@ static void xgene_gmac_set_mac_addr(struct xgene_enet_pdata *pdata)
|
|
|
(dev_addr[1] << 8) | dev_addr[0];
|
|
|
addr1 = (dev_addr[5] << 24) | (dev_addr[4] << 16);
|
|
|
|
|
|
- xgene_enet_wr_mcx_mac(pdata, STATION_ADDR0_ADDR, addr0);
|
|
|
- xgene_enet_wr_mcx_mac(pdata, STATION_ADDR1_ADDR, addr1);
|
|
|
+ xgene_enet_wr_mac(pdata, STATION_ADDR0_ADDR, addr0);
|
|
|
+ xgene_enet_wr_mac(pdata, STATION_ADDR1_ADDR, addr1);
|
|
|
}
|
|
|
|
|
|
static int xgene_enet_ecc_init(struct xgene_enet_pdata *pdata)
|
|
@@ -405,8 +423,8 @@ static int xgene_enet_ecc_init(struct xgene_enet_pdata *pdata)
|
|
|
|
|
|
static void xgene_gmac_reset(struct xgene_enet_pdata *pdata)
|
|
|
{
|
|
|
- xgene_enet_wr_mcx_mac(pdata, MAC_CONFIG_1_ADDR, SOFT_RESET1);
|
|
|
- xgene_enet_wr_mcx_mac(pdata, MAC_CONFIG_1_ADDR, 0);
|
|
|
+ xgene_enet_wr_mac(pdata, MAC_CONFIG_1_ADDR, SOFT_RESET1);
|
|
|
+ xgene_enet_wr_mac(pdata, MAC_CONFIG_1_ADDR, 0);
|
|
|
}
|
|
|
|
|
|
static void xgene_enet_configure_clock(struct xgene_enet_pdata *pdata)
|
|
@@ -456,8 +474,8 @@ static void xgene_gmac_set_speed(struct xgene_enet_pdata *pdata)
|
|
|
|
|
|
xgene_enet_rd_mcx_csr(pdata, ICM_CONFIG0_REG_0_ADDR, &icm0);
|
|
|
xgene_enet_rd_mcx_csr(pdata, ICM_CONFIG2_REG_0_ADDR, &icm2);
|
|
|
- xgene_enet_rd_mcx_mac(pdata, MAC_CONFIG_2_ADDR, &mc2);
|
|
|
- xgene_enet_rd_mcx_mac(pdata, INTERFACE_CONTROL_ADDR, &intf_ctl);
|
|
|
+ mc2 = xgene_enet_rd_mac(pdata, MAC_CONFIG_2_ADDR);
|
|
|
+ intf_ctl = xgene_enet_rd_mac(pdata, INTERFACE_CONTROL_ADDR);
|
|
|
xgene_enet_rd_csr(pdata, RGMII_REG_0_ADDR, &rgmii);
|
|
|
|
|
|
switch (pdata->phy_speed) {
|
|
@@ -495,8 +513,8 @@ static void xgene_gmac_set_speed(struct xgene_enet_pdata *pdata)
|
|
|
}
|
|
|
|
|
|
mc2 |= FULL_DUPLEX2 | PAD_CRC | LENGTH_CHK;
|
|
|
- xgene_enet_wr_mcx_mac(pdata, MAC_CONFIG_2_ADDR, mc2);
|
|
|
- xgene_enet_wr_mcx_mac(pdata, INTERFACE_CONTROL_ADDR, intf_ctl);
|
|
|
+ xgene_enet_wr_mac(pdata, MAC_CONFIG_2_ADDR, mc2);
|
|
|
+ xgene_enet_wr_mac(pdata, INTERFACE_CONTROL_ADDR, intf_ctl);
|
|
|
xgene_enet_wr_csr(pdata, RGMII_REG_0_ADDR, rgmii);
|
|
|
xgene_enet_configure_clock(pdata);
|
|
|
|
|
@@ -506,7 +524,7 @@ static void xgene_gmac_set_speed(struct xgene_enet_pdata *pdata)
|
|
|
|
|
|
static void xgene_enet_set_frame_size(struct xgene_enet_pdata *pdata, int size)
|
|
|
{
|
|
|
- xgene_enet_wr_mcx_mac(pdata, MAX_FRAME_LEN_ADDR, size);
|
|
|
+ xgene_enet_wr_mac(pdata, MAX_FRAME_LEN_ADDR, size);
|
|
|
}
|
|
|
|
|
|
static void xgene_gmac_enable_tx_pause(struct xgene_enet_pdata *pdata,
|
|
@@ -528,14 +546,14 @@ static void xgene_gmac_flowctl_tx(struct xgene_enet_pdata *pdata, bool enable)
|
|
|
{
|
|
|
u32 data;
|
|
|
|
|
|
- xgene_enet_rd_mcx_mac(pdata, MAC_CONFIG_1_ADDR, &data);
|
|
|
+ data = xgene_enet_rd_mac(pdata, MAC_CONFIG_1_ADDR);
|
|
|
|
|
|
if (enable)
|
|
|
data |= TX_FLOW_EN;
|
|
|
else
|
|
|
data &= ~TX_FLOW_EN;
|
|
|
|
|
|
- xgene_enet_wr_mcx_mac(pdata, MAC_CONFIG_1_ADDR, data);
|
|
|
+ xgene_enet_wr_mac(pdata, MAC_CONFIG_1_ADDR, data);
|
|
|
|
|
|
pdata->mac_ops->enable_tx_pause(pdata, enable);
|
|
|
}
|
|
@@ -544,14 +562,14 @@ static void xgene_gmac_flowctl_rx(struct xgene_enet_pdata *pdata, bool enable)
|
|
|
{
|
|
|
u32 data;
|
|
|
|
|
|
- xgene_enet_rd_mcx_mac(pdata, MAC_CONFIG_1_ADDR, &data);
|
|
|
+ data = xgene_enet_rd_mac(pdata, MAC_CONFIG_1_ADDR);
|
|
|
|
|
|
if (enable)
|
|
|
data |= RX_FLOW_EN;
|
|
|
else
|
|
|
data &= ~RX_FLOW_EN;
|
|
|
|
|
|
- xgene_enet_wr_mcx_mac(pdata, MAC_CONFIG_1_ADDR, data);
|
|
|
+ xgene_enet_wr_mac(pdata, MAC_CONFIG_1_ADDR, data);
|
|
|
}
|
|
|
|
|
|
static void xgene_gmac_init(struct xgene_enet_pdata *pdata)
|
|
@@ -565,9 +583,9 @@ static void xgene_gmac_init(struct xgene_enet_pdata *pdata)
|
|
|
xgene_gmac_set_mac_addr(pdata);
|
|
|
|
|
|
/* Adjust MDC clock frequency */
|
|
|
- xgene_enet_rd_mcx_mac(pdata, MII_MGMT_CONFIG_ADDR, &value);
|
|
|
+ value = xgene_enet_rd_mac(pdata, MII_MGMT_CONFIG_ADDR);
|
|
|
MGMT_CLOCK_SEL_SET(&value, 7);
|
|
|
- xgene_enet_wr_mcx_mac(pdata, MII_MGMT_CONFIG_ADDR, value);
|
|
|
+ xgene_enet_wr_mac(pdata, MII_MGMT_CONFIG_ADDR, value);
|
|
|
|
|
|
/* Enable drop if bufpool not available */
|
|
|
xgene_enet_rd_csr(pdata, RSIF_CONFIG_REG_ADDR, &value);
|
|
@@ -600,6 +618,18 @@ static void xgene_gmac_init(struct xgene_enet_pdata *pdata)
|
|
|
xgene_enet_wr_csr(pdata, CFG_BYPASS_ADDR, RESUME_TX);
|
|
|
}
|
|
|
|
|
|
+static void xgene_gmac_get_drop_cnt(struct xgene_enet_pdata *pdata,
|
|
|
+ u32 *rx, u32 *tx)
|
|
|
+{
|
|
|
+ u32 count;
|
|
|
+
|
|
|
+ xgene_enet_rd_mcx_csr(pdata, ICM_ECM_DROP_COUNT_REG0_ADDR, &count);
|
|
|
+ *rx = ICM_DROP_COUNT(count);
|
|
|
+ *tx = ECM_DROP_COUNT(count);
|
|
|
+ /* Errata: 10GE_4 - Fix ICM_ECM_DROP_COUNT not clear-on-read */
|
|
|
+ xgene_enet_rd_mcx_csr(pdata, ECM_CONFIG0_REG_0_ADDR, &count);
|
|
|
+}
|
|
|
+
|
|
|
static void xgene_enet_config_ring_if_assoc(struct xgene_enet_pdata *pdata)
|
|
|
{
|
|
|
u32 val = 0xffffffff;
|
|
@@ -637,32 +667,32 @@ static void xgene_gmac_rx_enable(struct xgene_enet_pdata *pdata)
|
|
|
{
|
|
|
u32 data;
|
|
|
|
|
|
- xgene_enet_rd_mcx_mac(pdata, MAC_CONFIG_1_ADDR, &data);
|
|
|
- xgene_enet_wr_mcx_mac(pdata, MAC_CONFIG_1_ADDR, data | RX_EN);
|
|
|
+ data = xgene_enet_rd_mac(pdata, MAC_CONFIG_1_ADDR);
|
|
|
+ xgene_enet_wr_mac(pdata, MAC_CONFIG_1_ADDR, data | RX_EN);
|
|
|
}
|
|
|
|
|
|
static void xgene_gmac_tx_enable(struct xgene_enet_pdata *pdata)
|
|
|
{
|
|
|
u32 data;
|
|
|
|
|
|
- xgene_enet_rd_mcx_mac(pdata, MAC_CONFIG_1_ADDR, &data);
|
|
|
- xgene_enet_wr_mcx_mac(pdata, MAC_CONFIG_1_ADDR, data | TX_EN);
|
|
|
+ data = xgene_enet_rd_mac(pdata, MAC_CONFIG_1_ADDR);
|
|
|
+ xgene_enet_wr_mac(pdata, MAC_CONFIG_1_ADDR, data | TX_EN);
|
|
|
}
|
|
|
|
|
|
static void xgene_gmac_rx_disable(struct xgene_enet_pdata *pdata)
|
|
|
{
|
|
|
u32 data;
|
|
|
|
|
|
- xgene_enet_rd_mcx_mac(pdata, MAC_CONFIG_1_ADDR, &data);
|
|
|
- xgene_enet_wr_mcx_mac(pdata, MAC_CONFIG_1_ADDR, data & ~RX_EN);
|
|
|
+ data = xgene_enet_rd_mac(pdata, MAC_CONFIG_1_ADDR);
|
|
|
+ xgene_enet_wr_mac(pdata, MAC_CONFIG_1_ADDR, data & ~RX_EN);
|
|
|
}
|
|
|
|
|
|
static void xgene_gmac_tx_disable(struct xgene_enet_pdata *pdata)
|
|
|
{
|
|
|
u32 data;
|
|
|
|
|
|
- xgene_enet_rd_mcx_mac(pdata, MAC_CONFIG_1_ADDR, &data);
|
|
|
- xgene_enet_wr_mcx_mac(pdata, MAC_CONFIG_1_ADDR, data & ~TX_EN);
|
|
|
+ data = xgene_enet_rd_mac(pdata, MAC_CONFIG_1_ADDR);
|
|
|
+ xgene_enet_wr_mac(pdata, MAC_CONFIG_1_ADDR, data & ~TX_EN);
|
|
|
}
|
|
|
|
|
|
bool xgene_ring_mgr_init(struct xgene_enet_pdata *p)
|
|
@@ -733,27 +763,6 @@ static void xgene_enet_clear(struct xgene_enet_pdata *pdata,
|
|
|
static void xgene_gport_shutdown(struct xgene_enet_pdata *pdata)
|
|
|
{
|
|
|
struct device *dev = &pdata->pdev->dev;
|
|
|
- struct xgene_enet_desc_ring *ring;
|
|
|
- u32 pb;
|
|
|
- int i;
|
|
|
-
|
|
|
- pb = 0;
|
|
|
- for (i = 0; i < pdata->rxq_cnt; i++) {
|
|
|
- ring = pdata->rx_ring[i]->buf_pool;
|
|
|
- pb |= BIT(xgene_enet_get_fpsel(ring->id));
|
|
|
- ring = pdata->rx_ring[i]->page_pool;
|
|
|
- if (ring)
|
|
|
- pb |= BIT(xgene_enet_get_fpsel(ring->id));
|
|
|
-
|
|
|
- }
|
|
|
- xgene_enet_wr_ring_if(pdata, ENET_CFGSSQMIFPRESET_ADDR, pb);
|
|
|
-
|
|
|
- pb = 0;
|
|
|
- for (i = 0; i < pdata->txq_cnt; i++) {
|
|
|
- ring = pdata->tx_ring[i];
|
|
|
- pb |= BIT(xgene_enet_ring_bufnum(ring->id));
|
|
|
- }
|
|
|
- xgene_enet_wr_ring_if(pdata, ENET_CFGSSQMIWQRESET_ADDR, pb);
|
|
|
|
|
|
if (dev->of_node) {
|
|
|
if (!IS_ERR(pdata->clk))
|
|
@@ -1009,6 +1018,7 @@ const struct xgene_mac_ops xgene_gmac_ops = {
|
|
|
.tx_enable = xgene_gmac_tx_enable,
|
|
|
.rx_disable = xgene_gmac_rx_disable,
|
|
|
.tx_disable = xgene_gmac_tx_disable,
|
|
|
+ .get_drop_cnt = xgene_gmac_get_drop_cnt,
|
|
|
.set_speed = xgene_gmac_set_speed,
|
|
|
.set_mac_addr = xgene_gmac_set_mac_addr,
|
|
|
.set_framesize = xgene_enet_set_frame_size,
|