|
@@ -2051,6 +2051,24 @@ static inline struct txbd8 *next_txbd(struct txbd8 *bdp, struct txbd8 *base,
|
|
|
return skip_txbd(bdp, 1, base, ring_size);
|
|
|
}
|
|
|
|
|
|
+/* eTSEC12: csum generation not supported for some fcb offsets */
|
|
|
+static inline bool gfar_csum_errata_12(struct gfar_private *priv,
|
|
|
+ unsigned long fcb_addr)
|
|
|
+{
|
|
|
+ return (gfar_has_errata(priv, GFAR_ERRATA_12) &&
|
|
|
+ (fcb_addr % 0x20) > 0x18);
|
|
|
+}
|
|
|
+
|
|
|
+/* eTSEC76: csum generation for frames larger than 2500 may
|
|
|
+ * cause excess delays before start of transmission
|
|
|
+ */
|
|
|
+static inline bool gfar_csum_errata_76(struct gfar_private *priv,
|
|
|
+ unsigned int len)
|
|
|
+{
|
|
|
+ return (gfar_has_errata(priv, GFAR_ERRATA_76) &&
|
|
|
+ (len > 2500));
|
|
|
+}
|
|
|
+
|
|
|
/* This is called by the kernel when a frame is ready for transmission.
|
|
|
* It is pointed to by the dev->hard_start_xmit function pointer
|
|
|
*/
|
|
@@ -2068,19 +2086,6 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev)
|
|
|
unsigned long flags;
|
|
|
unsigned int nr_frags, nr_txbds, length, fcb_length = GMAC_FCB_LEN;
|
|
|
|
|
|
- /* TOE=1 frames larger than 2500 bytes may see excess delays
|
|
|
- * before start of transmission.
|
|
|
- */
|
|
|
- if (unlikely(gfar_has_errata(priv, GFAR_ERRATA_76) &&
|
|
|
- skb->ip_summed == CHECKSUM_PARTIAL &&
|
|
|
- skb->len > 2500)) {
|
|
|
- int ret;
|
|
|
-
|
|
|
- ret = skb_checksum_help(skb);
|
|
|
- if (ret)
|
|
|
- return ret;
|
|
|
- }
|
|
|
-
|
|
|
rq = skb->queue_mapping;
|
|
|
tx_queue = priv->tx_queue[rq];
|
|
|
txq = netdev_get_tx_queue(dev, rq);
|
|
@@ -2187,14 +2192,15 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev)
|
|
|
/* Set up checksumming */
|
|
|
if (CHECKSUM_PARTIAL == skb->ip_summed) {
|
|
|
fcb = gfar_add_fcb(skb);
|
|
|
- /* as specified by errata */
|
|
|
- if (unlikely(gfar_has_errata(priv, GFAR_ERRATA_12) &&
|
|
|
- ((unsigned long)fcb % 0x20) > 0x18)) {
|
|
|
+ lstatus |= BD_LFLAG(TXBD_TOE);
|
|
|
+ gfar_tx_checksum(skb, fcb, fcb_length);
|
|
|
+
|
|
|
+ if (unlikely(gfar_csum_errata_12(priv, (unsigned long)fcb)) ||
|
|
|
+ unlikely(gfar_csum_errata_76(priv, skb->len))) {
|
|
|
__skb_pull(skb, GMAC_FCB_LEN);
|
|
|
skb_checksum_help(skb);
|
|
|
- } else {
|
|
|
- lstatus |= BD_LFLAG(TXBD_TOE);
|
|
|
- gfar_tx_checksum(skb, fcb, fcb_length);
|
|
|
+ lstatus &= ~(BD_LFLAG(TXBD_TOE));
|
|
|
+ fcb = NULL;
|
|
|
}
|
|
|
}
|
|
|
|