diff options
Diffstat (limited to 'drivers/net/stmmac')
-rw-r--r-- | drivers/net/stmmac/dwmac1000_core.c | 5 | ||||
-rw-r--r-- | drivers/net/stmmac/dwmac_lib.c | 28 | ||||
-rw-r--r-- | drivers/net/stmmac/stmmac.h | 1 | ||||
-rw-r--r-- | drivers/net/stmmac/stmmac_ethtool.c | 33 | ||||
-rw-r--r-- | drivers/net/stmmac/stmmac_main.c | 136 |
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 */ |