aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ethernet/stmicro
diff options
context:
space:
mode:
authorDeepak SIKRI <deepak.sikri@st.com>2012-04-04 00:33:21 -0400
committerDavid S. Miller <davem@davemloft.net>2012-04-04 18:39:23 -0400
commit38912bdbde5f39aa00dfc6228ef580ff79b46bd3 (patch)
treeedd34f950438e75d8b47a71c832830e934117b77 /drivers/net/ethernet/stmicro
parent55f9a4d6facb35198ddb88a8fe21ca2ee753af7a (diff)
stmmac: sanitize the rx coe and add the type-1 csum (v2)
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>
Diffstat (limited to 'drivers/net/ethernet/stmicro')
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/common.h6
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c4
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac100_core.c12
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/enh_desc.c13
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/norm_desc.c13
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/stmmac.h2
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/stmmac_main.c32
7 files changed, 58 insertions, 24 deletions
diff --git a/drivers/net/ethernet/stmicro/stmmac/common.h b/drivers/net/ethernet/stmicro/stmmac/common.h
index 0319d640f728..eec8d34b6c88 100644
--- a/drivers/net/ethernet/stmicro/stmmac/common.h
+++ b/drivers/net/ethernet/stmicro/stmmac/common.h
@@ -228,7 +228,7 @@ struct stmmac_desc_ops {
228 int (*get_rx_owner) (struct dma_desc *p); 228 int (*get_rx_owner) (struct dma_desc *p);
229 void (*set_rx_owner) (struct dma_desc *p); 229 void (*set_rx_owner) (struct dma_desc *p);
230 /* Get the receive frame size */ 230 /* Get the receive frame size */
231 int (*get_rx_frame_len) (struct dma_desc *p); 231 int (*get_rx_frame_len) (struct dma_desc *p, int rx_coe_type);
232 /* Return the reception status looking at the RDES1 */ 232 /* Return the reception status looking at the RDES1 */
233 int (*rx_status) (void *data, struct stmmac_extra_stats *x, 233 int (*rx_status) (void *data, struct stmmac_extra_stats *x,
234 struct dma_desc *p); 234 struct dma_desc *p);
@@ -261,8 +261,8 @@ struct stmmac_dma_ops {
261struct stmmac_ops { 261struct stmmac_ops {
262 /* MAC core initialization */ 262 /* MAC core initialization */
263 void (*core_init) (void __iomem *ioaddr) ____cacheline_aligned; 263 void (*core_init) (void __iomem *ioaddr) ____cacheline_aligned;
264 /* Support checksum offload engine */ 264 /* Enable and verify that the IPC module is supported */
265 int (*rx_coe) (void __iomem *ioaddr); 265 int (*rx_ipc) (void __iomem *ioaddr);
266 /* Dump MAC registers */ 266 /* Dump MAC registers */
267 void (*dump_regs) (void __iomem *ioaddr); 267 void (*dump_regs) (void __iomem *ioaddr);
268 /* Handle extra events on specific interrupts hw dependent */ 268 /* Handle extra events on specific interrupts hw dependent */
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c
index b1c48b975945..e7cbcd99c2cb 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c
@@ -46,7 +46,7 @@ static void dwmac1000_core_init(void __iomem *ioaddr)
46#endif 46#endif
47} 47}
48 48
49static int dwmac1000_rx_coe_supported(void __iomem *ioaddr) 49static int dwmac1000_rx_ipc_enable(void __iomem *ioaddr)
50{ 50{
51 u32 value = readl(ioaddr + GMAC_CONTROL); 51 u32 value = readl(ioaddr + GMAC_CONTROL);
52 52
@@ -211,7 +211,7 @@ static void dwmac1000_irq_status(void __iomem *ioaddr)
211 211
212static const struct stmmac_ops dwmac1000_ops = { 212static const struct stmmac_ops dwmac1000_ops = {
213 .core_init = dwmac1000_core_init, 213 .core_init = dwmac1000_core_init,
214 .rx_coe = dwmac1000_rx_coe_supported, 214 .rx_ipc = dwmac1000_rx_ipc_enable,
215 .dump_regs = dwmac1000_dump_regs, 215 .dump_regs = dwmac1000_dump_regs,
216 .host_irq_status = dwmac1000_irq_status, 216 .host_irq_status = dwmac1000_irq_status,
217 .set_filter = dwmac1000_set_filter, 217 .set_filter = dwmac1000_set_filter,
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac100_core.c b/drivers/net/ethernet/stmicro/stmmac/dwmac100_core.c
index 138fb8dd1e87..efde50ff03f8 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac100_core.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac100_core.c
@@ -43,11 +43,6 @@ static void dwmac100_core_init(void __iomem *ioaddr)
43#endif 43#endif
44} 44}
45 45
46static int dwmac100_rx_coe_supported(void __iomem *ioaddr)
47{
48 return 0;
49}
50
51static void dwmac100_dump_mac_regs(void __iomem *ioaddr) 46static void dwmac100_dump_mac_regs(void __iomem *ioaddr)
52{ 47{
53 pr_info("\t----------------------------------------------\n" 48 pr_info("\t----------------------------------------------\n"
@@ -72,6 +67,11 @@ static void dwmac100_dump_mac_regs(void __iomem *ioaddr)
72 readl(ioaddr + MAC_VLAN2)); 67 readl(ioaddr + MAC_VLAN2));
73} 68}
74 69
70static int dwmac100_rx_ipc_enable(void __iomem *ioaddr)
71{
72 return 0;
73}
74
75static void dwmac100_irq_status(void __iomem *ioaddr) 75static void dwmac100_irq_status(void __iomem *ioaddr)
76{ 76{
77 return; 77 return;
@@ -160,7 +160,7 @@ static void dwmac100_pmt(void __iomem *ioaddr, unsigned long mode)
160 160
161static const struct stmmac_ops dwmac100_ops = { 161static const struct stmmac_ops dwmac100_ops = {
162 .core_init = dwmac100_core_init, 162 .core_init = dwmac100_core_init,
163 .rx_coe = dwmac100_rx_coe_supported, 163 .rx_ipc = dwmac100_rx_ipc_enable,
164 .dump_regs = dwmac100_dump_mac_regs, 164 .dump_regs = dwmac100_dump_mac_regs,
165 .host_irq_status = dwmac100_irq_status, 165 .host_irq_status = dwmac100_irq_status,
166 .set_filter = dwmac100_set_filter, 166 .set_filter = dwmac100_set_filter,
diff --git a/drivers/net/ethernet/stmicro/stmmac/enh_desc.c b/drivers/net/ethernet/stmicro/stmmac/enh_desc.c
index ad1b627f8ec2..2fc8ef95f97a 100644
--- a/drivers/net/ethernet/stmicro/stmmac/enh_desc.c
+++ b/drivers/net/ethernet/stmicro/stmmac/enh_desc.c
@@ -22,6 +22,7 @@
22 Author: Giuseppe Cavallaro <peppe.cavallaro@st.com> 22 Author: Giuseppe Cavallaro <peppe.cavallaro@st.com>
23*******************************************************************************/ 23*******************************************************************************/
24 24
25#include <linux/stmmac.h>
25#include "common.h" 26#include "common.h"
26#include "descs_com.h" 27#include "descs_com.h"
27 28
@@ -309,9 +310,17 @@ static void enh_desc_close_tx_desc(struct dma_desc *p)
309 p->des01.etx.interrupt = 1; 310 p->des01.etx.interrupt = 1;
310} 311}
311 312
312static int enh_desc_get_rx_frame_len(struct dma_desc *p) 313static int enh_desc_get_rx_frame_len(struct dma_desc *p, int rx_coe_type)
313{ 314{
314 return p->des01.erx.frame_length; 315 /* The type-1 checksum offload engines append the checksum at
316 * the end of frame and the two bytes of checksum are added in
317 * the length.
318 * Adjust for that in the framelen for type-1 checksum offload
319 * engines. */
320 if (rx_coe_type == STMMAC_RX_COE_TYPE1)
321 return p->des01.erx.frame_length - 2;
322 else
323 return p->des01.erx.frame_length;
315} 324}
316 325
317const struct stmmac_desc_ops enh_desc_ops = { 326const struct stmmac_desc_ops enh_desc_ops = {
diff --git a/drivers/net/ethernet/stmicro/stmmac/norm_desc.c b/drivers/net/ethernet/stmicro/stmmac/norm_desc.c
index 25953bb45a73..68962c549a2d 100644
--- a/drivers/net/ethernet/stmicro/stmmac/norm_desc.c
+++ b/drivers/net/ethernet/stmicro/stmmac/norm_desc.c
@@ -22,6 +22,7 @@
22 Author: Giuseppe Cavallaro <peppe.cavallaro@st.com> 22 Author: Giuseppe Cavallaro <peppe.cavallaro@st.com>
23*******************************************************************************/ 23*******************************************************************************/
24 24
25#include <linux/stmmac.h>
25#include "common.h" 26#include "common.h"
26#include "descs_com.h" 27#include "descs_com.h"
27 28
@@ -201,9 +202,17 @@ static void ndesc_close_tx_desc(struct dma_desc *p)
201 p->des01.tx.interrupt = 1; 202 p->des01.tx.interrupt = 1;
202} 203}
203 204
204static int ndesc_get_rx_frame_len(struct dma_desc *p) 205static int ndesc_get_rx_frame_len(struct dma_desc *p, int rx_coe_type)
205{ 206{
206 return p->des01.rx.frame_length; 207 /* The type-1 checksum offload engines append the checksum at
208 * the end of frame and the two bytes of checksum are added in
209 * the length.
210 * Adjust for that in the framelen for type-1 checksum offload
211 * engines. */
212 if (rx_coe_type == STMMAC_RX_COE_TYPE1)
213 return p->des01.rx.frame_length - 2;
214 else
215 return p->des01.rx.frame_length;
207} 216}
208 217
209const struct stmmac_desc_ops ndesc_ops = { 218const struct stmmac_desc_ops ndesc_ops = {
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac.h b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
index b4b095fdcf29..b65d787fee69 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac.h
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
@@ -56,8 +56,6 @@ struct stmmac_priv {
56 56
57 struct stmmac_extra_stats xstats; 57 struct stmmac_extra_stats xstats;
58 struct napi_struct napi; 58 struct napi_struct napi;
59
60 int rx_coe;
61 int no_csum_insertion; 59 int no_csum_insertion;
62 60
63 struct phy_device *phydev; 61 struct phy_device *phydev;
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index 860519c4d9a1..84f6b348ec70 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -1282,7 +1282,8 @@ static int stmmac_rx(struct stmmac_priv *priv, int limit)
1282 struct sk_buff *skb; 1282 struct sk_buff *skb;
1283 int frame_len; 1283 int frame_len;
1284 1284
1285 frame_len = priv->hw->desc->get_rx_frame_len(p); 1285 frame_len = priv->hw->desc->get_rx_frame_len(p,
1286 priv->plat->rx_coe);
1286 /* ACS is set; GMAC core strips PAD/FCS for IEEE 802.3 1287 /* ACS is set; GMAC core strips PAD/FCS for IEEE 802.3
1287 * Type frames (LLC/LLC-SNAP) */ 1288 * Type frames (LLC/LLC-SNAP) */
1288 if (unlikely(status != llc_snap)) 1289 if (unlikely(status != llc_snap))
@@ -1318,7 +1319,7 @@ static int stmmac_rx(struct stmmac_priv *priv, int limit)
1318#endif 1319#endif
1319 skb->protocol = eth_type_trans(skb, priv->dev); 1320 skb->protocol = eth_type_trans(skb, priv->dev);
1320 1321
1321 if (unlikely(!priv->rx_coe)) { 1322 if (unlikely(!priv->plat->rx_coe)) {
1322 /* No RX COE for old mac10/100 devices */ 1323 /* No RX COE for old mac10/100 devices */
1323 skb_checksum_none_assert(skb); 1324 skb_checksum_none_assert(skb);
1324 netif_receive_skb(skb); 1325 netif_receive_skb(skb);
@@ -1465,8 +1466,10 @@ static netdev_features_t stmmac_fix_features(struct net_device *dev,
1465{ 1466{
1466 struct stmmac_priv *priv = netdev_priv(dev); 1467 struct stmmac_priv *priv = netdev_priv(dev);
1467 1468
1468 if (!priv->rx_coe) 1469 if (priv->plat->rx_coe == STMMAC_RX_COE_NONE)
1469 features &= ~NETIF_F_RXCSUM; 1470 features &= ~NETIF_F_RXCSUM;
1471 else if (priv->plat->rx_coe == STMMAC_RX_COE_TYPE1)
1472 features &= ~NETIF_F_IPV6_CSUM;
1470 if (!priv->plat->tx_coe) 1473 if (!priv->plat->tx_coe)
1471 features &= ~NETIF_F_ALL_CSUM; 1474 features &= ~NETIF_F_ALL_CSUM;
1472 1475
@@ -1769,17 +1772,32 @@ static int stmmac_hw_init(struct stmmac_priv *priv)
1769 * register (if supported). 1772 * register (if supported).
1770 */ 1773 */
1771 priv->plat->enh_desc = priv->dma_cap.enh_desc; 1774 priv->plat->enh_desc = priv->dma_cap.enh_desc;
1772 priv->plat->tx_coe = priv->dma_cap.tx_coe;
1773 priv->plat->pmt = priv->dma_cap.pmt_remote_wake_up; 1775 priv->plat->pmt = priv->dma_cap.pmt_remote_wake_up;
1776
1777 priv->plat->tx_coe = priv->dma_cap.tx_coe;
1778
1779 if (priv->dma_cap.rx_coe_type2)
1780 priv->plat->rx_coe = STMMAC_RX_COE_TYPE2;
1781 else if (priv->dma_cap.rx_coe_type1)
1782 priv->plat->rx_coe = STMMAC_RX_COE_TYPE1;
1783
1774 } else 1784 } else
1775 pr_info(" No HW DMA feature register supported"); 1785 pr_info(" No HW DMA feature register supported");
1776 1786
1777 /* Select the enhnaced/normal descriptor structures */ 1787 /* Select the enhnaced/normal descriptor structures */
1778 stmmac_selec_desc_mode(priv); 1788 stmmac_selec_desc_mode(priv);
1779 1789
1780 priv->rx_coe = priv->hw->mac->rx_coe(priv->ioaddr); 1790 /* Enable the IPC (Checksum Offload) and check if the feature has been
1781 if (priv->rx_coe) 1791 * enabled during the core configuration. */
1782 pr_info(" RX Checksum Offload Engine supported\n"); 1792 ret = priv->hw->mac->rx_ipc(priv->ioaddr);
1793 if (!ret) {
1794 pr_warning(" RX IPC Checksum Offload not configured.\n");
1795 priv->plat->rx_coe = STMMAC_RX_COE_NONE;
1796 }
1797
1798 if (priv->plat->rx_coe)
1799 pr_info(" RX Checksum Offload Engine supported (type %d)\n",
1800 priv->plat->rx_coe);
1783 if (priv->plat->tx_coe) 1801 if (priv->plat->tx_coe)
1784 pr_info(" TX Checksum insertion supported\n"); 1802 pr_info(" TX Checksum insertion supported\n");
1785 1803