Commit 3b12e014 authored by Stephen Hemminger's avatar Stephen Hemminger Committed by Jeff Garzik

sky2: sky2 FE+ receive status workaround

The Yukon FE+ chip appears to have a hardware glitch that causes bogus
receive status values to be posted. The data in the packet is good, but
the status value is random garbage.  As a temporary workaround until the
problem is better understood, implement the workaround the vendor driver
used of ignoring the status value on this chip.

Since this means trusting dodgy hardware values; add additional checking
of the receive packet length.
Signed-off-by: default avatarStephen Hemminger <shemminger@linux-foundation.org>
Signed-off-by: default avatarJeff Garzik <jeff@garzik.org>
parent ff0ce684
...@@ -2148,6 +2148,18 @@ static struct sk_buff *sky2_receive(struct net_device *dev, ...@@ -2148,6 +2148,18 @@ static struct sk_buff *sky2_receive(struct net_device *dev,
sky2->rx_next = (sky2->rx_next + 1) % sky2->rx_pending; sky2->rx_next = (sky2->rx_next + 1) % sky2->rx_pending;
prefetch(sky2->rx_ring + sky2->rx_next); prefetch(sky2->rx_ring + sky2->rx_next);
if (length < ETH_ZLEN || length > sky2->rx_data_size)
goto len_error;
/* This chip has hardware problems that generates bogus status.
* So do only marginal checking and expect higher level protocols
* to handle crap frames.
*/
if (sky2->hw->chip_id == CHIP_ID_YUKON_FE_P &&
sky2->hw->chip_rev == CHIP_REV_YU_FE2_A0 &&
length != count)
goto okay;
if (status & GMR_FS_ANY_ERR) if (status & GMR_FS_ANY_ERR)
goto error; goto error;
...@@ -2156,8 +2168,9 @@ static struct sk_buff *sky2_receive(struct net_device *dev, ...@@ -2156,8 +2168,9 @@ static struct sk_buff *sky2_receive(struct net_device *dev,
/* if length reported by DMA does not match PHY, packet was truncated */ /* if length reported by DMA does not match PHY, packet was truncated */
if (length != count) if (length != count)
goto len_mismatch; goto len_error;
okay:
if (length < copybreak) if (length < copybreak)
skb = receive_copy(sky2, re, length); skb = receive_copy(sky2, re, length);
else else
...@@ -2167,13 +2180,13 @@ static struct sk_buff *sky2_receive(struct net_device *dev, ...@@ -2167,13 +2180,13 @@ static struct sk_buff *sky2_receive(struct net_device *dev,
return skb; return skb;
len_mismatch: len_error:
/* Truncation of overlength packets /* Truncation of overlength packets
causes PHY length to not match MAC length */ causes PHY length to not match MAC length */
++sky2->net_stats.rx_length_errors; ++sky2->net_stats.rx_length_errors;
if (netif_msg_rx_err(sky2) && net_ratelimit()) if (netif_msg_rx_err(sky2) && net_ratelimit())
pr_info(PFX "%s: rx length mismatch: length %d status %#x\n", pr_info(PFX "%s: rx length error: status %#x length %d\n",
dev->name, length, status); dev->name, status, length);
goto resubmit; goto resubmit;
error: error:
...@@ -3934,13 +3947,6 @@ static __devinit struct net_device *sky2_init_netdev(struct sky2_hw *hw, ...@@ -3934,13 +3947,6 @@ static __devinit struct net_device *sky2_init_netdev(struct sky2_hw *hw,
sky2->hw = hw; sky2->hw = hw;
sky2->msg_enable = netif_msg_init(debug, default_msg); sky2->msg_enable = netif_msg_init(debug, default_msg);
/* This chip has hardware problems that generates
* bogus PHY receive status so by default shut up the message.
*/
if (hw->chip_id == CHIP_ID_YUKON_FE_P &&
hw->chip_rev == CHIP_REV_YU_FE2_A0)
sky2->msg_enable &= ~NETIF_MSG_RX_ERR;
/* Auto speed and flow control */ /* Auto speed and flow control */
sky2->autoneg = AUTONEG_ENABLE; sky2->autoneg = AUTONEG_ENABLE;
sky2->flow_mode = FC_BOTH; sky2->flow_mode = FC_BOTH;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment