summaryrefslogtreecommitdiff
path: root/drivers/net/skge.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/skge.c')
-rw-r--r--drivers/net/skge.c108
1 files changed, 38 insertions, 70 deletions
diff --git a/drivers/net/skge.c b/drivers/net/skge.c
index 6d62250fba07..186eb8ebfda6 100644
--- a/drivers/net/skge.c
+++ b/drivers/net/skge.c
@@ -44,7 +44,7 @@
#include "skge.h"
#define DRV_NAME "skge"
-#define DRV_VERSION "1.12"
+#define DRV_VERSION "1.13"
#define PFX DRV_NAME " "
#define DEFAULT_TX_RING_SIZE 128
@@ -1095,16 +1095,9 @@ static void xm_link_down(struct skge_hw *hw, int port)
{
struct net_device *dev = hw->dev[port];
struct skge_port *skge = netdev_priv(dev);
- u16 cmd = xm_read16(hw, port, XM_MMU_CMD);
xm_write16(hw, port, XM_IMSK, XM_IMSK_DISABLE);
- cmd &= ~(XM_MMU_ENA_RX | XM_MMU_ENA_TX);
- xm_write16(hw, port, XM_MMU_CMD, cmd);
-
- /* dummy read to ensure writing */
- xm_read16(hw, port, XM_MMU_CMD);
-
if (netif_carrier_ok(dev))
skge_link_down(skge);
}
@@ -1194,6 +1187,7 @@ static void genesis_init(struct skge_hw *hw)
static void genesis_reset(struct skge_hw *hw, int port)
{
const u8 zero[8] = { 0 };
+ u32 reg;
skge_write8(hw, SK_REG(port, GMAC_IRQ_MSK), 0);
@@ -1209,6 +1203,11 @@ static void genesis_reset(struct skge_hw *hw, int port)
xm_write16(hw, port, PHY_BCOM_INT_MASK, 0xffff);
xm_outhash(hw, port, XM_HSM, zero);
+
+ /* Flush TX and RX fifo */
+ reg = xm_read32(hw, port, XM_MODE);
+ xm_write32(hw, port, XM_MODE, reg | XM_MD_FTF);
+ xm_write32(hw, port, XM_MODE, reg | XM_MD_FRF);
}
@@ -1634,15 +1633,14 @@ static void genesis_mac_init(struct skge_hw *hw, int port)
}
xm_write16(hw, port, XM_RX_CMD, r);
-
/* We want short frames padded to 60 bytes. */
xm_write16(hw, port, XM_TX_CMD, XM_TX_AUTO_PAD);
- /*
- * Bump up the transmit threshold. This helps hold off transmit
- * underruns when we're blasting traffic from both ports at once.
- */
- xm_write16(hw, port, XM_TX_THR, 512);
+ /* Increase threshold for jumbo frames on dual port */
+ if (hw->ports > 1 && jumbo)
+ xm_write16(hw, port, XM_TX_THR, 1020);
+ else
+ xm_write16(hw, port, XM_TX_THR, 512);
/*
* Enable the reception of all error frames. This is is
@@ -1713,7 +1711,13 @@ static void genesis_stop(struct skge_port *skge)
{
struct skge_hw *hw = skge->hw;
int port = skge->port;
- u32 reg;
+ unsigned retries = 1000;
+ u16 cmd;
+
+ /* Disable Tx and Rx */
+ cmd = xm_read16(hw, port, XM_MMU_CMD);
+ cmd &= ~(XM_MMU_ENA_RX | XM_MMU_ENA_TX);
+ xm_write16(hw, port, XM_MMU_CMD, cmd);
genesis_reset(hw, port);
@@ -1721,20 +1725,17 @@ static void genesis_stop(struct skge_port *skge)
skge_write16(hw, B3_PA_CTRL,
port == 0 ? PA_CLR_TO_TX1 : PA_CLR_TO_TX2);
- /*
- * If the transfer sticks at the MAC the STOP command will not
- * terminate if we don't flush the XMAC's transmit FIFO !
- */
- xm_write32(hw, port, XM_MODE,
- xm_read32(hw, port, XM_MODE)|XM_MD_FTF);
-
-
/* Reset the MAC */
- skge_write16(hw, SK_REG(port, TX_MFF_CTRL1), MFF_SET_MAC_RST);
+ skge_write16(hw, SK_REG(port, TX_MFF_CTRL1), MFF_CLR_MAC_RST);
+ do {
+ skge_write16(hw, SK_REG(port, TX_MFF_CTRL1), MFF_SET_MAC_RST);
+ if (!(skge_read16(hw, SK_REG(port, TX_MFF_CTRL1)) & MFF_SET_MAC_RST))
+ break;
+ } while (--retries > 0);
/* For external PHYs there must be special handling */
if (hw->phy_type != SK_PHY_XMAC) {
- reg = skge_read32(hw, B2_GP_IO);
+ u32 reg = skge_read32(hw, B2_GP_IO);
if (port == 0) {
reg |= GP_DIR_0;
reg &= ~GP_IO_0;
@@ -1801,11 +1802,6 @@ static void genesis_mac_intr(struct skge_hw *hw, int port)
xm_write32(hw, port, XM_MODE, XM_MD_FTF);
++dev->stats.tx_fifo_errors;
}
-
- if (status & XM_IS_RXF_OV) {
- xm_write32(hw, port, XM_MODE, XM_MD_FRF);
- ++dev->stats.rx_fifo_errors;
- }
}
static void genesis_link_up(struct skge_port *skge)
@@ -1862,9 +1858,9 @@ static void genesis_link_up(struct skge_port *skge)
xm_write32(hw, port, XM_MODE, mode);
- /* Turn on detection of Tx underrun, Rx overrun */
+ /* Turn on detection of Tx underrun */
msk = xm_read16(hw, port, XM_IMSK);
- msk &= ~(XM_IS_RXF_OV | XM_IS_TXF_UR);
+ msk &= ~XM_IS_TXF_UR;
xm_write16(hw, port, XM_IMSK, msk);
xm_read16(hw, port, XM_ISRC);
@@ -2194,9 +2190,12 @@ static void yukon_mac_init(struct skge_hw *hw, int port)
TX_JAM_IPG_VAL(TX_JAM_IPG_DEF) |
TX_IPG_JAM_DATA(TX_IPG_JAM_DEF));
- /* serial mode register */
- reg = GM_SMOD_VLAN_ENA | IPG_DATA_VAL(IPG_DATA_DEF);
- if (hw->dev[port]->mtu > 1500)
+ /* configure the Serial Mode Register */
+ reg = DATA_BLIND_VAL(DATA_BLIND_DEF)
+ | GM_SMOD_VLAN_ENA
+ | IPG_DATA_VAL(IPG_DATA_DEF);
+
+ if (hw->dev[port]->mtu > ETH_DATA_LEN)
reg |= GM_SMOD_JUMBO_ENA;
gma_write16(hw, port, GM_SERIAL_MODE, reg);
@@ -2619,8 +2618,8 @@ static int skge_up(struct net_device *dev)
yukon_mac_init(hw, port);
spin_unlock_bh(&hw->phy_lock);
- /* Configure RAMbuffers */
- chunk = hw->ram_size / ((hw->ports + 1)*2);
+ /* Configure RAMbuffers - equally between ports and tx/rx */
+ chunk = (hw->ram_size - hw->ram_offset) / (hw->ports * 2);
ram_addr = hw->ram_offset + 2 * chunk * port;
skge_ramset(hw, rxqaddr[port], ram_addr, chunk);
@@ -2897,11 +2896,7 @@ static void skge_tx_timeout(struct net_device *dev)
static int skge_change_mtu(struct net_device *dev, int new_mtu)
{
- struct skge_port *skge = netdev_priv(dev);
- struct skge_hw *hw = skge->hw;
- int port = skge->port;
int err;
- u16 ctl, reg;
if (new_mtu < ETH_ZLEN || new_mtu > ETH_JUMBO_MTU)
return -EINVAL;
@@ -2911,40 +2906,13 @@ static int skge_change_mtu(struct net_device *dev, int new_mtu)
return 0;
}
- skge_write32(hw, B0_IMSK, 0);
- dev->trans_start = jiffies; /* prevent tx timeout */
- netif_stop_queue(dev);
- napi_disable(&skge->napi);
-
- ctl = gma_read16(hw, port, GM_GP_CTRL);
- gma_write16(hw, port, GM_GP_CTRL, ctl & ~GM_GPCR_RX_ENA);
-
- skge_rx_clean(skge);
- skge_rx_stop(hw, port);
+ skge_down(dev);
dev->mtu = new_mtu;
- reg = GM_SMOD_VLAN_ENA | IPG_DATA_VAL(IPG_DATA_DEF);
- if (new_mtu > 1500)
- reg |= GM_SMOD_JUMBO_ENA;
- gma_write16(hw, port, GM_SERIAL_MODE, reg);
-
- skge_write8(hw, RB_ADDR(rxqaddr[port], RB_CTRL), RB_ENA_OP_MD);
-
- err = skge_rx_fill(dev);
- wmb();
- if (!err)
- skge_write8(hw, Q_ADDR(rxqaddr[port], Q_CSR), CSR_START | CSR_IRQ_CL_F);
- skge_write32(hw, B0_IMSK, hw->intr_mask);
-
+ err = skge_up(dev);
if (err)
dev_close(dev);
- else {
- gma_write16(hw, port, GM_GP_CTRL, ctl);
-
- napi_enable(&skge->napi);
- netif_wake_queue(dev);
- }
return err;
}