stmmac: sanitize the rx coe and add the type-1 csum (v2)
authorDeepak SIKRI <deepak.sikri@st.com>
Wed, 4 Apr 2012 04:33:21 +0000 (04:33 +0000)
committerDavid S. Miller <davem@davemloft.net>
Wed, 4 Apr 2012 22:39:23 +0000 (18:39 -0400)
This patch sanities the RX coe and adds the Type-1 Rx checksum offload engine (COE).

So the RX COE can be passed through the platform but can be fixed
at run-time in case of the core has the HW capability register.

Also to support the Type-1 Rx COE the driver must append the
HW checksum at the end of payload in case the Rx checksum
engine was used to  offload the HW checksum.

This v2 version also fixes the IPC that has to be enabled and verified.

Signed-off-by: Deepak Sikri <deepak.sikri@st.com>
Hacked-by: Giuseppe Cavallaro <peppe.cavallaro@st.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/stmicro/stmmac/common.h
drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c
drivers/net/ethernet/stmicro/stmmac/dwmac100_core.c
drivers/net/ethernet/stmicro/stmmac/enh_desc.c
drivers/net/ethernet/stmicro/stmmac/norm_desc.c
drivers/net/ethernet/stmicro/stmmac/stmmac.h
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c

index 0319d640f72839cd47ad331718bc2ed2c6972539..eec8d34b6c88220d61f2a3d53b6b7afac7b66aea 100644 (file)
@@ -228,7 +228,7 @@ struct stmmac_desc_ops {
        int (*get_rx_owner) (struct dma_desc *p);
        void (*set_rx_owner) (struct dma_desc *p);
        /* Get the receive frame size */
-       int (*get_rx_frame_len) (struct dma_desc *p);
+       int (*get_rx_frame_len) (struct dma_desc *p, int rx_coe_type);
        /* Return the reception status looking at the RDES1 */
        int (*rx_status) (void *data, struct stmmac_extra_stats *x,
                          struct dma_desc *p);
@@ -261,8 +261,8 @@ struct stmmac_dma_ops {
 struct stmmac_ops {
        /* MAC core initialization */
        void (*core_init) (void __iomem *ioaddr) ____cacheline_aligned;
-       /* Support checksum offload engine */
-       int  (*rx_coe) (void __iomem *ioaddr);
+       /* Enable and verify that the IPC module is supported */
+       int (*rx_ipc) (void __iomem *ioaddr);
        /* Dump MAC registers */
        void (*dump_regs) (void __iomem *ioaddr);
        /* Handle extra events on specific interrupts hw dependent */
index b1c48b975945b951c27e1853ad3388283bcf6dbe..e7cbcd99c2cbd1a3f4688e54fc69aa16e1f89c28 100644 (file)
@@ -46,7 +46,7 @@ static void dwmac1000_core_init(void __iomem *ioaddr)
 #endif
 }
 
-static int dwmac1000_rx_coe_supported(void __iomem *ioaddr)
+static int dwmac1000_rx_ipc_enable(void __iomem *ioaddr)
 {
        u32 value = readl(ioaddr + GMAC_CONTROL);
 
@@ -211,7 +211,7 @@ static void dwmac1000_irq_status(void __iomem *ioaddr)
 
 static const struct stmmac_ops dwmac1000_ops = {
        .core_init = dwmac1000_core_init,
-       .rx_coe = dwmac1000_rx_coe_supported,
+       .rx_ipc = dwmac1000_rx_ipc_enable,
        .dump_regs = dwmac1000_dump_regs,
        .host_irq_status = dwmac1000_irq_status,
        .set_filter = dwmac1000_set_filter,
index 138fb8dd1e878f3f5512cd4baf19b1d197a18e2b..efde50ff03f8691b66856ba05289ab5ff399c01e 100644 (file)
@@ -43,11 +43,6 @@ static void dwmac100_core_init(void __iomem *ioaddr)
 #endif
 }
 
-static int dwmac100_rx_coe_supported(void __iomem *ioaddr)
-{
-       return 0;
-}
-
 static void dwmac100_dump_mac_regs(void __iomem *ioaddr)
 {
        pr_info("\t----------------------------------------------\n"
@@ -72,6 +67,11 @@ static void dwmac100_dump_mac_regs(void __iomem *ioaddr)
                readl(ioaddr + MAC_VLAN2));
 }
 
+static int dwmac100_rx_ipc_enable(void __iomem *ioaddr)
+{
+       return 0;
+}
+
 static void dwmac100_irq_status(void __iomem *ioaddr)
 {
        return;
@@ -160,7 +160,7 @@ static void dwmac100_pmt(void __iomem *ioaddr, unsigned long mode)
 
 static const struct stmmac_ops dwmac100_ops = {
        .core_init = dwmac100_core_init,
-       .rx_coe = dwmac100_rx_coe_supported,
+       .rx_ipc = dwmac100_rx_ipc_enable,
        .dump_regs = dwmac100_dump_mac_regs,
        .host_irq_status = dwmac100_irq_status,
        .set_filter = dwmac100_set_filter,
index ad1b627f8ec2fe83607b6ef489f668825be645df..2fc8ef95f97af22b1d368dd15f40b6ea2e2a5070 100644 (file)
@@ -22,6 +22,7 @@
   Author: Giuseppe Cavallaro <peppe.cavallaro@st.com>
 *******************************************************************************/
 
+#include <linux/stmmac.h>
 #include "common.h"
 #include "descs_com.h"
 
@@ -309,9 +310,17 @@ static void enh_desc_close_tx_desc(struct dma_desc *p)
        p->des01.etx.interrupt = 1;
 }
 
-static int enh_desc_get_rx_frame_len(struct dma_desc *p)
+static int enh_desc_get_rx_frame_len(struct dma_desc *p, int rx_coe_type)
 {
-       return p->des01.erx.frame_length;
+       /* The type-1 checksum offload engines append the checksum at
+        * the end of frame and the two bytes of checksum are added in
+        * the length.
+        * Adjust for that in the framelen for type-1 checksum offload
+        * engines. */
+       if (rx_coe_type == STMMAC_RX_COE_TYPE1)
+               return p->des01.erx.frame_length - 2;
+       else
+               return p->des01.erx.frame_length;
 }
 
 const struct stmmac_desc_ops enh_desc_ops = {
index 25953bb45a736acdd517859b98c52850715765b8..68962c549a2d6296815853abaa10cd92e56cfb39 100644 (file)
@@ -22,6 +22,7 @@
   Author: Giuseppe Cavallaro <peppe.cavallaro@st.com>
 *******************************************************************************/
 
+#include <linux/stmmac.h>
 #include "common.h"
 #include "descs_com.h"
 
@@ -201,9 +202,17 @@ static void ndesc_close_tx_desc(struct dma_desc *p)
        p->des01.tx.interrupt = 1;
 }
 
-static int ndesc_get_rx_frame_len(struct dma_desc *p)
+static int ndesc_get_rx_frame_len(struct dma_desc *p, int rx_coe_type)
 {
-       return p->des01.rx.frame_length;
+       /* The type-1 checksum offload engines append the checksum at
+        * the end of frame and the two bytes of checksum are added in
+        * the length.
+        * Adjust for that in the framelen for type-1 checksum offload
+        * engines. */
+       if (rx_coe_type == STMMAC_RX_COE_TYPE1)
+               return p->des01.rx.frame_length - 2;
+       else
+               return p->des01.rx.frame_length;
 }
 
 const struct stmmac_desc_ops ndesc_ops = {
index b4b095fdcf2964f87bdb433b223b940dcb683687..b65d787fee69aeca293f7d3ab9ddd323f8e40442 100644 (file)
@@ -56,8 +56,6 @@ struct stmmac_priv {
 
        struct stmmac_extra_stats xstats;
        struct napi_struct napi;
-
-       int rx_coe;
        int no_csum_insertion;
 
        struct phy_device *phydev;
index 860519c4d9a13964eab4cc6eb59a9bd8feb9372b..84f6b348ec7057c847b780b95582c47a4e40d304 100644 (file)
@@ -1282,7 +1282,8 @@ static int stmmac_rx(struct stmmac_priv *priv, int limit)
                        struct sk_buff *skb;
                        int frame_len;
 
-                       frame_len = priv->hw->desc->get_rx_frame_len(p);
+                       frame_len = priv->hw->desc->get_rx_frame_len(p,
+                                       priv->plat->rx_coe);
                        /* ACS is set; GMAC core strips PAD/FCS for IEEE 802.3
                         * Type frames (LLC/LLC-SNAP) */
                        if (unlikely(status != llc_snap))
@@ -1318,7 +1319,7 @@ static int stmmac_rx(struct stmmac_priv *priv, int limit)
 #endif
                        skb->protocol = eth_type_trans(skb, priv->dev);
 
-                       if (unlikely(!priv->rx_coe)) {
+                       if (unlikely(!priv->plat->rx_coe)) {
                                /* No RX COE for old mac10/100 devices */
                                skb_checksum_none_assert(skb);
                                netif_receive_skb(skb);
@@ -1465,8 +1466,10 @@ static netdev_features_t stmmac_fix_features(struct net_device *dev,
 {
        struct stmmac_priv *priv = netdev_priv(dev);
 
-       if (!priv->rx_coe)
+       if (priv->plat->rx_coe == STMMAC_RX_COE_NONE)
                features &= ~NETIF_F_RXCSUM;
+       else if (priv->plat->rx_coe == STMMAC_RX_COE_TYPE1)
+               features &= ~NETIF_F_IPV6_CSUM;
        if (!priv->plat->tx_coe)
                features &= ~NETIF_F_ALL_CSUM;
 
@@ -1769,17 +1772,32 @@ static int stmmac_hw_init(struct stmmac_priv *priv)
                 * register (if supported).
                 */
                priv->plat->enh_desc = priv->dma_cap.enh_desc;
-               priv->plat->tx_coe = priv->dma_cap.tx_coe;
                priv->plat->pmt = priv->dma_cap.pmt_remote_wake_up;
+
+               priv->plat->tx_coe = priv->dma_cap.tx_coe;
+
+               if (priv->dma_cap.rx_coe_type2)
+                       priv->plat->rx_coe = STMMAC_RX_COE_TYPE2;
+               else if (priv->dma_cap.rx_coe_type1)
+                       priv->plat->rx_coe = STMMAC_RX_COE_TYPE1;
+
        } else
                pr_info(" No HW DMA feature register supported");
 
        /* Select the enhnaced/normal descriptor structures */
        stmmac_selec_desc_mode(priv);
 
-       priv->rx_coe = priv->hw->mac->rx_coe(priv->ioaddr);
-       if (priv->rx_coe)
-               pr_info(" RX Checksum Offload Engine supported\n");
+       /* Enable the IPC (Checksum Offload) and check if the feature has been
+        * enabled during the core configuration. */
+       ret = priv->hw->mac->rx_ipc(priv->ioaddr);
+       if (!ret) {
+               pr_warning(" RX IPC Checksum Offload not configured.\n");
+               priv->plat->rx_coe = STMMAC_RX_COE_NONE;
+       }
+
+       if (priv->plat->rx_coe)
+               pr_info(" RX Checksum Offload Engine supported (type %d)\n",
+                       priv->plat->rx_coe);
        if (priv->plat->tx_coe)
                pr_info(" TX Checksum insertion supported\n");