]> asedeno.scripts.mit.edu Git - linux.git/blobdiff - drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
Merge tag 'uuid-for-4.13-2' of git://git.infradead.org/users/hch/uuid
[linux.git] / drivers / net / ethernet / stmicro / stmmac / stmmac_main.c
index 6e4cbc6ce0efd9843a55341ec47eb76fd9932327..1763e48c84e2090678f4ffc1b55cf1d7a62382e4 100644 (file)
@@ -235,6 +235,17 @@ static void stmmac_clk_csr_set(struct stmmac_priv *priv)
                else if ((clk_rate >= CSR_F_250M) && (clk_rate < CSR_F_300M))
                        priv->clk_csr = STMMAC_CSR_250_300M;
        }
+
+       if (priv->plat->has_sun8i) {
+               if (clk_rate > 160000000)
+                       priv->clk_csr = 0x03;
+               else if (clk_rate > 80000000)
+                       priv->clk_csr = 0x02;
+               else if (clk_rate > 40000000)
+                       priv->clk_csr = 0x01;
+               else
+                       priv->clk_csr = 0;
+       }
 }
 
 static void print_pkt(unsigned char *buf, int len)
@@ -653,6 +664,7 @@ static int stmmac_hwtstamp_ioctl(struct net_device *dev, struct ifreq *ifr)
                        ptp_over_ethernet = PTP_TCR_TSIPENA;
                        break;
 
+               case HWTSTAMP_FILTER_NTP_ALL:
                case HWTSTAMP_FILTER_ALL:
                        /* time stamp any incoming packet */
                        config.rx_filter = HWTSTAMP_FILTER_ALL;
@@ -783,7 +795,7 @@ static void stmmac_adjust_link(struct net_device *dev)
        struct stmmac_priv *priv = netdev_priv(dev);
        struct phy_device *phydev = dev->phydev;
        unsigned long flags;
-       int new_state = 0;
+       bool new_state = false;
 
        if (!phydev)
                return;
@@ -796,8 +808,8 @@ static void stmmac_adjust_link(struct net_device *dev)
                /* Now we make sure that we can be in full duplex mode.
                 * If not, we operate in half-duplex mode. */
                if (phydev->duplex != priv->oldduplex) {
-                       new_state = 1;
-                       if (!(phydev->duplex))
+                       new_state = true;
+                       if (!phydev->duplex)
                                ctrl &= ~priv->hw->link.duplex;
                        else
                                ctrl |= priv->hw->link.duplex;
@@ -808,30 +820,17 @@ static void stmmac_adjust_link(struct net_device *dev)
                        stmmac_mac_flow_ctrl(priv, phydev->duplex);
 
                if (phydev->speed != priv->speed) {
-                       new_state = 1;
+                       new_state = true;
+                       ctrl &= ~priv->hw->link.speed_mask;
                        switch (phydev->speed) {
-                       case 1000:
-                               if (priv->plat->has_gmac ||
-                                   priv->plat->has_gmac4)
-                                       ctrl &= ~priv->hw->link.port;
+                       case SPEED_1000:
+                               ctrl |= priv->hw->link.speed1000;
                                break;
-                       case 100:
-                               if (priv->plat->has_gmac ||
-                                   priv->plat->has_gmac4) {
-                                       ctrl |= priv->hw->link.port;
-                                       ctrl |= priv->hw->link.speed;
-                               } else {
-                                       ctrl &= ~priv->hw->link.port;
-                               }
+                       case SPEED_100:
+                               ctrl |= priv->hw->link.speed100;
                                break;
-                       case 10:
-                               if (priv->plat->has_gmac ||
-                                   priv->plat->has_gmac4) {
-                                       ctrl |= priv->hw->link.port;
-                                       ctrl &= ~(priv->hw->link.speed);
-                               } else {
-                                       ctrl &= ~priv->hw->link.port;
-                               }
+                       case SPEED_10:
+                               ctrl |= priv->hw->link.speed10;
                                break;
                        default:
                                netif_warn(priv, link, priv->dev,
@@ -847,12 +846,12 @@ static void stmmac_adjust_link(struct net_device *dev)
                writel(ctrl, priv->ioaddr + MAC_CTRL_REG);
 
                if (!priv->oldlink) {
-                       new_state = 1;
-                       priv->oldlink = 1;
+                       new_state = true;
+                       priv->oldlink = true;
                }
        } else if (priv->oldlink) {
-               new_state = 1;
-               priv->oldlink = 0;
+               new_state = true;
+               priv->oldlink = false;
                priv->speed = SPEED_UNKNOWN;
                priv->oldduplex = DUPLEX_UNKNOWN;
        }
@@ -915,7 +914,7 @@ static int stmmac_init_phy(struct net_device *dev)
        char bus_id[MII_BUS_ID_SIZE];
        int interface = priv->plat->interface;
        int max_speed = priv->plat->max_speed;
-       priv->oldlink = 0;
+       priv->oldlink = false;
        priv->speed = SPEED_UNKNOWN;
        priv->oldduplex = DUPLEX_UNKNOWN;
 
@@ -1450,7 +1449,7 @@ static void free_dma_rx_desc_resources(struct stmmac_priv *priv)
 static void free_dma_tx_desc_resources(struct stmmac_priv *priv)
 {
        u32 tx_count = priv->plat->tx_queues_to_use;
-       u32 queue = 0;
+       u32 queue;
 
        /* Free TX queue resources */
        for (queue = 0; queue < tx_count; queue++) {
@@ -1499,7 +1498,7 @@ static int alloc_dma_rx_desc_resources(struct stmmac_priv *priv)
                                                    sizeof(dma_addr_t),
                                                    GFP_KERNEL);
                if (!rx_q->rx_skbuff_dma)
-                       return -ENOMEM;
+                       goto err_dma;
 
                rx_q->rx_skbuff = kmalloc_array(DMA_RX_SIZE,
                                                sizeof(struct sk_buff *),
@@ -1562,13 +1561,13 @@ static int alloc_dma_tx_desc_resources(struct stmmac_priv *priv)
                                                    sizeof(*tx_q->tx_skbuff_dma),
                                                    GFP_KERNEL);
                if (!tx_q->tx_skbuff_dma)
-                       return -ENOMEM;
+                       goto err_dma;
 
                tx_q->tx_skbuff = kmalloc_array(DMA_TX_SIZE,
                                                sizeof(struct sk_buff *),
                                                GFP_KERNEL);
                if (!tx_q->tx_skbuff)
-                       goto err_dma_buffers;
+                       goto err_dma;
 
                if (priv->extend_desc) {
                        tx_q->dma_etx = dma_zalloc_coherent(priv->device,
@@ -1578,7 +1577,7 @@ static int alloc_dma_tx_desc_resources(struct stmmac_priv *priv)
                                                            &tx_q->dma_tx_phy,
                                                            GFP_KERNEL);
                        if (!tx_q->dma_etx)
-                               goto err_dma_buffers;
+                               goto err_dma;
                } else {
                        tx_q->dma_tx = dma_zalloc_coherent(priv->device,
                                                           DMA_TX_SIZE *
@@ -1587,13 +1586,13 @@ static int alloc_dma_tx_desc_resources(struct stmmac_priv *priv)
                                                           &tx_q->dma_tx_phy,
                                                           GFP_KERNEL);
                        if (!tx_q->dma_tx)
-                               goto err_dma_buffers;
+                               goto err_dma;
                }
        }
 
        return 0;
 
-err_dma_buffers:
+err_dma:
        free_dma_tx_desc_resources(priv);
 
        return ret;
@@ -2895,8 +2894,7 @@ static netdev_tx_t stmmac_tso_xmit(struct sk_buff *skb, struct net_device *dev)
                priv->xstats.tx_set_ic_bit++;
        }
 
-       if (!priv->hwts_tx_en)
-               skb_tx_timestamp(skb);
+       skb_tx_timestamp(skb);
 
        if (unlikely((skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP) &&
                     priv->hwts_tx_en)) {
@@ -2974,7 +2972,7 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev)
 
        /* Manage oversized TCP frames for GMAC4 device */
        if (skb_is_gso(skb) && priv->tso) {
-               if (ip_hdr(skb)->protocol == IPPROTO_TCP)
+               if (skb_shinfo(skb)->gso_type & (SKB_GSO_TCPV4 | SKB_GSO_TCPV6))
                        return stmmac_tso_xmit(skb, dev);
        }
 
@@ -3105,8 +3103,7 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev)
                priv->xstats.tx_set_ic_bit++;
        }
 
