]> bbs.cooldavid.org Git - net-next-2.6.git/commitdiff
stmmac: consolidate and tidy-up the COE support
authorGiuseppe CAVALLARO <peppe.cavallaro@st.com>
Fri, 17 Sep 2010 03:23:40 +0000 (03:23 +0000)
committerDavid S. Miller <davem@davemloft.net>
Fri, 17 Sep 2010 23:12:57 +0000 (16:12 -0700)
The first version of the driver had hard-coded the logic
for handling the checksum offloading.
This was designed according to the chips included in
the STM platforms where:
o MAC10/100 supports no COE at all.
o GMAC fully supports RX/TX COE.

This is not good for other chip configurations where,
for example, the mac10/100 supports the tx csum in HW
or when the GMAC has no IPC.

Thanks to Johannes Stezenbach; he provided me a first
draft of this patch that only reviewed the IPC for the
GMAC devices.

This patch also helps on SPEAr platforms where the
MAC10/100 can perform the TX csum in HW.
Thanks to Deepak SIKRI for his support on this.

In the end, GMAC devices for STM platforms have
a bugged Jumbo frame support that needs to have
the Tx COE disabled for oversized frames (due to
limited buffer sizes). This information is also
passed through the driver's platform structure.

Signed-off-by: Giuseppe Cavallaro <peppe.cavallaro@st.com>
Signed-off-by: Johannes Stezenbach <js@sig21.net>
Signed-off-by: Deepak SIKRI <deepak.sikri@st.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/stmmac/common.h
drivers/net/stmmac/dwmac1000.h
drivers/net/stmmac/dwmac1000_core.c
drivers/net/stmmac/dwmac100_core.c
drivers/net/stmmac/stmmac.h
drivers/net/stmmac/stmmac_ethtool.c
drivers/net/stmmac/stmmac_main.c
include/linux/stmmac.h

index e8cbcb5c206eaea4ca7945d1def5d96b7acbce3d..673ef86a063f52f1a68cb2b419e4976a5655b861 100644 (file)
@@ -102,8 +102,6 @@ struct stmmac_extra_stats {
 
 #define SF_DMA_MODE 1 /* DMA STORE-AND-FORWARD Operation Mode */
 
-#define HW_CSUM 1
-#define NO_HW_CSUM 0
 enum rx_frame_status { /* IPC status */
        good_frame = 0,
        discard_frame = 1,
@@ -205,6 +203,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);
        /* Dump MAC registers */
        void (*dump_regs) (void __iomem *ioaddr);
        /* Handle extra events on specific interrupts hw dependent */
index 8b20b19971cbe6e0156ce5bee9edc96f73f06785..81ee4fd04386d0163585fc731461af254911fee2 100644 (file)
@@ -99,7 +99,7 @@ enum inter_frame_gap {
 #define GMAC_CONTROL_RE                0x00000004 /* Receiver Enable */
 
 #define GMAC_CORE_INIT (GMAC_CONTROL_JD | GMAC_CONTROL_PS | GMAC_CONTROL_ACS | \
-                       GMAC_CONTROL_IPC | GMAC_CONTROL_JE | GMAC_CONTROL_BE)
+                       GMAC_CONTROL_JE | GMAC_CONTROL_BE)
 
 /* GMAC Frame Filter defines */
 #define GMAC_FRAME_FILTER_PR   0x00000001      /* Promiscuous Mode */
index f1f426146f403be79ed4f20832392bfb53215d88..c18c85993179b7e862a18b5f1b8acc3951ab61a0 100644 (file)
@@ -50,6 +50,18 @@ static void dwmac1000_core_init(void __iomem *ioaddr)
 #endif
 }
 
