1
0
Fork 0

[PATCH] mv643xx: add workaround for HW checksum generation bug

[PATCH] [NET] mv643xx: add workaround for HW checksum generation bug

The hardware checksum generator on the mv64xxx occasionally generates
an incorrect checksum.  This patch works around the issue and enables
hardware checksum generation.

Signed-off-by: Dale Farnsworth <dale@farnsworth.org>
Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
hifive-unleashed-5.1
Dale Farnsworth 2005-08-22 15:53:29 -07:00 committed by Jeff Garzik
parent e960fc5c7d
commit 2600636065
2 changed files with 21 additions and 12 deletions

View File

@ -1157,16 +1157,20 @@ static int mv643xx_eth_start_xmit(struct sk_buff *skb, struct net_device *dev)
if (!skb_shinfo(skb)->nr_frags) {
linear:
if (skb->ip_summed != CHECKSUM_HW) {
/* Errata BTS #50, IHL must be 5 if no HW checksum */
pkt_info.cmd_sts = ETH_TX_ENABLE_INTERRUPT |
ETH_TX_FIRST_DESC | ETH_TX_LAST_DESC;
ETH_TX_FIRST_DESC |
ETH_TX_LAST_DESC |
5 << ETH_TX_IHL_SHIFT;
pkt_info.l4i_chk = 0;
} else {
u32 ipheader = skb->nh.iph->ihl << 11;
pkt_info.cmd_sts = ETH_TX_ENABLE_INTERRUPT |
ETH_TX_FIRST_DESC | ETH_TX_LAST_DESC |
ETH_GEN_TCP_UDP_CHECKSUM |
ETH_GEN_IP_V_4_CHECKSUM | ipheader;
ETH_TX_FIRST_DESC |
ETH_TX_LAST_DESC |
ETH_GEN_TCP_UDP_CHECKSUM |
ETH_GEN_IP_V_4_CHECKSUM |
skb->nh.iph->ihl << ETH_TX_IHL_SHIFT;
/* CPU already calculated pseudo header checksum. */
if (skb->nh.iph->protocol == IPPROTO_UDP) {
pkt_info.cmd_sts |= ETH_UDP_FRAME;
@ -1193,7 +1197,6 @@ linear:
stats->tx_bytes += pkt_info.byte_cnt;
} else {
unsigned int frag;
u32 ipheader;
/* Since hardware can't handle unaligned fragments smaller
* than 9 bytes, if we find any, we linearize the skb
@ -1222,12 +1225,16 @@ linear:
DMA_TO_DEVICE);
pkt_info.l4i_chk = 0;
pkt_info.return_info = 0;
pkt_info.cmd_sts = ETH_TX_FIRST_DESC;
if (skb->ip_summed == CHECKSUM_HW) {
ipheader = skb->nh.iph->ihl << 11;
pkt_info.cmd_sts |= ETH_GEN_TCP_UDP_CHECKSUM |
ETH_GEN_IP_V_4_CHECKSUM | ipheader;
if (skb->ip_summed != CHECKSUM_HW)
/* Errata BTS #50, IHL must be 5 if no HW checksum */
pkt_info.cmd_sts = ETH_TX_FIRST_DESC |
5 << ETH_TX_IHL_SHIFT;
else {
pkt_info.cmd_sts = ETH_TX_FIRST_DESC |
ETH_GEN_TCP_UDP_CHECKSUM |
ETH_GEN_IP_V_4_CHECKSUM |
skb->nh.iph->ihl << ETH_TX_IHL_SHIFT;
/* CPU already calculated pseudo header checksum. */
if (skb->nh.iph->protocol == IPPROTO_UDP) {
pkt_info.cmd_sts |= ETH_UDP_FRAME;

View File

@ -49,7 +49,7 @@
/* Checksum offload for Tx works for most packets, but
* fails if previous packet sent did not use hw csum
*/
#undef MV643XX_CHECKSUM_OFFLOAD_TX
#define MV643XX_CHECKSUM_OFFLOAD_TX
#define MV643XX_NAPI
#define MV643XX_TX_FAST_REFILL
#undef MV643XX_RX_QUEUE_FILL_ON_TASK /* Does not work, yet */
@ -217,6 +217,8 @@
#define ETH_TX_ENABLE_INTERRUPT (BIT23)
#define ETH_AUTO_MODE (BIT30)
#define ETH_TX_IHL_SHIFT 11
/* typedefs */
typedef enum _eth_func_ret_status {