-       if (!priv->hwts_tx_en)
-               skb_tx_timestamp(skb);
+       skb_tx_timestamp(skb);
 
        /* Ready to fill the first descriptor and set the OWN bit w/o any
         * problems because all the descriptors are actually ready to be
@@ -3969,7 +3966,9 @@ static int stmmac_hw_init(struct stmmac_priv *priv)
        struct mac_device_info *mac;
 
        /* Identify the MAC HW device */
-       if (priv->plat->has_gmac) {
+       if (priv->plat->setup) {
+               mac = priv->plat->setup(priv);
+       } else if (priv->plat->has_gmac) {
                priv->dev->priv_flags |= IFF_UNICAST_FLT;
                mac = dwmac1000_setup(priv->ioaddr,
                                      priv->plat->multicast_filter_bins,
@@ -3989,6 +3988,10 @@ static int stmmac_hw_init(struct stmmac_priv *priv)
 
        priv->hw = mac;
 
+       /* dwmac-sun8i only work in chain mode */
+       if (priv->plat->has_sun8i)
+               chain_mode = 1;
+
        /* To use the chained or ring mode */
        if (priv->synopsys_id >= DWMAC_CORE_4_00) {
                priv->hw->mode = &dwmac4_ring_mode_ops;
@@ -4117,8 +4120,15 @@ int stmmac_dvr_probe(struct device *device,
        if ((phyaddr >= 0) && (phyaddr <= 31))
                priv->plat->phy_addr = phyaddr;
 
-       if (priv->plat->stmmac_rst)
+       if (priv->plat->stmmac_rst) {
+               ret = reset_control_assert(priv->plat->stmmac_rst);
                reset_control_deassert(priv->plat->stmmac_rst);
+               /* Some reset controllers have only reset callback instead of
+                * assert + deassert callbacks pair.
+                */
+               if (ret == -ENOTSUPP)
+                       reset_control_reset(priv->plat->stmmac_rst);
+       }
 
        /* Init MAC and get the capabilities */
        ret = stmmac_hw_init(priv);
@@ -4135,7 +4145,7 @@ int stmmac_dvr_probe(struct device *device,
                            NETIF_F_RXCSUM;
 
        if ((priv->plat->tso_en) && (priv->dma_cap.tsoen)) {
-               ndev->hw_features |= NETIF_F_TSO;
+               ndev->hw_features |= NETIF_F_TSO | NETIF_F_TSO6;
                priv->tso = true;
                dev_info(priv->device, "TSO feature enabled\n");
        }
@@ -4314,7 +4324,7 @@ int stmmac_suspend(struct device *dev)
        }
        spin_unlock_irqrestore(&priv->lock, flags);
 
-       priv->oldlink = 0;
+       priv->oldlink = false;
        priv->speed = SPEED_UNKNOWN;
        priv->oldduplex = DUPLEX_UNKNOWN;
        return 0;