aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorGiuseppe CAVALLARO <peppe.cavallaro@st.com>2010-09-16 23:23:40 -0400
committerDavid S. Miller <davem@davemloft.net>2010-09-17 19:12:57 -0400
commitebbb293f8b3021ae2009fcb7cb3b8a52fb5fd06a (patch)
tree9ee381c887f2bc585c103a34b349d85fd95a2567 /drivers
parentdfb8fb96ae2b5126cd0c08c0ccd7c42e1f46568a (diff)
stmmac: consolidate and tidy-up the COE support
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>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/stmmac/common.h4
-rw-r--r--drivers/net/stmmac/dwmac1000.h2
-rw-r--r--drivers/net/stmmac/dwmac1000_core.c13
-rw-r--r--drivers/net/stmmac/dwmac100_core.c6
-rw-r--r--drivers/net/stmmac/stmmac.h4
-rw-r--r--drivers/net/stmmac/stmmac_ethtool.c2
-rw-r--r--drivers/net/stmmac/stmmac_main.c66
7 files changed, 58 insertions, 39 deletions
diff --git a/drivers/net/stmmac/common.h b/drivers/net/stmmac/common.h
index e8cbcb5c206e..673ef86a063f 100644
--- a/drivers/net/stmmac/common.h
+++ b/drivers/net/stmmac/common.h
@@ -102,8 +102,6 @@ struct stmmac_extra_stats {
102 102
103#define SF_DMA_MODE 1 /* DMA STORE-AND-FORWARD Operation Mode */ 103#define SF_DMA_MODE 1 /* DMA STORE-AND-FORWARD Operation Mode */
104 104
105#define HW_CSUM 1
106#define NO_HW_CSUM 0
107enum rx_frame_status { /* IPC status */ 105enum rx_frame_status { /* IPC status */
108 good_frame = 0, 106 good_frame = 0,
109 discard_frame = 1, 107 discard_frame = 1,
@@ -205,6 +203,8 @@ struct stmmac_dma_ops {
205struct stmmac_ops { 203struct stmmac_ops {
206 /* MAC core initialization */ 204 /* MAC core initialization */
207 void (*core_init) (void __iomem *ioaddr) ____cacheline_aligned; 205 void (*core_init) (void __iomem *ioaddr) ____cacheline_aligned;
206 /* Support checksum offload engine */
207 int (*rx_coe) (void __iomem *ioaddr);
208 /* Dump MAC registers */ 208 /* Dump MAC registers */
209 void (*dump_regs) (void __iomem *ioaddr); 209 void (*dump_regs) (void __iomem *ioaddr);
210 /* Handle extra events on specific interrupts hw dependent */ 210 /* Handle extra events on specific interrupts hw dependent */
diff --git a/drivers/net/stmmac/dwmac1000.h b/drivers/net/stmmac/dwmac1000.h
index 8b20b19971cb..81ee4fd04386 100644
--- a/drivers/net/stmmac/dwmac1000.h
+++ b/drivers/net/stmmac/dwmac1000.h
@@ -99,7 +99,7 @@ enum inter_frame_gap {
99#define GMAC_CONTROL_RE 0x00000004 /* Receiver Enable */ 99#define GMAC_CONTROL_RE 0x00000004 /* Receiver Enable */
100 100
101#define GMAC_CORE_INIT (GMAC_CONTROL_JD | GMAC_CONTROL_PS | GMAC_CONTROL_ACS | \ 101#define GMAC_CORE_INIT (GMAC_CONTROL_JD | GMAC_CONTROL_PS | GMAC_CONTROL_ACS | \
102 GMAC_CONTROL_IPC | GMAC_CONTROL_JE | GMAC_CONTROL_BE) 102 GMAC_CONTROL_JE | GMAC_CONTROL_BE)
103 103
104/* GMAC Frame Filter defines */ 104/* GMAC Frame Filter defines */
105#define GMAC_FRAME_FILTER_PR 0x00000001 /* Promiscuous Mode */ 105#define GMAC_FRAME_FILTER_PR 0x00000001 /* Promiscuous Mode */
diff --git a/drivers/net/stmmac/dwmac1000_core.c b/drivers/net/stmmac/dwmac1000_core.c
index f1f426146f40..c18c85993179 100644
--- a/drivers/net/stmmac/dwmac1000_core.c
+++ b/drivers/net/stmmac/dwmac1000_core.c
@@ -50,6 +50,18 @@ static void dwmac1000_core_init(void __iomem *ioaddr)
50#endif 50#endif
51} 51}
52 52
53static int dwmac1000_rx_coe_supported(void __iomem *ioaddr)
54{
55 u32 value = readl(ioaddr + GMAC_CONTROL);
56
57 value |= GMAC_CONTROL_IPC;
58 writel(value, ioaddr + GMAC_CONTROL);
59
60 value = readl(ioaddr + GMAC_CONTROL);
61
62 return !!(value & GMAC_CONTROL_IPC);
63}
64
53static void dwmac1000_dump_regs(void __iomem *ioaddr) 65static void dwmac1000_dump_regs(void __iomem *ioaddr)
54{ 66{
55 int i; 67 int i;
@@ -202,6 +214,7 @@ static void dwmac1000_irq_status(void __iomem *ioaddr)
202 214
203struct stmmac_ops dwmac1000_ops = { 215struct stmmac_ops dwmac1000_ops = {
204 .core_init = dwmac1000_core_init, 216 .core_init = dwmac1000_core_init,
217 .rx_coe = dwmac1000_rx_coe_supported,
205 .dump_regs = dwmac1000_dump_regs, 218 .dump_regs = dwmac1000_dump_regs,
206 .host_irq_status = dwmac1000_irq_status, 219 .host_irq_status = dwmac1000_irq_status,
207 .set_filter = dwmac1000_set_filter, 220 .set_filter = dwmac1000_set_filter,
diff --git a/drivers/net/stmmac/dwmac100_core.c b/drivers/net/stmmac/dwmac100_core.c
index db06c04ce480..58a914b27003 100644
--- a/drivers/net/stmmac/dwmac100_core.c
+++ b/drivers/net/stmmac/dwmac100_core.c
@@ -42,6 +42,11 @@ static void dwmac100_core_init(void __iomem *ioaddr)
42#endif 42#endif
43} 43}
44 44
45static int dwmac100_rx_coe_supported(void __iomem *ioaddr)
46{
47 return 0;
48}
49
45static void dwmac100_dump_mac_regs(void __iomem *ioaddr) 50static void dwmac100_dump_mac_regs(void __iomem *ioaddr)
46{ 51{
47 pr_info("\t----------------------------------------------\n" 52 pr_info("\t----------------------------------------------\n"
@@ -165,6 +170,7 @@ static void dwmac100_pmt(void __iomem *ioaddr, unsigned long mode)
165 170
166struct stmmac_ops dwmac100_ops = { 171struct stmmac_ops dwmac100_ops = {
167 .core_init = dwmac100_core_init, 172 .core_init = dwmac100_core_init,
173 .rx_coe = dwmac100_rx_coe_supported,
168 .dump_regs = dwmac100_dump_mac_regs, 174 .dump_regs = dwmac100_dump_mac_regs,
169 .host_irq_status = dwmac100_irq_status, 175 .host_irq_status = dwmac100_irq_status,
170 .set_filter = dwmac100_set_filter, 176 .set_filter = dwmac100_set_filter,
diff --git a/drivers/net/stmmac/stmmac.h b/drivers/net/stmmac/stmmac.h
index 12d1cb00c0d7..92154ff7d702 100644
--- a/drivers/net/stmmac/stmmac.h
+++ b/drivers/net/stmmac/stmmac.h
@@ -51,7 +51,6 @@ struct stmmac_priv {
51 int is_gmac; 51 int is_gmac;
52 dma_addr_t dma_rx_phy; 52 dma_addr_t dma_rx_phy;
53 unsigned int dma_rx_size; 53 unsigned int dma_rx_size;
54 int rx_csum;
55 unsigned int dma_buf_sz; 54 unsigned int dma_buf_sz;
56 struct device *device; 55 struct device *device;
57 struct mac_device_info *hw; 56 struct mac_device_info *hw;
@@ -92,6 +91,9 @@ struct stmmac_priv {
92 struct vlan_group *vlgrp; 91 struct vlan_group *vlgrp;
93#endif 92#endif
94 int enh_desc; 93 int enh_desc;
94 int rx_coe;
95 int bugged_jumbo;
96 int no_csum_insertion;
95}; 97};
96 98
97#ifdef CONFIG_STM_DRIVERS 99#ifdef CONFIG_STM_DRIVERS
diff --git a/drivers/net/stmmac/stmmac_ethtool.c b/drivers/net/stmmac/stmmac_ethtool.c
index 63b68e61afce..b32c16ae55c6 100644
--- a/drivers/net/stmmac/stmmac_ethtool.c
+++ b/drivers/net/stmmac/stmmac_ethtool.c
@@ -209,7 +209,7 @@ u32 stmmac_ethtool_get_rx_csum(struct net_device *dev)
209{ 209{
210 struct stmmac_priv *priv = netdev_priv(dev); 210 struct stmmac_priv *priv = netdev_priv(dev);
211 211
212 return priv->rx_csum; 212 return priv->rx_coe;
213} 213}
214 214
215static void 215static void
diff --git a/drivers/net/stmmac/stmmac_main.c b/drivers/net/stmmac/stmmac_main.c
index a169b1441d50..a908f7201aae 100644
--- a/drivers/net/stmmac/stmmac_main.c
+++ b/drivers/net/stmmac/stmmac_main.c
@@ -134,13 +134,6 @@ static int buf_sz = DMA_BUFFER_SIZE;
134module_param(buf_sz, int, S_IRUGO | S_IWUSR); 134module_param(buf_sz, int, S_IRUGO | S_IWUSR);
135MODULE_PARM_DESC(buf_sz, "DMA buffer size"); 135MODULE_PARM_DESC(buf_sz, "DMA buffer size");
136 136
137/* In case of Giga ETH, we can enable/disable the COE for the
138 * transmit HW checksum computation.
139 * Note that, if tx csum is off in HW, SG will be still supported. */
140static int tx_coe = HW_CSUM;
141module_param(tx_coe, int, S_IRUGO | S_IWUSR);
142MODULE_PARM_DESC(tx_coe, "GMAC COE type 2 [on/off]");
143
144static const u32 default_msg_level = (NETIF_MSG_DRV | NETIF_MSG_PROBE | 137static const u32 default_msg_level = (NETIF_MSG_DRV | NETIF_MSG_PROBE |
145 NETIF_MSG_LINK | NETIF_MSG_IFUP | 138 NETIF_MSG_LINK | NETIF_MSG_IFUP |
146 NETIF_MSG_IFDOWN | NETIF_MSG_TIMER); 139 NETIF_MSG_IFDOWN | NETIF_MSG_TIMER);
@@ -569,29 +562,22 @@ static void free_dma_desc_resources(struct stmmac_priv *priv)
569 * stmmac_dma_operation_mode - HW DMA operation mode 562 * stmmac_dma_operation_mode - HW DMA operation mode
570 * @priv : pointer to the private device structure. 563 * @priv : pointer to the private device structure.
571 * Description: it sets the DMA operation mode: tx/rx DMA thresholds 564 * Description: it sets the DMA operation mode: tx/rx DMA thresholds
572 * or Store-And-Forward capability. It also verifies the COE for the 565 * or Store-And-Forward capability.
573 * transmission in case of Giga ETH.
574 */ 566 */
575static void stmmac_dma_operation_mode(struct stmmac_priv *priv) 567static void stmmac_dma_operation_mode(struct stmmac_priv *priv)
576{ 568{
577 if (!priv->is_gmac) { 569 if (likely((priv->tx_coe) && (!priv->no_csum_insertion))) {
578 /* MAC 10/100 */ 570 /* In case of GMAC, SF mode has to be enabled
579 priv->hw->dma->dma_mode(priv->ioaddr, tc, 0); 571 * to perform the TX COE. This depends on:
580 priv->tx_coe = NO_HW_CSUM; 572 * 1) TX COE if actually supported
581 } else { 573 * 2) There is no bugged Jumbo frame support
582 if ((priv->dev->mtu <= ETH_DATA_LEN) && (tx_coe)) { 574 * that needs to not insert csum in the TDES.
583 priv->hw->dma->dma_mode(priv->ioaddr, 575 */
584 SF_DMA_MODE, SF_DMA_MODE); 576 priv->hw->dma->dma_mode(priv->ioaddr,
585 tc = SF_DMA_MODE; 577 SF_DMA_MODE, SF_DMA_MODE);
586 priv->tx_coe = HW_CSUM; 578 tc = SF_DMA_MODE;
587 } else { 579 } else
588 /* Checksum computation is performed in software. */ 580 priv->hw->dma->dma_mode(priv->ioaddr, tc, SF_DMA_MODE);
589 priv->hw->dma->dma_mode(priv->ioaddr, tc,
590 SF_DMA_MODE);
591 priv->tx_coe = NO_HW_CSUM;
592 }
593 }
594 tx_coe = priv->tx_coe;
595} 581}
596 582
597/** 583/**
@@ -858,6 +844,12 @@ static int stmmac_open(struct net_device *dev)
858 /* Initialize the MAC Core */ 844 /* Initialize the MAC Core */
859 priv->hw->mac->core_init(priv->ioaddr); 845 priv->hw->mac->core_init(priv->ioaddr);
860 846
847 priv->rx_coe = priv->hw->mac->rx_coe(priv->ioaddr);
848 if (priv->rx_coe)
849 pr_info("stmmac: Rx Checksum Offload Engine supported\n");
850 if (priv->tx_coe)
851 pr_info("\tTX Checksum insertion supported\n");
852
861 priv->shutdown = 0; 853 priv->shutdown = 0;
862 854
863 /* Initialise the MMC (if present) to disable all interrupts. */ 855 /* 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)
1066 return stmmac_sw_tso(priv, skb); 1058 return stmmac_sw_tso(priv, skb);
1067 1059
1068 if (likely((skb->ip_summed == CHECKSUM_PARTIAL))) { 1060 if (likely((skb->ip_summed == CHECKSUM_PARTIAL))) {
1069 if (likely(priv->tx_coe == NO_HW_CSUM)) 1061 if (unlikely((!priv->tx_coe) || (priv->no_csum_insertion)))
1070 skb_checksum_help(skb); 1062 skb_checksum_help(skb);
1071 else 1063 else
1072 csum_insertion = 1; 1064 csum_insertion = 1;
@@ -1390,6 +1382,15 @@ static int stmmac_change_mtu(struct net_device *dev, int new_mtu)
1390 return -EINVAL; 1382 return -EINVAL;
1391 } 1383 }
1392 1384
1385 /* Some GMAC devices have a bugged Jumbo frame support that
1386 * needs to have the Tx COE disabled for oversized frames
1387 * (due to limited buffer sizes). In this case we disable
1388 * the TX csum insertionin the TDES and not use SF. */
1389 if ((priv->bugged_jumbo) && (priv->dev->mtu > ETH_DATA_LEN))
1390 priv->no_csum_insertion = 1;
1391 else
1392 priv->no_csum_insertion = 0;
1393
1393 dev->mtu = new_mtu; 1394 dev->mtu = new_mtu;
1394 1395
1395 return 0; 1396 return 0;
@@ -1510,9 +1511,6 @@ static int stmmac_probe(struct net_device *dev)
1510#endif 1511#endif
1511 priv->msg_enable = netif_msg_init(debug, default_msg_level); 1512 priv->msg_enable = netif_msg_init(debug, default_msg_level);
1512 1513
1513 if (priv->is_gmac)
1514 priv->rx_csum = 1;
1515
1516 if (flow_ctrl) 1514 if (flow_ctrl)
1517 priv->flow_ctrl = FLOW_AUTO; /* RX/TX pause on */ 1515 priv->flow_ctrl = FLOW_AUTO; /* RX/TX pause on */
1518 1516
@@ -1662,7 +1660,7 @@ static int stmmac_dvr_probe(struct platform_device *pdev)
1662 ret = -ENODEV; 1660 ret = -ENODEV;
1663 goto out; 1661 goto out;
1664 } 1662 }
1665 pr_info("done!\n"); 1663 pr_info("\tdone!\n");
1666 1664
1667 if (!request_mem_region(res->start, resource_size(res), 1665 if (!request_mem_region(res->start, resource_size(res),
1668 pdev->name)) { 1666 pdev->name)) {
@@ -1705,6 +1703,8 @@ static int stmmac_dvr_probe(struct platform_device *pdev)
1705 priv->bus_id = plat_dat->bus_id; 1703 priv->bus_id = plat_dat->bus_id;
1706 priv->pbl = plat_dat->pbl; /* TLI */ 1704 priv->pbl = plat_dat->pbl; /* TLI */
1707 priv->mii_clk_csr = plat_dat->clk_csr; 1705 priv->mii_clk_csr = plat_dat->clk_csr;
1706 priv->tx_coe = plat_dat->tx_coe;
1707 priv->bugged_jumbo = plat_dat->bugged_jumbo;
1708 priv->is_gmac = plat_dat->has_gmac; /* GMAC is on board */ 1708 priv->is_gmac = plat_dat->has_gmac; /* GMAC is on board */
1709 priv->enh_desc = plat_dat->enh_desc; 1709 priv->enh_desc = plat_dat->enh_desc;
1710 priv->ioaddr = addr; 1710 priv->ioaddr = addr;
@@ -1966,8 +1966,6 @@ static int __init stmmac_cmdline_opt(char *str)
1966 strict_strtoul(opt + 7, 0, (unsigned long *)&buf_sz); 1966 strict_strtoul(opt + 7, 0, (unsigned long *)&buf_sz);
1967 else if (!strncmp(opt, "tc:", 3)) 1967 else if (!strncmp(opt, "tc:", 3))
1968 strict_strtoul(opt + 3, 0, (unsigned long *)&tc); 1968 strict_strtoul(opt + 3, 0, (unsigned long *)&tc);
1969 else if (!strncmp(opt, "tx_coe:", 7))
1970 strict_strtoul(opt + 7, 0, (unsigned long *)&tx_coe);
1971 else if (!strncmp(opt, "watchdog:", 9)) 1969 else if (!strncmp(opt, "watchdog:", 9))
1972 strict_strtoul(opt + 9, 0, (unsigned long *)&watchdog); 1970 strict_strtoul(opt + 9, 0, (unsigned long *)&watchdog);
1973 else if (!strncmp(opt, "flow_ctrl:", 10)) 1971 else if (!strncmp(opt, "flow_ctrl:", 10))