+static int dwmac1000_rx_coe_supported(void __iomem *ioaddr)
+{
+       u32 value = readl(ioaddr + GMAC_CONTROL);
+
+       value |= GMAC_CONTROL_IPC;
+       writel(value, ioaddr + GMAC_CONTROL);
+
+       value = readl(ioaddr + GMAC_CONTROL);
+
+       return !!(value & GMAC_CONTROL_IPC);
+}
+
 static void dwmac1000_dump_regs(void __iomem *ioaddr)
 {
        int i;
@@ -202,6 +214,7 @@ static void dwmac1000_irq_status(void __iomem *ioaddr)
 
 struct stmmac_ops dwmac1000_ops = {
        .core_init = dwmac1000_core_init,
+       .rx_coe = dwmac1000_rx_coe_supported,
        .dump_regs = dwmac1000_dump_regs,
        .host_irq_status = dwmac1000_irq_status,
        .set_filter = dwmac1000_set_filter,
index db06c04ce4802621d61d6fdab5e17b174b14da1d..58a914b27003418b06253fc19378d3b9f23e4023 100644 (file)
@@ -42,6 +42,11 @@ 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"
@@ -165,6 +170,7 @@ static void dwmac100_pmt(void __iomem *ioaddr, unsigned long mode)
 
 struct stmmac_ops dwmac100_ops = {
        .core_init = dwmac100_core_init,
+       .rx_coe = dwmac100_rx_coe_supported,
        .dump_regs = dwmac100_dump_mac_regs,
        .host_irq_status = dwmac100_irq_status,
        .set_filter = dwmac100_set_filter,
index 12d1cb00c0d72bc22625ef0dcb90b25304b7bf4b..92154ff7d70203cc3c6cbc7f710a46ba36831033 100644 (file)
@@ -51,7 +51,6 @@ struct stmmac_priv {
        int is_gmac;
        dma_addr_t dma_rx_phy;
        unsigned int dma_rx_size;
-       int rx_csum;
        unsigned int dma_buf_sz;
        struct device *device;
        struct mac_device_info *hw;
@@ -92,6 +91,9 @@ struct stmmac_priv {
        struct vlan_group *vlgrp;
 #endif
        int enh_desc;
+       int rx_coe;
+       int bugged_jumbo;
+       int no_csum_insertion;
 };
 
 #ifdef CONFIG_STM_DRIVERS
index 63b68e61afce3ebfadd07efa1b49c55dc821bbae..b32c16ae55c6717b915e4ca73795c914d889655f 100644 (file)
@@ -209,7 +209,7 @@ u32 stmmac_ethtool_get_rx_csum(struct net_device *dev)
 {
        struct stmmac_priv *priv = netdev_priv(dev);
 
-       return priv->rx_csum;
+       return priv->rx_coe;
 }
 
 static void
index a169b1441d5051b1156a9b51f03439538e70dbec..a908f7201aae4dda64949787330570b98983e583 100644 (file)
@@ -134,13 +134,6 @@ static int buf_sz = DMA_BUFFER_SIZE;
 module_param(buf_sz, int, S_IRUGO | S_IWUSR);
 MODULE_PARM_DESC(buf_sz, "DMA buffer size");
 
-/* In case of Giga ETH, we can enable/disable the COE for the
- * transmit HW checksum computation.
- * Note that, if tx csum is off in HW, SG will be still supported. */
-static int tx_coe = HW_CSUM;
-module_param(tx_coe, int, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(tx_coe, "GMAC COE type 2 [on/off]");
-
 static const u32 default_msg_level = (NETIF_MSG_DRV | NETIF_MSG_PROBE |
                                      NETIF_MSG_LINK | NETIF_MSG_IFUP |
                                      NETIF_MSG_IFDOWN | NETIF_MSG_TIMER);
@@ -569,29 +562,22 @@ static void free_dma_desc_resources(struct stmmac_priv *priv)
  *  stmmac_dma_operation_mode - HW DMA operation mode
  *  @priv : pointer to the private device structure.
  *  Description: it sets the DMA operation mode: tx/rx DMA thresholds
- *  or Store-And-Forward capability. It also verifies the COE for the
- *  transmission in case of Giga ETH.
+ *  or Store-And-Forward capability.
  */
 static void stmmac_dma_operation_mode(struct stmmac_priv *priv)
 {
-       if (!priv->is_gmac) {
-               /* MAC 10/100 */
-               priv->hw->dma->dma_mode(priv->ioaddr, tc, 0);
-               priv->tx_coe = NO_HW_CSUM;
-       } else {
-               if ((priv->dev->mtu <= ETH_DATA_LEN) && (tx_coe)) {
-                       priv->hw->dma->dma_mode(priv->ioaddr,
-                                               SF_DMA_MODE, SF_DMA_MODE);
-                       tc = SF_DMA_MODE;
-                       priv->tx_coe = HW_CSUM;
-               } else {
-                       /* Checksum computation is performed in software. */
-                       priv->hw->dma->dma_mode(priv->ioaddr, tc,
-                                               SF_DMA_MODE);
-                       priv->tx_coe = NO_HW_CSUM;
-               }
-       }
-       tx_coe = priv->tx_coe;
+       if (likely((priv->tx_coe) && (!priv->no_csum_insertion))) {
+               /* In case of GMAC, SF mode has to be enabled
+                * to perform the TX COE. This depends on:
+                * 1) TX COE if actually supported
+                * 2) There is no bugged Jumbo frame support
+                *    that needs to not insert csum in the TDES.
+                */
+               priv->hw->dma->dma_mode(priv->ioaddr,
+                                       SF_DMA_MODE, SF_DMA_MODE);
+               tc = SF_DMA_MODE;
+       } else
+               priv->hw->dma->dma_mode(priv->ioaddr, tc, SF_DMA_MODE);
 }
 
 /**
@@ -858,6 +844,12 @@ static int stmmac_open(struct net_device *dev)
        /* Initialize the MAC Core */
        priv->hw->mac->core_init(priv->ioaddr);
 
+       priv->rx_coe = priv->hw->mac->rx_coe(priv->ioaddr);
+       if (priv->rx_coe)
+               pr_info("stmmac: Rx Checksum Offload Engine supported\n");
+       if (priv->tx_coe)
+               pr_info("\tTX Checksum insertion supported\n");
+
        priv->shutdown = 0;
 
        /* Initialise the MMC (if present) to disable all interrupts. */
@@ -1066,7 +1058,7 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev)
                return stmmac_sw_tso(priv, skb);
 
        if (likely((skb->ip_summed == CHECKSUM_PARTIAL))) {
-               if (likely(priv->tx_coe == NO_HW_CSUM))
+               if (unlikely((!priv->tx_coe) || (priv->no_csum_insertion)))
                        skb_checksum_help(skb);
                else
                        csum_insertion = 1;
@@ -1390,6 +1382,15 @@ static int stmmac_change_mtu(struct net_device *dev, int new_mtu)
                return -EINVAL;
        }
 
+       /* 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->bugged_jumbo) && (priv->dev->mtu > ETH_DATA_LEN))
+               priv->no_csum_insertion = 1;
+       else
+               priv->no_csum_insertion = 0;
+
        dev->mtu = new_mtu;
 
        return 0;
@@ -1510,9 +1511,6 @@ static int stmmac_probe(struct net_device *dev)
 #endif
        priv->msg_enable = netif_msg_init(debug, default_msg_level);
 
-       if (priv->is_gmac)
-               priv->rx_csum = 1;
-
        if (flow_ctrl)
                priv->flow_ctrl = FLOW_AUTO;    /* RX/TX pause on */
 
@@ -1662,7 +1660,7 @@ static int stmmac_dvr_probe(struct platform_device *pdev)
                ret = -ENODEV;
                goto out;
        }
-       pr_info("done!\n");
+       pr_info("\tdone!\n");
 
        if (!request_mem_region(res->start, resource_size(res),
                                pdev->name)) {
@@ -1705,6 +1703,8 @@ static int stmmac_dvr_probe(struct platform_device *pdev)
        priv->bus_id = plat_dat->bus_id;
        priv->pbl = plat_dat->pbl;      /* TLI */
        priv->mii_clk_csr = plat_dat->clk_csr;
+       priv->tx_coe = plat_dat->tx_coe;
+       priv->bugged_jumbo = plat_dat->bugged_jumbo;
        priv->is_gmac = plat_dat->has_gmac;     /* GMAC is on board */
        priv->enh_desc = plat_dat->enh_desc;
        priv->ioaddr = addr;
@@ -1966,8 +1966,6 @@ static int __init stmmac_cmdline_opt(char *str)
                        strict_strtoul(opt + 7, 0, (unsigned long *)&buf_sz);
                else if (!strncmp(opt, "tc:", 3))
                        strict_strtoul(opt + 3, 0, (unsigned long *)&tc);
-               else if (!strncmp(opt, "tx_coe:", 7))
-                       strict_strtoul(opt + 7, 0, (unsigned long *)&tx_coe);
                else if (!strncmp(opt, "watchdog:", 9))
                        strict_strtoul(opt + 9, 0, (unsigned long *)&watchdog);
                else if (!strncmp(opt, "flow_ctrl:", 10))
index c87c88ccffc0464cad4eceae65655aa650b27019..1d8baf719211e5324af6beaf70ce8a4ee1c353ac 100644 (file)
@@ -35,6 +35,8 @@ struct plat_stmmacenet_data {
        int clk_csr;
        int has_gmac;
        int enh_desc;
+       int tx_coe;
+       int bugged_jumbo;
        void (*fix_mac_speed)(void *priv, unsigned int speed);
        void (*bus_setup)(void __iomem *ioaddr);
 #ifdef CONFIG_STM_DRIVERS