summaryrefslogtreecommitdiffstats
path: root/drivers/net/stmmac
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/stmmac')
-rw-r--r--drivers/net/stmmac/dwmac1000_core.c5
-rw-r--r--drivers/net/stmmac/dwmac_lib.c28
-rw-r--r--drivers/net/stmmac/stmmac.h1
-rw-r--r--drivers/net/stmmac/stmmac_ethtool.c33
-rw-r--r--drivers/net/stmmac/stmmac_main.c136
5 files changed, 74 insertions, 129 deletions
diff --git a/drivers/net/stmmac/dwmac1000_core.c b/drivers/net/stmmac/dwmac1000_core.c
index 6ae4c3f4c63..f20455cbfbb 100644
--- a/drivers/net/stmmac/dwmac1000_core.c
+++ b/drivers/net/stmmac/dwmac1000_core.c
@@ -178,10 +178,11 @@ static void dwmac1000_pmt(void __iomem *ioaddr, unsigned long mode)
{
unsigned int pmt = 0;
- if (mode == WAKE_MAGIC) {
+ if (mode & WAKE_MAGIC) {
CHIP_DBG(KERN_DEBUG "GMAC: WOL Magic frame\n");
pmt |= power_down | magic_pkt_en;
- } else if (mode == WAKE_UCAST) {
+ }
+ if (mode & WAKE_UCAST) {
CHIP_DBG(KERN_DEBUG "GMAC: WOL on global unicast\n");
pmt |= global_unicast;
}
diff --git a/drivers/net/stmmac/dwmac_lib.c b/drivers/net/stmmac/dwmac_lib.c
index d65fab1ba79..e25093510b0 100644
--- a/drivers/net/stmmac/dwmac_lib.c
+++ b/drivers/net/stmmac/dwmac_lib.c
@@ -26,9 +26,9 @@
#undef DWMAC_DMA_DEBUG
#ifdef DWMAC_DMA_DEBUG
-#define DBG(fmt, args...) printk(fmt, ## args)
+#define DWMAC_LIB_DBG(fmt, args...) printk(fmt, ## args)
#else
-#define DBG(fmt, args...) do { } while (0)
+#define DWMAC_LIB_DBG(fmt, args...) do { } while (0)
#endif
/* CSR1 enables the transmit DMA to check for new descriptor */
@@ -152,7 +152,7 @@ int dwmac_dma_interrupt(void __iomem *ioaddr,
/* read the status register (CSR5) */
u32 intr_status = readl(ioaddr + DMA_STATUS);
- DBG(INFO, "%s: [CSR5: 0x%08x]\n", __func__, intr_status);
+ DWMAC_LIB_DBG(KERN_INFO "%s: [CSR5: 0x%08x]\n", __func__, intr_status);
#ifdef DWMAC_DMA_DEBUG
/* It displays the DMA process states (CSR5 register) */
show_tx_process_state(intr_status);
@@ -160,43 +160,43 @@ int dwmac_dma_interrupt(void __iomem *ioaddr,
#endif
/* ABNORMAL interrupts */
if (unlikely(intr_status & DMA_STATUS_AIS)) {
- DBG(INFO, "CSR5[15] DMA ABNORMAL IRQ: ");
+ DWMAC_LIB_DBG(KERN_INFO "CSR5[15] DMA ABNORMAL IRQ: ");
if (unlikely(intr_status & DMA_STATUS_UNF)) {
- DBG(INFO, "transmit underflow\n");
+ DWMAC_LIB_DBG(KERN_INFO "transmit underflow\n");
ret = tx_hard_error_bump_tc;
x->tx_undeflow_irq++;
}
if (unlikely(intr_status & DMA_STATUS_TJT)) {
- DBG(INFO, "transmit jabber\n");
+ DWMAC_LIB_DBG(KERN_INFO "transmit jabber\n");
x->tx_jabber_irq++;
}
if (unlikely(intr_status & DMA_STATUS_OVF)) {
- DBG(INFO, "recv overflow\n");
+ DWMAC_LIB_DBG(KERN_INFO "recv overflow\n");
x->rx_overflow_irq++;
}
if (unlikely(intr_status & DMA_STATUS_RU)) {
- DBG(INFO, "receive buffer unavailable\n");
+ DWMAC_LIB_DBG(KERN_INFO "receive buffer unavailable\n");
x->rx_buf_unav_irq++;
}
if (unlikely(intr_status & DMA_STATUS_RPS)) {
- DBG(INFO, "receive process stopped\n");
+ DWMAC_LIB_DBG(KERN_INFO "receive process stopped\n");
x->rx_process_stopped_irq++;
}
if (unlikely(intr_status & DMA_STATUS_RWT)) {
- DBG(INFO, "receive watchdog\n");
+ DWMAC_LIB_DBG(KERN_INFO "receive watchdog\n");
x->rx_watchdog_irq++;
}
if (unlikely(intr_status & DMA_STATUS_ETI)) {
- DBG(INFO, "transmit early interrupt\n");
+ DWMAC_LIB_DBG(KERN_INFO "transmit early interrupt\n");
x->tx_early_irq++;
}
if (unlikely(intr_status & DMA_STATUS_TPS)) {
- DBG(INFO, "transmit process stopped\n");
+ DWMAC_LIB_DBG(KERN_INFO "transmit process stopped\n");
x->tx_process_stopped_irq++;
ret = tx_hard_error;
}
if (unlikely(intr_status & DMA_STATUS_FBI)) {
- DBG(INFO, "fatal bus error\n");
+ DWMAC_LIB_DBG(KERN_INFO "fatal bus error\n");
x->fatal_bus_error_irq++;
ret = tx_hard_error;
}
@@ -215,7 +215,7 @@ int dwmac_dma_interrupt(void __iomem *ioaddr,
/* Clear the interrupt by writing a logic 1 to the CSR5[15-0] */
writel((intr_status & 0x1ffff), ioaddr + DMA_STATUS);
- DBG(INFO, "\n\n");
+ DWMAC_LIB_DBG(KERN_INFO "\n\n");
return ret;
}
diff --git a/drivers/net/stmmac/stmmac.h b/drivers/net/stmmac/stmmac.h
index 5f06c4706ab..2b076b31362 100644
--- a/drivers/net/stmmac/stmmac.h
+++ b/drivers/net/stmmac/stmmac.h
@@ -21,7 +21,6 @@
*******************************************************************************/
#define DRV_MODULE_VERSION "Nov_2010"
-#include <linux/platform_device.h>
#include <linux/stmmac.h>
#include "common.h"
diff --git a/drivers/net/stmmac/stmmac_ethtool.c b/drivers/net/stmmac/stmmac_ethtool.c
index fd719edc7f7..ae5213a8c4c 100644
--- a/drivers/net/stmmac/stmmac_ethtool.c
+++ b/drivers/net/stmmac/stmmac_ethtool.c
@@ -197,13 +197,6 @@ static void stmmac_ethtool_gregs(struct net_device *dev,
}
}
-static u32 stmmac_ethtool_get_rx_csum(struct net_device *dev)
-{
- struct stmmac_priv *priv = netdev_priv(dev);
-
- return priv->rx_coe;
-}
-
static void
stmmac_get_pauseparam(struct net_device *netdev,
struct ethtool_pauseparam *pause)
@@ -241,20 +234,11 @@ stmmac_set_pauseparam(struct net_device *netdev,
new_pause |= FLOW_TX;
priv->flow_ctrl = new_pause;
+ phy->autoneg = pause->autoneg;
if (phy->autoneg) {
- if (netif_running(netdev)) {
- struct ethtool_cmd cmd;
- /* auto-negotiation automatically restarted */
- cmd.cmd = ETHTOOL_NWAY_RST;
- cmd.supported = phy->supported;
- cmd.advertising = phy->advertising;
- cmd.autoneg = phy->autoneg;
- cmd.speed = phy->speed;
- cmd.duplex = phy->duplex;
- cmd.phy_address = phy->addr;
- ret = phy_ethtool_sset(phy, &cmd);
- }
+ if (netif_running(netdev))
+ ret = phy_start_aneg(phy);
} else
priv->hw->mac->flow_ctrl(priv->ioaddr, phy->duplex,
priv->flow_ctrl, priv->pause);
@@ -315,7 +299,7 @@ static void stmmac_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
spin_lock_irq(&priv->lock);
if (device_can_wakeup(priv->device)) {
- wol->supported = WAKE_MAGIC;
+ wol->supported = WAKE_MAGIC | WAKE_UCAST;
wol->wolopts = priv->wolopts;
}
spin_unlock_irq(&priv->lock);
@@ -324,7 +308,7 @@ static void stmmac_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
static int stmmac_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
{
struct stmmac_priv *priv = netdev_priv(dev);
- u32 support = WAKE_MAGIC;
+ u32 support = WAKE_MAGIC | WAKE_UCAST;
if (!device_can_wakeup(priv->device))
return -EINVAL;
@@ -358,11 +342,6 @@ static struct ethtool_ops stmmac_ethtool_ops = {
.get_regs = stmmac_ethtool_gregs,
.get_regs_len = stmmac_ethtool_get_regs_len,
.get_link = ethtool_op_get_link,
- .get_rx_csum = stmmac_ethtool_get_rx_csum,
- .get_tx_csum = ethtool_op_get_tx_csum,
- .set_tx_csum = ethtool_op_set_tx_ipv6_csum,
- .get_sg = ethtool_op_get_sg,
- .set_sg = ethtool_op_set_sg,
.get_pauseparam = stmmac_get_pauseparam,
.set_pauseparam = stmmac_set_pauseparam,
.get_ethtool_stats = stmmac_get_ethtool_stats,
@@ -370,8 +349,6 @@ static struct ethtool_ops stmmac_ethtool_ops = {
.get_wol = stmmac_get_wol,
.set_wol = stmmac_set_wol,
.get_sset_count = stmmac_get_sset_count,
- .get_tso = ethtool_op_get_tso,
- .set_tso = ethtool_op_set_tso,
};
void stmmac_set_ethtool_ops(struct net_device *netdev)
diff --git a/drivers/net/stmmac/stmmac_main.c b/drivers/net/stmmac/stmmac_main.c
index 0e5f03135b5..e25e44a45c2 100644
--- a/drivers/net/stmmac/stmmac_main.c
+++ b/drivers/net/stmmac/stmmac_main.c
@@ -45,6 +45,7 @@
#include <linux/if_vlan.h>
#include <linux/dma-mapping.h>
#include <linux/slab.h>
+#include <linux/prefetch.h>
#include "stmmac.h"
#define STMMAC_RESOURCE_NAME "stmmaceth"
@@ -116,9 +117,6 @@ static int tc = TC_DEFAULT;
module_param(tc, int, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(tc, "DMA threshold control value");
-#define RX_NO_COALESCE 1 /* Always interrupt on completion */
-#define TX_NO_COALESCE -1 /* No moderation by default */
-
/* Pay attention to tune this parameter; take care of both
* hardware capability and network stabitily/performance impact.
* Many tests showed that ~4ms latency seems to be good enough. */
@@ -139,7 +137,6 @@ static const u32 default_msg_level = (NETIF_MSG_DRV | NETIF_MSG_PROBE |
NETIF_MSG_IFDOWN | NETIF_MSG_TIMER);
static irqreturn_t stmmac_interrupt(int irq, void *dev_id);
-static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev);
/**
* stmmac_verify_args - verify the driver parameters.
@@ -750,7 +747,6 @@ static void stmmac_dma_interrupt(struct stmmac_priv *priv)
priv->hw->dma->dma_mode(priv->ioaddr, tc, SF_DMA_MODE);
priv->xstats.threshold = tc;
}
- stmmac_tx_err(priv);
} else if (unlikely(status == tx_hard_error))
stmmac_tx_err(priv);
}
@@ -781,21 +777,6 @@ static int stmmac_open(struct net_device *dev)
stmmac_verify_args();
- ret = stmmac_init_phy(dev);
- if (unlikely(ret)) {
- pr_err("%s: Cannot attach to PHY (error: %d)\n", __func__, ret);
- return ret;
- }
-
- /* Request the IRQ lines */
- ret = request_irq(dev->irq, stmmac_interrupt,
- IRQF_SHARED, dev->name, dev);
- if (unlikely(ret < 0)) {
- pr_err("%s: ERROR: allocating the IRQ %d (error: %d)\n",
- __func__, dev->irq, ret);
- return ret;
- }
-
#ifdef CONFIG_STMMAC_TIMER
priv->tm = kzalloc(sizeof(struct stmmac_timer *), GFP_KERNEL);
if (unlikely(priv->tm == NULL)) {
@@ -814,6 +795,11 @@ static int stmmac_open(struct net_device *dev)
} else
priv->tm->enable = 1;
#endif
+ ret = stmmac_init_phy(dev);
+ if (unlikely(ret)) {
+ pr_err("%s: Cannot attach to PHY (error: %d)\n", __func__, ret);
+ goto open_error;
+ }
/* Create and initialize the TX/RX descriptors chains. */
priv->dma_tx_size = STMMAC_ALIGN(dma_txsize);
@@ -822,12 +808,11 @@ static int stmmac_open(struct net_device *dev)
init_dma_desc_rings(dev);
/* DMA initialization and SW reset */
- if (unlikely(priv->hw->dma->init(priv->ioaddr, priv->plat->pbl,
- priv->dma_tx_phy,
- priv->dma_rx_phy) < 0)) {
-
+ ret = priv->hw->dma->init(priv->ioaddr, priv->plat->pbl,
+ priv->dma_tx_phy, priv->dma_rx_phy);
+ if (ret < 0) {
pr_err("%s: DMA initialization failed\n", __func__);
- return -1;
+ goto open_error;
}
/* Copy the MAC addr into the HW */
@@ -843,11 +828,21 @@ static int stmmac_open(struct net_device *dev)
pr_info("stmmac: Rx Checksum Offload Engine supported\n");
if (priv->plat->tx_coe)
pr_info("\tTX Checksum insertion supported\n");
+ netdev_update_features(dev);
/* Initialise the MMC (if present) to disable all interrupts. */
writel(0xffffffff, priv->ioaddr + MMC_HIGH_INTR_MASK);
writel(0xffffffff, priv->ioaddr + MMC_LOW_INTR_MASK);
+ /* Request the IRQ lines */
+ ret = request_irq(dev->irq, stmmac_interrupt,
+ IRQF_SHARED, dev->name, dev);
+ if (unlikely(ret < 0)) {
+ pr_err("%s: ERROR: allocating the IRQ %d (error: %d)\n",
+ __func__, dev->irq, ret);
+ goto open_error;
+ }
+
/* Enable the MAC Rx/Tx */
stmmac_enable_mac(priv->ioaddr);
@@ -878,7 +873,17 @@ static int stmmac_open(struct net_device *dev)
napi_enable(&priv->napi);
skb_queue_head_init(&priv->rx_recycle);
netif_start_queue(dev);
+
return 0;
+
+open_error:
+#ifdef CONFIG_STMMAC_TIMER
+ kfree(priv->tm);
+#endif
+ if (priv->phydev)
+ phy_disconnect(priv->phydev);
+
+ return ret;
}
/**
@@ -927,46 +932,6 @@ static int stmmac_release(struct net_device *dev)
return 0;
}
-/*
- * To perform emulated hardware segmentation on skb.
- */
-static int stmmac_sw_tso(struct stmmac_priv *priv, struct sk_buff *skb)
-{
- struct sk_buff *segs, *curr_skb;
- int gso_segs = skb_shinfo(skb)->gso_segs;
-
- /* Estimate the number of fragments in the worst case */
- if (unlikely(stmmac_tx_avail(priv) < gso_segs)) {
- netif_stop_queue(priv->dev);
- TX_DBG(KERN_ERR "%s: TSO BUG! Tx Ring full when queue awake\n",
- __func__);
- if (stmmac_tx_avail(priv) < gso_segs)
- return NETDEV_TX_BUSY;
-
- netif_wake_queue(priv->dev);
- }
- TX_DBG("\tstmmac_sw_tso: segmenting: skb %p (len %d)\n",
- skb, skb->len);
-
- segs = skb_gso_segment(skb, priv->dev->features & ~NETIF_F_TSO);
- if (IS_ERR(segs))
- goto sw_tso_end;
-
- do {
- curr_skb = segs;
- segs = segs->next;
- TX_DBG("\t\tcurrent skb->len: %d, *curr %p,"
- "*next %p\n", curr_skb->len, curr_skb, segs);
- curr_skb->next = NULL;
- stmmac_xmit(curr_skb, priv->dev);
- } while (segs);
-
-sw_tso_end:
- dev_kfree_skb(skb);
-
- return NETDEV_TX_OK;
-}
-
static unsigned int stmmac_handle_jumbo_frames(struct sk_buff *skb,
struct net_device *dev,
int csum_insertion)
@@ -1044,16 +1009,7 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev)
!skb_is_gso(skb) ? "isn't" : "is");
#endif
- if (unlikely(skb_is_gso(skb)))
- return stmmac_sw_tso(priv, skb);
-
- if (likely((skb->ip_summed == CHECKSUM_PARTIAL))) {
- if (unlikely((!priv->plat->tx_coe) ||
- (priv->no_csum_insertion)))
- skb_checksum_help(skb);
- else
- csum_insertion = 1;
- }
+ csum_insertion = (skb->ip_summed == CHECKSUM_PARTIAL);
desc = priv->dma_tx + entry;
first = desc;
@@ -1373,18 +1329,29 @@ static int stmmac_change_mtu(struct net_device *dev, int new_mtu)
return -EINVAL;
}
+ dev->mtu = new_mtu;
+ netdev_update_features(dev);
+
+ return 0;
+}
+
+static u32 stmmac_fix_features(struct net_device *dev, u32 features)
+{
+ struct stmmac_priv *priv = netdev_priv(dev);
+
+ if (!priv->rx_coe)
+ features &= ~NETIF_F_RXCSUM;
+ if (!priv->plat->tx_coe)
+ features &= ~NETIF_F_ALL_CSUM;
+
/* Some GMAC devices have a bugged Jumbo frame support that
* needs to have the Tx COE disabled for oversized frames
* (due to limited buffer sizes). In this case we disable
* the TX csum insertionin the TDES and not use SF. */
- if ((priv->plat->bugged_jumbo) && (priv->dev->mtu > ETH_DATA_LEN))
- priv->no_csum_insertion = 1;
- else
- priv->no_csum_insertion = 0;
+ if (priv->plat->bugged_jumbo && (dev->mtu > ETH_DATA_LEN))
+ features &= ~NETIF_F_ALL_CSUM;
- dev->mtu = new_mtu;
-
- return 0;
+ return features;
}
static irqreturn_t stmmac_interrupt(int irq, void *dev_id)
@@ -1464,6 +1431,7 @@ static const struct net_device_ops stmmac_netdev_ops = {
.ndo_start_xmit = stmmac_xmit,
.ndo_stop = stmmac_release,
.ndo_change_mtu = stmmac_change_mtu,
+ .ndo_fix_features = stmmac_fix_features,
.ndo_set_multicast_list = stmmac_multicast_list,
.ndo_tx_timeout = stmmac_tx_timeout,
.ndo_do_ioctl = stmmac_ioctl,
@@ -1494,8 +1462,8 @@ static int stmmac_probe(struct net_device *dev)
dev->netdev_ops = &stmmac_netdev_ops;
stmmac_set_ethtool_ops(dev);
- dev->features |= NETIF_F_SG | NETIF_F_HIGHDMA |
- NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM;
+ dev->hw_features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM;
+ dev->features |= dev->hw_features | NETIF_F_HIGHDMA;
dev->watchdog_timeo = msecs_to_jiffies(watchdog);
#ifdef STMMAC_VLAN_TAG_USED
/* Both mac100 and gmac support receive VLAN tag detection */