diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c index cee8ae71473113087b138bf32e43ecec0e56e3bc..c2fabc1853adb2c0c1c40d7ff33dc4338ee766a8 100644 --- a/drivers/net/gianfar.c +++ b/drivers/net/gianfar.c @@ -942,6 +942,11 @@ static void gfar_detect_errata(struct gfar_private *priv) (pvr == 0x80861010 && (mod & 0xfff9) == 0x80c0)) priv->errata |= GFAR_ERRATA_74; + /* MPC8313 and MPC837x all rev */ + if ((pvr == 0x80850010 && mod == 0x80b0) || + (pvr == 0x80861010 && (mod & 0xfff9) == 0x80c0)) + priv->errata |= GFAR_ERRATA_76; + if (priv->errata) dev_info(dev, "enabled errata workarounds, flags: 0x%x\n", priv->errata); @@ -2011,6 +2016,20 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev) unsigned int nr_frags, nr_txbds, length; union skb_shared_tx *shtx; + /* + * 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); diff --git a/drivers/net/gianfar.h b/drivers/net/gianfar.h index 0a0483ce21d25e7173c8a7870dcbc934b98791a0..c414374f407fdac58924501c206b76bdd607c5f3 100644 --- a/drivers/net/gianfar.h +++ b/drivers/net/gianfar.h @@ -1027,6 +1027,7 @@ struct gfar_priv_grp { enum gfar_errata { GFAR_ERRATA_74 = 0x01, + GFAR_ERRATA_76 = 0x02, }; /* Struct stolen almost completely (and shamelessly) from the FCC enet source