enc28j60: Fix sporadic packet loss (corrected again)

Packet data read from the RX buffer the when the RSV is at the end of the RX
buffer does not warp around. This causes packet loss, as the actual data is
never read. Fix this by calculating the right packet data location.

Thanks to Shachar Shemesh for suggesting the fix.

Signed-off-by: Baruch Siach <baruch@tkos.co.il>
Acked-by: Claudio Lanconelli <lanconelli.claudio@eptar.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Baruch Siach and committed by
David S. Miller
5176da7e bd091410

+14 -2
+14 -2
drivers/net/enc28j60.c
··· 568 return erxrdpt; 569 } 570 571 static void nolock_rxfifo_init(struct enc28j60_net *priv, u16 start, u16 end) 572 { 573 u16 erxrdpt; ··· 949 skb->dev = ndev; 950 skb_reserve(skb, NET_IP_ALIGN); 951 /* copy the packet from the receive buffer */ 952 - enc28j60_mem_read(priv, priv->next_pk_ptr + sizeof(rsv), 953 - len, skb_put(skb, len)); 954 if (netif_msg_pktdata(priv)) 955 dump_packet(__func__, skb->len, skb->data); 956 skb->protocol = eth_type_trans(skb, ndev);
··· 568 return erxrdpt; 569 } 570 571 + /* 572 + * Calculate wrap around when reading beyond the end of the RX buffer 573 + */ 574 + static u16 rx_packet_start(u16 ptr) 575 + { 576 + if (ptr + RSV_SIZE > RXEND_INIT) 577 + return (ptr + RSV_SIZE) - (RXEND_INIT - RXSTART_INIT + 1); 578 + else 579 + return ptr + RSV_SIZE; 580 + } 581 + 582 static void nolock_rxfifo_init(struct enc28j60_net *priv, u16 start, u16 end) 583 { 584 u16 erxrdpt; ··· 938 skb->dev = ndev; 939 skb_reserve(skb, NET_IP_ALIGN); 940 /* copy the packet from the receive buffer */ 941 + enc28j60_mem_read(priv, 942 + rx_packet_start(priv->next_pk_ptr), 943 + len, skb_put(skb, len)); 944 if (netif_msg_pktdata(priv)) 945 dump_packet(__func__, skb->len, skb->data); 946 skb->protocol = eth_type_trans(skb, ndev);