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>
This commit is contained in:
parent
ff0ce6845b
commit
3b12e0141f
|
@ -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,
|
||||||
|
|
||||||
/* 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 @@ resubmit:
|
||||||
|
|
||||||
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,
|
||||||
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;
|
||||||
|
|
Loading…
Reference in New Issue