diff options
Diffstat (limited to 'drivers/net/sky2.c')
-rw-r--r-- | drivers/net/sky2.c | 116 |
1 files changed, 70 insertions, 46 deletions
diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index c27c7d63b6a5..a2070db725c9 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c | |||
@@ -52,7 +52,7 @@ | |||
52 | #include "sky2.h" | 52 | #include "sky2.h" |
53 | 53 | ||
54 | #define DRV_NAME "sky2" | 54 | #define DRV_NAME "sky2" |
55 | #define DRV_VERSION "1.19" | 55 | #define DRV_VERSION "1.20" |
56 | #define PFX DRV_NAME " " | 56 | #define PFX DRV_NAME " " |
57 | 57 | ||
58 | /* | 58 | /* |
@@ -121,6 +121,7 @@ static const struct pci_device_id sky2_id_table[] = { | |||
121 | { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4353) }, /* 88E8039 */ | 121 | { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4353) }, /* 88E8039 */ |
122 | { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4354) }, /* 88E8040 */ | 122 | { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4354) }, /* 88E8040 */ |
123 | { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4356) }, /* 88EC033 */ | 123 | { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4356) }, /* 88EC033 */ |
124 | { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4357) }, /* 88E8042 */ | ||
124 | { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x435A) }, /* 88E8048 */ | 125 | { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x435A) }, /* 88E8048 */ |
125 | { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4360) }, /* 88E8052 */ | 126 | { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4360) }, /* 88E8052 */ |
126 | { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4361) }, /* 88E8050 */ | 127 | { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4361) }, /* 88E8050 */ |
@@ -134,6 +135,7 @@ static const struct pci_device_id sky2_id_table[] = { | |||
134 | { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4369) }, /* 88EC042 */ | 135 | { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4369) }, /* 88EC042 */ |
135 | { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x436A) }, /* 88E8058 */ | 136 | { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x436A) }, /* 88E8058 */ |
136 | { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x436B) }, /* 88E8071 */ | 137 | { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x436B) }, /* 88E8071 */ |
138 | { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x436C) }, /* 88E8072 */ | ||
137 | { 0 } | 139 | { 0 } |
138 | }; | 140 | }; |
139 | 141 | ||
@@ -156,7 +158,7 @@ static const char *yukon2_name[] = { | |||
156 | 158 | ||
157 | static void sky2_set_multicast(struct net_device *dev); | 159 | static void sky2_set_multicast(struct net_device *dev); |
158 | 160 | ||
159 | /* Access to external PHY */ | 161 | /* Access to PHY via serial interconnect */ |
160 | static int gm_phy_write(struct sky2_hw *hw, unsigned port, u16 reg, u16 val) | 162 | static int gm_phy_write(struct sky2_hw *hw, unsigned port, u16 reg, u16 val) |
161 | { | 163 | { |
162 | int i; | 164 | int i; |
@@ -166,13 +168,22 @@ static int gm_phy_write(struct sky2_hw *hw, unsigned port, u16 reg, u16 val) | |||
166 | GM_SMI_CT_PHY_AD(PHY_ADDR_MARV) | GM_SMI_CT_REG_AD(reg)); | 168 | GM_SMI_CT_PHY_AD(PHY_ADDR_MARV) | GM_SMI_CT_REG_AD(reg)); |
167 | 169 | ||
168 | for (i = 0; i < PHY_RETRIES; i++) { | 170 | for (i = 0; i < PHY_RETRIES; i++) { |
169 | if (!(gma_read16(hw, port, GM_SMI_CTRL) & GM_SMI_CT_BUSY)) | 171 | u16 ctrl = gma_read16(hw, port, GM_SMI_CTRL); |
172 | if (ctrl == 0xffff) | ||
173 | goto io_error; | ||
174 | |||
175 | if (!(ctrl & GM_SMI_CT_BUSY)) | ||
170 | return 0; | 176 | return 0; |
171 | udelay(1); | 177 | |
178 | udelay(10); | ||
172 | } | 179 | } |
173 | 180 | ||
174 | printk(KERN_WARNING PFX "%s: phy write timeout\n", hw->dev[port]->name); | 181 | dev_warn(&hw->pdev->dev,"%s: phy write timeout\n", hw->dev[port]->name); |
175 | return -ETIMEDOUT; | 182 | return -ETIMEDOUT; |
183 | |||
184 | io_error: | ||
185 | dev_err(&hw->pdev->dev, "%s: phy I/O error\n", hw->dev[port]->name); | ||
186 | return -EIO; | ||
176 | } | 187 | } |
177 | 188 | ||
178 | static int __gm_phy_read(struct sky2_hw *hw, unsigned port, u16 reg, u16 *val) | 189 | static int __gm_phy_read(struct sky2_hw *hw, unsigned port, u16 reg, u16 *val) |
@@ -183,23 +194,29 @@ static int __gm_phy_read(struct sky2_hw *hw, unsigned port, u16 reg, u16 *val) | |||
183 | | GM_SMI_CT_REG_AD(reg) | GM_SMI_CT_OP_RD); | 194 | | GM_SMI_CT_REG_AD(reg) | GM_SMI_CT_OP_RD); |
184 | 195 | ||
185 | for (i = 0; i < PHY_RETRIES; i++) { | 196 | for (i = 0; i < PHY_RETRIES; i++) { |
186 | if (gma_read16(hw, port, GM_SMI_CTRL) & GM_SMI_CT_RD_VAL) { | 197 | u16 ctrl = gma_read16(hw, port, GM_SMI_CTRL); |
198 | if (ctrl == 0xffff) | ||
199 | goto io_error; | ||
200 | |||
201 | if (ctrl & GM_SMI_CT_RD_VAL) { | ||
187 | *val = gma_read16(hw, port, GM_SMI_DATA); | 202 | *val = gma_read16(hw, port, GM_SMI_DATA); |
188 | return 0; | 203 | return 0; |
189 | } | 204 | } |
190 | 205 | ||
191 | udelay(1); | 206 | udelay(10); |
192 | } | 207 | } |
193 | 208 | ||
209 | dev_warn(&hw->pdev->dev, "%s: phy read timeout\n", hw->dev[port]->name); | ||
194 | return -ETIMEDOUT; | 210 | return -ETIMEDOUT; |
211 | io_error: | ||
212 | dev_err(&hw->pdev->dev, "%s: phy I/O error\n", hw->dev[port]->name); | ||
213 | return -EIO; | ||
195 | } | 214 | } |
196 | 215 | ||
197 | static u16 gm_phy_read(struct sky2_hw *hw, unsigned port, u16 reg) | 216 | static inline u16 gm_phy_read(struct sky2_hw *hw, unsigned port, u16 reg) |
198 | { | 217 | { |
199 | u16 v; | 218 | u16 v; |
200 | 219 | __gm_phy_read(hw, port, reg, &v); | |
201 | if (__gm_phy_read(hw, port, reg, &v) != 0) | ||
202 | printk(KERN_WARNING PFX "%s: phy read timeout\n", hw->dev[port]->name); | ||
203 | return v; | 220 | return v; |
204 | } | 221 | } |
205 | 222 | ||
@@ -273,8 +290,6 @@ static void sky2_gmac_reset(struct sky2_hw *hw, unsigned port) | |||
273 | 290 | ||
274 | /* disable all GMAC IRQ's */ | 291 | /* disable all GMAC IRQ's */ |
275 | sky2_write8(hw, SK_REG(port, GMAC_IRQ_MSK), 0); | 292 | sky2_write8(hw, SK_REG(port, GMAC_IRQ_MSK), 0); |
276 | /* disable PHY IRQs */ | ||
277 | gm_phy_write(hw, port, PHY_MARV_INT_MASK, 0); | ||
278 | 293 | ||
279 | gma_write16(hw, port, GM_MC_ADDR_H1, 0); /* clear MC hash */ | 294 | gma_write16(hw, port, GM_MC_ADDR_H1, 0); /* clear MC hash */ |
280 | gma_write16(hw, port, GM_MC_ADDR_H2, 0); | 295 | gma_write16(hw, port, GM_MC_ADDR_H2, 0); |
@@ -1805,29 +1820,6 @@ static void sky2_link_up(struct sky2_port *sky2) | |||
1805 | sky2_write8(hw, SK_REG(port, LNK_LED_REG), | 1820 | sky2_write8(hw, SK_REG(port, LNK_LED_REG), |
1806 | LINKLED_ON | LINKLED_BLINK_OFF | LINKLED_LINKSYNC_OFF); | 1821 | LINKLED_ON | LINKLED_BLINK_OFF | LINKLED_LINKSYNC_OFF); |
1807 | 1822 | ||
1808 | if (hw->flags & SKY2_HW_NEWER_PHY) { | ||
1809 | u16 pg = gm_phy_read(hw, port, PHY_MARV_EXT_ADR); | ||
1810 | u16 led = PHY_M_LEDC_LOS_CTRL(1); /* link active */ | ||
1811 | |||
1812 | switch(sky2->speed) { | ||
1813 | case SPEED_10: | ||
1814 | led |= PHY_M_LEDC_INIT_CTRL(7); | ||
1815 | break; | ||
1816 | |||
1817 | case SPEED_100: | ||
1818 | led |= PHY_M_LEDC_STA1_CTRL(7); | ||
1819 | break; | ||
1820 | |||
1821 | case SPEED_1000: | ||
1822 | led |= PHY_M_LEDC_STA0_CTRL(7); | ||
1823 | break; | ||
1824 | } | ||
1825 | |||
1826 | gm_phy_write(hw, port, PHY_MARV_EXT_ADR, 3); | ||
1827 | gm_phy_write(hw, port, PHY_MARV_PHY_CTRL, led); | ||
1828 | gm_phy_write(hw, port, PHY_MARV_EXT_ADR, pg); | ||
1829 | } | ||
1830 | |||
1831 | if (netif_msg_link(sky2)) | 1823 | if (netif_msg_link(sky2)) |
1832 | printk(KERN_INFO PFX | 1824 | printk(KERN_INFO PFX |
1833 | "%s: Link is up at %d Mbps, %s duplex, flow control %s\n", | 1825 | "%s: Link is up at %d Mbps, %s duplex, flow control %s\n", |
@@ -2247,20 +2239,26 @@ static int sky2_status_intr(struct sky2_hw *hw, int to_do, u16 idx) | |||
2247 | do { | 2239 | do { |
2248 | struct sky2_port *sky2; | 2240 | struct sky2_port *sky2; |
2249 | struct sky2_status_le *le = hw->st_le + hw->st_idx; | 2241 | struct sky2_status_le *le = hw->st_le + hw->st_idx; |
2250 | unsigned port = le->css & CSS_LINK_BIT; | 2242 | unsigned port; |
2251 | struct net_device *dev; | 2243 | struct net_device *dev; |
2252 | struct sk_buff *skb; | 2244 | struct sk_buff *skb; |
2253 | u32 status; | 2245 | u32 status; |
2254 | u16 length; | 2246 | u16 length; |
2247 | u8 opcode = le->opcode; | ||
2248 | |||
2249 | if (!(opcode & HW_OWNER)) | ||
2250 | break; | ||
2255 | 2251 | ||
2256 | hw->st_idx = RING_NEXT(hw->st_idx, STATUS_RING_SIZE); | 2252 | hw->st_idx = RING_NEXT(hw->st_idx, STATUS_RING_SIZE); |
2257 | 2253 | ||
2254 | port = le->css & CSS_LINK_BIT; | ||
2258 | dev = hw->dev[port]; | 2255 | dev = hw->dev[port]; |
2259 | sky2 = netdev_priv(dev); | 2256 | sky2 = netdev_priv(dev); |
2260 | length = le16_to_cpu(le->length); | 2257 | length = le16_to_cpu(le->length); |
2261 | status = le32_to_cpu(le->status); | 2258 | status = le32_to_cpu(le->status); |
2262 | 2259 | ||
2263 | switch (le->opcode & ~HW_OWNER) { | 2260 | le->opcode = 0; |
2261 | switch (opcode & ~HW_OWNER) { | ||
2264 | case OP_RXSTAT: | 2262 | case OP_RXSTAT: |
2265 | ++rx[port]; | 2263 | ++rx[port]; |
2266 | skb = sky2_receive(dev, length, status); | 2264 | skb = sky2_receive(dev, length, status); |
@@ -2353,7 +2351,7 @@ static int sky2_status_intr(struct sky2_hw *hw, int to_do, u16 idx) | |||
2353 | default: | 2351 | default: |
2354 | if (net_ratelimit()) | 2352 | if (net_ratelimit()) |
2355 | printk(KERN_WARNING PFX | 2353 | printk(KERN_WARNING PFX |
2356 | "unknown status opcode 0x%x\n", le->opcode); | 2354 | "unknown status opcode 0x%x\n", opcode); |
2357 | } | 2355 | } |
2358 | } while (hw->st_idx != idx); | 2356 | } while (hw->st_idx != idx); |
2359 | 2357 | ||
@@ -2439,13 +2437,26 @@ static void sky2_hw_intr(struct sky2_hw *hw) | |||
2439 | 2437 | ||
2440 | if (status & Y2_IS_PCI_EXP) { | 2438 | if (status & Y2_IS_PCI_EXP) { |
2441 | /* PCI-Express uncorrectable Error occurred */ | 2439 | /* PCI-Express uncorrectable Error occurred */ |
2442 | int pos = pci_find_aer_capability(hw->pdev); | 2440 | int aer = pci_find_aer_capability(hw->pdev); |
2443 | u32 err; | 2441 | u32 err; |
2444 | 2442 | ||
2445 | pci_read_config_dword(pdev, pos + PCI_ERR_UNCOR_STATUS, &err); | 2443 | if (aer) { |
2444 | pci_read_config_dword(pdev, aer + PCI_ERR_UNCOR_STATUS, | ||
2445 | &err); | ||
2446 | pci_cleanup_aer_uncorrect_error_status(pdev); | ||
2447 | } else { | ||
2448 | /* Either AER not configured, or not working | ||
2449 | * because of bad MMCONFIG, so just do recover | ||
2450 | * manually. | ||
2451 | */ | ||
2452 | err = sky2_read32(hw, Y2_CFG_AER + PCI_ERR_UNCOR_STATUS); | ||
2453 | sky2_write32(hw, Y2_CFG_AER + PCI_ERR_UNCOR_STATUS, | ||
2454 | 0xfffffffful); | ||
2455 | } | ||
2456 | |||
2446 | if (net_ratelimit()) | 2457 | if (net_ratelimit()) |
2447 | dev_err(&pdev->dev, "PCI Express error (0x%x)\n", err); | 2458 | dev_err(&pdev->dev, "PCI Express error (0x%x)\n", err); |
2448 | pci_cleanup_aer_uncorrect_error_status(pdev); | 2459 | |
2449 | } | 2460 | } |
2450 | 2461 | ||
2451 | if (status & Y2_HWE_L1_MASK) | 2462 | if (status & Y2_HWE_L1_MASK) |
@@ -2791,6 +2802,9 @@ static void sky2_reset(struct sky2_hw *hw) | |||
2791 | sky2_write8(hw, B0_CTST, CS_RST_SET); | 2802 | sky2_write8(hw, B0_CTST, CS_RST_SET); |
2792 | sky2_write8(hw, B0_CTST, CS_RST_CLR); | 2803 | sky2_write8(hw, B0_CTST, CS_RST_CLR); |
2793 | 2804 | ||
2805 | /* allow writes to PCI config */ | ||
2806 | sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_ON); | ||
2807 | |||
2794 | /* clear PCI errors, if any */ | 2808 | /* clear PCI errors, if any */ |
2795 | pci_read_config_word(pdev, PCI_STATUS, &status); | 2809 | pci_read_config_word(pdev, PCI_STATUS, &status); |
2796 | status |= PCI_STATUS_ERROR_BITS; | 2810 | status |= PCI_STATUS_ERROR_BITS; |
@@ -2800,9 +2814,18 @@ static void sky2_reset(struct sky2_hw *hw) | |||
2800 | 2814 | ||
2801 | cap = pci_find_capability(pdev, PCI_CAP_ID_EXP); | 2815 | cap = pci_find_capability(pdev, PCI_CAP_ID_EXP); |
2802 | if (cap) { | 2816 | if (cap) { |
2803 | /* Check for advanced error reporting */ | 2817 | if (pci_find_aer_capability(pdev)) { |
2804 | pci_cleanup_aer_uncorrect_error_status(pdev); | 2818 | /* Check for advanced error reporting */ |
2805 | pci_cleanup_aer_correct_error_status(pdev); | 2819 | pci_cleanup_aer_uncorrect_error_status(pdev); |
2820 | pci_cleanup_aer_correct_error_status(pdev); | ||
2821 | } else { | ||
2822 | dev_warn(&pdev->dev, | ||
2823 | "PCI Express Advanced Error Reporting" | ||
2824 | " not configured or MMCONFIG problem?\n"); | ||
2825 | |||
2826 | sky2_write32(hw, Y2_CFG_AER + PCI_ERR_UNCOR_STATUS, | ||
2827 | 0xfffffffful); | ||
2828 | } | ||
2806 | 2829 | ||
2807 | /* If error bit is stuck on ignore it */ | 2830 | /* If error bit is stuck on ignore it */ |
2808 | if (sky2_read32(hw, B0_HWE_ISRC) & Y2_IS_PCI_EXP) | 2831 | if (sky2_read32(hw, B0_HWE_ISRC) & Y2_IS_PCI_EXP) |
@@ -3974,7 +3997,8 @@ static __devinit struct net_device *sky2_init_netdev(struct sky2_hw *hw, | |||
3974 | dev->tx_timeout = sky2_tx_timeout; | 3997 | dev->tx_timeout = sky2_tx_timeout; |
3975 | dev->watchdog_timeo = TX_WATCHDOG; | 3998 | dev->watchdog_timeo = TX_WATCHDOG; |
3976 | #ifdef CONFIG_NET_POLL_CONTROLLER | 3999 | #ifdef CONFIG_NET_POLL_CONTROLLER |
3977 | dev->poll_controller = sky2_netpoll; | 4000 | if (port == 0) |
4001 | dev->poll_controller = sky2_netpoll; | ||
3978 | #endif | 4002 | #endif |
3979 | 4003 | ||
3980 | sky2 = netdev_priv(dev); | 4004 | sky2 = netdev_priv(dev); |