diff options
Diffstat (limited to 'drivers/net/sky2.c')
-rw-r--r-- | drivers/net/sky2.c | 408 |
1 files changed, 293 insertions, 115 deletions
diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index 5d812de65d90..162489b9f599 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c | |||
@@ -51,7 +51,7 @@ | |||
51 | #include "sky2.h" | 51 | #include "sky2.h" |
52 | 52 | ||
53 | #define DRV_NAME "sky2" | 53 | #define DRV_NAME "sky2" |
54 | #define DRV_VERSION "1.17" | 54 | #define DRV_VERSION "1.18" |
55 | #define PFX DRV_NAME " " | 55 | #define PFX DRV_NAME " " |
56 | 56 | ||
57 | /* | 57 | /* |
@@ -118,12 +118,15 @@ static const struct pci_device_id sky2_id_table[] = { | |||
118 | { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4351) }, /* 88E8036 */ | 118 | { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4351) }, /* 88E8036 */ |
119 | { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4352) }, /* 88E8038 */ | 119 | { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4352) }, /* 88E8038 */ |
120 | { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4353) }, /* 88E8039 */ | 120 | { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4353) }, /* 88E8039 */ |
121 | { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4354) }, /* 88E8040 */ | ||
121 | { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4356) }, /* 88EC033 */ | 122 | { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4356) }, /* 88EC033 */ |
123 | { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x435A) }, /* 88E8048 */ | ||
122 | { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4360) }, /* 88E8052 */ | 124 | { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4360) }, /* 88E8052 */ |
123 | { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4361) }, /* 88E8050 */ | 125 | { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4361) }, /* 88E8050 */ |
124 | { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4362) }, /* 88E8053 */ | 126 | { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4362) }, /* 88E8053 */ |
125 | { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4363) }, /* 88E8055 */ | 127 | { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4363) }, /* 88E8055 */ |
126 | { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4364) }, /* 88E8056 */ | 128 | { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4364) }, /* 88E8056 */ |
129 | { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4365) }, /* 88E8070 */ | ||
127 | { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4366) }, /* 88EC036 */ | 130 | { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4366) }, /* 88EC036 */ |
128 | { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4367) }, /* 88EC032 */ | 131 | { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4367) }, /* 88EC032 */ |
129 | { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4368) }, /* 88EC034 */ | 132 | { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4368) }, /* 88EC034 */ |
@@ -147,6 +150,7 @@ static const char *yukon2_name[] = { | |||
147 | "Extreme", /* 0xb5 */ | 150 | "Extreme", /* 0xb5 */ |
148 | "EC", /* 0xb6 */ | 151 | "EC", /* 0xb6 */ |
149 | "FE", /* 0xb7 */ | 152 | "FE", /* 0xb7 */ |
153 | "FE+", /* 0xb8 */ | ||
150 | }; | 154 | }; |
151 | 155 | ||
152 | static void sky2_set_multicast(struct net_device *dev); | 156 | static void sky2_set_multicast(struct net_device *dev); |
@@ -217,8 +221,7 @@ static void sky2_power_on(struct sky2_hw *hw) | |||
217 | else | 221 | else |
218 | sky2_write8(hw, B2_Y2_CLK_GATE, 0); | 222 | sky2_write8(hw, B2_Y2_CLK_GATE, 0); |
219 | 223 | ||
220 | if (hw->chip_id == CHIP_ID_YUKON_EC_U || | 224 | if (hw->flags & SKY2_HW_ADV_POWER_CTL) { |
221 | hw->chip_id == CHIP_ID_YUKON_EX) { | ||
222 | u32 reg; | 225 | u32 reg; |
223 | 226 | ||
224 | sky2_pci_write32(hw, PCI_DEV_REG3, 0); | 227 | sky2_pci_write32(hw, PCI_DEV_REG3, 0); |
@@ -311,10 +314,8 @@ static void sky2_phy_init(struct sky2_hw *hw, unsigned port) | |||
311 | struct sky2_port *sky2 = netdev_priv(hw->dev[port]); | 314 | struct sky2_port *sky2 = netdev_priv(hw->dev[port]); |
312 | u16 ctrl, ct1000, adv, pg, ledctrl, ledover, reg; | 315 | u16 ctrl, ct1000, adv, pg, ledctrl, ledover, reg; |
313 | 316 | ||
314 | if (sky2->autoneg == AUTONEG_ENABLE | 317 | if (sky2->autoneg == AUTONEG_ENABLE && |
315 | && !(hw->chip_id == CHIP_ID_YUKON_XL | 318 | !(hw->flags & SKY2_HW_NEWER_PHY)) { |
316 | || hw->chip_id == CHIP_ID_YUKON_EC_U | ||
317 | || hw->chip_id == CHIP_ID_YUKON_EX)) { | ||
318 | u16 ectrl = gm_phy_read(hw, port, PHY_MARV_EXT_CTRL); | 319 | u16 ectrl = gm_phy_read(hw, port, PHY_MARV_EXT_CTRL); |
319 | 320 | ||
320 | ectrl &= ~(PHY_M_EC_M_DSC_MSK | PHY_M_EC_S_DSC_MSK | | 321 | ectrl &= ~(PHY_M_EC_M_DSC_MSK | PHY_M_EC_S_DSC_MSK | |
@@ -334,9 +335,19 @@ static void sky2_phy_init(struct sky2_hw *hw, unsigned port) | |||
334 | 335 | ||
335 | ctrl = gm_phy_read(hw, port, PHY_MARV_PHY_CTRL); | 336 | ctrl = gm_phy_read(hw, port, PHY_MARV_PHY_CTRL); |
336 | if (sky2_is_copper(hw)) { | 337 | if (sky2_is_copper(hw)) { |
337 | if (hw->chip_id == CHIP_ID_YUKON_FE) { | 338 | if (!(hw->flags & SKY2_HW_GIGABIT)) { |
338 | /* enable automatic crossover */ | 339 | /* enable automatic crossover */ |
339 | ctrl |= PHY_M_PC_MDI_XMODE(PHY_M_PC_ENA_AUTO) >> 1; | 340 | ctrl |= PHY_M_PC_MDI_XMODE(PHY_M_PC_ENA_AUTO) >> 1; |
341 | |||
342 | if (hw->chip_id == CHIP_ID_YUKON_FE_P && | ||
343 | hw->chip_rev == CHIP_REV_YU_FE2_A0) { | ||
344 | u16 spec; | ||
345 | |||
346 | /* Enable Class A driver for FE+ A0 */ | ||
347 | spec = gm_phy_read(hw, port, PHY_MARV_FE_SPEC_2); | ||
348 | spec |= PHY_M_FESC_SEL_CL_A; | ||
349 | gm_phy_write(hw, port, PHY_MARV_FE_SPEC_2, spec); | ||
350 | } | ||
340 | } else { | 351 | } else { |
341 | /* disable energy detect */ | 352 | /* disable energy detect */ |
342 | ctrl &= ~PHY_M_PC_EN_DET_MSK; | 353 | ctrl &= ~PHY_M_PC_EN_DET_MSK; |
@@ -346,9 +357,7 @@ static void sky2_phy_init(struct sky2_hw *hw, unsigned port) | |||
346 | 357 | ||
347 | /* downshift on PHY 88E1112 and 88E1149 is changed */ | 358 | /* downshift on PHY 88E1112 and 88E1149 is changed */ |
348 | if (sky2->autoneg == AUTONEG_ENABLE | 359 | if (sky2->autoneg == AUTONEG_ENABLE |
349 | && (hw->chip_id == CHIP_ID_YUKON_XL | 360 | && (hw->flags & SKY2_HW_NEWER_PHY)) { |
350 | || hw->chip_id == CHIP_ID_YUKON_EC_U | ||
351 | || hw->chip_id == CHIP_ID_YUKON_EX)) { | ||
352 | /* set downshift counter to 3x and enable downshift */ | 361 | /* set downshift counter to 3x and enable downshift */ |
353 | ctrl &= ~PHY_M_PC_DSC_MSK; | 362 | ctrl &= ~PHY_M_PC_DSC_MSK; |
354 | ctrl |= PHY_M_PC_DSC(2) | PHY_M_PC_DOWN_S_ENA; | 363 | ctrl |= PHY_M_PC_DSC(2) | PHY_M_PC_DOWN_S_ENA; |
@@ -364,7 +373,7 @@ static void sky2_phy_init(struct sky2_hw *hw, unsigned port) | |||
364 | gm_phy_write(hw, port, PHY_MARV_PHY_CTRL, ctrl); | 373 | gm_phy_write(hw, port, PHY_MARV_PHY_CTRL, ctrl); |
365 | 374 | ||
366 | /* special setup for PHY 88E1112 Fiber */ | 375 | /* special setup for PHY 88E1112 Fiber */ |
367 | if (hw->chip_id == CHIP_ID_YUKON_XL && !sky2_is_copper(hw)) { | 376 | if (hw->chip_id == CHIP_ID_YUKON_XL && (hw->flags & SKY2_HW_FIBRE_PHY)) { |
368 | pg = gm_phy_read(hw, port, PHY_MARV_EXT_ADR); | 377 | pg = gm_phy_read(hw, port, PHY_MARV_EXT_ADR); |
369 | 378 | ||
370 | /* Fiber: select 1000BASE-X only mode MAC Specific Ctrl Reg. */ | 379 | /* Fiber: select 1000BASE-X only mode MAC Specific Ctrl Reg. */ |
@@ -455,7 +464,7 @@ static void sky2_phy_init(struct sky2_hw *hw, unsigned port) | |||
455 | 464 | ||
456 | gma_write16(hw, port, GM_GP_CTRL, reg); | 465 | gma_write16(hw, port, GM_GP_CTRL, reg); |
457 | 466 | ||
458 | if (hw->chip_id != CHIP_ID_YUKON_FE) | 467 | if (hw->flags & SKY2_HW_GIGABIT) |
459 | gm_phy_write(hw, port, PHY_MARV_1000T_CTRL, ct1000); | 468 | gm_phy_write(hw, port, PHY_MARV_1000T_CTRL, ct1000); |
460 | 469 | ||
461 | gm_phy_write(hw, port, PHY_MARV_AUNE_ADV, adv); | 470 | gm_phy_write(hw, port, PHY_MARV_AUNE_ADV, adv); |
@@ -479,6 +488,23 @@ static void sky2_phy_init(struct sky2_hw *hw, unsigned port) | |||
479 | gm_phy_write(hw, port, PHY_MARV_FE_LED_PAR, ctrl); | 488 | gm_phy_write(hw, port, PHY_MARV_FE_LED_PAR, ctrl); |
480 | break; | 489 | break; |
481 | 490 | ||
491 | case CHIP_ID_YUKON_FE_P: | ||
492 | /* Enable Link Partner Next Page */ | ||
493 | ctrl = gm_phy_read(hw, port, PHY_MARV_PHY_CTRL); | ||
494 | ctrl |= PHY_M_PC_ENA_LIP_NP; | ||
495 | |||
496 | /* disable Energy Detect and enable scrambler */ | ||
497 | ctrl &= ~(PHY_M_PC_ENA_ENE_DT | PHY_M_PC_DIS_SCRAMB); | ||
498 | gm_phy_write(hw, port, PHY_MARV_PHY_CTRL, ctrl); | ||
499 | |||
500 | /* set LED2 -> ACT, LED1 -> LINK, LED0 -> SPEED */ | ||
501 | ctrl = PHY_M_FELP_LED2_CTRL(LED_PAR_CTRL_ACT_BL) | | ||
502 | PHY_M_FELP_LED1_CTRL(LED_PAR_CTRL_LINK) | | ||
503 | PHY_M_FELP_LED0_CTRL(LED_PAR_CTRL_SPEED); | ||
504 | |||
505 | gm_phy_write(hw, port, PHY_MARV_FE_LED_PAR, ctrl); | ||
506 | break; | ||
507 | |||
482 | case CHIP_ID_YUKON_XL: | 508 | case CHIP_ID_YUKON_XL: |
483 | pg = gm_phy_read(hw, port, PHY_MARV_EXT_ADR); | 509 | pg = gm_phy_read(hw, port, PHY_MARV_EXT_ADR); |
484 | 510 | ||
@@ -548,7 +574,13 @@ static void sky2_phy_init(struct sky2_hw *hw, unsigned port) | |||
548 | 574 | ||
549 | /* set page register to 0 */ | 575 | /* set page register to 0 */ |
550 | gm_phy_write(hw, port, PHY_MARV_EXT_ADR, 0); | 576 | gm_phy_write(hw, port, PHY_MARV_EXT_ADR, 0); |
577 | } else if (hw->chip_id == CHIP_ID_YUKON_FE_P && | ||
578 | hw->chip_rev == CHIP_REV_YU_FE2_A0) { | ||
579 | /* apply workaround for integrated resistors calibration */ | ||
580 | gm_phy_write(hw, port, PHY_MARV_PAGE_ADDR, 17); | ||
581 | gm_phy_write(hw, port, PHY_MARV_PAGE_DATA, 0x3f60); | ||
551 | } else if (hw->chip_id != CHIP_ID_YUKON_EX) { | 582 | } else if (hw->chip_id != CHIP_ID_YUKON_EX) { |
583 | /* no effect on Yukon-XL */ | ||
552 | gm_phy_write(hw, port, PHY_MARV_LED_CTRL, ledctrl); | 584 | gm_phy_write(hw, port, PHY_MARV_LED_CTRL, ledctrl); |
553 | 585 | ||
554 | if (sky2->autoneg == AUTONEG_DISABLE || sky2->speed == SPEED_100) { | 586 | if (sky2->autoneg == AUTONEG_DISABLE || sky2->speed == SPEED_100) { |
@@ -669,25 +701,25 @@ static void sky2_wol_init(struct sky2_port *sky2) | |||
669 | 701 | ||
670 | static void sky2_set_tx_stfwd(struct sky2_hw *hw, unsigned port) | 702 | static void sky2_set_tx_stfwd(struct sky2_hw *hw, unsigned port) |
671 | { | 703 | { |
672 | if (hw->chip_id == CHIP_ID_YUKON_EX && hw->chip_rev != CHIP_REV_YU_EX_A0) { | 704 | struct net_device *dev = hw->dev[port]; |
705 | |||
706 | if (dev->mtu <= ETH_DATA_LEN) | ||
673 | sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T), | 707 | sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T), |
674 | TX_STFW_ENA | | 708 | TX_JUMBO_DIS | TX_STFW_ENA); |
675 | (hw->dev[port]->mtu > ETH_DATA_LEN) ? TX_JUMBO_ENA : TX_JUMBO_DIS); | ||
676 | } else { | ||
677 | if (hw->dev[port]->mtu > ETH_DATA_LEN) { | ||
678 | /* set Tx GMAC FIFO Almost Empty Threshold */ | ||
679 | sky2_write32(hw, SK_REG(port, TX_GMF_AE_THR), | ||
680 | (ECU_JUMBO_WM << 16) | ECU_AE_THR); | ||
681 | 709 | ||
682 | sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T), | 710 | else if (hw->chip_id != CHIP_ID_YUKON_EC_U) |
683 | TX_JUMBO_ENA | TX_STFW_DIS); | 711 | sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T), |
712 | TX_STFW_ENA | TX_JUMBO_ENA); | ||
713 | else { | ||
714 | /* set Tx GMAC FIFO Almost Empty Threshold */ | ||
715 | sky2_write32(hw, SK_REG(port, TX_GMF_AE_THR), | ||
716 | (ECU_JUMBO_WM << 16) | ECU_AE_THR); | ||
684 | 717 | ||
685 | /* Can't do offload because of lack of store/forward */ | 718 | sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T), |
686 | hw->dev[port]->features &= ~(NETIF_F_TSO | NETIF_F_SG | 719 | TX_JUMBO_ENA | TX_STFW_DIS); |
687 | | NETIF_F_ALL_CSUM); | 720 | |
688 | } else | 721 | /* Can't do offload because of lack of store/forward */ |
689 | sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T), | 722 | dev->features &= ~(NETIF_F_TSO | NETIF_F_SG | NETIF_F_ALL_CSUM); |
690 | TX_JUMBO_DIS | TX_STFW_ENA); | ||
691 | } | 723 | } |
692 | } | 724 | } |
693 | 725 | ||
@@ -773,7 +805,8 @@ static void sky2_mac_init(struct sky2_hw *hw, unsigned port) | |||
773 | /* Configure Rx MAC FIFO */ | 805 | /* Configure Rx MAC FIFO */ |
774 | sky2_write8(hw, SK_REG(port, RX_GMF_CTRL_T), GMF_RST_CLR); | 806 | sky2_write8(hw, SK_REG(port, RX_GMF_CTRL_T), GMF_RST_CLR); |
775 | rx_reg = GMF_OPER_ON | GMF_RX_F_FL_ON; | 807 | rx_reg = GMF_OPER_ON | GMF_RX_F_FL_ON; |
776 | if (hw->chip_id == CHIP_ID_YUKON_EX) | 808 | if (hw->chip_id == CHIP_ID_YUKON_EX || |
809 | hw->chip_id == CHIP_ID_YUKON_FE_P) | ||
777 | rx_reg |= GMF_RX_OVER_ON; | 810 | rx_reg |= GMF_RX_OVER_ON; |
778 | 811 | ||
779 | sky2_write32(hw, SK_REG(port, RX_GMF_CTRL_T), rx_reg); | 812 | sky2_write32(hw, SK_REG(port, RX_GMF_CTRL_T), rx_reg); |
@@ -782,13 +815,19 @@ static void sky2_mac_init(struct sky2_hw *hw, unsigned port) | |||
782 | sky2_write16(hw, SK_REG(port, RX_GMF_FL_MSK), GMR_FS_ANY_ERR); | 815 | sky2_write16(hw, SK_REG(port, RX_GMF_FL_MSK), GMR_FS_ANY_ERR); |
783 | 816 | ||
784 | /* Set threshold to 0xa (64 bytes) + 1 to workaround pause bug */ | 817 | /* Set threshold to 0xa (64 bytes) + 1 to workaround pause bug */ |
785 | sky2_write16(hw, SK_REG(port, RX_GMF_FL_THR), RX_GMF_FL_THR_DEF+1); | 818 | reg = RX_GMF_FL_THR_DEF + 1; |
819 | /* Another magic mystery workaround from sk98lin */ | ||
820 | if (hw->chip_id == CHIP_ID_YUKON_FE_P && | ||
821 | hw->chip_rev == CHIP_REV_YU_FE2_A0) | ||
822 | reg = 0x178; | ||
823 | sky2_write16(hw, SK_REG(port, RX_GMF_FL_THR), reg); | ||
786 | 824 | ||
787 | /* Configure Tx MAC FIFO */ | 825 | /* Configure Tx MAC FIFO */ |
788 | sky2_write8(hw, SK_REG(port, TX_GMF_CTRL_T), GMF_RST_CLR); | 826 | sky2_write8(hw, SK_REG(port, TX_GMF_CTRL_T), GMF_RST_CLR); |
789 | sky2_write16(hw, SK_REG(port, TX_GMF_CTRL_T), GMF_OPER_ON); | 827 | sky2_write16(hw, SK_REG(port, TX_GMF_CTRL_T), GMF_OPER_ON); |
790 | 828 | ||
791 | if (hw->chip_id == CHIP_ID_YUKON_EC_U || hw->chip_id == CHIP_ID_YUKON_EX) { | 829 | /* On chips without ram buffer, pause is controled by MAC level */ |
830 | if (sky2_read8(hw, B2_E_0) == 0) { | ||
792 | sky2_write8(hw, SK_REG(port, RX_GMF_LP_THR), 768/8); | 831 | sky2_write8(hw, SK_REG(port, RX_GMF_LP_THR), 768/8); |
793 | sky2_write8(hw, SK_REG(port, RX_GMF_UP_THR), 1024/8); | 832 | sky2_write8(hw, SK_REG(port, RX_GMF_UP_THR), 1024/8); |
794 | 833 | ||
@@ -871,6 +910,20 @@ static inline struct sky2_tx_le *get_tx_le(struct sky2_port *sky2) | |||
871 | return le; | 910 | return le; |
872 | } | 911 | } |
873 | 912 | ||
913 | static void tx_init(struct sky2_port *sky2) | ||
914 | { | ||
915 | struct sky2_tx_le *le; | ||
916 | |||
917 | sky2->tx_prod = sky2->tx_cons = 0; | ||
918 | sky2->tx_tcpsum = 0; | ||
919 | sky2->tx_last_mss = 0; | ||
920 | |||
921 | le = get_tx_le(sky2); | ||
922 | le->addr = 0; | ||
923 | le->opcode = OP_ADDR64 | HW_OWNER; | ||
924 | sky2->tx_addr64 = 0; | ||
925 | } | ||
926 | |||
874 | static inline struct tx_ring_info *tx_le_re(struct sky2_port *sky2, | 927 | static inline struct tx_ring_info *tx_le_re(struct sky2_port *sky2, |
875 | struct sky2_tx_le *le) | 928 | struct sky2_tx_le *le) |
876 | { | 929 | { |
@@ -967,19 +1020,15 @@ static void sky2_rx_unmap_skb(struct pci_dev *pdev, struct rx_ring_info *re) | |||
967 | */ | 1020 | */ |
968 | static void rx_set_checksum(struct sky2_port *sky2) | 1021 | static void rx_set_checksum(struct sky2_port *sky2) |
969 | { | 1022 | { |
970 | struct sky2_rx_le *le; | 1023 | struct sky2_rx_le *le = sky2_next_rx(sky2); |
971 | |||
972 | if (sky2->hw->chip_id != CHIP_ID_YUKON_EX) { | ||
973 | le = sky2_next_rx(sky2); | ||
974 | le->addr = cpu_to_le32((ETH_HLEN << 16) | ETH_HLEN); | ||
975 | le->ctrl = 0; | ||
976 | le->opcode = OP_TCPSTART | HW_OWNER; | ||
977 | 1024 | ||
978 | sky2_write32(sky2->hw, | 1025 | le->addr = cpu_to_le32((ETH_HLEN << 16) | ETH_HLEN); |
979 | Q_ADDR(rxqaddr[sky2->port], Q_CSR), | 1026 | le->ctrl = 0; |
980 | sky2->rx_csum ? BMU_ENA_RX_CHKSUM : BMU_DIS_RX_CHKSUM); | 1027 | le->opcode = OP_TCPSTART | HW_OWNER; |
981 | } | ||
982 | 1028 | ||
1029 | sky2_write32(sky2->hw, | ||
1030 | Q_ADDR(rxqaddr[sky2->port], Q_CSR), | ||
1031 | sky2->rx_csum ? BMU_ENA_RX_CHKSUM : BMU_DIS_RX_CHKSUM); | ||
983 | } | 1032 | } |
984 | 1033 | ||
985 | /* | 1034 | /* |
@@ -1175,7 +1224,8 @@ static int sky2_rx_start(struct sky2_port *sky2) | |||
1175 | 1224 | ||
1176 | sky2_prefetch_init(hw, rxq, sky2->rx_le_map, RX_LE_SIZE - 1); | 1225 | sky2_prefetch_init(hw, rxq, sky2->rx_le_map, RX_LE_SIZE - 1); |
1177 | 1226 | ||
1178 | rx_set_checksum(sky2); | 1227 | if (!(hw->flags & SKY2_HW_NEW_LE)) |
1228 | rx_set_checksum(sky2); | ||
1179 | 1229 | ||
1180 | /* Space needed for frame data + headers rounded up */ | 1230 | /* Space needed for frame data + headers rounded up */ |
1181 | size = roundup(sky2->netdev->mtu + ETH_HLEN + VLAN_HLEN, 8); | 1231 | size = roundup(sky2->netdev->mtu + ETH_HLEN + VLAN_HLEN, 8); |
@@ -1246,7 +1296,7 @@ static int sky2_up(struct net_device *dev) | |||
1246 | struct sky2_port *sky2 = netdev_priv(dev); | 1296 | struct sky2_port *sky2 = netdev_priv(dev); |
1247 | struct sky2_hw *hw = sky2->hw; | 1297 | struct sky2_hw *hw = sky2->hw; |
1248 | unsigned port = sky2->port; | 1298 | unsigned port = sky2->port; |
1249 | u32 ramsize, imask; | 1299 | u32 imask, ramsize; |
1250 | int cap, err = -ENOMEM; | 1300 | int cap, err = -ENOMEM; |
1251 | struct net_device *otherdev = hw->dev[sky2->port^1]; | 1301 | struct net_device *otherdev = hw->dev[sky2->port^1]; |
1252 | 1302 | ||
@@ -1284,7 +1334,8 @@ static int sky2_up(struct net_device *dev) | |||
1284 | GFP_KERNEL); | 1334 | GFP_KERNEL); |
1285 | if (!sky2->tx_ring) | 1335 | if (!sky2->tx_ring) |
1286 | goto err_out; | 1336 | goto err_out; |
1287 | sky2->tx_prod = sky2->tx_cons = 0; | 1337 | |
1338 | tx_init(sky2); | ||
1288 | 1339 | ||
1289 | sky2->rx_le = pci_alloc_consistent(hw->pdev, RX_LE_BYTES, | 1340 | sky2->rx_le = pci_alloc_consistent(hw->pdev, RX_LE_BYTES, |
1290 | &sky2->rx_le_map); | 1341 | &sky2->rx_le_map); |
@@ -1303,11 +1354,10 @@ static int sky2_up(struct net_device *dev) | |||
1303 | 1354 | ||
1304 | /* Register is number of 4K blocks on internal RAM buffer. */ | 1355 | /* Register is number of 4K blocks on internal RAM buffer. */ |
1305 | ramsize = sky2_read8(hw, B2_E_0) * 4; | 1356 | ramsize = sky2_read8(hw, B2_E_0) * 4; |
1306 | printk(KERN_INFO PFX "%s: ram buffer %dK\n", dev->name, ramsize); | ||
1307 | |||
1308 | if (ramsize > 0) { | 1357 | if (ramsize > 0) { |
1309 | u32 rxspace; | 1358 | u32 rxspace; |
1310 | 1359 | ||
1360 | pr_debug(PFX "%s: ram buffer %dK\n", dev->name, ramsize); | ||
1311 | if (ramsize < 16) | 1361 | if (ramsize < 16) |
1312 | rxspace = ramsize / 2; | 1362 | rxspace = ramsize / 2; |
1313 | else | 1363 | else |
@@ -1436,13 +1486,15 @@ static int sky2_xmit_frame(struct sk_buff *skb, struct net_device *dev) | |||
1436 | /* Check for TCP Segmentation Offload */ | 1486 | /* Check for TCP Segmentation Offload */ |
1437 | mss = skb_shinfo(skb)->gso_size; | 1487 | mss = skb_shinfo(skb)->gso_size; |
1438 | if (mss != 0) { | 1488 | if (mss != 0) { |
1439 | if (hw->chip_id != CHIP_ID_YUKON_EX) | 1489 | |
1490 | if (!(hw->flags & SKY2_HW_NEW_LE)) | ||
1440 | mss += ETH_HLEN + ip_hdrlen(skb) + tcp_hdrlen(skb); | 1491 | mss += ETH_HLEN + ip_hdrlen(skb) + tcp_hdrlen(skb); |
1441 | 1492 | ||
1442 | if (mss != sky2->tx_last_mss) { | 1493 | if (mss != sky2->tx_last_mss) { |
1443 | le = get_tx_le(sky2); | 1494 | le = get_tx_le(sky2); |
1444 | le->addr = cpu_to_le32(mss); | 1495 | le->addr = cpu_to_le32(mss); |
1445 | if (hw->chip_id == CHIP_ID_YUKON_EX) | 1496 | |
1497 | if (hw->flags & SKY2_HW_NEW_LE) | ||
1446 | le->opcode = OP_MSS | HW_OWNER; | 1498 | le->opcode = OP_MSS | HW_OWNER; |
1447 | else | 1499 | else |
1448 | le->opcode = OP_LRGLEN | HW_OWNER; | 1500 | le->opcode = OP_LRGLEN | HW_OWNER; |
@@ -1468,8 +1520,7 @@ static int sky2_xmit_frame(struct sk_buff *skb, struct net_device *dev) | |||
1468 | /* Handle TCP checksum offload */ | 1520 | /* Handle TCP checksum offload */ |
1469 | if (skb->ip_summed == CHECKSUM_PARTIAL) { | 1521 | if (skb->ip_summed == CHECKSUM_PARTIAL) { |
1470 | /* On Yukon EX (some versions) encoding change. */ | 1522 | /* On Yukon EX (some versions) encoding change. */ |
1471 | if (hw->chip_id == CHIP_ID_YUKON_EX | 1523 | if (hw->flags & SKY2_HW_AUTO_TX_SUM) |
1472 | && hw->chip_rev != CHIP_REV_YU_EX_B0) | ||
1473 | ctrl |= CALSUM; /* auto checksum */ | 1524 | ctrl |= CALSUM; /* auto checksum */ |
1474 | else { | 1525 | else { |
1475 | const unsigned offset = skb_transport_offset(skb); | 1526 | const unsigned offset = skb_transport_offset(skb); |
@@ -1622,9 +1673,6 @@ static int sky2_down(struct net_device *dev) | |||
1622 | if (netif_msg_ifdown(sky2)) | 1673 | if (netif_msg_ifdown(sky2)) |
1623 | printk(KERN_INFO PFX "%s: disabling interface\n", dev->name); | 1674 | printk(KERN_INFO PFX "%s: disabling interface\n", dev->name); |
1624 | 1675 | ||
1625 | if (netif_carrier_ok(dev) && --hw->active == 0) | ||
1626 | del_timer(&hw->watchdog_timer); | ||
1627 | |||
1628 | /* Stop more packets from being queued */ | 1676 | /* Stop more packets from being queued */ |
1629 | netif_stop_queue(dev); | 1677 | netif_stop_queue(dev); |
1630 | 1678 | ||
@@ -1708,11 +1756,15 @@ static int sky2_down(struct net_device *dev) | |||
1708 | 1756 | ||
1709 | static u16 sky2_phy_speed(const struct sky2_hw *hw, u16 aux) | 1757 | static u16 sky2_phy_speed(const struct sky2_hw *hw, u16 aux) |
1710 | { | 1758 | { |
1711 | if (!sky2_is_copper(hw)) | 1759 | if (hw->flags & SKY2_HW_FIBRE_PHY) |
1712 | return SPEED_1000; | 1760 | return SPEED_1000; |
1713 | 1761 | ||
1714 | if (hw->chip_id == CHIP_ID_YUKON_FE) | 1762 | if (!(hw->flags & SKY2_HW_GIGABIT)) { |
1715 | return (aux & PHY_M_PS_SPEED_100) ? SPEED_100 : SPEED_10; | 1763 | if (aux & PHY_M_PS_SPEED_100) |
1764 | return SPEED_100; | ||
1765 | else | ||
1766 | return SPEED_10; | ||
1767 | } | ||
1716 | 1768 | ||
1717 | switch (aux & PHY_M_PS_SPEED_MSK) { | 1769 | switch (aux & PHY_M_PS_SPEED_MSK) { |
1718 | case PHY_M_PS_SPEED_1000: | 1770 | case PHY_M_PS_SPEED_1000: |
@@ -1745,17 +1797,13 @@ static void sky2_link_up(struct sky2_port *sky2) | |||
1745 | 1797 | ||
1746 | netif_carrier_on(sky2->netdev); | 1798 | netif_carrier_on(sky2->netdev); |
1747 | 1799 | ||
1748 | if (hw->active++ == 0) | 1800 | mod_timer(&hw->watchdog_timer, jiffies + 1); |
1749 | mod_timer(&hw->watchdog_timer, jiffies + 1); | ||
1750 | |||
1751 | 1801 | ||
1752 | /* Turn on link LED */ | 1802 | /* Turn on link LED */ |
1753 | sky2_write8(hw, SK_REG(port, LNK_LED_REG), | 1803 | sky2_write8(hw, SK_REG(port, LNK_LED_REG), |
1754 | LINKLED_ON | LINKLED_BLINK_OFF | LINKLED_LINKSYNC_OFF); | 1804 | LINKLED_ON | LINKLED_BLINK_OFF | LINKLED_LINKSYNC_OFF); |
1755 | 1805 | ||
1756 | if (hw->chip_id == CHIP_ID_YUKON_XL | 1806 | if (hw->flags & SKY2_HW_NEWER_PHY) { |
1757 | || hw->chip_id == CHIP_ID_YUKON_EC_U | ||
1758 | || hw->chip_id == CHIP_ID_YUKON_EX) { | ||
1759 | u16 pg = gm_phy_read(hw, port, PHY_MARV_EXT_ADR); | 1807 | u16 pg = gm_phy_read(hw, port, PHY_MARV_EXT_ADR); |
1760 | u16 led = PHY_M_LEDC_LOS_CTRL(1); /* link active */ | 1808 | u16 led = PHY_M_LEDC_LOS_CTRL(1); /* link active */ |
1761 | 1809 | ||
@@ -1800,11 +1848,6 @@ static void sky2_link_down(struct sky2_port *sky2) | |||
1800 | 1848 | ||
1801 | netif_carrier_off(sky2->netdev); | 1849 | netif_carrier_off(sky2->netdev); |
1802 | 1850 | ||
1803 | /* Stop watchdog if both ports are not active */ | ||
1804 | if (--hw->active == 0) | ||
1805 | del_timer(&hw->watchdog_timer); | ||
1806 | |||
1807 | |||
1808 | /* Turn on link LED */ | 1851 | /* Turn on link LED */ |
1809 | sky2_write8(hw, SK_REG(port, LNK_LED_REG), LINKLED_OFF); | 1852 | sky2_write8(hw, SK_REG(port, LNK_LED_REG), LINKLED_OFF); |
1810 | 1853 | ||
@@ -1847,7 +1890,7 @@ static int sky2_autoneg_done(struct sky2_port *sky2, u16 aux) | |||
1847 | /* Since the pause result bits seem to in different positions on | 1890 | /* Since the pause result bits seem to in different positions on |
1848 | * different chips. look at registers. | 1891 | * different chips. look at registers. |
1849 | */ | 1892 | */ |
1850 | if (!sky2_is_copper(hw)) { | 1893 | if (hw->flags & SKY2_HW_FIBRE_PHY) { |
1851 | /* Shift for bits in fiber PHY */ | 1894 | /* Shift for bits in fiber PHY */ |
1852 | advert &= ~(ADVERTISE_PAUSE_CAP|ADVERTISE_PAUSE_ASYM); | 1895 | advert &= ~(ADVERTISE_PAUSE_CAP|ADVERTISE_PAUSE_ASYM); |
1853 | lpa &= ~(LPA_PAUSE_CAP|LPA_PAUSE_ASYM); | 1896 | lpa &= ~(LPA_PAUSE_CAP|LPA_PAUSE_ASYM); |
@@ -1958,7 +2001,9 @@ static int sky2_change_mtu(struct net_device *dev, int new_mtu) | |||
1958 | if (new_mtu < ETH_ZLEN || new_mtu > ETH_JUMBO_MTU) | 2001 | if (new_mtu < ETH_ZLEN || new_mtu > ETH_JUMBO_MTU) |
1959 | return -EINVAL; | 2002 | return -EINVAL; |
1960 | 2003 | ||
1961 | if (new_mtu > ETH_DATA_LEN && hw->chip_id == CHIP_ID_YUKON_FE) | 2004 | if (new_mtu > ETH_DATA_LEN && |
2005 | (hw->chip_id == CHIP_ID_YUKON_FE || | ||
2006 | hw->chip_id == CHIP_ID_YUKON_FE_P)) | ||
1962 | return -EINVAL; | 2007 | return -EINVAL; |
1963 | 2008 | ||
1964 | if (!netif_running(dev)) { | 2009 | if (!netif_running(dev)) { |
@@ -1975,7 +2020,7 @@ static int sky2_change_mtu(struct net_device *dev, int new_mtu) | |||
1975 | 2020 | ||
1976 | synchronize_irq(hw->pdev->irq); | 2021 | synchronize_irq(hw->pdev->irq); |
1977 | 2022 | ||
1978 | if (hw->chip_id == CHIP_ID_YUKON_EC_U || hw->chip_id == CHIP_ID_YUKON_EX) | 2023 | if (sky2_read8(hw, B2_E_0) == 0) |
1979 | sky2_set_tx_stfwd(hw, port); | 2024 | sky2_set_tx_stfwd(hw, port); |
1980 | 2025 | ||
1981 | ctl = gma_read16(hw, port, GM_GP_CTRL); | 2026 | ctl = gma_read16(hw, port, GM_GP_CTRL); |
@@ -2103,6 +2148,13 @@ static struct sk_buff *sky2_receive(struct net_device *dev, | |||
2103 | struct sky2_port *sky2 = netdev_priv(dev); | 2148 | struct sky2_port *sky2 = netdev_priv(dev); |
2104 | struct rx_ring_info *re = sky2->rx_ring + sky2->rx_next; | 2149 | struct rx_ring_info *re = sky2->rx_ring + sky2->rx_next; |
2105 | struct sk_buff *skb = NULL; | 2150 | struct sk_buff *skb = NULL; |
2151 | u16 count = (status & GMR_FS_LEN) >> 16; | ||
2152 | |||
2153 | #ifdef SKY2_VLAN_TAG_USED | ||
2154 | /* Account for vlan tag */ | ||
2155 | if (sky2->vlgrp && (status & GMR_FS_VLAN)) | ||
2156 | count -= VLAN_HLEN; | ||
2157 | #endif | ||
2106 | 2158 | ||
2107 | if (unlikely(netif_msg_rx_status(sky2))) | 2159 | if (unlikely(netif_msg_rx_status(sky2))) |
2108 | printk(KERN_DEBUG PFX "%s: rx slot %u status 0x%x len %d\n", | 2160 | printk(KERN_DEBUG PFX "%s: rx slot %u status 0x%x len %d\n", |
@@ -2111,15 +2163,29 @@ static struct sk_buff *sky2_receive(struct net_device *dev, | |||
2111 | sky2->rx_next = (sky2->rx_next + 1) % sky2->rx_pending; | 2163 | sky2->rx_next = (sky2->rx_next + 1) % sky2->rx_pending; |
2112 | prefetch(sky2->rx_ring + sky2->rx_next); | 2164 | prefetch(sky2->rx_ring + sky2->rx_next); |
2113 | 2165 | ||
2166 | if (length < ETH_ZLEN || length > sky2->rx_data_size) | ||
2167 | goto len_error; | ||
2168 | |||
2169 | /* This chip has hardware problems that generates bogus status. | ||
2170 | * So do only marginal checking and expect higher level protocols | ||
2171 | * to handle crap frames. | ||
2172 | */ | ||
2173 | if (sky2->hw->chip_id == CHIP_ID_YUKON_FE_P && | ||
2174 | sky2->hw->chip_rev == CHIP_REV_YU_FE2_A0 && | ||
2175 | length != count) | ||
2176 | goto okay; | ||
2177 | |||
2114 | if (status & GMR_FS_ANY_ERR) | 2178 | if (status & GMR_FS_ANY_ERR) |
2115 | goto error; | 2179 | goto error; |
2116 | 2180 | ||
2117 | if (!(status & GMR_FS_RX_OK)) | 2181 | if (!(status & GMR_FS_RX_OK)) |
2118 | goto resubmit; | 2182 | goto resubmit; |
2119 | 2183 | ||
2120 | if (status >> 16 != length) | 2184 | /* if length reported by DMA does not match PHY, packet was truncated */ |
2121 | goto len_mismatch; | 2185 | if (length != count) |
2186 | goto len_error; | ||
2122 | 2187 | ||
2188 | okay: | ||
2123 | if (length < copybreak) | 2189 | if (length < copybreak) |
2124 | skb = receive_copy(sky2, re, length); | 2190 | skb = receive_copy(sky2, re, length); |
2125 | else | 2191 | else |
@@ -2129,10 +2195,14 @@ resubmit: | |||
2129 | 2195 | ||
2130 | return skb; | 2196 | return skb; |
2131 | 2197 | ||
2132 | len_mismatch: | 2198 | len_error: |
2133 | /* Truncation of overlength packets | 2199 | /* Truncation of overlength packets |
2134 | causes PHY length to not match MAC length */ | 2200 | causes PHY length to not match MAC length */ |
2135 | ++sky2->net_stats.rx_length_errors; | 2201 | ++sky2->net_stats.rx_length_errors; |
2202 | if (netif_msg_rx_err(sky2) && net_ratelimit()) | ||
2203 | pr_info(PFX "%s: rx length error: status %#x length %d\n", | ||
2204 | dev->name, status, length); | ||
2205 | goto resubmit; | ||
2136 | 2206 | ||
2137 | error: | 2207 | error: |
2138 | ++sky2->net_stats.rx_errors; | 2208 | ++sky2->net_stats.rx_errors; |
@@ -2202,7 +2272,7 @@ static int sky2_status_intr(struct sky2_hw *hw, int to_do) | |||
2202 | } | 2272 | } |
2203 | 2273 | ||
2204 | /* This chip reports checksum status differently */ | 2274 | /* This chip reports checksum status differently */ |
2205 | if (hw->chip_id == CHIP_ID_YUKON_EX) { | 2275 | if (hw->flags & SKY2_HW_NEW_LE) { |
2206 | if (sky2->rx_csum && | 2276 | if (sky2->rx_csum && |
2207 | (le->css & (CSS_ISIPV4 | CSS_ISIPV6)) && | 2277 | (le->css & (CSS_ISIPV4 | CSS_ISIPV6)) && |
2208 | (le->css & CSS_TCPUDPCSOK)) | 2278 | (le->css & CSS_TCPUDPCSOK)) |
@@ -2243,8 +2313,14 @@ static int sky2_status_intr(struct sky2_hw *hw, int to_do) | |||
2243 | if (!sky2->rx_csum) | 2313 | if (!sky2->rx_csum) |
2244 | break; | 2314 | break; |
2245 | 2315 | ||
2246 | if (hw->chip_id == CHIP_ID_YUKON_EX) | 2316 | /* If this happens then driver assuming wrong format */ |
2317 | if (unlikely(hw->flags & SKY2_HW_NEW_LE)) { | ||
2318 | if (net_ratelimit()) | ||
2319 | printk(KERN_NOTICE "%s: unexpected" | ||
2320 | " checksum status\n", | ||
2321 | dev->name); | ||
2247 | break; | 2322 | break; |
2323 | } | ||
2248 | 2324 | ||
2249 | /* Both checksum counters are programmed to start at | 2325 | /* Both checksum counters are programmed to start at |
2250 | * the same offset, so unless there is a problem they | 2326 | * the same offset, so unless there is a problem they |
@@ -2436,20 +2512,72 @@ static void sky2_le_error(struct sky2_hw *hw, unsigned port, | |||
2436 | sky2_write32(hw, Q_ADDR(q, Q_CSR), BMU_CLR_IRQ_CHK); | 2512 | sky2_write32(hw, Q_ADDR(q, Q_CSR), BMU_CLR_IRQ_CHK); |
2437 | } | 2513 | } |
2438 | 2514 | ||
2439 | /* Check for lost IRQ once a second */ | 2515 | static int sky2_rx_hung(struct net_device *dev) |
2516 | { | ||
2517 | struct sky2_port *sky2 = netdev_priv(dev); | ||
2518 | struct sky2_hw *hw = sky2->hw; | ||
2519 | unsigned port = sky2->port; | ||
2520 | unsigned rxq = rxqaddr[port]; | ||
2521 | u32 mac_rp = sky2_read32(hw, SK_REG(port, RX_GMF_RP)); | ||
2522 | u8 mac_lev = sky2_read8(hw, SK_REG(port, RX_GMF_RLEV)); | ||
2523 | u8 fifo_rp = sky2_read8(hw, Q_ADDR(rxq, Q_RP)); | ||
2524 | u8 fifo_lev = sky2_read8(hw, Q_ADDR(rxq, Q_RL)); | ||
2525 | |||
2526 | /* If idle and MAC or PCI is stuck */ | ||
2527 | if (sky2->check.last == dev->last_rx && | ||
2528 | ((mac_rp == sky2->check.mac_rp && | ||
2529 | mac_lev != 0 && mac_lev >= sky2->check.mac_lev) || | ||
2530 | /* Check if the PCI RX hang */ | ||
2531 | (fifo_rp == sky2->check.fifo_rp && | ||
2532 | fifo_lev != 0 && fifo_lev >= sky2->check.fifo_lev))) { | ||
2533 | printk(KERN_DEBUG PFX "%s: hung mac %d:%d fifo %d (%d:%d)\n", | ||
2534 | dev->name, mac_lev, mac_rp, fifo_lev, fifo_rp, | ||
2535 | sky2_read8(hw, Q_ADDR(rxq, Q_WP))); | ||
2536 | return 1; | ||
2537 | } else { | ||
2538 | sky2->check.last = dev->last_rx; | ||
2539 | sky2->check.mac_rp = mac_rp; | ||
2540 | sky2->check.mac_lev = mac_lev; | ||
2541 | sky2->check.fifo_rp = fifo_rp; | ||
2542 | sky2->check.fifo_lev = fifo_lev; | ||
2543 | return 0; | ||
2544 | } | ||
2545 | } | ||
2546 | |||
2440 | static void sky2_watchdog(unsigned long arg) | 2547 | static void sky2_watchdog(unsigned long arg) |
2441 | { | 2548 | { |
2442 | struct sky2_hw *hw = (struct sky2_hw *) arg; | 2549 | struct sky2_hw *hw = (struct sky2_hw *) arg; |
2550 | struct net_device *dev; | ||
2443 | 2551 | ||
2552 | /* Check for lost IRQ once a second */ | ||
2444 | if (sky2_read32(hw, B0_ISRC)) { | 2553 | if (sky2_read32(hw, B0_ISRC)) { |
2445 | struct net_device *dev = hw->dev[0]; | 2554 | dev = hw->dev[0]; |
2446 | |||
2447 | if (__netif_rx_schedule_prep(dev)) | 2555 | if (__netif_rx_schedule_prep(dev)) |
2448 | __netif_rx_schedule(dev); | 2556 | __netif_rx_schedule(dev); |
2557 | } else { | ||
2558 | int i, active = 0; | ||
2559 | |||
2560 | for (i = 0; i < hw->ports; i++) { | ||
2561 | dev = hw->dev[i]; | ||
2562 | if (!netif_running(dev)) | ||
2563 | continue; | ||
2564 | ++active; | ||
2565 | |||
2566 | /* For chips with Rx FIFO, check if stuck */ | ||
2567 | if ((hw->flags & SKY2_HW_FIFO_HANG_CHECK) && | ||
2568 | sky2_rx_hung(dev)) { | ||
2569 | pr_info(PFX "%s: receiver hang detected\n", | ||
2570 | dev->name); | ||
2571 | schedule_work(&hw->restart_work); | ||
2572 | return; | ||
2573 | } | ||
2574 | } | ||
2575 | |||
2576 | if (active == 0) | ||
2577 | return; | ||
2449 | } | 2578 | } |
2450 | 2579 | ||
2451 | if (hw->active > 0) | 2580 | mod_timer(&hw->watchdog_timer, round_jiffies(jiffies + HZ)); |
2452 | mod_timer(&hw->watchdog_timer, round_jiffies(jiffies + HZ)); | ||
2453 | } | 2581 | } |
2454 | 2582 | ||
2455 | /* Hardware/software error handling */ | 2583 | /* Hardware/software error handling */ |
@@ -2546,17 +2674,25 @@ static void sky2_netpoll(struct net_device *dev) | |||
2546 | #endif | 2674 | #endif |
2547 | 2675 | ||
2548 | /* Chip internal frequency for clock calculations */ | 2676 | /* Chip internal frequency for clock calculations */ |
2549 | static inline u32 sky2_mhz(const struct sky2_hw *hw) | 2677 | static u32 sky2_mhz(const struct sky2_hw *hw) |
2550 | { | 2678 | { |
2551 | switch (hw->chip_id) { | 2679 | switch (hw->chip_id) { |
2552 | case CHIP_ID_YUKON_EC: | 2680 | case CHIP_ID_YUKON_EC: |
2553 | case CHIP_ID_YUKON_EC_U: | 2681 | case CHIP_ID_YUKON_EC_U: |
2554 | case CHIP_ID_YUKON_EX: | 2682 | case CHIP_ID_YUKON_EX: |
2555 | return 125; /* 125 Mhz */ | 2683 | return 125; |
2684 | |||
2556 | case CHIP_ID_YUKON_FE: | 2685 | case CHIP_ID_YUKON_FE: |
2557 | return 100; /* 100 Mhz */ | 2686 | return 100; |
2558 | default: /* YUKON_XL */ | 2687 | |
2559 | return 156; /* 156 Mhz */ | 2688 | case CHIP_ID_YUKON_FE_P: |
2689 | return 50; | ||
2690 | |||
2691 | case CHIP_ID_YUKON_XL: | ||
2692 | return 156; | ||
2693 | |||
2694 | default: | ||
2695 | BUG(); | ||
2560 | } | 2696 | } |
2561 | } | 2697 | } |
2562 | 2698 | ||
@@ -2581,23 +2717,63 @@ static int __devinit sky2_init(struct sky2_hw *hw) | |||
2581 | sky2_write8(hw, B0_CTST, CS_RST_CLR); | 2717 | sky2_write8(hw, B0_CTST, CS_RST_CLR); |
2582 | 2718 | ||
2583 | hw->chip_id = sky2_read8(hw, B2_CHIP_ID); | 2719 | hw->chip_id = sky2_read8(hw, B2_CHIP_ID); |
2584 | if (hw->chip_id < CHIP_ID_YUKON_XL || hw->chip_id > CHIP_ID_YUKON_FE) { | 2720 | hw->chip_rev = (sky2_read8(hw, B2_MAC_CFG) & CFG_CHIP_R_MSK) >> 4; |
2721 | |||
2722 | switch(hw->chip_id) { | ||
2723 | case CHIP_ID_YUKON_XL: | ||
2724 | hw->flags = SKY2_HW_GIGABIT | ||
2725 | | SKY2_HW_NEWER_PHY; | ||
2726 | if (hw->chip_rev < 3) | ||
2727 | hw->flags |= SKY2_HW_FIFO_HANG_CHECK; | ||
2728 | |||
2729 | break; | ||
2730 | |||
2731 | case CHIP_ID_YUKON_EC_U: | ||
2732 | hw->flags = SKY2_HW_GIGABIT | ||
2733 | | SKY2_HW_NEWER_PHY | ||
2734 | | SKY2_HW_ADV_POWER_CTL; | ||
2735 | break; | ||
2736 | |||
2737 | case CHIP_ID_YUKON_EX: | ||
2738 | hw->flags = SKY2_HW_GIGABIT | ||
2739 | | SKY2_HW_NEWER_PHY | ||
2740 | | SKY2_HW_NEW_LE | ||
2741 | | SKY2_HW_ADV_POWER_CTL; | ||
2742 | |||
2743 | /* New transmit checksum */ | ||
2744 | if (hw->chip_rev != CHIP_REV_YU_EX_B0) | ||
2745 | hw->flags |= SKY2_HW_AUTO_TX_SUM; | ||
2746 | break; | ||
2747 | |||
2748 | case CHIP_ID_YUKON_EC: | ||
2749 | /* This rev is really old, and requires untested workarounds */ | ||
2750 | if (hw->chip_rev == CHIP_REV_YU_EC_A1) { | ||
2751 | dev_err(&hw->pdev->dev, "unsupported revision Yukon-EC rev A1\n"); | ||
2752 | return -EOPNOTSUPP; | ||
2753 | } | ||
2754 | hw->flags = SKY2_HW_GIGABIT | SKY2_HW_FIFO_HANG_CHECK; | ||
2755 | break; | ||
2756 | |||
2757 | case CHIP_ID_YUKON_FE: | ||
2758 | break; | ||
2759 | |||
2760 | case CHIP_ID_YUKON_FE_P: | ||
2761 | hw->flags = SKY2_HW_NEWER_PHY | ||
2762 | | SKY2_HW_NEW_LE | ||
2763 | | SKY2_HW_AUTO_TX_SUM | ||
2764 | | SKY2_HW_ADV_POWER_CTL; | ||
2765 | break; | ||
2766 | default: | ||
2585 | dev_err(&hw->pdev->dev, "unsupported chip type 0x%x\n", | 2767 | dev_err(&hw->pdev->dev, "unsupported chip type 0x%x\n", |
2586 | hw->chip_id); | 2768 | hw->chip_id); |
2587 | return -EOPNOTSUPP; | 2769 | return -EOPNOTSUPP; |
2588 | } | 2770 | } |
2589 | 2771 | ||
2590 | hw->chip_rev = (sky2_read8(hw, B2_MAC_CFG) & CFG_CHIP_R_MSK) >> 4; | 2772 | hw->pmd_type = sky2_read8(hw, B2_PMD_TYP); |
2773 | if (hw->pmd_type == 'L' || hw->pmd_type == 'S' || hw->pmd_type == 'P') | ||
2774 | hw->flags |= SKY2_HW_FIBRE_PHY; | ||
2591 | 2775 | ||
2592 | /* This rev is really old, and requires untested workarounds */ | ||
2593 | if (hw->chip_id == CHIP_ID_YUKON_EC && hw->chip_rev == CHIP_REV_YU_EC_A1) { | ||
2594 | dev_err(&hw->pdev->dev, "unsupported revision Yukon-%s (0x%x) rev %d\n", | ||
2595 | yukon2_name[hw->chip_id - CHIP_ID_YUKON_XL], | ||
2596 | hw->chip_id, hw->chip_rev); | ||
2597 | return -EOPNOTSUPP; | ||
2598 | } | ||
2599 | 2776 | ||
2600 | hw->pmd_type = sky2_read8(hw, B2_PMD_TYP); | ||
2601 | hw->ports = 1; | 2777 | hw->ports = 1; |
2602 | t8 = sky2_read8(hw, B2_Y2_HW_RES); | 2778 | t8 = sky2_read8(hw, B2_Y2_HW_RES); |
2603 | if ((t8 & CFG_DUAL_MAC_MSK) == CFG_DUAL_MAC_MSK) { | 2779 | if ((t8 & CFG_DUAL_MAC_MSK) == CFG_DUAL_MAC_MSK) { |
@@ -2791,7 +2967,9 @@ static int sky2_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) | |||
2791 | 2967 | ||
2792 | sky2->wol = wol->wolopts; | 2968 | sky2->wol = wol->wolopts; |
2793 | 2969 | ||
2794 | if (hw->chip_id == CHIP_ID_YUKON_EC_U || hw->chip_id == CHIP_ID_YUKON_EX) | 2970 | if (hw->chip_id == CHIP_ID_YUKON_EC_U || |
2971 | hw->chip_id == CHIP_ID_YUKON_EX || | ||
2972 | hw->chip_id == CHIP_ID_YUKON_FE_P) | ||
2795 | sky2_write32(hw, B0_CTST, sky2->wol | 2973 | sky2_write32(hw, B0_CTST, sky2->wol |
2796 | ? Y2_HW_WOL_ON : Y2_HW_WOL_OFF); | 2974 | ? Y2_HW_WOL_ON : Y2_HW_WOL_OFF); |
2797 | 2975 | ||
@@ -2809,7 +2987,7 @@ static u32 sky2_supported_modes(const struct sky2_hw *hw) | |||
2809 | | SUPPORTED_100baseT_Full | 2987 | | SUPPORTED_100baseT_Full |
2810 | | SUPPORTED_Autoneg | SUPPORTED_TP; | 2988 | | SUPPORTED_Autoneg | SUPPORTED_TP; |
2811 | 2989 | ||
2812 | if (hw->chip_id != CHIP_ID_YUKON_FE) | 2990 | if (hw->flags & SKY2_HW_GIGABIT) |
2813 | modes |= SUPPORTED_1000baseT_Half | 2991 | modes |= SUPPORTED_1000baseT_Half |
2814 | | SUPPORTED_1000baseT_Full; | 2992 | | SUPPORTED_1000baseT_Full; |
2815 | return modes; | 2993 | return modes; |
@@ -2829,13 +3007,6 @@ static int sky2_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd) | |||
2829 | ecmd->supported = sky2_supported_modes(hw); | 3007 | ecmd->supported = sky2_supported_modes(hw); |
2830 | ecmd->phy_address = PHY_ADDR_MARV; | 3008 | ecmd->phy_address = PHY_ADDR_MARV; |
2831 | if (sky2_is_copper(hw)) { | 3009 | if (sky2_is_copper(hw)) { |
2832 | ecmd->supported = SUPPORTED_10baseT_Half | ||
2833 | | SUPPORTED_10baseT_Full | ||
2834 | | SUPPORTED_100baseT_Half | ||
2835 | | SUPPORTED_100baseT_Full | ||
2836 | | SUPPORTED_1000baseT_Half | ||
2837 | | SUPPORTED_1000baseT_Full | ||
2838 | | SUPPORTED_Autoneg | SUPPORTED_TP; | ||
2839 | ecmd->port = PORT_TP; | 3010 | ecmd->port = PORT_TP; |
2840 | ecmd->speed = sky2->speed; | 3011 | ecmd->speed = sky2->speed; |
2841 | } else { | 3012 | } else { |
@@ -3814,8 +3985,12 @@ static __devinit struct net_device *sky2_init_netdev(struct sky2_hw *hw, | |||
3814 | dev->features |= NETIF_F_HIGHDMA; | 3985 | dev->features |= NETIF_F_HIGHDMA; |
3815 | 3986 | ||
3816 | #ifdef SKY2_VLAN_TAG_USED | 3987 | #ifdef SKY2_VLAN_TAG_USED |
3817 | dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX; | 3988 | /* The workaround for FE+ status conflicts with VLAN tag detection. */ |
3818 | dev->vlan_rx_register = sky2_vlan_rx_register; | 3989 | if (!(sky2->hw->chip_id == CHIP_ID_YUKON_FE_P && |
3990 | sky2->hw->chip_rev == CHIP_REV_YU_FE2_A0)) { | ||
3991 | dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX; | ||
3992 | dev->vlan_rx_register = sky2_vlan_rx_register; | ||
3993 | } | ||
3819 | #endif | 3994 | #endif |
3820 | 3995 | ||
3821 | /* read the mac address */ | 3996 | /* read the mac address */ |
@@ -3846,7 +4021,7 @@ static irqreturn_t __devinit sky2_test_intr(int irq, void *dev_id) | |||
3846 | return IRQ_NONE; | 4021 | return IRQ_NONE; |
3847 | 4022 | ||
3848 | if (status & Y2_IS_IRQ_SW) { | 4023 | if (status & Y2_IS_IRQ_SW) { |
3849 | hw->msi = 1; | 4024 | hw->flags |= SKY2_HW_USE_MSI; |
3850 | wake_up(&hw->msi_wait); | 4025 | wake_up(&hw->msi_wait); |
3851 | sky2_write8(hw, B0_CTST, CS_CL_SW_IRQ); | 4026 | sky2_write8(hw, B0_CTST, CS_CL_SW_IRQ); |
3852 | } | 4027 | } |
@@ -3874,9 +4049,9 @@ static int __devinit sky2_test_msi(struct sky2_hw *hw) | |||
3874 | sky2_write8(hw, B0_CTST, CS_ST_SW_IRQ); | 4049 | sky2_write8(hw, B0_CTST, CS_ST_SW_IRQ); |
3875 | sky2_read8(hw, B0_CTST); | 4050 | sky2_read8(hw, B0_CTST); |
3876 | 4051 | ||
3877 | wait_event_timeout(hw->msi_wait, hw->msi, HZ/10); | 4052 | wait_event_timeout(hw->msi_wait, (hw->flags & SKY2_HW_USE_MSI), HZ/10); |
3878 | 4053 | ||
3879 | if (!hw->msi) { | 4054 | if (!(hw->flags & SKY2_HW_USE_MSI)) { |
3880 | /* MSI test failed, go back to INTx mode */ | 4055 | /* MSI test failed, go back to INTx mode */ |
3881 | dev_info(&pdev->dev, "No interrupt generated using MSI, " | 4056 | dev_info(&pdev->dev, "No interrupt generated using MSI, " |
3882 | "switching to INTx mode.\n"); | 4057 | "switching to INTx mode.\n"); |
@@ -4009,7 +4184,8 @@ static int __devinit sky2_probe(struct pci_dev *pdev, | |||
4009 | goto err_out_free_netdev; | 4184 | goto err_out_free_netdev; |
4010 | } | 4185 | } |
4011 | 4186 | ||
4012 | err = request_irq(pdev->irq, sky2_intr, hw->msi ? 0 : IRQF_SHARED, | 4187 | err = request_irq(pdev->irq, sky2_intr, |
4188 | (hw->flags & SKY2_HW_USE_MSI) ? 0 : IRQF_SHARED, | ||
4013 | dev->name, hw); | 4189 | dev->name, hw); |
4014 | if (err) { | 4190 | if (err) { |
4015 | dev_err(&pdev->dev, "cannot assign irq %d\n", pdev->irq); | 4191 | dev_err(&pdev->dev, "cannot assign irq %d\n", pdev->irq); |
@@ -4042,7 +4218,7 @@ static int __devinit sky2_probe(struct pci_dev *pdev, | |||
4042 | return 0; | 4218 | return 0; |
4043 | 4219 | ||
4044 | err_out_unregister: | 4220 | err_out_unregister: |
4045 | if (hw->msi) | 4221 | if (hw->flags & SKY2_HW_USE_MSI) |
4046 | pci_disable_msi(pdev); | 4222 | pci_disable_msi(pdev); |
4047 | unregister_netdev(dev); | 4223 | unregister_netdev(dev); |
4048 | err_out_free_netdev: | 4224 | err_out_free_netdev: |
@@ -4091,7 +4267,7 @@ static void __devexit sky2_remove(struct pci_dev *pdev) | |||
4091 | sky2_read8(hw, B0_CTST); | 4267 | sky2_read8(hw, B0_CTST); |
4092 | 4268 | ||
4093 | free_irq(pdev->irq, hw); | 4269 | free_irq(pdev->irq, hw); |
4094 | if (hw->msi) | 4270 | if (hw->flags & SKY2_HW_USE_MSI) |
4095 | pci_disable_msi(pdev); | 4271 | pci_disable_msi(pdev); |
4096 | pci_free_consistent(pdev, STATUS_LE_BYTES, hw->st_le, hw->st_dma); | 4272 | pci_free_consistent(pdev, STATUS_LE_BYTES, hw->st_le, hw->st_dma); |
4097 | pci_release_regions(pdev); | 4273 | pci_release_regions(pdev); |
@@ -4159,7 +4335,9 @@ static int sky2_resume(struct pci_dev *pdev) | |||
4159 | pci_enable_wake(pdev, PCI_D0, 0); | 4335 | pci_enable_wake(pdev, PCI_D0, 0); |
4160 | 4336 | ||
4161 | /* Re-enable all clocks */ | 4337 | /* Re-enable all clocks */ |
4162 | if (hw->chip_id == CHIP_ID_YUKON_EX || hw->chip_id == CHIP_ID_YUKON_EC_U) | 4338 | if (hw->chip_id == CHIP_ID_YUKON_EX || |
4339 | hw->chip_id == CHIP_ID_YUKON_EC_U || | ||
4340 | hw->chip_id == CHIP_ID_YUKON_FE_P) | ||
4163 | sky2_pci_write32(hw, PCI_DEV_REG3, 0); | 4341 | sky2_pci_write32(hw, PCI_DEV_REG3, 0); |
4164 | 4342 | ||
4165 | sky2_reset(hw); | 4343 | sky2_reset(hw); |