These changes are the raw update to linux-4.4.6-rt14. Kernel sources
[kvmfornfv.git] / kernel / drivers / net / ethernet / stmicro / stmmac / stmmac_main.c
index c274cdc..a5b869e 100644 (file)
@@ -52,6 +52,7 @@
 #include "stmmac_ptp.h"
 #include "stmmac.h"
 #include <linux/reset.h>
+#include <linux/of_mdio.h>
 
 #define STMMAC_ALIGN(x)        L1_CACHE_ALIGN(x)
 
@@ -184,7 +185,7 @@ static void stmmac_clk_csr_set(struct stmmac_priv *priv)
                        priv->clk_csr = STMMAC_CSR_100_150M;
                else if ((clk_rate >= CSR_F_150M) && (clk_rate < CSR_F_250M))
                        priv->clk_csr = STMMAC_CSR_150_250M;
-               else if ((clk_rate >= CSR_F_250M) && (clk_rate < CSR_F_300M))
+               else if ((clk_rate >= CSR_F_250M) && (clk_rate <= CSR_F_300M))
                        priv->clk_csr = STMMAC_CSR_250_300M;
        }
 }
@@ -423,7 +424,7 @@ static int stmmac_hwtstamp_ioctl(struct net_device *dev, struct ifreq *ifr)
 {
        struct stmmac_priv *priv = netdev_priv(dev);
        struct hwtstamp_config config;
-       struct timespec now;
+       struct timespec64 now;
        u64 temp = 0;
        u32 ptp_v2 = 0;
        u32 tstamp_all = 0;
@@ -620,8 +621,10 @@ static int stmmac_hwtstamp_ioctl(struct net_device *dev, struct ifreq *ifr)
                                             priv->default_addend);
 
                /* initialize system time */
-               getnstimeofday(&now);
-               priv->hw->ptp->init_systime(priv->ioaddr, now.tv_sec,
+               ktime_get_real_ts64(&now);
+
+               /* lower 32 bits of tv_sec are safe until y2106 */
+               priv->hw->ptp->init_systime(priv->ioaddr, (u32)now.tv_sec,
                                            now.tv_nsec);
        }
 
@@ -816,18 +819,25 @@ static int stmmac_init_phy(struct net_device *dev)
        priv->speed = 0;
        priv->oldduplex = -1;
 
