aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/sky2.c
diff options
context:
space:
mode:
authorStephen Hemminger <shemminger@linux-foundation.org>2007-09-26 20:58:47 -0400
committerJeff Garzik <jeff@garzik.org>2007-09-27 23:32:28 -0400
commit3b12e0141f7a97c3b84731b5f935ed738bb6f960 (patch)
treebf6913c8d7097175688a3fb0d39dd4b0ca3d1f7b /drivers/net/sky2.c
parentff0ce6845bc18292e80ea40d11c3d3a539a3fc5e (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.c28
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
2173okay:
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
2170len_mismatch: 2183len_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
2179error: 2192error:
@@ -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;