Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
[firefly-linux-kernel-4.4.55.git] / drivers / net / ethernet / stmicro / stmmac / chain_mode.c
index 0668659803ed3230ababc2b3b9a1aa2a531dae0b..d234ab540b29101a825afacee7d58e27ef5186f5 100644 (file)
@@ -28,9 +28,9 @@
 
 #include "stmmac.h"
 
-unsigned int stmmac_jumbo_frm(void *p, struct sk_buff *skb, int csum)
+static unsigned int stmmac_jumbo_frm(void *p, struct sk_buff *skb, int csum)
 {
-       struct stmmac_priv *priv = (struct stmmac_priv *) p;
+       struct stmmac_priv *priv = (struct stmmac_priv *)p;
        unsigned int txsize = priv->dma_tx_size;
        unsigned int entry = priv->cur_tx % txsize;
        struct dma_desc *desc = priv->dma_tx + entry;
@@ -47,7 +47,8 @@ unsigned int stmmac_jumbo_frm(void *p, struct sk_buff *skb, int csum)
 
        desc->des2 = dma_map_single(priv->device, skb->data,
                                    bmax, DMA_TO_DEVICE);
-       priv->hw->desc->prepare_tx_desc(desc, 1, bmax, csum);
+       priv->tx_skbuff_dma[entry] = desc->des2;
+       priv->hw->desc->prepare_tx_desc(desc, 1, bmax, csum, STMMAC_CHAIN_MODE);
 
        while (len != 0) {
                entry = (++priv->cur_tx) % txsize;
@@ -57,8 +58,9 @@ unsigned int stmmac_jumbo_frm(void *p, struct sk_buff *skb, int csum)
                        desc->des2 = dma_map_single(priv->device,
                                                    (skb->data + bmax * i),
                                                    bmax, DMA_TO_DEVICE);
-                       priv->hw->desc->prepare_tx_desc(desc, 0, bmax,
-                                                       csum);
+                       priv->tx_skbuff_dma[entry] = desc->des2;
+                       priv->hw->desc->prepare_tx_desc(desc, 0, bmax, csum,
+                                                       STMMAC_CHAIN_MODE);
                        priv->hw->desc->set_tx_owner(desc);
                        priv->tx_skbuff[entry] = NULL;
                        len -= bmax;
@@ -67,8 +69,9 @@ unsigned int stmmac_jumbo_frm(void *p, struct sk_buff *skb, int csum)
                        desc->des2 = dma_map_single(priv->device,
                                                    (skb->data + bmax * i), len,
                                                    DMA_TO_DEVICE);
-                       priv->hw->desc->prepare_tx_desc(desc, 0, len,
-                                                       csum);
+                       priv->tx_skbuff_dma[entry] = desc->des2;
+                       priv->hw->desc->prepare_tx_desc(desc, 0, len, csum,
+                                                       STMMAC_CHAIN_MODE);
                        priv->hw->desc->set_tx_owner(desc);
                        priv->tx_skbuff[entry] = NULL;
                        len = 0;
@@ -89,49 +92,70 @@ static unsigned int stmmac_is_jumbo_frm(int len, int enh_desc)
        return ret;
 }
 
-static void stmmac_refill_desc3(int bfsize, struct dma_desc *p)
-{
-}
-
-static void stmmac_init_desc3(int des3_as_data_buf, struct dma_desc *p)
-{
-}
-
-static void stmmac_clean_desc3(struct dma_desc *p)
-{
-}
-
-static void stmmac_init_dma_chain(struct dma_desc *des, dma_addr_t phy_addr,
-                                 unsigned int size)
+static void stmmac_init_dma_chain(void *des, dma_addr_t phy_addr,
+                                 unsigned int size, unsigned int extend_desc)
 {
        /*
         * In chained mode the des3 points to the next element in the ring.
         * The latest element has to point to the head.
         */
        int i;
-       struct dma_desc *p = des;
        dma_addr_t dma_phy = phy_addr;
 
-       for (i = 0; i < (size - 1); i++) {
-               dma_phy += sizeof(struct dma_desc);
-               p->des3 = (unsigned int)dma_phy;
-               p++;
+       if (extend_desc) {
+               struct dma_extended_desc *p = (struct dma_extended_desc *)des;
+               for (i = 0; i < (size - 1); i++) {
+                       dma_phy += sizeof(struct dma_extended_desc);
+                       p->basic.des3 = (unsigned int)dma_phy;
+                       p++;
+               }
+               p->basic.des3 = (unsigned int)phy_addr;
+
+       } else {
+               struct dma_desc *p = (struct dma_desc *)des;
+               for (i = 0; i < (size - 1); i++) {
+                       dma_phy += sizeof(struct dma_desc);
+                       p->des3 = (unsigned int)dma_phy;
+                       p++;
+               }
+               p->des3 = (unsigned int)phy_addr;
        }
-       p->des3 = (unsigned int)phy_addr;
 }
 
-static int stmmac_set_16kib_bfsize(int mtu)
+static void stmmac_refill_desc3(void *priv_ptr, struct dma_desc *p)
+{
+       struct stmmac_priv *priv = (struct stmmac_priv *)priv_ptr;
+
+       if (priv->hwts_rx_en && !priv->extend_desc)
+               /* NOTE: Device will overwrite des3 with timestamp value if
+                * 1588-2002 time stamping is enabled, hence reinitialize it
+                * to keep explicit chaining in the descriptor.
+                */
+               p->des3 = (unsigned int)(priv->dma_rx_phy +
+                                        (((priv->dirty_rx) + 1) %
+                                         priv->dma_rx_size) *
+                                        sizeof(struct dma_desc));
+}
+
+static void stmmac_clean_desc3(void *priv_ptr, struct dma_desc *p)
 {
-       /* Not supported */
-       return 0;
+       struct stmmac_priv *priv = (struct stmmac_priv *)priv_ptr;
+
+       if (priv->hw->desc->get_tx_ls(p) && !priv->extend_desc)
+               /* NOTE: Device will overwrite des3 with timestamp value if
+                * 1588-2002 time stamping is enabled, hence reinitialize it
+                * to keep explicit chaining in the descriptor.
+                */
+               p->des3 = (unsigned int)(priv->dma_tx_phy +
+                                        (((priv->dirty_tx + 1) %
+                                          priv->dma_tx_size) *
+                                         sizeof(struct dma_desc)));
 }
 
-const struct stmmac_ring_mode_ops ring_mode_ops = {
+const struct stmmac_chain_mode_ops chain_mode_ops = {
+       .init = stmmac_init_dma_chain,
        .is_jumbo_frm = stmmac_is_jumbo_frm,
        .jumbo_frm = stmmac_jumbo_frm,
        .refill_desc3 = stmmac_refill_desc3,
-       .init_desc3 = stmmac_init_desc3,
-       .init_dma_chain = stmmac_init_dma_chain,
        .clean_desc3 = stmmac_clean_desc3,
-       .set_16kib_bfsize = stmmac_set_16kib_bfsize,
 };