-       if (priv->plat->phy_bus_name)
-               snprintf(bus_id, MII_BUS_ID_SIZE, "%s-%x",
-                        priv->plat->phy_bus_name, priv->plat->bus_id);
-       else
-               snprintf(bus_id, MII_BUS_ID_SIZE, "stmmac-%x",
-                        priv->plat->bus_id);
+       if (priv->plat->phy_node) {
+               phydev = of_phy_connect(dev, priv->plat->phy_node,
+                                       &stmmac_adjust_link, 0, interface);
+       } else {
+               if (priv->plat->phy_bus_name)
+                       snprintf(bus_id, MII_BUS_ID_SIZE, "%s-%x",
+                                priv->plat->phy_bus_name, priv->plat->bus_id);
+               else
+                       snprintf(bus_id, MII_BUS_ID_SIZE, "stmmac-%x",
+                                priv->plat->bus_id);
 
-       snprintf(phy_id_fmt, MII_BUS_ID_SIZE + 3, PHY_ID_FMT, bus_id,
-                priv->plat->phy_addr);
-       pr_debug("stmmac_init_phy:  trying to attach to %s\n", phy_id_fmt);
+               snprintf(phy_id_fmt, MII_BUS_ID_SIZE + 3, PHY_ID_FMT, bus_id,
+                        priv->plat->phy_addr);
+               pr_debug("stmmac_init_phy:  trying to attach to %s\n",
+                        phy_id_fmt);
 
-       phydev = phy_connect(dev, phy_id_fmt, &stmmac_adjust_link, interface);
+               phydev = phy_connect(dev, phy_id_fmt, &stmmac_adjust_link,
+                                    interface);
+       }
 
        if (IS_ERR_OR_NULL(phydev)) {
                pr_err("%s: Could not attach to PHY\n", dev->name);
@@ -851,7 +861,7 @@ static int stmmac_init_phy(struct net_device *dev)
         * device as well.
         * Note: phydev->phy_id is the result of reading the UID PHY registers.
         */
-       if (phydev->phy_id == 0) {
+       if (!priv->plat->phy_node && phydev->phy_id == 0) {
                phy_disconnect(phydev);
                return -ENODEV;
        }
@@ -978,13 +988,11 @@ static int stmmac_init_rx_buffers(struct stmmac_priv *priv, struct dma_desc *p,
 {
        struct sk_buff *skb;
 
-       skb = __netdev_alloc_skb(priv->dev, priv->dma_buf_sz + NET_IP_ALIGN,
-                                flags);
+       skb = __netdev_alloc_skb_ip_align(priv->dev, priv->dma_buf_sz, flags);
        if (!skb) {
                pr_err("%s: Rx init fails; skb is NULL\n", __func__);
                return -ENOMEM;
        }
-       skb_reserve(skb, NET_IP_ALIGN);
        priv->rx_skbuff[i] = skb;
        priv->rx_skbuff_dma[i] = dma_map_single(priv->device, skb->data,
                                                priv->dma_buf_sz,
@@ -1939,7 +1947,7 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev)
 {
        struct stmmac_priv *priv = netdev_priv(dev);
        unsigned int txsize = priv->dma_tx_size;
-       unsigned int entry;
+       int entry;
        int i, csum_insertion = 0, is_jumbo = 0;
        int nfrags = skb_shinfo(skb)->nr_frags;
        struct dma_desc *desc, *first;
@@ -2224,6 +2232,12 @@ static int stmmac_rx(struct stmmac_priv *priv, int limit)
 
                        frame_len = priv->hw->desc->get_rx_frame_len(p, coe);
 
+                       /*  check if frame_len fits the preallocated memory */
+                       if (frame_len > priv->dma_buf_sz) {
+                               priv->dev->stats.rx_length_errors++;
+                               break;
+                       }
+
                        /* ACS is set; GMAC core strips PAD/FCS for IEEE 802.3
                         * Type frames (LLC/LLC-SNAP)
                         */
@@ -2803,16 +2817,15 @@ static int stmmac_hw_init(struct stmmac_priv *priv)
  * stmmac_dvr_probe
  * @device: device pointer
  * @plat_dat: platform data pointer
- * @addr: iobase memory address
+ * @res: stmmac resource pointer
  * Description: this is the main probe function used to
  * call the alloc_etherdev, allocate the priv structure.
  * Return:
- * on success the new private structure is returned, otherwise the error
- * pointer.
+ * returns 0 on success, otherwise errno.
  */
-struct stmmac_priv *stmmac_dvr_probe(struct device *device,
-                                    struct plat_stmmacenet_data *plat_dat,
-                                    void __iomem *addr)
+int stmmac_dvr_probe(struct device *device,
+                    struct plat_stmmacenet_data *plat_dat,
+                    struct stmmac_resources *res)
 {
        int ret = 0;
        struct net_device *ndev = NULL;
@@ -2820,7 +2833,7 @@ struct stmmac_priv *stmmac_dvr_probe(struct device *device,
 
        ndev = alloc_etherdev(sizeof(struct stmmac_priv));
        if (!ndev)
-               return ERR_PTR(-ENOMEM);
+               return -ENOMEM;
 
        SET_NETDEV_DEV(ndev, device);
 
@@ -2831,8 +2844,17 @@ struct stmmac_priv *stmmac_dvr_probe(struct device *device,
        stmmac_set_ethtool_ops(ndev);
        priv->pause = pause;
        priv->plat = plat_dat;
-       priv->ioaddr = addr;
-       priv->dev->base_addr = (unsigned long)addr;
+       priv->ioaddr = res->addr;
+       priv->dev->base_addr = (unsigned long)res->addr;
+
+       priv->dev->irq = res->irq;
+       priv->wol_irq = res->wol_irq;
+       priv->lpi_irq = res->lpi_irq;
+
+       if (res->mac)
+               memcpy(priv->dev->dev_addr, res->mac, ETH_ALEN);
+
+       dev_set_drvdata(device, priv->dev);
 
        /* Verify driver arguments */
        stmmac_verify_args();
@@ -2947,7 +2969,7 @@ struct stmmac_priv *stmmac_dvr_probe(struct device *device,
                }
        }
 
-       return priv;
+       return 0;
 
 error_mdio_register:
        unregister_netdev(ndev);
@@ -2960,7 +2982,7 @@ error_pclk_get:
 error_clk_get:
        free_netdev(ndev);
 
-       return ERR_PTR(ret);
+       return ret;
 }
 EXPORT_SYMBOL_GPL(stmmac_dvr_probe);
 
@@ -3024,8 +3046,6 @@ int stmmac_suspend(struct net_device *ndev)
        priv->hw->dma->stop_tx(priv->ioaddr);
        priv->hw->dma->stop_rx(priv->ioaddr);
 
-       stmmac_clear_descriptors(priv);
-
        /* Enable Power down mode by programming the PMT regs */
        if (device_may_wakeup(priv->device)) {
                priv->hw->mac->pmt(priv->hw, priv->wolopts);
@@ -3083,9 +3103,15 @@ int stmmac_resume(struct net_device *ndev)
 
        netif_device_attach(ndev);
 
-       init_dma_desc_rings(ndev, GFP_ATOMIC);
+       priv->cur_rx = 0;
+       priv->dirty_rx = 0;
+       priv->dirty_tx = 0;
+       priv->cur_tx = 0;
+       stmmac_clear_descriptors(priv);
+
        stmmac_hw_setup(ndev, false);
        stmmac_init_tx_coalesce(priv);
+       stmmac_set_rx_mode(ndev);
 
        napi_enable(&priv->napi);