diff options
-rw-r--r-- | drivers/net/sky2.c | 55 | ||||
-rw-r--r-- | drivers/net/sky2.h | 6 |
2 files changed, 49 insertions, 12 deletions
diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index ab36a7460a26..380bb59f3517 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c | |||
@@ -2066,6 +2066,27 @@ static void sky2_mac_intr(struct sky2_hw *hw, unsigned port) | |||
2066 | } | 2066 | } |
2067 | } | 2067 | } |
2068 | 2068 | ||
2069 | /* This should never happen it is a fatal situation */ | ||
2070 | static void sky2_descriptor_error(struct sky2_hw *hw, unsigned port, | ||
2071 | const char *rxtx, u32 mask) | ||
2072 | { | ||
2073 | struct net_device *dev = hw->dev[port]; | ||
2074 | struct sky2_port *sky2 = netdev_priv(dev); | ||
2075 | u32 imask; | ||
2076 | |||
2077 | printk(KERN_ERR PFX "%s: %s descriptor error (hardware problem)\n", | ||
2078 | dev ? dev->name : "<not registered>", rxtx); | ||
2079 | |||
2080 | imask = sky2_read32(hw, B0_IMSK); | ||
2081 | imask &= ~mask; | ||
2082 | sky2_write32(hw, B0_IMSK, imask); | ||
2083 | |||
2084 | if (dev) { | ||
2085 | spin_lock(&sky2->phy_lock); | ||
2086 | sky2_link_down(sky2); | ||
2087 | spin_unlock(&sky2->phy_lock); | ||
2088 | } | ||
2089 | } | ||
2069 | 2090 | ||
2070 | static int sky2_poll(struct net_device *dev0, int *budget) | 2091 | static int sky2_poll(struct net_device *dev0, int *budget) |
2071 | { | 2092 | { |
@@ -2074,20 +2095,34 @@ static int sky2_poll(struct net_device *dev0, int *budget) | |||
2074 | int work_done = 0; | 2095 | int work_done = 0; |
2075 | u32 status = sky2_read32(hw, B0_Y2_SP_EISR); | 2096 | u32 status = sky2_read32(hw, B0_Y2_SP_EISR); |
2076 | 2097 | ||
2077 | if (status & Y2_IS_HW_ERR) | 2098 | if (unlikely(status & ~Y2_IS_STAT_BMU)) { |
2078 | sky2_hw_intr(hw); | 2099 | if (status & Y2_IS_HW_ERR) |
2100 | sky2_hw_intr(hw); | ||
2101 | |||
2102 | if (status & Y2_IS_IRQ_PHY1) | ||
2103 | sky2_phy_intr(hw, 0); | ||
2079 | 2104 | ||
2080 | if (status & Y2_IS_IRQ_PHY1) | 2105 | if (status & Y2_IS_IRQ_PHY2) |
2081 | sky2_phy_intr(hw, 0); | 2106 | sky2_phy_intr(hw, 1); |
2082 | 2107 | ||
2083 | if (status & Y2_IS_IRQ_PHY2) | 2108 | if (status & Y2_IS_IRQ_MAC1) |
2084 | sky2_phy_intr(hw, 1); | 2109 | sky2_mac_intr(hw, 0); |
2085 | 2110 | ||
2086 | if (status & Y2_IS_IRQ_MAC1) | 2111 | if (status & Y2_IS_IRQ_MAC2) |
2087 | sky2_mac_intr(hw, 0); | 2112 | sky2_mac_intr(hw, 1); |
2088 | 2113 | ||
2089 | if (status & Y2_IS_IRQ_MAC2) | 2114 | if (status & Y2_IS_CHK_RX1) |
2090 | sky2_mac_intr(hw, 1); | 2115 | sky2_descriptor_error(hw, 0, "receive", Y2_IS_CHK_RX1); |
2116 | |||
2117 | if (status & Y2_IS_CHK_RX2) | ||
2118 | sky2_descriptor_error(hw, 1, "receive", Y2_IS_CHK_RX2); | ||
2119 | |||
2120 | if (status & Y2_IS_CHK_TXA1) | ||
2121 | sky2_descriptor_error(hw, 0, "transmit", Y2_IS_CHK_TXA1); | ||
2122 | |||
2123 | if (status & Y2_IS_CHK_TXA2) | ||
2124 | sky2_descriptor_error(hw, 1, "transmit", Y2_IS_CHK_TXA2); | ||
2125 | } | ||
2091 | 2126 | ||
2092 | if (status & Y2_IS_STAT_BMU) { | 2127 | if (status & Y2_IS_STAT_BMU) { |
2093 | work_done = sky2_status_intr(hw, work_limit); | 2128 | work_done = sky2_status_intr(hw, work_limit); |
diff --git a/drivers/net/sky2.h b/drivers/net/sky2.h index 50e9f7d38bf3..d63cd5a1b71c 100644 --- a/drivers/net/sky2.h +++ b/drivers/net/sky2.h | |||
@@ -279,8 +279,10 @@ enum { | |||
279 | Y2_IS_CHK_TXA1 = 1<<0, /* Descriptor error TXA 1 */ | 279 | Y2_IS_CHK_TXA1 = 1<<0, /* Descriptor error TXA 1 */ |
280 | 280 | ||
281 | Y2_IS_BASE = Y2_IS_HW_ERR | Y2_IS_STAT_BMU, | 281 | Y2_IS_BASE = Y2_IS_HW_ERR | Y2_IS_STAT_BMU, |
282 | Y2_IS_PORT_1 = Y2_IS_IRQ_PHY1 | Y2_IS_IRQ_MAC1, | 282 | Y2_IS_PORT_1 = Y2_IS_IRQ_PHY1 | Y2_IS_IRQ_MAC1 |
283 | Y2_IS_PORT_2 = Y2_IS_IRQ_PHY2 | Y2_IS_IRQ_MAC2, | 283 | | Y2_IS_CHK_TXA1 | Y2_IS_CHK_RX1, |
284 | Y2_IS_PORT_2 = Y2_IS_IRQ_PHY2 | Y2_IS_IRQ_MAC2 | ||
285 | | Y2_IS_CHK_TXA2 | Y2_IS_CHK_RX2, | ||
284 | }; | 286 | }; |
285 | 287 | ||
286 | /* B2_IRQM_HWE_MSK 32 bit IRQ Moderation HW Error Mask */ | 288 | /* B2_IRQM_HWE_MSK 32 bit IRQ Moderation HW Error Mask */ |