aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ethernet/freescale
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/ethernet/freescale')
-rw-r--r--drivers/net/ethernet/freescale/gianfar.c44
1 files changed, 25 insertions, 19 deletions
diff --git a/drivers/net/ethernet/freescale/gianfar.c b/drivers/net/ethernet/freescale/gianfar.c
index dbb34f7ce448..352035e440d8 100644
--- a/drivers/net/ethernet/freescale/gianfar.c
+++ b/drivers/net/ethernet/freescale/gianfar.c
@@ -2051,6 +2051,24 @@ static inline struct txbd8 *next_txbd(struct txbd8 *bdp, struct txbd8 *base,
2051 return skip_txbd(bdp, 1, base, ring_size); 2051 return skip_txbd(bdp, 1, base, ring_size);
2052} 2052}
2053 2053
2054/* eTSEC12: csum generation not supported for some fcb offsets */
2055static inline bool gfar_csum_errata_12(struct gfar_private *priv,
2056 unsigned long fcb_addr)
2057{
2058 return (gfar_has_errata(priv, GFAR_ERRATA_12) &&
2059 (fcb_addr % 0x20) > 0x18);
2060}
2061
2062/* eTSEC76: csum generation for frames larger than 2500 may
2063 * cause excess delays before start of transmission
2064 */
2065static inline bool gfar_csum_errata_76(struct gfar_private *priv,
2066 unsigned int len)
2067{
2068 return (gfar_has_errata(priv, GFAR_ERRATA_76) &&
2069 (len > 2500));
2070}
2071
2054/* This is called by the kernel when a frame is ready for transmission. 2072/* This is called by the kernel when a frame is ready for transmission.
2055 * It is pointed to by the dev->hard_start_xmit function pointer 2073 * It is pointed to by the dev->hard_start_xmit function pointer
2056 */ 2074 */
@@ -2068,19 +2086,6 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev)
2068 unsigned long flags; 2086 unsigned long flags;
2069 unsigned int nr_frags, nr_txbds, length, fcb_length = GMAC_FCB_LEN; 2087 unsigned int nr_frags, nr_txbds, length, fcb_length = GMAC_FCB_LEN;
2070 2088
2071 /* TOE=1 frames larger than 2500 bytes may see excess delays
2072 * before start of transmission.
2073 */
2074 if (unlikely(gfar_has_errata(priv, GFAR_ERRATA_76) &&
2075 skb->ip_summed == CHECKSUM_PARTIAL &&
2076 skb->len > 2500)) {
2077 int ret;
2078
2079 ret = skb_checksum_help(skb);
2080 if (ret)
2081 return ret;
2082 }
2083
2084 rq = skb->queue_mapping; 2089 rq = skb->queue_mapping;
2085 tx_queue = priv->tx_queue[rq]; 2090 tx_queue = priv->tx_queue[rq];
2086 txq = netdev_get_tx_queue(dev, rq); 2091 txq = netdev_get_tx_queue(dev, rq);
@@ -2187,14 +2192,15 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev)
2187 /* Set up checksumming */ 2192 /* Set up checksumming */
2188 if (CHECKSUM_PARTIAL == skb->ip_summed) { 2193 if (CHECKSUM_PARTIAL == skb->ip_summed) {
2189 fcb = gfar_add_fcb(skb); 2194 fcb = gfar_add_fcb(skb);
2190 /* as specified by errata */ 2195 lstatus |= BD_LFLAG(TXBD_TOE);
2191 if (unlikely(gfar_has_errata(priv, GFAR_ERRATA_12) && 2196 gfar_tx_checksum(skb, fcb, fcb_length);
2192 ((unsigned long)fcb % 0x20) > 0x18)) { 2197
2198 if (unlikely(gfar_csum_errata_12(priv, (unsigned long)fcb)) ||
2199 unlikely(gfar_csum_errata_76(priv, skb->len))) {
2193 __skb_pull(skb, GMAC_FCB_LEN); 2200 __skb_pull(skb, GMAC_FCB_LEN);
2194 skb_checksum_help(skb); 2201 skb_checksum_help(skb);
2195 } else { 2202 lstatus &= ~(BD_LFLAG(TXBD_TOE));
2196 lstatus |= BD_LFLAG(TXBD_TOE); 2203 fcb = NULL;
2197 gfar_tx_checksum(skb, fcb, fcb_length);
2198 } 2204 }
2199 } 2205 }
2200 2206