diff options
author | Giuseppe CAVALLARO <peppe.cavallaro@st.com> | 2010-09-16 23:23:40 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2010-09-17 19:12:57 -0400 |
commit | ebbb293f8b3021ae2009fcb7cb3b8a52fb5fd06a (patch) | |
tree | 9ee381c887f2bc585c103a34b349d85fd95a2567 /drivers/net/stmmac | |
parent | dfb8fb96ae2b5126cd0c08c0ccd7c42e1f46568a (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/net/stmmac')
-rw-r--r-- | drivers/net/stmmac/common.h | 4 | ||||
-rw-r--r-- | drivers/net/stmmac/dwmac1000.h | 2 | ||||
-rw-r--r-- | drivers/net/stmmac/dwmac1000_core.c | 13 | ||||
-rw-r--r-- | drivers/net/stmmac/dwmac100_core.c | 6 | ||||
-rw-r--r-- | drivers/net/stmmac/stmmac.h | 4 | ||||
-rw-r--r-- | drivers/net/stmmac/stmmac_ethtool.c | 2 | ||||
-rw-r--r-- | drivers/net/stmmac/stmmac_main.c | 66 |
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 | ||
107 | enum rx_frame_status { /* IPC status */ | 105 | enum 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 { | |||
205 | struct stmmac_ops { | 203 | struct 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 | ||
53 | static 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 | |||
53 | static void dwmac1000_dump_regs(void __iomem *ioaddr) | 65 | static 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 | ||
203 | struct stmmac_ops dwmac1000_ops = { | 215 | struct 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 | ||
45 | static int dwmac100_rx_coe_supported(void __iomem *ioaddr) | ||
46 | { | ||
47 | return 0; | ||
48 | } | ||
49 | |||
45 | static void dwmac100_dump_mac_regs(void __iomem *ioaddr) | 50 | static 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 | ||
166 | struct stmmac_ops dwmac100_ops = { | 171 | struct 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 | ||
215 | static void | 215 | static 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; | |||
134 | module_param(buf_sz, int, S_IRUGO | S_IWUSR); | 134 | module_param(buf_sz, int, S_IRUGO | S_IWUSR); |
135 | MODULE_PARM_DESC(buf_sz, "DMA buffer size"); | 135 | MODULE_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. */ | ||
140 | static int tx_coe = HW_CSUM; | ||
141 | module_param(tx_coe, int, S_IRUGO | S_IWUSR); | ||
142 | MODULE_PARM_DESC(tx_coe, "GMAC COE type 2 [on/off]"); | ||
143 | |||
144 | static const u32 default_msg_level = (NETIF_MSG_DRV | NETIF_MSG_PROBE | | 137 | static 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 | */ |
575 | static void stmmac_dma_operation_mode(struct stmmac_priv *priv) | 567 | static 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)) |