[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>
This commit is contained in:
parent
e960fc5c7d
commit
2600636065
|
@ -1157,16 +1157,20 @@ static int mv643xx_eth_start_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||||
if (!skb_shinfo(skb)->nr_frags) {
|
if (!skb_shinfo(skb)->nr_frags) {
|
||||||
linear:
|
linear:
|
||||||
if (skb->ip_summed != CHECKSUM_HW) {
|
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 |
|
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;
|
pkt_info.l4i_chk = 0;
|
||||||
} else {
|
} else {
|
||||||
u32 ipheader = skb->nh.iph->ihl << 11;
|
|
||||||
|
|
||||||
pkt_info.cmd_sts = ETH_TX_ENABLE_INTERRUPT |
|
pkt_info.cmd_sts = ETH_TX_ENABLE_INTERRUPT |
|
||||||
ETH_TX_FIRST_DESC | ETH_TX_LAST_DESC |
|
ETH_TX_FIRST_DESC |
|
||||||
ETH_GEN_TCP_UDP_CHECKSUM |
|
ETH_TX_LAST_DESC |
|
||||||
ETH_GEN_IP_V_4_CHECKSUM | ipheader;
|
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. */
|
/* CPU already calculated pseudo header checksum. */
|
||||||
if (skb->nh.iph->protocol == IPPROTO_UDP) {
|
if (skb->nh.iph->protocol == IPPROTO_UDP) {
|
||||||
pkt_info.cmd_sts |= ETH_UDP_FRAME;
|
pkt_info.cmd_sts |= ETH_UDP_FRAME;
|
||||||
|
@ -1193,7 +1197,6 @@ linear:
|
||||||
stats->tx_bytes += pkt_info.byte_cnt;
|
stats->tx_bytes += pkt_info.byte_cnt;
|
||||||
} else {
|
} else {
|
||||||
unsigned int frag;
|
unsigned int frag;
|
||||||
u32 ipheader;
|
|
||||||
|
|
||||||
/* Since hardware can't handle unaligned fragments smaller
|
/* Since hardware can't handle unaligned fragments smaller
|
||||||
* than 9 bytes, if we find any, we linearize the skb
|
* than 9 bytes, if we find any, we linearize the skb
|
||||||
|
@ -1222,12 +1225,16 @@ linear:
|
||||||
DMA_TO_DEVICE);
|
DMA_TO_DEVICE);
|
||||||
pkt_info.l4i_chk = 0;
|
pkt_info.l4i_chk = 0;
|
||||||
pkt_info.return_info = 0;
|
pkt_info.return_info = 0;
|
||||||
pkt_info.cmd_sts = ETH_TX_FIRST_DESC;
|
|
||||||
|
|
||||||
if (skb->ip_summed == CHECKSUM_HW) {
|
if (skb->ip_summed != CHECKSUM_HW)
|
||||||
ipheader = skb->nh.iph->ihl << 11;
|
/* Errata BTS #50, IHL must be 5 if no HW checksum */
|
||||||
pkt_info.cmd_sts |= ETH_GEN_TCP_UDP_CHECKSUM |
|
pkt_info.cmd_sts = ETH_TX_FIRST_DESC |
|
||||||
ETH_GEN_IP_V_4_CHECKSUM | ipheader;
|
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. */
|
/* CPU already calculated pseudo header checksum. */
|
||||||
if (skb->nh.iph->protocol == IPPROTO_UDP) {
|
if (skb->nh.iph->protocol == IPPROTO_UDP) {
|
||||||
pkt_info.cmd_sts |= ETH_UDP_FRAME;
|
pkt_info.cmd_sts |= ETH_UDP_FRAME;
|
||||||
|
|
|
@ -49,7 +49,7 @@
|
||||||
/* Checksum offload for Tx works for most packets, but
|
/* Checksum offload for Tx works for most packets, but
|
||||||
* fails if previous packet sent did not use hw csum
|
* 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_NAPI
|
||||||
#define MV643XX_TX_FAST_REFILL
|
#define MV643XX_TX_FAST_REFILL
|
||||||
#undef MV643XX_RX_QUEUE_FILL_ON_TASK /* Does not work, yet */
|
#undef MV643XX_RX_QUEUE_FILL_ON_TASK /* Does not work, yet */
|
||||||
|
@ -217,6 +217,8 @@
|
||||||
#define ETH_TX_ENABLE_INTERRUPT (BIT23)
|
#define ETH_TX_ENABLE_INTERRUPT (BIT23)
|
||||||
#define ETH_AUTO_MODE (BIT30)
|
#define ETH_AUTO_MODE (BIT30)
|
||||||
|
|
||||||
|
#define ETH_TX_IHL_SHIFT 11
|
||||||
|
|
||||||
/* typedefs */
|
/* typedefs */
|
||||||
|
|
||||||
typedef enum _eth_func_ret_status {
|
typedef enum _eth_func_ret_status {
|
||||||
|
|
Loading…
Reference in New Issue