diff options
Diffstat (limited to 'drivers/net/sky2.c')
-rw-r--r-- | drivers/net/sky2.c | 543 |
1 files changed, 336 insertions, 207 deletions
diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index 822dd0b13133..f2ab3d56e565 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c | |||
@@ -49,7 +49,7 @@ | |||
49 | #include "sky2.h" | 49 | #include "sky2.h" |
50 | 50 | ||
51 | #define DRV_NAME "sky2" | 51 | #define DRV_NAME "sky2" |
52 | #define DRV_VERSION "1.10" | 52 | #define DRV_VERSION "1.12" |
53 | #define PFX DRV_NAME " " | 53 | #define PFX DRV_NAME " " |
54 | 54 | ||
55 | /* | 55 | /* |
@@ -105,6 +105,7 @@ static const struct pci_device_id sky2_id_table[] = { | |||
105 | { PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x4b00) }, /* DGE-560T */ | 105 | { PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x4b00) }, /* DGE-560T */ |
106 | { PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x4001) }, /* DGE-550SX */ | 106 | { PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x4001) }, /* DGE-550SX */ |
107 | { PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x4B02) }, /* DGE-560SX */ | 107 | { PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x4B02) }, /* DGE-560SX */ |
108 | { PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x4B03) }, /* DGE-550T */ | ||
108 | { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4340) }, /* 88E8021 */ | 109 | { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4340) }, /* 88E8021 */ |
109 | { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4341) }, /* 88E8022 */ | 110 | { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4341) }, /* 88E8022 */ |
110 | { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4342) }, /* 88E8061 */ | 111 | { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4342) }, /* 88E8061 */ |
@@ -126,6 +127,9 @@ static const struct pci_device_id sky2_id_table[] = { | |||
126 | { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4366) }, /* 88EC036 */ | 127 | { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4366) }, /* 88EC036 */ |
127 | { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4367) }, /* 88EC032 */ | 128 | { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4367) }, /* 88EC032 */ |
128 | { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4368) }, /* 88EC034 */ | 129 | { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4368) }, /* 88EC034 */ |
130 | { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4369) }, /* 88EC042 */ | ||
131 | { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x436A) }, /* 88E8058 */ | ||
132 | { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x436B) }, /* 88E8071 */ | ||
129 | { 0 } | 133 | { 0 } |
130 | }; | 134 | }; |
131 | 135 | ||
@@ -140,7 +144,7 @@ static const u32 portirq_msk[] = { Y2_IS_PORT_1, Y2_IS_PORT_2 }; | |||
140 | static const char *yukon2_name[] = { | 144 | static const char *yukon2_name[] = { |
141 | "XL", /* 0xb3 */ | 145 | "XL", /* 0xb3 */ |
142 | "EC Ultra", /* 0xb4 */ | 146 | "EC Ultra", /* 0xb4 */ |
143 | "UNKNOWN", /* 0xb5 */ | 147 | "Extreme", /* 0xb5 */ |
144 | "EC", /* 0xb6 */ | 148 | "EC", /* 0xb6 */ |
145 | "FE", /* 0xb7 */ | 149 | "FE", /* 0xb7 */ |
146 | }; | 150 | }; |
@@ -192,76 +196,52 @@ static u16 gm_phy_read(struct sky2_hw *hw, unsigned port, u16 reg) | |||
192 | return v; | 196 | return v; |
193 | } | 197 | } |
194 | 198 | ||
195 | static void sky2_set_power_state(struct sky2_hw *hw, pci_power_t state) | ||
196 | { | ||
197 | u16 power_control; | ||
198 | int vaux; | ||
199 | |||
200 | pr_debug("sky2_set_power_state %d\n", state); | ||
201 | sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_ON); | ||
202 | |||
203 | power_control = sky2_pci_read16(hw, hw->pm_cap + PCI_PM_PMC); | ||
204 | vaux = (sky2_read16(hw, B0_CTST) & Y2_VAUX_AVAIL) && | ||
205 | (power_control & PCI_PM_CAP_PME_D3cold); | ||
206 | |||
207 | power_control = sky2_pci_read16(hw, hw->pm_cap + PCI_PM_CTRL); | ||
208 | |||
209 | power_control |= PCI_PM_CTRL_PME_STATUS; | ||
210 | power_control &= ~(PCI_PM_CTRL_STATE_MASK); | ||
211 | 199 | ||
212 | switch (state) { | 200 | static void sky2_power_on(struct sky2_hw *hw) |
213 | case PCI_D0: | 201 | { |
214 | /* switch power to VCC (WA for VAUX problem) */ | 202 | /* switch power to VCC (WA for VAUX problem) */ |
215 | sky2_write8(hw, B0_POWER_CTRL, | 203 | sky2_write8(hw, B0_POWER_CTRL, |
216 | PC_VAUX_ENA | PC_VCC_ENA | PC_VAUX_OFF | PC_VCC_ON); | 204 | PC_VAUX_ENA | PC_VCC_ENA | PC_VAUX_OFF | PC_VCC_ON); |
217 | |||
218 | /* disable Core Clock Division, */ | ||
219 | sky2_write32(hw, B2_Y2_CLK_CTRL, Y2_CLK_DIV_DIS); | ||
220 | |||
221 | if (hw->chip_id == CHIP_ID_YUKON_XL && hw->chip_rev > 1) | ||
222 | /* enable bits are inverted */ | ||
223 | sky2_write8(hw, B2_Y2_CLK_GATE, | ||
224 | Y2_PCI_CLK_LNK1_DIS | Y2_COR_CLK_LNK1_DIS | | ||
225 | Y2_CLK_GAT_LNK1_DIS | Y2_PCI_CLK_LNK2_DIS | | ||
226 | Y2_COR_CLK_LNK2_DIS | Y2_CLK_GAT_LNK2_DIS); | ||
227 | else | ||
228 | sky2_write8(hw, B2_Y2_CLK_GATE, 0); | ||
229 | 205 | ||
230 | if (hw->chip_id == CHIP_ID_YUKON_EC_U) { | 206 | /* disable Core Clock Division, */ |
231 | u32 reg1; | 207 | sky2_write32(hw, B2_Y2_CLK_CTRL, Y2_CLK_DIV_DIS); |
232 | 208 | ||
233 | sky2_pci_write32(hw, PCI_DEV_REG3, 0); | 209 | if (hw->chip_id == CHIP_ID_YUKON_XL && hw->chip_rev > 1) |
234 | reg1 = sky2_pci_read32(hw, PCI_DEV_REG4); | 210 | /* enable bits are inverted */ |
235 | reg1 &= P_ASPM_CONTROL_MSK; | 211 | sky2_write8(hw, B2_Y2_CLK_GATE, |
236 | sky2_pci_write32(hw, PCI_DEV_REG4, reg1); | 212 | Y2_PCI_CLK_LNK1_DIS | Y2_COR_CLK_LNK1_DIS | |
237 | sky2_pci_write32(hw, PCI_DEV_REG5, 0); | 213 | Y2_CLK_GAT_LNK1_DIS | Y2_PCI_CLK_LNK2_DIS | |
238 | } | 214 | Y2_COR_CLK_LNK2_DIS | Y2_CLK_GAT_LNK2_DIS); |
215 | else | ||
216 | sky2_write8(hw, B2_Y2_CLK_GATE, 0); | ||
239 | 217 | ||
240 | break; | 218 | if (hw->chip_id == CHIP_ID_YUKON_EC_U || hw->chip_id == CHIP_ID_YUKON_EX) { |
219 | u32 reg1; | ||
241 | 220 | ||
242 | case PCI_D3hot: | 221 | sky2_pci_write32(hw, PCI_DEV_REG3, 0); |
243 | case PCI_D3cold: | 222 | reg1 = sky2_pci_read32(hw, PCI_DEV_REG4); |
244 | if (hw->chip_id == CHIP_ID_YUKON_XL && hw->chip_rev > 1) | 223 | reg1 &= P_ASPM_CONTROL_MSK; |
245 | sky2_write8(hw, B2_Y2_CLK_GATE, 0); | 224 | sky2_pci_write32(hw, PCI_DEV_REG4, reg1); |
246 | else | 225 | sky2_pci_write32(hw, PCI_DEV_REG5, 0); |
247 | /* enable bits are inverted */ | ||
248 | sky2_write8(hw, B2_Y2_CLK_GATE, | ||
249 | Y2_PCI_CLK_LNK1_DIS | Y2_COR_CLK_LNK1_DIS | | ||
250 | Y2_CLK_GAT_LNK1_DIS | Y2_PCI_CLK_LNK2_DIS | | ||
251 | Y2_COR_CLK_LNK2_DIS | Y2_CLK_GAT_LNK2_DIS); | ||
252 | |||
253 | /* switch power to VAUX */ | ||
254 | if (vaux && state != PCI_D3cold) | ||
255 | sky2_write8(hw, B0_POWER_CTRL, | ||
256 | (PC_VAUX_ENA | PC_VCC_ENA | | ||
257 | PC_VAUX_ON | PC_VCC_OFF)); | ||
258 | break; | ||
259 | default: | ||
260 | printk(KERN_ERR PFX "Unknown power state %d\n", state); | ||
261 | } | 226 | } |
227 | } | ||
262 | 228 | ||
263 | sky2_pci_write16(hw, hw->pm_cap + PCI_PM_CTRL, power_control); | 229 | static void sky2_power_aux(struct sky2_hw *hw) |
264 | sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_OFF); | 230 | { |
231 | if (hw->chip_id == CHIP_ID_YUKON_XL && hw->chip_rev > 1) | ||
232 | sky2_write8(hw, B2_Y2_CLK_GATE, 0); | ||
233 | else | ||
234 | /* enable bits are inverted */ | ||
235 | sky2_write8(hw, B2_Y2_CLK_GATE, | ||
236 | Y2_PCI_CLK_LNK1_DIS | Y2_COR_CLK_LNK1_DIS | | ||
237 | Y2_CLK_GAT_LNK1_DIS | Y2_PCI_CLK_LNK2_DIS | | ||
238 | Y2_COR_CLK_LNK2_DIS | Y2_CLK_GAT_LNK2_DIS); | ||
239 | |||
240 | /* switch power to VAUX */ | ||
241 | if (sky2_read16(hw, B0_CTST) & Y2_VAUX_AVAIL) | ||
242 | sky2_write8(hw, B0_POWER_CTRL, | ||
243 | (PC_VAUX_ENA | PC_VCC_ENA | | ||
244 | PC_VAUX_ON | PC_VCC_OFF)); | ||
265 | } | 245 | } |
266 | 246 | ||
267 | static void sky2_gmac_reset(struct sky2_hw *hw, unsigned port) | 247 | static void sky2_gmac_reset(struct sky2_hw *hw, unsigned port) |
@@ -313,8 +293,10 @@ static void sky2_phy_init(struct sky2_hw *hw, unsigned port) | |||
313 | struct sky2_port *sky2 = netdev_priv(hw->dev[port]); | 293 | struct sky2_port *sky2 = netdev_priv(hw->dev[port]); |
314 | u16 ctrl, ct1000, adv, pg, ledctrl, ledover, reg; | 294 | u16 ctrl, ct1000, adv, pg, ledctrl, ledover, reg; |
315 | 295 | ||
316 | if (sky2->autoneg == AUTONEG_ENABLE && | 296 | if (sky2->autoneg == AUTONEG_ENABLE |
317 | !(hw->chip_id == CHIP_ID_YUKON_XL || hw->chip_id == CHIP_ID_YUKON_EC_U)) { | 297 | && !(hw->chip_id == CHIP_ID_YUKON_XL |
298 | || hw->chip_id == CHIP_ID_YUKON_EC_U | ||
299 | || hw->chip_id == CHIP_ID_YUKON_EX)) { | ||
318 | u16 ectrl = gm_phy_read(hw, port, PHY_MARV_EXT_CTRL); | 300 | u16 ectrl = gm_phy_read(hw, port, PHY_MARV_EXT_CTRL); |
319 | 301 | ||
320 | ectrl &= ~(PHY_M_EC_M_DSC_MSK | PHY_M_EC_S_DSC_MSK | | 302 | ectrl &= ~(PHY_M_EC_M_DSC_MSK | PHY_M_EC_S_DSC_MSK | |
@@ -341,8 +323,10 @@ static void sky2_phy_init(struct sky2_hw *hw, unsigned port) | |||
341 | /* enable automatic crossover */ | 323 | /* enable automatic crossover */ |
342 | ctrl |= PHY_M_PC_MDI_XMODE(PHY_M_PC_ENA_AUTO); | 324 | ctrl |= PHY_M_PC_MDI_XMODE(PHY_M_PC_ENA_AUTO); |
343 | 325 | ||
344 | if (sky2->autoneg == AUTONEG_ENABLE && | 326 | if (sky2->autoneg == AUTONEG_ENABLE |
345 | (hw->chip_id == CHIP_ID_YUKON_XL || hw->chip_id == CHIP_ID_YUKON_EC_U)) { | 327 | && (hw->chip_id == CHIP_ID_YUKON_XL |
328 | || hw->chip_id == CHIP_ID_YUKON_EC_U | ||
329 | || hw->chip_id == CHIP_ID_YUKON_EX)) { | ||
346 | ctrl &= ~PHY_M_PC_DSC_MSK; | 330 | ctrl &= ~PHY_M_PC_DSC_MSK; |
347 | ctrl |= PHY_M_PC_DSC(2) | PHY_M_PC_DOWN_S_ENA; | 331 | ctrl |= PHY_M_PC_DSC(2) | PHY_M_PC_DOWN_S_ENA; |
348 | } | 332 | } |
@@ -497,7 +481,9 @@ static void sky2_phy_init(struct sky2_hw *hw, unsigned port) | |||
497 | /* restore page register */ | 481 | /* restore page register */ |
498 | gm_phy_write(hw, port, PHY_MARV_EXT_ADR, pg); | 482 | gm_phy_write(hw, port, PHY_MARV_EXT_ADR, pg); |
499 | break; | 483 | break; |
484 | |||
500 | case CHIP_ID_YUKON_EC_U: | 485 | case CHIP_ID_YUKON_EC_U: |
486 | case CHIP_ID_YUKON_EX: | ||
501 | pg = gm_phy_read(hw, port, PHY_MARV_EXT_ADR); | 487 | pg = gm_phy_read(hw, port, PHY_MARV_EXT_ADR); |
502 | 488 | ||
503 | /* select page 3 to access LED control register */ | 489 | /* select page 3 to access LED control register */ |
@@ -539,7 +525,7 @@ static void sky2_phy_init(struct sky2_hw *hw, unsigned port) | |||
539 | 525 | ||
540 | /* set page register to 0 */ | 526 | /* set page register to 0 */ |
541 | gm_phy_write(hw, port, PHY_MARV_EXT_ADR, pg); | 527 | gm_phy_write(hw, port, PHY_MARV_EXT_ADR, pg); |
542 | } else { | 528 | } else if (hw->chip_id != CHIP_ID_YUKON_EX) { |
543 | gm_phy_write(hw, port, PHY_MARV_LED_CTRL, ledctrl); | 529 | gm_phy_write(hw, port, PHY_MARV_LED_CTRL, ledctrl); |
544 | 530 | ||
545 | if (sky2->autoneg == AUTONEG_DISABLE || sky2->speed == SPEED_100) { | 531 | if (sky2->autoneg == AUTONEG_DISABLE || sky2->speed == SPEED_100) { |
@@ -591,6 +577,73 @@ static void sky2_phy_reinit(struct sky2_port *sky2) | |||
591 | spin_unlock_bh(&sky2->phy_lock); | 577 | spin_unlock_bh(&sky2->phy_lock); |
592 | } | 578 | } |
593 | 579 | ||
580 | /* Put device in state to listen for Wake On Lan */ | ||
581 | static void sky2_wol_init(struct sky2_port *sky2) | ||
582 | { | ||
583 | struct sky2_hw *hw = sky2->hw; | ||
584 | unsigned port = sky2->port; | ||
585 | enum flow_control save_mode; | ||
586 | u16 ctrl; | ||
587 | u32 reg1; | ||
588 | |||
589 | /* Bring hardware out of reset */ | ||
590 | sky2_write16(hw, B0_CTST, CS_RST_CLR); | ||
591 | sky2_write16(hw, SK_REG(port, GMAC_LINK_CTRL), GMLC_RST_CLR); | ||
592 | |||
593 | sky2_write8(hw, SK_REG(port, GPHY_CTRL), GPC_RST_CLR); | ||
594 | sky2_write8(hw, SK_REG(port, GMAC_CTRL), GMC_RST_CLR); | ||
595 | |||
596 | /* Force to 10/100 | ||
597 | * sky2_reset will re-enable on resume | ||
598 | */ | ||
599 | save_mode = sky2->flow_mode; | ||
600 | ctrl = sky2->advertising; | ||
601 | |||
602 | sky2->advertising &= ~(ADVERTISED_1000baseT_Half|ADVERTISED_1000baseT_Full); | ||
603 | sky2->flow_mode = FC_NONE; | ||
604 | sky2_phy_power(hw, port, 1); | ||
605 | sky2_phy_reinit(sky2); | ||
606 | |||
607 | sky2->flow_mode = save_mode; | ||
608 | sky2->advertising = ctrl; | ||
609 | |||
610 | /* Set GMAC to no flow control and auto update for speed/duplex */ | ||
611 | gma_write16(hw, port, GM_GP_CTRL, | ||
612 | GM_GPCR_FC_TX_DIS|GM_GPCR_TX_ENA|GM_GPCR_RX_ENA| | ||
613 | GM_GPCR_DUP_FULL|GM_GPCR_FC_RX_DIS|GM_GPCR_AU_FCT_DIS); | ||
614 | |||
615 | /* Set WOL address */ | ||
616 | memcpy_toio(hw->regs + WOL_REGS(port, WOL_MAC_ADDR), | ||
617 | sky2->netdev->dev_addr, ETH_ALEN); | ||
618 | |||
619 | /* Turn on appropriate WOL control bits */ | ||
620 | sky2_write16(hw, WOL_REGS(port, WOL_CTRL_STAT), WOL_CTL_CLEAR_RESULT); | ||
621 | ctrl = 0; | ||
622 | if (sky2->wol & WAKE_PHY) | ||
623 | ctrl |= WOL_CTL_ENA_PME_ON_LINK_CHG|WOL_CTL_ENA_LINK_CHG_UNIT; | ||
624 | else | ||
625 | ctrl |= WOL_CTL_DIS_PME_ON_LINK_CHG|WOL_CTL_DIS_LINK_CHG_UNIT; | ||
626 | |||
627 | if (sky2->wol & WAKE_MAGIC) | ||
628 | ctrl |= WOL_CTL_ENA_PME_ON_MAGIC_PKT|WOL_CTL_ENA_MAGIC_PKT_UNIT; | ||
629 | else | ||
630 | ctrl |= WOL_CTL_DIS_PME_ON_MAGIC_PKT|WOL_CTL_DIS_MAGIC_PKT_UNIT;; | ||
631 | |||
632 | ctrl |= WOL_CTL_DIS_PME_ON_PATTERN|WOL_CTL_DIS_PATTERN_UNIT; | ||
633 | sky2_write16(hw, WOL_REGS(port, WOL_CTRL_STAT), ctrl); | ||
634 | |||
635 | /* Turn on legacy PCI-Express PME mode */ | ||
636 | sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_ON); | ||
637 | reg1 = sky2_pci_read32(hw, PCI_DEV_REG1); | ||
638 | reg1 |= PCI_Y2_PME_LEGACY; | ||
639 | sky2_pci_write32(hw, PCI_DEV_REG1, reg1); | ||
640 | sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_OFF); | ||
641 | |||
642 | /* block receiver */ | ||
643 | sky2_write8(hw, SK_REG(port, RX_GMF_CTRL_T), GMF_RST_SET); | ||
644 | |||
645 | } | ||
646 | |||
594 | static void sky2_mac_init(struct sky2_hw *hw, unsigned port) | 647 | static void sky2_mac_init(struct sky2_hw *hw, unsigned port) |
595 | { | 648 | { |
596 | struct sky2_port *sky2 = netdev_priv(hw->dev[port]); | 649 | struct sky2_port *sky2 = netdev_priv(hw->dev[port]); |
@@ -684,7 +737,7 @@ static void sky2_mac_init(struct sky2_hw *hw, unsigned port) | |||
684 | sky2_write8(hw, SK_REG(port, TX_GMF_CTRL_T), GMF_RST_CLR); | 737 | sky2_write8(hw, SK_REG(port, TX_GMF_CTRL_T), GMF_RST_CLR); |
685 | sky2_write16(hw, SK_REG(port, TX_GMF_CTRL_T), GMF_OPER_ON); | 738 | sky2_write16(hw, SK_REG(port, TX_GMF_CTRL_T), GMF_OPER_ON); |
686 | 739 | ||
687 | if (hw->chip_id == CHIP_ID_YUKON_EC_U) { | 740 | if (hw->chip_id == CHIP_ID_YUKON_EC_U || hw->chip_id == CHIP_ID_YUKON_EX) { |
688 | sky2_write8(hw, SK_REG(port, RX_GMF_LP_THR), 768/8); | 741 | sky2_write8(hw, SK_REG(port, RX_GMF_LP_THR), 768/8); |
689 | sky2_write8(hw, SK_REG(port, RX_GMF_UP_THR), 1024/8); | 742 | sky2_write8(hw, SK_REG(port, RX_GMF_UP_THR), 1024/8); |
690 | if (hw->dev[port]->mtu > ETH_DATA_LEN) { | 743 | if (hw->dev[port]->mtu > ETH_DATA_LEN) { |
@@ -1467,6 +1520,9 @@ static void sky2_tx_complete(struct sky2_port *sky2, u16 done) | |||
1467 | if (unlikely(netif_msg_tx_done(sky2))) | 1520 | if (unlikely(netif_msg_tx_done(sky2))) |
1468 | printk(KERN_DEBUG "%s: tx done %u\n", | 1521 | printk(KERN_DEBUG "%s: tx done %u\n", |
1469 | dev->name, idx); | 1522 | dev->name, idx); |
1523 | sky2->net_stats.tx_packets++; | ||
1524 | sky2->net_stats.tx_bytes += re->skb->len; | ||
1525 | |||
1470 | dev_kfree_skb_any(re->skb); | 1526 | dev_kfree_skb_any(re->skb); |
1471 | } | 1527 | } |
1472 | 1528 | ||
@@ -1641,7 +1697,9 @@ static void sky2_link_up(struct sky2_port *sky2) | |||
1641 | sky2_write8(hw, SK_REG(port, LNK_LED_REG), | 1697 | sky2_write8(hw, SK_REG(port, LNK_LED_REG), |
1642 | LINKLED_ON | LINKLED_BLINK_OFF | LINKLED_LINKSYNC_OFF); | 1698 | LINKLED_ON | LINKLED_BLINK_OFF | LINKLED_LINKSYNC_OFF); |
1643 | 1699 | ||
1644 | if (hw->chip_id == CHIP_ID_YUKON_XL || hw->chip_id == CHIP_ID_YUKON_EC_U) { | 1700 | if (hw->chip_id == CHIP_ID_YUKON_XL |
1701 | || hw->chip_id == CHIP_ID_YUKON_EC_U | ||
1702 | || hw->chip_id == CHIP_ID_YUKON_EX) { | ||
1645 | u16 pg = gm_phy_read(hw, port, PHY_MARV_EXT_ADR); | 1703 | u16 pg = gm_phy_read(hw, port, PHY_MARV_EXT_ADR); |
1646 | u16 led = PHY_M_LEDC_LOS_CTRL(1); /* link active */ | 1704 | u16 led = PHY_M_LEDC_LOS_CTRL(1); /* link active */ |
1647 | 1705 | ||
@@ -1734,14 +1792,16 @@ static int sky2_autoneg_done(struct sky2_port *sky2, u16 aux) | |||
1734 | sky2->duplex = (aux & PHY_M_PS_FULL_DUP) ? DUPLEX_FULL : DUPLEX_HALF; | 1792 | sky2->duplex = (aux & PHY_M_PS_FULL_DUP) ? DUPLEX_FULL : DUPLEX_HALF; |
1735 | 1793 | ||
1736 | /* Pause bits are offset (9..8) */ | 1794 | /* Pause bits are offset (9..8) */ |
1737 | if (hw->chip_id == CHIP_ID_YUKON_XL || hw->chip_id == CHIP_ID_YUKON_EC_U) | 1795 | if (hw->chip_id == CHIP_ID_YUKON_XL |
1796 | || hw->chip_id == CHIP_ID_YUKON_EC_U | ||
1797 | || hw->chip_id == CHIP_ID_YUKON_EX) | ||
1738 | aux >>= 6; | 1798 | aux >>= 6; |
1739 | 1799 | ||
1740 | sky2->flow_status = sky2_flow(aux & PHY_M_PS_RX_P_EN, | 1800 | sky2->flow_status = sky2_flow(aux & PHY_M_PS_RX_P_EN, |
1741 | aux & PHY_M_PS_TX_P_EN); | 1801 | aux & PHY_M_PS_TX_P_EN); |
1742 | 1802 | ||
1743 | if (sky2->duplex == DUPLEX_HALF && sky2->speed < SPEED_1000 | 1803 | if (sky2->duplex == DUPLEX_HALF && sky2->speed < SPEED_1000 |
1744 | && hw->chip_id != CHIP_ID_YUKON_EC_U) | 1804 | && !(hw->chip_id == CHIP_ID_YUKON_EC_U || hw->chip_id == CHIP_ID_YUKON_EX)) |
1745 | sky2->flow_status = FC_NONE; | 1805 | sky2->flow_status = FC_NONE; |
1746 | 1806 | ||
1747 | if (aux & PHY_M_PS_RX_P_EN) | 1807 | if (aux & PHY_M_PS_RX_P_EN) |
@@ -1794,48 +1854,37 @@ out: | |||
1794 | } | 1854 | } |
1795 | 1855 | ||
1796 | 1856 | ||
1797 | /* Transmit timeout is only called if we are running, carries is up | 1857 | /* Transmit timeout is only called if we are running, carrier is up |
1798 | * and tx queue is full (stopped). | 1858 | * and tx queue is full (stopped). |
1859 | * Called with netif_tx_lock held. | ||
1799 | */ | 1860 | */ |
1800 | static void sky2_tx_timeout(struct net_device *dev) | 1861 | static void sky2_tx_timeout(struct net_device *dev) |
1801 | { | 1862 | { |
1802 | struct sky2_port *sky2 = netdev_priv(dev); | 1863 | struct sky2_port *sky2 = netdev_priv(dev); |
1803 | struct sky2_hw *hw = sky2->hw; | 1864 | struct sky2_hw *hw = sky2->hw; |
1804 | unsigned txq = txqaddr[sky2->port]; | 1865 | u32 imask; |
1805 | u16 report, done; | ||
1806 | 1866 | ||
1807 | if (netif_msg_timer(sky2)) | 1867 | if (netif_msg_timer(sky2)) |
1808 | printk(KERN_ERR PFX "%s: tx timeout\n", dev->name); | 1868 | printk(KERN_ERR PFX "%s: tx timeout\n", dev->name); |
1809 | 1869 | ||
1810 | report = sky2_read16(hw, sky2->port == 0 ? STAT_TXA1_RIDX : STAT_TXA2_RIDX); | ||
1811 | done = sky2_read16(hw, Q_ADDR(txq, Q_DONE)); | ||
1812 | |||
1813 | printk(KERN_DEBUG PFX "%s: transmit ring %u .. %u report=%u done=%u\n", | 1870 | printk(KERN_DEBUG PFX "%s: transmit ring %u .. %u report=%u done=%u\n", |
1814 | dev->name, | 1871 | dev->name, sky2->tx_cons, sky2->tx_prod, |
1815 | sky2->tx_cons, sky2->tx_prod, report, done); | 1872 | sky2_read16(hw, sky2->port == 0 ? STAT_TXA1_RIDX : STAT_TXA2_RIDX), |
1873 | sky2_read16(hw, Q_ADDR(txqaddr[sky2->port], Q_DONE))); | ||
1816 | 1874 | ||
1817 | if (report != done) { | 1875 | imask = sky2_read32(hw, B0_IMSK); /* block IRQ in hw */ |
1818 | printk(KERN_INFO PFX "status burst pending (irq moderation?)\n"); | 1876 | sky2_write32(hw, B0_IMSK, 0); |
1819 | 1877 | sky2_read32(hw, B0_IMSK); | |
1820 | sky2_write8(hw, STAT_TX_TIMER_CTRL, TIM_STOP); | ||
1821 | sky2_write8(hw, STAT_TX_TIMER_CTRL, TIM_START); | ||
1822 | } else if (report != sky2->tx_cons) { | ||
1823 | printk(KERN_INFO PFX "status report lost?\n"); | ||
1824 | 1878 | ||
1825 | netif_tx_lock_bh(dev); | 1879 | netif_poll_disable(hw->dev[0]); /* stop NAPI poll */ |
1826 | sky2_tx_complete(sky2, report); | 1880 | synchronize_irq(hw->pdev->irq); |
1827 | netif_tx_unlock_bh(dev); | ||
1828 | } else { | ||
1829 | printk(KERN_INFO PFX "hardware hung? flushing\n"); | ||
1830 | 1881 | ||
1831 | sky2_write32(hw, Q_ADDR(txq, Q_CSR), BMU_STOP); | 1882 | netif_start_queue(dev); /* don't wakeup during flush */ |
1832 | sky2_write32(hw, Y2_QADDR(txq, PREF_UNIT_CTRL), PREF_UNIT_RST_SET); | 1883 | sky2_tx_complete(sky2, sky2->tx_prod); /* Flush transmit queue */ |
1833 | 1884 | ||
1834 | sky2_tx_clean(dev); | 1885 | sky2_write32(hw, B0_IMSK, imask); |
1835 | 1886 | ||
1836 | sky2_qset(hw, txq); | 1887 | sky2_phy_reinit(sky2); /* this clears flow control etc */ |
1837 | sky2_prefetch_init(hw, txq, sky2->tx_le_map, TX_RING_SIZE - 1); | ||
1838 | } | ||
1839 | } | 1888 | } |
1840 | 1889 | ||
1841 | static int sky2_change_mtu(struct net_device *dev, int new_mtu) | 1890 | static int sky2_change_mtu(struct net_device *dev, int new_mtu) |
@@ -1849,8 +1898,9 @@ static int sky2_change_mtu(struct net_device *dev, int new_mtu) | |||
1849 | if (new_mtu < ETH_ZLEN || new_mtu > ETH_JUMBO_MTU) | 1898 | if (new_mtu < ETH_ZLEN || new_mtu > ETH_JUMBO_MTU) |
1850 | return -EINVAL; | 1899 | return -EINVAL; |
1851 | 1900 | ||
1901 | /* TSO on Yukon Ultra and MTU > 1500 not supported */ | ||
1852 | if (hw->chip_id == CHIP_ID_YUKON_EC_U && new_mtu > ETH_DATA_LEN) | 1902 | if (hw->chip_id == CHIP_ID_YUKON_EC_U && new_mtu > ETH_DATA_LEN) |
1853 | return -EINVAL; | 1903 | dev->features &= ~NETIF_F_TSO; |
1854 | 1904 | ||
1855 | if (!netif_running(dev)) { | 1905 | if (!netif_running(dev)) { |
1856 | dev->mtu = new_mtu; | 1906 | dev->mtu = new_mtu; |
@@ -2089,6 +2139,8 @@ static int sky2_status_intr(struct sky2_hw *hw, int to_do) | |||
2089 | goto force_update; | 2139 | goto force_update; |
2090 | 2140 | ||
2091 | skb->protocol = eth_type_trans(skb, dev); | 2141 | skb->protocol = eth_type_trans(skb, dev); |
2142 | sky2->net_stats.rx_packets++; | ||
2143 | sky2->net_stats.rx_bytes += skb->len; | ||
2092 | dev->last_rx = jiffies; | 2144 | dev->last_rx = jiffies; |
2093 | 2145 | ||
2094 | #ifdef SKY2_VLAN_TAG_USED | 2146 | #ifdef SKY2_VLAN_TAG_USED |
@@ -2218,8 +2270,8 @@ static void sky2_hw_intr(struct sky2_hw *hw) | |||
2218 | 2270 | ||
2219 | pci_err = sky2_pci_read16(hw, PCI_STATUS); | 2271 | pci_err = sky2_pci_read16(hw, PCI_STATUS); |
2220 | if (net_ratelimit()) | 2272 | if (net_ratelimit()) |
2221 | printk(KERN_ERR PFX "%s: pci hw error (0x%x)\n", | 2273 | dev_err(&hw->pdev->dev, "PCI hardware error (0x%x)\n", |
2222 | pci_name(hw->pdev), pci_err); | 2274 | pci_err); |
2223 | 2275 | ||
2224 | sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_ON); | 2276 | sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_ON); |
2225 | sky2_pci_write16(hw, PCI_STATUS, | 2277 | sky2_pci_write16(hw, PCI_STATUS, |
@@ -2234,8 +2286,8 @@ static void sky2_hw_intr(struct sky2_hw *hw) | |||
2234 | pex_err = sky2_pci_read32(hw, PEX_UNC_ERR_STAT); | 2286 | pex_err = sky2_pci_read32(hw, PEX_UNC_ERR_STAT); |
2235 | 2287 | ||
2236 | if (net_ratelimit()) | 2288 | if (net_ratelimit()) |
2237 | printk(KERN_ERR PFX "%s: pci express error (0x%x)\n", | 2289 | dev_err(&hw->pdev->dev, "PCI Express error (0x%x)\n", |
2238 | pci_name(hw->pdev), pex_err); | 2290 | pex_err); |
2239 | 2291 | ||
2240 | /* clear the interrupt */ | 2292 | /* clear the interrupt */ |
2241 | sky2_write32(hw, B2_TST_CTRL1, TST_CFG_WRITE_ON); | 2293 | sky2_write32(hw, B2_TST_CTRL1, TST_CFG_WRITE_ON); |
@@ -2404,6 +2456,7 @@ static inline u32 sky2_mhz(const struct sky2_hw *hw) | |||
2404 | switch (hw->chip_id) { | 2456 | switch (hw->chip_id) { |
2405 | case CHIP_ID_YUKON_EC: | 2457 | case CHIP_ID_YUKON_EC: |
2406 | case CHIP_ID_YUKON_EC_U: | 2458 | case CHIP_ID_YUKON_EC_U: |
2459 | case CHIP_ID_YUKON_EX: | ||
2407 | return 125; /* 125 Mhz */ | 2460 | return 125; /* 125 Mhz */ |
2408 | case CHIP_ID_YUKON_FE: | 2461 | case CHIP_ID_YUKON_FE: |
2409 | return 100; /* 100 Mhz */ | 2462 | return 100; /* 100 Mhz */ |
@@ -2423,34 +2476,62 @@ static inline u32 sky2_clk2us(const struct sky2_hw *hw, u32 clk) | |||
2423 | } | 2476 | } |
2424 | 2477 | ||
2425 | 2478 | ||
2426 | static int sky2_reset(struct sky2_hw *hw) | 2479 | static int __devinit sky2_init(struct sky2_hw *hw) |
2427 | { | 2480 | { |
2428 | u16 status; | ||
2429 | u8 t8; | 2481 | u8 t8; |
2430 | int i; | ||
2431 | 2482 | ||
2432 | sky2_write8(hw, B0_CTST, CS_RST_CLR); | 2483 | sky2_write8(hw, B0_CTST, CS_RST_CLR); |
2433 | 2484 | ||
2434 | hw->chip_id = sky2_read8(hw, B2_CHIP_ID); | 2485 | hw->chip_id = sky2_read8(hw, B2_CHIP_ID); |
2435 | if (hw->chip_id < CHIP_ID_YUKON_XL || hw->chip_id > CHIP_ID_YUKON_FE) { | 2486 | if (hw->chip_id < CHIP_ID_YUKON_XL || hw->chip_id > CHIP_ID_YUKON_FE) { |
2436 | printk(KERN_ERR PFX "%s: unsupported chip type 0x%x\n", | 2487 | dev_err(&hw->pdev->dev, "unsupported chip type 0x%x\n", |
2437 | pci_name(hw->pdev), hw->chip_id); | 2488 | hw->chip_id); |
2438 | return -EOPNOTSUPP; | 2489 | return -EOPNOTSUPP; |
2439 | } | 2490 | } |
2440 | 2491 | ||
2492 | if (hw->chip_id == CHIP_ID_YUKON_EX) | ||
2493 | dev_warn(&hw->pdev->dev, "this driver not yet tested on this chip type\n" | ||
2494 | "Please report success or failure to <netdev@vger.kernel.org>\n"); | ||
2495 | |||
2496 | /* Make sure and enable all clocks */ | ||
2497 | if (hw->chip_id == CHIP_ID_YUKON_EX || hw->chip_id == CHIP_ID_YUKON_EC_U) | ||
2498 | sky2_pci_write32(hw, PCI_DEV_REG3, 0); | ||
2499 | |||
2441 | hw->chip_rev = (sky2_read8(hw, B2_MAC_CFG) & CFG_CHIP_R_MSK) >> 4; | 2500 | hw->chip_rev = (sky2_read8(hw, B2_MAC_CFG) & CFG_CHIP_R_MSK) >> 4; |
2442 | 2501 | ||
2443 | /* This rev is really old, and requires untested workarounds */ | 2502 | /* This rev is really old, and requires untested workarounds */ |
2444 | if (hw->chip_id == CHIP_ID_YUKON_EC && hw->chip_rev == CHIP_REV_YU_EC_A1) { | 2503 | if (hw->chip_id == CHIP_ID_YUKON_EC && hw->chip_rev == CHIP_REV_YU_EC_A1) { |
2445 | printk(KERN_ERR PFX "%s: unsupported revision Yukon-%s (0x%x) rev %d\n", | 2504 | dev_err(&hw->pdev->dev, "unsupported revision Yukon-%s (0x%x) rev %d\n", |
2446 | pci_name(hw->pdev), yukon2_name[hw->chip_id - CHIP_ID_YUKON_XL], | 2505 | yukon2_name[hw->chip_id - CHIP_ID_YUKON_XL], |
2447 | hw->chip_id, hw->chip_rev); | 2506 | hw->chip_id, hw->chip_rev); |
2448 | return -EOPNOTSUPP; | 2507 | return -EOPNOTSUPP; |
2449 | } | 2508 | } |
2450 | 2509 | ||
2510 | hw->pmd_type = sky2_read8(hw, B2_PMD_TYP); | ||
2511 | hw->ports = 1; | ||
2512 | t8 = sky2_read8(hw, B2_Y2_HW_RES); | ||
2513 | if ((t8 & CFG_DUAL_MAC_MSK) == CFG_DUAL_MAC_MSK) { | ||
2514 | if (!(sky2_read8(hw, B2_Y2_CLK_GATE) & Y2_STATUS_LNK2_INAC)) | ||
2515 | ++hw->ports; | ||
2516 | } | ||
2517 | |||
2518 | return 0; | ||
2519 | } | ||
2520 | |||
2521 | static void sky2_reset(struct sky2_hw *hw) | ||
2522 | { | ||
2523 | u16 status; | ||
2524 | int i; | ||
2525 | |||
2451 | /* disable ASF */ | 2526 | /* disable ASF */ |
2452 | if (hw->chip_id <= CHIP_ID_YUKON_EC) { | 2527 | if (hw->chip_id <= CHIP_ID_YUKON_EC) { |
2453 | sky2_write8(hw, B28_Y2_ASF_STAT_CMD, Y2_ASF_RESET); | 2528 | if (hw->chip_id == CHIP_ID_YUKON_EX) { |
2529 | status = sky2_read16(hw, HCU_CCSR); | ||
2530 | status &= ~(HCU_CCSR_AHB_RST | HCU_CCSR_CPU_RST_MODE | | ||
2531 | HCU_CCSR_UC_STATE_MSK); | ||
2532 | sky2_write16(hw, HCU_CCSR, status); | ||
2533 | } else | ||
2534 | sky2_write8(hw, B28_Y2_ASF_STAT_CMD, Y2_ASF_RESET); | ||
2454 | sky2_write16(hw, B0_CTST, Y2_ASF_DISABLE); | 2535 | sky2_write16(hw, B0_CTST, Y2_ASF_DISABLE); |
2455 | } | 2536 | } |
2456 | 2537 | ||
@@ -2472,15 +2553,7 @@ static int sky2_reset(struct sky2_hw *hw) | |||
2472 | sky2_pci_write32(hw, PEX_UNC_ERR_STAT, 0xffffffffUL); | 2553 | sky2_pci_write32(hw, PEX_UNC_ERR_STAT, 0xffffffffUL); |
2473 | 2554 | ||
2474 | 2555 | ||
2475 | hw->pmd_type = sky2_read8(hw, B2_PMD_TYP); | 2556 | sky2_power_on(hw); |
2476 | hw->ports = 1; | ||
2477 | t8 = sky2_read8(hw, B2_Y2_HW_RES); | ||
2478 | if ((t8 & CFG_DUAL_MAC_MSK) == CFG_DUAL_MAC_MSK) { | ||
2479 | if (!(sky2_read8(hw, B2_Y2_CLK_GATE) & Y2_STATUS_LNK2_INAC)) | ||
2480 | ++hw->ports; | ||
2481 | } | ||
2482 | |||
2483 | sky2_set_power_state(hw, PCI_D0); | ||
2484 | 2557 | ||
2485 | for (i = 0; i < hw->ports; i++) { | 2558 | for (i = 0; i < hw->ports; i++) { |
2486 | sky2_write8(hw, SK_REG(i, GMAC_LINK_CTRL), GMLC_RST_SET); | 2559 | sky2_write8(hw, SK_REG(i, GMAC_LINK_CTRL), GMLC_RST_SET); |
@@ -2563,7 +2636,37 @@ static int sky2_reset(struct sky2_hw *hw) | |||
2563 | sky2_write8(hw, STAT_TX_TIMER_CTRL, TIM_START); | 2636 | sky2_write8(hw, STAT_TX_TIMER_CTRL, TIM_START); |
2564 | sky2_write8(hw, STAT_LEV_TIMER_CTRL, TIM_START); | 2637 | sky2_write8(hw, STAT_LEV_TIMER_CTRL, TIM_START); |
2565 | sky2_write8(hw, STAT_ISR_TIMER_CTRL, TIM_START); | 2638 | sky2_write8(hw, STAT_ISR_TIMER_CTRL, TIM_START); |
2639 | } | ||
2640 | |||
2641 | static inline u8 sky2_wol_supported(const struct sky2_hw *hw) | ||
2642 | { | ||
2643 | return sky2_is_copper(hw) ? (WAKE_PHY | WAKE_MAGIC) : 0; | ||
2644 | } | ||
2645 | |||
2646 | static void sky2_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol) | ||
2647 | { | ||
2648 | const struct sky2_port *sky2 = netdev_priv(dev); | ||
2649 | |||
2650 | wol->supported = sky2_wol_supported(sky2->hw); | ||
2651 | wol->wolopts = sky2->wol; | ||
2652 | } | ||
2653 | |||
2654 | static int sky2_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) | ||
2655 | { | ||
2656 | struct sky2_port *sky2 = netdev_priv(dev); | ||
2657 | struct sky2_hw *hw = sky2->hw; | ||
2658 | |||
2659 | if (wol->wolopts & ~sky2_wol_supported(sky2->hw)) | ||
2660 | return -EOPNOTSUPP; | ||
2661 | |||
2662 | sky2->wol = wol->wolopts; | ||
2663 | |||
2664 | if (hw->chip_id == CHIP_ID_YUKON_EC_U) | ||
2665 | sky2_write32(hw, B0_CTST, sky2->wol | ||
2666 | ? Y2_HW_WOL_ON : Y2_HW_WOL_OFF); | ||
2566 | 2667 | ||
2668 | if (!netif_running(dev)) | ||
2669 | sky2_wol_init(sky2); | ||
2567 | return 0; | 2670 | return 0; |
2568 | } | 2671 | } |
2569 | 2672 | ||
@@ -2814,25 +2917,9 @@ static void sky2_get_strings(struct net_device *dev, u32 stringset, u8 * data) | |||
2814 | } | 2917 | } |
2815 | } | 2918 | } |
2816 | 2919 | ||
2817 | /* Use hardware MIB variables for critical path statistics and | ||
2818 | * transmit feedback not reported at interrupt. | ||
2819 | * Other errors are accounted for in interrupt handler. | ||
2820 | */ | ||
2821 | static struct net_device_stats *sky2_get_stats(struct net_device *dev) | 2920 | static struct net_device_stats *sky2_get_stats(struct net_device *dev) |
2822 | { | 2921 | { |
2823 | struct sky2_port *sky2 = netdev_priv(dev); | 2922 | struct sky2_port *sky2 = netdev_priv(dev); |
2824 | u64 data[13]; | ||
2825 | |||
2826 | sky2_phy_stats(sky2, data, ARRAY_SIZE(data)); | ||
2827 | |||
2828 | sky2->net_stats.tx_bytes = data[0]; | ||
2829 | sky2->net_stats.rx_bytes = data[1]; | ||
2830 | sky2->net_stats.tx_packets = data[2] + data[4] + data[6]; | ||
2831 | sky2->net_stats.rx_packets = data[3] + data[5] + data[7]; | ||
2832 | sky2->net_stats.multicast = data[3] + data[5]; | ||
2833 | sky2->net_stats.collisions = data[10]; | ||
2834 | sky2->net_stats.tx_aborted_errors = data[12]; | ||
2835 | |||
2836 | return &sky2->net_stats; | 2923 | return &sky2->net_stats; |
2837 | } | 2924 | } |
2838 | 2925 | ||
@@ -3191,7 +3278,9 @@ static void sky2_get_regs(struct net_device *dev, struct ethtool_regs *regs, | |||
3191 | static const struct ethtool_ops sky2_ethtool_ops = { | 3278 | static const struct ethtool_ops sky2_ethtool_ops = { |
3192 | .get_settings = sky2_get_settings, | 3279 | .get_settings = sky2_get_settings, |
3193 | .set_settings = sky2_set_settings, | 3280 | .set_settings = sky2_set_settings, |
3194 | .get_drvinfo = sky2_get_drvinfo, | 3281 | .get_drvinfo = sky2_get_drvinfo, |
3282 | .get_wol = sky2_get_wol, | ||
3283 | .set_wol = sky2_set_wol, | ||
3195 | .get_msglevel = sky2_get_msglevel, | 3284 | .get_msglevel = sky2_get_msglevel, |
3196 | .set_msglevel = sky2_set_msglevel, | 3285 | .set_msglevel = sky2_set_msglevel, |
3197 | .nway_reset = sky2_nway_reset, | 3286 | .nway_reset = sky2_nway_reset, |
@@ -3221,13 +3310,14 @@ static const struct ethtool_ops sky2_ethtool_ops = { | |||
3221 | 3310 | ||
3222 | /* Initialize network device */ | 3311 | /* Initialize network device */ |
3223 | static __devinit struct net_device *sky2_init_netdev(struct sky2_hw *hw, | 3312 | static __devinit struct net_device *sky2_init_netdev(struct sky2_hw *hw, |
3224 | unsigned port, int highmem) | 3313 | unsigned port, |
3314 | int highmem, int wol) | ||
3225 | { | 3315 | { |
3226 | struct sky2_port *sky2; | 3316 | struct sky2_port *sky2; |
3227 | struct net_device *dev = alloc_etherdev(sizeof(*sky2)); | 3317 | struct net_device *dev = alloc_etherdev(sizeof(*sky2)); |
3228 | 3318 | ||
3229 | if (!dev) { | 3319 | if (!dev) { |
3230 | printk(KERN_ERR "sky2 etherdev alloc failed"); | 3320 | dev_err(&hw->pdev->dev, "etherdev alloc failed"); |
3231 | return NULL; | 3321 | return NULL; |
3232 | } | 3322 | } |
3233 | 3323 | ||
@@ -3269,6 +3359,7 @@ static __devinit struct net_device *sky2_init_netdev(struct sky2_hw *hw, | |||
3269 | sky2->speed = -1; | 3359 | sky2->speed = -1; |
3270 | sky2->advertising = sky2_supported_modes(hw); | 3360 | sky2->advertising = sky2_supported_modes(hw); |
3271 | sky2->rx_csum = 1; | 3361 | sky2->rx_csum = 1; |
3362 | sky2->wol = wol; | ||
3272 | 3363 | ||
3273 | spin_lock_init(&sky2->phy_lock); | 3364 | spin_lock_init(&sky2->phy_lock); |
3274 | sky2->tx_pending = TX_DEF_PENDING; | 3365 | sky2->tx_pending = TX_DEF_PENDING; |
@@ -3278,11 +3369,9 @@ static __devinit struct net_device *sky2_init_netdev(struct sky2_hw *hw, | |||
3278 | 3369 | ||
3279 | sky2->port = port; | 3370 | sky2->port = port; |
3280 | 3371 | ||
3281 | if (hw->chip_id != CHIP_ID_YUKON_EC_U) | 3372 | dev->features |= NETIF_F_TSO | NETIF_F_IP_CSUM | NETIF_F_SG; |
3282 | dev->features |= NETIF_F_TSO; | ||
3283 | if (highmem) | 3373 | if (highmem) |
3284 | dev->features |= NETIF_F_HIGHDMA; | 3374 | dev->features |= NETIF_F_HIGHDMA; |
3285 | dev->features |= NETIF_F_IP_CSUM | NETIF_F_SG; | ||
3286 | 3375 | ||
3287 | #ifdef SKY2_VLAN_TAG_USED | 3376 | #ifdef SKY2_VLAN_TAG_USED |
3288 | dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX; | 3377 | dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX; |
@@ -3343,8 +3432,7 @@ static int __devinit sky2_test_msi(struct sky2_hw *hw) | |||
3343 | 3432 | ||
3344 | err = request_irq(pdev->irq, sky2_test_intr, 0, DRV_NAME, hw); | 3433 | err = request_irq(pdev->irq, sky2_test_intr, 0, DRV_NAME, hw); |
3345 | if (err) { | 3434 | if (err) { |
3346 | printk(KERN_ERR PFX "%s: cannot assign irq %d\n", | 3435 | dev_err(&pdev->dev, "cannot assign irq %d\n", pdev->irq); |
3347 | pci_name(pdev), pdev->irq); | ||
3348 | return err; | 3436 | return err; |
3349 | } | 3437 | } |
3350 | 3438 | ||
@@ -3355,9 +3443,8 @@ static int __devinit sky2_test_msi(struct sky2_hw *hw) | |||
3355 | 3443 | ||
3356 | if (!hw->msi) { | 3444 | if (!hw->msi) { |
3357 | /* MSI test failed, go back to INTx mode */ | 3445 | /* MSI test failed, go back to INTx mode */ |
3358 | printk(KERN_INFO PFX "%s: No interrupt generated using MSI, " | 3446 | dev_info(&pdev->dev, "No interrupt generated using MSI, " |
3359 | "switching to INTx mode.\n", | 3447 | "switching to INTx mode.\n"); |
3360 | pci_name(pdev)); | ||
3361 | 3448 | ||
3362 | err = -EOPNOTSUPP; | 3449 | err = -EOPNOTSUPP; |
3363 | sky2_write8(hw, B0_CTST, CS_CL_SW_IRQ); | 3450 | sky2_write8(hw, B0_CTST, CS_CL_SW_IRQ); |
@@ -3371,62 +3458,62 @@ static int __devinit sky2_test_msi(struct sky2_hw *hw) | |||
3371 | return err; | 3458 | return err; |
3372 | } | 3459 | } |
3373 | 3460 | ||
3461 | static int __devinit pci_wake_enabled(struct pci_dev *dev) | ||
3462 | { | ||
3463 | int pm = pci_find_capability(dev, PCI_CAP_ID_PM); | ||
3464 | u16 value; | ||
3465 | |||
3466 | if (!pm) | ||
3467 | return 0; | ||
3468 | if (pci_read_config_word(dev, pm + PCI_PM_CTRL, &value)) | ||
3469 | return 0; | ||
3470 | return value & PCI_PM_CTRL_PME_ENABLE; | ||
3471 | } | ||
3472 | |||
3374 | static int __devinit sky2_probe(struct pci_dev *pdev, | 3473 | static int __devinit sky2_probe(struct pci_dev *pdev, |
3375 | const struct pci_device_id *ent) | 3474 | const struct pci_device_id *ent) |
3376 | { | 3475 | { |
3377 | struct net_device *dev, *dev1 = NULL; | 3476 | struct net_device *dev; |
3378 | struct sky2_hw *hw; | 3477 | struct sky2_hw *hw; |
3379 | int err, pm_cap, using_dac = 0; | 3478 | int err, using_dac = 0, wol_default; |
3380 | 3479 | ||
3381 | err = pci_enable_device(pdev); | 3480 | err = pci_enable_device(pdev); |
3382 | if (err) { | 3481 | if (err) { |
3383 | printk(KERN_ERR PFX "%s cannot enable PCI device\n", | 3482 | dev_err(&pdev->dev, "cannot enable PCI device\n"); |
3384 | pci_name(pdev)); | ||
3385 | goto err_out; | 3483 | goto err_out; |
3386 | } | 3484 | } |
3387 | 3485 | ||
3388 | err = pci_request_regions(pdev, DRV_NAME); | 3486 | err = pci_request_regions(pdev, DRV_NAME); |
3389 | if (err) { | 3487 | if (err) { |
3390 | printk(KERN_ERR PFX "%s cannot obtain PCI resources\n", | 3488 | dev_err(&pdev->dev, "cannot obtain PCI resources\n"); |
3391 | pci_name(pdev)); | ||
3392 | goto err_out; | 3489 | goto err_out; |
3393 | } | 3490 | } |
3394 | 3491 | ||
3395 | pci_set_master(pdev); | 3492 | pci_set_master(pdev); |
3396 | 3493 | ||
3397 | /* Find power-management capability. */ | ||
3398 | pm_cap = pci_find_capability(pdev, PCI_CAP_ID_PM); | ||
3399 | if (pm_cap == 0) { | ||
3400 | printk(KERN_ERR PFX "Cannot find PowerManagement capability, " | ||
3401 | "aborting.\n"); | ||
3402 | err = -EIO; | ||
3403 | goto err_out_free_regions; | ||
3404 | } | ||
3405 | |||
3406 | if (sizeof(dma_addr_t) > sizeof(u32) && | 3494 | if (sizeof(dma_addr_t) > sizeof(u32) && |
3407 | !(err = pci_set_dma_mask(pdev, DMA_64BIT_MASK))) { | 3495 | !(err = pci_set_dma_mask(pdev, DMA_64BIT_MASK))) { |
3408 | using_dac = 1; | 3496 | using_dac = 1; |
3409 | err = pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK); | 3497 | err = pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK); |
3410 | if (err < 0) { | 3498 | if (err < 0) { |
3411 | printk(KERN_ERR PFX "%s unable to obtain 64 bit DMA " | 3499 | dev_err(&pdev->dev, "unable to obtain 64 bit DMA " |
3412 | "for consistent allocations\n", pci_name(pdev)); | 3500 | "for consistent allocations\n"); |
3413 | goto err_out_free_regions; | 3501 | goto err_out_free_regions; |
3414 | } | 3502 | } |
3415 | |||
3416 | } else { | 3503 | } else { |
3417 | err = pci_set_dma_mask(pdev, DMA_32BIT_MASK); | 3504 | err = pci_set_dma_mask(pdev, DMA_32BIT_MASK); |
3418 | if (err) { | 3505 | if (err) { |
3419 | printk(KERN_ERR PFX "%s no usable DMA configuration\n", | 3506 | dev_err(&pdev->dev, "no usable DMA configuration\n"); |
3420 | pci_name(pdev)); | ||
3421 | goto err_out_free_regions; | 3507 | goto err_out_free_regions; |
3422 | } | 3508 | } |
3423 | } | 3509 | } |
3424 | 3510 | ||
3511 | wol_default = pci_wake_enabled(pdev) ? WAKE_MAGIC : 0; | ||
3512 | |||
3425 | err = -ENOMEM; | 3513 | err = -ENOMEM; |
3426 | hw = kzalloc(sizeof(*hw), GFP_KERNEL); | 3514 | hw = kzalloc(sizeof(*hw), GFP_KERNEL); |
3427 | if (!hw) { | 3515 | if (!hw) { |
3428 | printk(KERN_ERR PFX "%s: cannot allocate hardware struct\n", | 3516 | dev_err(&pdev->dev, "cannot allocate hardware struct\n"); |
3429 | pci_name(pdev)); | ||
3430 | goto err_out_free_regions; | 3517 | goto err_out_free_regions; |
3431 | } | 3518 | } |
3432 | 3519 | ||
@@ -3434,11 +3521,9 @@ static int __devinit sky2_probe(struct pci_dev *pdev, | |||
3434 | 3521 | ||
3435 | hw->regs = ioremap_nocache(pci_resource_start(pdev, 0), 0x4000); | 3522 | hw->regs = ioremap_nocache(pci_resource_start(pdev, 0), 0x4000); |
3436 | if (!hw->regs) { | 3523 | if (!hw->regs) { |
3437 | printk(KERN_ERR PFX "%s: cannot map device registers\n", | 3524 | dev_err(&pdev->dev, "cannot map device registers\n"); |
3438 | pci_name(pdev)); | ||
3439 | goto err_out_free_hw; | 3525 | goto err_out_free_hw; |
3440 | } | 3526 | } |
3441 | hw->pm_cap = pm_cap; | ||
3442 | 3527 | ||
3443 | #ifdef __BIG_ENDIAN | 3528 | #ifdef __BIG_ENDIAN |
3444 | /* The sk98lin vendor driver uses hardware byte swapping but | 3529 | /* The sk98lin vendor driver uses hardware byte swapping but |
@@ -3458,18 +3543,22 @@ static int __devinit sky2_probe(struct pci_dev *pdev, | |||
3458 | if (!hw->st_le) | 3543 | if (!hw->st_le) |
3459 | goto err_out_iounmap; | 3544 | goto err_out_iounmap; |
3460 | 3545 | ||
3461 | err = sky2_reset(hw); | 3546 | err = sky2_init(hw); |
3462 | if (err) | 3547 | if (err) |
3463 | goto err_out_iounmap; | 3548 | goto err_out_iounmap; |
3464 | 3549 | ||
3465 | printk(KERN_INFO PFX "v%s addr 0x%llx irq %d Yukon-%s (0x%x) rev %d\n", | 3550 | dev_info(&pdev->dev, "v%s addr 0x%llx irq %d Yukon-%s (0x%x) rev %d\n", |
3466 | DRV_VERSION, (unsigned long long)pci_resource_start(pdev, 0), | 3551 | DRV_VERSION, (unsigned long long)pci_resource_start(pdev, 0), |
3467 | pdev->irq, yukon2_name[hw->chip_id - CHIP_ID_YUKON_XL], | 3552 | pdev->irq, yukon2_name[hw->chip_id - CHIP_ID_YUKON_XL], |
3468 | hw->chip_id, hw->chip_rev); | 3553 | hw->chip_id, hw->chip_rev); |
3469 | 3554 | ||
3470 | dev = sky2_init_netdev(hw, 0, using_dac); | 3555 | sky2_reset(hw); |
3471 | if (!dev) | 3556 | |
3557 | dev = sky2_init_netdev(hw, 0, using_dac, wol_default); | ||
3558 | if (!dev) { | ||
3559 | err = -ENOMEM; | ||
3472 | goto err_out_free_pci; | 3560 | goto err_out_free_pci; |
3561 | } | ||
3473 | 3562 | ||
3474 | if (!disable_msi && pci_enable_msi(pdev) == 0) { | 3563 | if (!disable_msi && pci_enable_msi(pdev) == 0) { |
3475 | err = sky2_test_msi(hw); | 3564 | err = sky2_test_msi(hw); |
@@ -3481,32 +3570,33 @@ static int __devinit sky2_probe(struct pci_dev *pdev, | |||
3481 | 3570 | ||
3482 | err = register_netdev(dev); | 3571 | err = register_netdev(dev); |
3483 | if (err) { | 3572 | if (err) { |
3484 | printk(KERN_ERR PFX "%s: cannot register net device\n", | 3573 | dev_err(&pdev->dev, "cannot register net device\n"); |
3485 | pci_name(pdev)); | ||
3486 | goto err_out_free_netdev; | 3574 | goto err_out_free_netdev; |
3487 | } | 3575 | } |
3488 | 3576 | ||
3489 | err = request_irq(pdev->irq, sky2_intr, hw->msi ? 0 : IRQF_SHARED, | 3577 | err = request_irq(pdev->irq, sky2_intr, hw->msi ? 0 : IRQF_SHARED, |
3490 | dev->name, hw); | 3578 | dev->name, hw); |
3491 | if (err) { | 3579 | if (err) { |
3492 | printk(KERN_ERR PFX "%s: cannot assign irq %d\n", | 3580 | dev_err(&pdev->dev, "cannot assign irq %d\n", pdev->irq); |
3493 | pci_name(pdev), pdev->irq); | ||
3494 | goto err_out_unregister; | 3581 | goto err_out_unregister; |
3495 | } | 3582 | } |
3496 | sky2_write32(hw, B0_IMSK, Y2_IS_BASE); | 3583 | sky2_write32(hw, B0_IMSK, Y2_IS_BASE); |
3497 | 3584 | ||
3498 | sky2_show_addr(dev); | 3585 | sky2_show_addr(dev); |
3499 | 3586 | ||
3500 | if (hw->ports > 1 && (dev1 = sky2_init_netdev(hw, 1, using_dac))) { | 3587 | if (hw->ports > 1) { |
3501 | if (register_netdev(dev1) == 0) | 3588 | struct net_device *dev1; |
3502 | sky2_show_addr(dev1); | 3589 | |
3503 | else { | 3590 | dev1 = sky2_init_netdev(hw, 1, using_dac, wol_default); |
3504 | /* Failure to register second port need not be fatal */ | 3591 | if (!dev1) |
3505 | printk(KERN_WARNING PFX | 3592 | dev_warn(&pdev->dev, "allocation for second device failed\n"); |
3506 | "register of second port failed\n"); | 3593 | else if ((err = register_netdev(dev1))) { |
3594 | dev_warn(&pdev->dev, | ||
3595 | "register of second port failed (%d)\n", err); | ||
3507 | hw->dev[1] = NULL; | 3596 | hw->dev[1] = NULL; |
3508 | free_netdev(dev1); | 3597 | free_netdev(dev1); |
3509 | } | 3598 | } else |
3599 | sky2_show_addr(dev1); | ||
3510 | } | 3600 | } |
3511 | 3601 | ||
3512 | setup_timer(&hw->idle_timer, sky2_idle, (unsigned long) hw); | 3602 | setup_timer(&hw->idle_timer, sky2_idle, (unsigned long) hw); |
@@ -3555,7 +3645,8 @@ static void __devexit sky2_remove(struct pci_dev *pdev) | |||
3555 | unregister_netdev(dev1); | 3645 | unregister_netdev(dev1); |
3556 | unregister_netdev(dev0); | 3646 | unregister_netdev(dev0); |
3557 | 3647 | ||
3558 | sky2_set_power_state(hw, PCI_D3hot); | 3648 | sky2_power_aux(hw); |
3649 | |||
3559 | sky2_write16(hw, B0_Y2LED, LED_STAT_OFF); | 3650 | sky2_write16(hw, B0_Y2LED, LED_STAT_OFF); |
3560 | sky2_write8(hw, B0_CTST, CS_RST_SET); | 3651 | sky2_write8(hw, B0_CTST, CS_RST_SET); |
3561 | sky2_read8(hw, B0_CTST); | 3652 | sky2_read8(hw, B0_CTST); |
@@ -3580,27 +3671,31 @@ static void __devexit sky2_remove(struct pci_dev *pdev) | |||
3580 | static int sky2_suspend(struct pci_dev *pdev, pm_message_t state) | 3671 | static int sky2_suspend(struct pci_dev *pdev, pm_message_t state) |
3581 | { | 3672 | { |
3582 | struct sky2_hw *hw = pci_get_drvdata(pdev); | 3673 | struct sky2_hw *hw = pci_get_drvdata(pdev); |
3583 | int i; | 3674 | int i, wol = 0; |
3584 | pci_power_t pstate = pci_choose_state(pdev, state); | ||
3585 | |||
3586 | if (!(pstate == PCI_D3hot || pstate == PCI_D3cold)) | ||
3587 | return -EINVAL; | ||
3588 | 3675 | ||
3589 | del_timer_sync(&hw->idle_timer); | 3676 | del_timer_sync(&hw->idle_timer); |
3590 | netif_poll_disable(hw->dev[0]); | 3677 | netif_poll_disable(hw->dev[0]); |
3591 | 3678 | ||
3592 | for (i = 0; i < hw->ports; i++) { | 3679 | for (i = 0; i < hw->ports; i++) { |
3593 | struct net_device *dev = hw->dev[i]; | 3680 | struct net_device *dev = hw->dev[i]; |
3681 | struct sky2_port *sky2 = netdev_priv(dev); | ||
3594 | 3682 | ||
3595 | if (netif_running(dev)) { | 3683 | if (netif_running(dev)) |
3596 | sky2_down(dev); | 3684 | sky2_down(dev); |
3597 | netif_device_detach(dev); | 3685 | |
3598 | } | 3686 | if (sky2->wol) |
3687 | sky2_wol_init(sky2); | ||
3688 | |||
3689 | wol |= sky2->wol; | ||
3599 | } | 3690 | } |
3600 | 3691 | ||
3601 | sky2_write32(hw, B0_IMSK, 0); | 3692 | sky2_write32(hw, B0_IMSK, 0); |
3693 | sky2_power_aux(hw); | ||
3694 | |||
3602 | pci_save_state(pdev); | 3695 | pci_save_state(pdev); |
3603 | sky2_set_power_state(hw, pstate); | 3696 | pci_enable_wake(pdev, pci_choose_state(pdev, state), wol); |
3697 | pci_set_power_state(pdev, pci_choose_state(pdev, state)); | ||
3698 | |||
3604 | return 0; | 3699 | return 0; |
3605 | } | 3700 | } |
3606 | 3701 | ||
@@ -3609,21 +3704,22 @@ static int sky2_resume(struct pci_dev *pdev) | |||
3609 | struct sky2_hw *hw = pci_get_drvdata(pdev); | 3704 | struct sky2_hw *hw = pci_get_drvdata(pdev); |
3610 | int i, err; | 3705 | int i, err; |
3611 | 3706 | ||
3612 | pci_restore_state(pdev); | 3707 | err = pci_set_power_state(pdev, PCI_D0); |
3613 | pci_enable_wake(pdev, PCI_D0, 0); | 3708 | if (err) |
3614 | sky2_set_power_state(hw, PCI_D0); | 3709 | goto out; |
3615 | 3710 | ||
3616 | err = sky2_reset(hw); | 3711 | err = pci_restore_state(pdev); |
3617 | if (err) | 3712 | if (err) |
3618 | goto out; | 3713 | goto out; |
3619 | 3714 | ||
3715 | pci_enable_wake(pdev, PCI_D0, 0); | ||
3716 | sky2_reset(hw); | ||
3717 | |||
3620 | sky2_write32(hw, B0_IMSK, Y2_IS_BASE); | 3718 | sky2_write32(hw, B0_IMSK, Y2_IS_BASE); |
3621 | 3719 | ||
3622 | for (i = 0; i < hw->ports; i++) { | 3720 | for (i = 0; i < hw->ports; i++) { |
3623 | struct net_device *dev = hw->dev[i]; | 3721 | struct net_device *dev = hw->dev[i]; |
3624 | if (netif_running(dev)) { | 3722 | if (netif_running(dev)) { |
3625 | netif_device_attach(dev); | ||
3626 | |||
3627 | err = sky2_up(dev); | 3723 | err = sky2_up(dev); |
3628 | if (err) { | 3724 | if (err) { |
3629 | printk(KERN_ERR PFX "%s: could not up: %d\n", | 3725 | printk(KERN_ERR PFX "%s: could not up: %d\n", |
@@ -3636,11 +3732,43 @@ static int sky2_resume(struct pci_dev *pdev) | |||
3636 | 3732 | ||
3637 | netif_poll_enable(hw->dev[0]); | 3733 | netif_poll_enable(hw->dev[0]); |
3638 | sky2_idle_start(hw); | 3734 | sky2_idle_start(hw); |
3735 | return 0; | ||
3639 | out: | 3736 | out: |
3737 | dev_err(&pdev->dev, "resume failed (%d)\n", err); | ||
3738 | pci_disable_device(pdev); | ||
3640 | return err; | 3739 | return err; |
3641 | } | 3740 | } |
3642 | #endif | 3741 | #endif |
3643 | 3742 | ||
3743 | static void sky2_shutdown(struct pci_dev *pdev) | ||
3744 | { | ||
3745 | struct sky2_hw *hw = pci_get_drvdata(pdev); | ||
3746 | int i, wol = 0; | ||
3747 | |||
3748 | del_timer_sync(&hw->idle_timer); | ||
3749 | netif_poll_disable(hw->dev[0]); | ||
3750 | |||
3751 | for (i = 0; i < hw->ports; i++) { | ||
3752 | struct net_device *dev = hw->dev[i]; | ||
3753 | struct sky2_port *sky2 = netdev_priv(dev); | ||
3754 | |||
3755 | if (sky2->wol) { | ||
3756 | wol = 1; | ||
3757 | sky2_wol_init(sky2); | ||
3758 | } | ||
3759 | } | ||
3760 | |||
3761 | if (wol) | ||
3762 | sky2_power_aux(hw); | ||
3763 | |||
3764 | pci_enable_wake(pdev, PCI_D3hot, wol); | ||
3765 | pci_enable_wake(pdev, PCI_D3cold, wol); | ||
3766 | |||
3767 | pci_disable_device(pdev); | ||
3768 | pci_set_power_state(pdev, PCI_D3hot); | ||
3769 | |||
3770 | } | ||
3771 | |||
3644 | static struct pci_driver sky2_driver = { | 3772 | static struct pci_driver sky2_driver = { |
3645 | .name = DRV_NAME, | 3773 | .name = DRV_NAME, |
3646 | .id_table = sky2_id_table, | 3774 | .id_table = sky2_id_table, |
@@ -3650,6 +3778,7 @@ static struct pci_driver sky2_driver = { | |||
3650 | .suspend = sky2_suspend, | 3778 | .suspend = sky2_suspend, |
3651 | .resume = sky2_resume, | 3779 | .resume = sky2_resume, |
3652 | #endif | 3780 | #endif |
3781 | .shutdown = sky2_shutdown, | ||
3653 | }; | 3782 | }; |
3654 | 3783 | ||
3655 | static int __init sky2_init_module(void) | 3784 | static int __init sky2_init_module(void) |