diff options
author | Stephen Hemminger <shemminger@linux-foundation.org> | 2007-09-26 20:58:47 -0400 |
---|---|---|
committer | Jeff Garzik <jeff@garzik.org> | 2007-09-27 23:32:28 -0400 |
commit | 3b12e0141f7a97c3b84731b5f935ed738bb6f960 (patch) | |
tree | bf6913c8d7097175688a3fb0d39dd4b0ca3d1f7b /drivers/net/sky2.c | |
parent | ff0ce6845bc18292e80ea40d11c3d3a539a3fc5e (diff) |
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: Stephen Hemminger <shemminger@linux-foundation.org>
Signed-off-by: Jeff Garzik <jeff@garzik.org>
Diffstat (limited to 'drivers/net/sky2.c')
-rw-r--r-- | drivers/net/sky2.c | 28 |
1 files changed, 17 insertions, 11 deletions
diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index 0792031a5cf9..a3de0b6127eb 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c | |||
@@ -2148,6 +2148,18 @@ static struct sk_buff *sky2_receive(struct net_device *dev, | |||
2148 | sky2->rx_next = (sky2->rx_next + 1) % sky2->rx_pending; | 2148 | sky2->rx_next = (sky2->rx_next + 1) % sky2->rx_pending; |
2149 | prefetch(sky2->rx_ring + sky2->rx_next); | 2149 | prefetch(sky2->rx_ring + sky2->rx_next); |
2150 | 2150 | ||
2151 | if (length < ETH_ZLEN || length > sky2->rx_data_size) | ||
2152 | goto len_error; | ||
2153 | |||
2154 | /* This chip has hardware problems that generates bogus status. | ||
2155 | * So do only marginal checking and expect higher level protocols | ||
2156 | * to handle crap frames. | ||
2157 | */ | ||
2158 | if (sky2->hw->chip_id == CHIP_ID_YUKON_FE_P && | ||
2159 | sky2->hw->chip_rev == CHIP_REV_YU_FE2_A0 && | ||
2160 | length != count) | ||
2161 | goto okay; | ||
2162 | |||
2151 | if (status & GMR_FS_ANY_ERR) | 2163 | if (status & GMR_FS_ANY_ERR) |
2152 | goto error; | 2164 | goto error; |
2153 | 2165 | ||
@@ -2156,8 +2168,9 @@ static struct sk_buff *sky2_receive(struct net_device *dev, | |||
2156 | 2168 | ||
2157 | /* if length reported by DMA does not match PHY, packet was truncated */ | 2169 | /* if length reported by DMA does not match PHY, packet was truncated */ |
2158 | if (length != count) | 2170 | if (length != count) |
2159 | goto len_mismatch; | 2171 | goto len_error; |
2160 | 2172 | ||
2173 | okay: | ||
2161 | if (length < copybreak) | 2174 | if (length < copybreak) |
2162 | skb = receive_copy(sky2, re, length); | 2175 | skb = receive_copy(sky2, re, length); |
2163 | else | 2176 | else |
@@ -2167,13 +2180,13 @@ resubmit: | |||
2167 | 2180 | ||
2168 | return skb; | 2181 | return skb; |
2169 | 2182 | ||
2170 | len_mismatch: | 2183 | len_error: |
2171 | /* Truncation of overlength packets | 2184 | /* Truncation of overlength packets |
2172 | causes PHY length to not match MAC length */ | 2185 | causes PHY length to not match MAC length */ |
2173 | ++sky2->net_stats.rx_length_errors; | 2186 | ++sky2->net_stats.rx_length_errors; |
2174 | if (netif_msg_rx_err(sky2) && net_ratelimit()) | 2187 | if (netif_msg_rx_err(sky2) && net_ratelimit()) |
2175 | pr_info(PFX "%s: rx length mismatch: length %d status %#x\n", | 2188 | pr_info(PFX "%s: rx length error: status %#x length %d\n", |
2176 | dev->name, length, status); | 2189 | dev->name, status, length); |
2177 | goto resubmit; | 2190 | goto resubmit; |
2178 | 2191 | ||
2179 | error: | 2192 | error: |
@@ -3934,13 +3947,6 @@ static __devinit struct net_device *sky2_init_netdev(struct sky2_hw *hw, | |||
3934 | sky2->hw = hw; | 3947 | sky2->hw = hw; |
3935 | sky2->msg_enable = netif_msg_init(debug, default_msg); | 3948 | sky2->msg_enable = netif_msg_init(debug, default_msg); |
3936 | 3949 | ||
3937 | /* This chip has hardware problems that generates | ||
3938 | * bogus PHY receive status so by default shut up the message. | ||
3939 | */ | ||
3940 | if (hw->chip_id == CHIP_ID_YUKON_FE_P && | ||
3941 | hw->chip_rev == CHIP_REV_YU_FE2_A0) | ||
3942 | sky2->msg_enable &= ~NETIF_MSG_RX_ERR; | ||
3943 | |||
3944 | /* Auto speed and flow control */ | 3950 | /* Auto speed and flow control */ |
3945 | sky2->autoneg = AUTONEG_ENABLE; | 3951 | sky2->autoneg = AUTONEG_ENABLE; |
3946 | sky2->flow_mode = FC_BOTH; | 3952 | sky2->flow_mode = FC_BOTH; |