diff options
Diffstat (limited to 'drivers/net/bnx2.c')
-rw-r--r-- | drivers/net/bnx2.c | 974 |
1 files changed, 694 insertions, 280 deletions
diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c index f98a2205a090..88b33c6ddda8 100644 --- a/drivers/net/bnx2.c +++ b/drivers/net/bnx2.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* bnx2.c: Broadcom NX2 network driver. | 1 | /* bnx2.c: Broadcom NX2 network driver. |
2 | * | 2 | * |
3 | * Copyright (c) 2004, 2005, 2006 Broadcom Corporation | 3 | * Copyright (c) 2004-2007 Broadcom Corporation |
4 | * | 4 | * |
5 | * This program is free software; you can redistribute it and/or modify | 5 | * This program is free software; you can redistribute it and/or modify |
6 | * it under the terms of the GNU General Public License as published by | 6 | * it under the terms of the GNU General Public License as published by |
@@ -54,8 +54,8 @@ | |||
54 | 54 | ||
55 | #define DRV_MODULE_NAME "bnx2" | 55 | #define DRV_MODULE_NAME "bnx2" |
56 | #define PFX DRV_MODULE_NAME ": " | 56 | #define PFX DRV_MODULE_NAME ": " |
57 | #define DRV_MODULE_VERSION "1.5.8" | 57 | #define DRV_MODULE_VERSION "1.5.10" |
58 | #define DRV_MODULE_RELDATE "April 24, 2007" | 58 | #define DRV_MODULE_RELDATE "May 1, 2007" |
59 | 59 | ||
60 | #define RUN_AT(x) (jiffies + (x)) | 60 | #define RUN_AT(x) (jiffies + (x)) |
61 | 61 | ||
@@ -84,6 +84,7 @@ typedef enum { | |||
84 | BCM5708, | 84 | BCM5708, |
85 | BCM5708S, | 85 | BCM5708S, |
86 | BCM5709, | 86 | BCM5709, |
87 | BCM5709S, | ||
87 | } board_t; | 88 | } board_t; |
88 | 89 | ||
89 | /* indexed by board_t, above */ | 90 | /* indexed by board_t, above */ |
@@ -98,6 +99,7 @@ static const struct { | |||
98 | { "Broadcom NetXtreme II BCM5708 1000Base-T" }, | 99 | { "Broadcom NetXtreme II BCM5708 1000Base-T" }, |
99 | { "Broadcom NetXtreme II BCM5708 1000Base-SX" }, | 100 | { "Broadcom NetXtreme II BCM5708 1000Base-SX" }, |
100 | { "Broadcom NetXtreme II BCM5709 1000Base-T" }, | 101 | { "Broadcom NetXtreme II BCM5709 1000Base-T" }, |
102 | { "Broadcom NetXtreme II BCM5709 1000Base-SX" }, | ||
101 | }; | 103 | }; |
102 | 104 | ||
103 | static struct pci_device_id bnx2_pci_tbl[] = { | 105 | static struct pci_device_id bnx2_pci_tbl[] = { |
@@ -117,6 +119,8 @@ static struct pci_device_id bnx2_pci_tbl[] = { | |||
117 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5708S }, | 119 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5708S }, |
118 | { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_NX2_5709, | 120 | { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_NX2_5709, |
119 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5709 }, | 121 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5709 }, |
122 | { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_NX2_5709S, | ||
123 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5709S }, | ||
120 | { 0, } | 124 | { 0, } |
121 | }; | 125 | }; |
122 | 126 | ||
@@ -230,21 +234,29 @@ static inline u32 bnx2_tx_avail(struct bnx2 *bp) | |||
230 | static u32 | 234 | static u32 |
231 | bnx2_reg_rd_ind(struct bnx2 *bp, u32 offset) | 235 | bnx2_reg_rd_ind(struct bnx2 *bp, u32 offset) |
232 | { | 236 | { |
237 | u32 val; | ||
238 | |||
239 | spin_lock_bh(&bp->indirect_lock); | ||
233 | REG_WR(bp, BNX2_PCICFG_REG_WINDOW_ADDRESS, offset); | 240 | REG_WR(bp, BNX2_PCICFG_REG_WINDOW_ADDRESS, offset); |
234 | return (REG_RD(bp, BNX2_PCICFG_REG_WINDOW)); | 241 | val = REG_RD(bp, BNX2_PCICFG_REG_WINDOW); |
242 | spin_unlock_bh(&bp->indirect_lock); | ||
243 | return val; | ||
235 | } | 244 | } |
236 | 245 | ||
237 | static void | 246 | static void |
238 | bnx2_reg_wr_ind(struct bnx2 *bp, u32 offset, u32 val) | 247 | bnx2_reg_wr_ind(struct bnx2 *bp, u32 offset, u32 val) |
239 | { | 248 | { |
249 | spin_lock_bh(&bp->indirect_lock); | ||
240 | REG_WR(bp, BNX2_PCICFG_REG_WINDOW_ADDRESS, offset); | 250 | REG_WR(bp, BNX2_PCICFG_REG_WINDOW_ADDRESS, offset); |
241 | REG_WR(bp, BNX2_PCICFG_REG_WINDOW, val); | 251 | REG_WR(bp, BNX2_PCICFG_REG_WINDOW, val); |
252 | spin_unlock_bh(&bp->indirect_lock); | ||
242 | } | 253 | } |
243 | 254 | ||
244 | static void | 255 | static void |
245 | bnx2_ctx_wr(struct bnx2 *bp, u32 cid_addr, u32 offset, u32 val) | 256 | bnx2_ctx_wr(struct bnx2 *bp, u32 cid_addr, u32 offset, u32 val) |
246 | { | 257 | { |
247 | offset += cid_addr; | 258 | offset += cid_addr; |
259 | spin_lock_bh(&bp->indirect_lock); | ||
248 | if (CHIP_NUM(bp) == CHIP_NUM_5709) { | 260 | if (CHIP_NUM(bp) == CHIP_NUM_5709) { |
249 | int i; | 261 | int i; |
250 | 262 | ||
@@ -262,6 +274,7 @@ bnx2_ctx_wr(struct bnx2 *bp, u32 cid_addr, u32 offset, u32 val) | |||
262 | REG_WR(bp, BNX2_CTX_DATA_ADR, offset); | 274 | REG_WR(bp, BNX2_CTX_DATA_ADR, offset); |
263 | REG_WR(bp, BNX2_CTX_DATA, val); | 275 | REG_WR(bp, BNX2_CTX_DATA, val); |
264 | } | 276 | } |
277 | spin_unlock_bh(&bp->indirect_lock); | ||
265 | } | 278 | } |
266 | 279 | ||
267 | static int | 280 | static int |
@@ -572,8 +585,8 @@ bnx2_report_fw_link(struct bnx2 *bp) | |||
572 | if (bp->autoneg) { | 585 | if (bp->autoneg) { |
573 | fw_link_status |= BNX2_LINK_STATUS_AN_ENABLED; | 586 | fw_link_status |= BNX2_LINK_STATUS_AN_ENABLED; |
574 | 587 | ||
575 | bnx2_read_phy(bp, MII_BMSR, &bmsr); | 588 | bnx2_read_phy(bp, bp->mii_bmsr, &bmsr); |
576 | bnx2_read_phy(bp, MII_BMSR, &bmsr); | 589 | bnx2_read_phy(bp, bp->mii_bmsr, &bmsr); |
577 | 590 | ||
578 | if (!(bmsr & BMSR_ANEGCOMPLETE) || | 591 | if (!(bmsr & BMSR_ANEGCOMPLETE) || |
579 | bp->phy_flags & PHY_PARALLEL_DETECT_FLAG) | 592 | bp->phy_flags & PHY_PARALLEL_DETECT_FLAG) |
@@ -654,8 +667,8 @@ bnx2_resolve_flow_ctrl(struct bnx2 *bp) | |||
654 | return; | 667 | return; |
655 | } | 668 | } |
656 | 669 | ||
657 | bnx2_read_phy(bp, MII_ADVERTISE, &local_adv); | 670 | bnx2_read_phy(bp, bp->mii_adv, &local_adv); |
658 | bnx2_read_phy(bp, MII_LPA, &remote_adv); | 671 | bnx2_read_phy(bp, bp->mii_lpa, &remote_adv); |
659 | 672 | ||
660 | if (bp->phy_flags & PHY_SERDES_FLAG) { | 673 | if (bp->phy_flags & PHY_SERDES_FLAG) { |
661 | u32 new_local_adv = 0; | 674 | u32 new_local_adv = 0; |
@@ -700,6 +713,45 @@ bnx2_resolve_flow_ctrl(struct bnx2 *bp) | |||
700 | } | 713 | } |
701 | 714 | ||
702 | static int | 715 | static int |
716 | bnx2_5709s_linkup(struct bnx2 *bp) | ||
717 | { | ||
718 | u32 val, speed; | ||
719 | |||
720 | bp->link_up = 1; | ||
721 | |||
722 | bnx2_write_phy(bp, MII_BNX2_BLK_ADDR, MII_BNX2_BLK_ADDR_GP_STATUS); | ||
723 | bnx2_read_phy(bp, MII_BNX2_GP_TOP_AN_STATUS1, &val); | ||
724 | bnx2_write_phy(bp, MII_BNX2_BLK_ADDR, MII_BNX2_BLK_ADDR_COMBO_IEEEB0); | ||
725 | |||
726 | if ((bp->autoneg & AUTONEG_SPEED) == 0) { | ||
727 | bp->line_speed = bp->req_line_speed; | ||
728 | bp->duplex = bp->req_duplex; | ||
729 | return 0; | ||
730 | } | ||
731 | speed = val & MII_BNX2_GP_TOP_AN_SPEED_MSK; | ||
732 | switch (speed) { | ||
733 | case MII_BNX2_GP_TOP_AN_SPEED_10: | ||
734 | bp->line_speed = SPEED_10; | ||
735 | break; | ||
736 | case MII_BNX2_GP_TOP_AN_SPEED_100: | ||
737 | bp->line_speed = SPEED_100; | ||
738 | break; | ||
739 | case MII_BNX2_GP_TOP_AN_SPEED_1G: | ||
740 | case MII_BNX2_GP_TOP_AN_SPEED_1GKV: | ||
741 | bp->line_speed = SPEED_1000; | ||
742 | break; | ||
743 | case MII_BNX2_GP_TOP_AN_SPEED_2_5G: | ||
744 | bp->line_speed = SPEED_2500; | ||
745 | break; | ||
746 | } | ||
747 | if (val & MII_BNX2_GP_TOP_AN_FD) | ||
748 | bp->duplex = DUPLEX_FULL; | ||
749 | else | ||
750 | bp->duplex = DUPLEX_HALF; | ||
751 | return 0; | ||
752 | } | ||
753 | |||
754 | static int | ||
703 | bnx2_5708s_linkup(struct bnx2 *bp) | 755 | bnx2_5708s_linkup(struct bnx2 *bp) |
704 | { | 756 | { |
705 | u32 val; | 757 | u32 val; |
@@ -736,7 +788,7 @@ bnx2_5706s_linkup(struct bnx2 *bp) | |||
736 | bp->link_up = 1; | 788 | bp->link_up = 1; |
737 | bp->line_speed = SPEED_1000; | 789 | bp->line_speed = SPEED_1000; |
738 | 790 | ||
739 | bnx2_read_phy(bp, MII_BMCR, &bmcr); | 791 | bnx2_read_phy(bp, bp->mii_bmcr, &bmcr); |
740 | if (bmcr & BMCR_FULLDPLX) { | 792 | if (bmcr & BMCR_FULLDPLX) { |
741 | bp->duplex = DUPLEX_FULL; | 793 | bp->duplex = DUPLEX_FULL; |
742 | } | 794 | } |
@@ -748,8 +800,8 @@ bnx2_5706s_linkup(struct bnx2 *bp) | |||
748 | return 0; | 800 | return 0; |
749 | } | 801 | } |
750 | 802 | ||
751 | bnx2_read_phy(bp, MII_ADVERTISE, &local_adv); | 803 | bnx2_read_phy(bp, bp->mii_adv, &local_adv); |
752 | bnx2_read_phy(bp, MII_LPA, &remote_adv); | 804 | bnx2_read_phy(bp, bp->mii_lpa, &remote_adv); |
753 | 805 | ||
754 | common = local_adv & remote_adv; | 806 | common = local_adv & remote_adv; |
755 | if (common & (ADVERTISE_1000XHALF | ADVERTISE_1000XFULL)) { | 807 | if (common & (ADVERTISE_1000XHALF | ADVERTISE_1000XFULL)) { |
@@ -770,7 +822,7 @@ bnx2_copper_linkup(struct bnx2 *bp) | |||
770 | { | 822 | { |
771 | u32 bmcr; | 823 | u32 bmcr; |
772 | 824 | ||
773 | bnx2_read_phy(bp, MII_BMCR, &bmcr); | 825 | bnx2_read_phy(bp, bp->mii_bmcr, &bmcr); |
774 | if (bmcr & BMCR_ANENABLE) { | 826 | if (bmcr & BMCR_ANENABLE) { |
775 | u32 local_adv, remote_adv, common; | 827 | u32 local_adv, remote_adv, common; |
776 | 828 | ||
@@ -787,8 +839,8 @@ bnx2_copper_linkup(struct bnx2 *bp) | |||
787 | bp->duplex = DUPLEX_HALF; | 839 | bp->duplex = DUPLEX_HALF; |
788 | } | 840 | } |
789 | else { | 841 | else { |
790 | bnx2_read_phy(bp, MII_ADVERTISE, &local_adv); | 842 | bnx2_read_phy(bp, bp->mii_adv, &local_adv); |
791 | bnx2_read_phy(bp, MII_LPA, &remote_adv); | 843 | bnx2_read_phy(bp, bp->mii_lpa, &remote_adv); |
792 | 844 | ||
793 | common = local_adv & remote_adv; | 845 | common = local_adv & remote_adv; |
794 | if (common & ADVERTISE_100FULL) { | 846 | if (common & ADVERTISE_100FULL) { |
@@ -898,6 +950,145 @@ bnx2_set_mac_link(struct bnx2 *bp) | |||
898 | return 0; | 950 | return 0; |
899 | } | 951 | } |
900 | 952 | ||
953 | static void | ||
954 | bnx2_enable_bmsr1(struct bnx2 *bp) | ||
955 | { | ||
956 | if ((bp->phy_flags & PHY_SERDES_FLAG) && | ||
957 | (CHIP_NUM(bp) == CHIP_NUM_5709)) | ||
958 | bnx2_write_phy(bp, MII_BNX2_BLK_ADDR, | ||
959 | MII_BNX2_BLK_ADDR_GP_STATUS); | ||
960 | } | ||
961 | |||
962 | static void | ||
963 | bnx2_disable_bmsr1(struct bnx2 *bp) | ||
964 | { | ||
965 | if ((bp->phy_flags & PHY_SERDES_FLAG) && | ||
966 | (CHIP_NUM(bp) == CHIP_NUM_5709)) | ||
967 | bnx2_write_phy(bp, MII_BNX2_BLK_ADDR, | ||
968 | MII_BNX2_BLK_ADDR_COMBO_IEEEB0); | ||
969 | } | ||
970 | |||
971 | static int | ||
972 | bnx2_test_and_enable_2g5(struct bnx2 *bp) | ||
973 | { | ||
974 | u32 up1; | ||
975 | int ret = 1; | ||
976 | |||
977 | if (!(bp->phy_flags & PHY_2_5G_CAPABLE_FLAG)) | ||
978 | return 0; | ||
979 | |||
980 | if (bp->autoneg & AUTONEG_SPEED) | ||
981 | bp->advertising |= ADVERTISED_2500baseX_Full; | ||
982 | |||
983 | if (CHIP_NUM(bp) == CHIP_NUM_5709) | ||
984 | bnx2_write_phy(bp, MII_BNX2_BLK_ADDR, MII_BNX2_BLK_ADDR_OVER1G); | ||
985 | |||
986 | bnx2_read_phy(bp, bp->mii_up1, &up1); | ||
987 | if (!(up1 & BCM5708S_UP1_2G5)) { | ||
988 | up1 |= BCM5708S_UP1_2G5; | ||
989 | bnx2_write_phy(bp, bp->mii_up1, up1); | ||
990 | ret = 0; | ||
991 | } | ||
992 | |||
993 | if (CHIP_NUM(bp) == CHIP_NUM_5709) | ||
994 | bnx2_write_phy(bp, MII_BNX2_BLK_ADDR, | ||
995 | MII_BNX2_BLK_ADDR_COMBO_IEEEB0); | ||
996 | |||
997 | return ret; | ||
998 | } | ||
999 | |||
1000 | static int | ||
1001 | bnx2_test_and_disable_2g5(struct bnx2 *bp) | ||
1002 | { | ||
1003 | u32 up1; | ||
1004 | int ret = 0; | ||
1005 | |||
1006 | if (!(bp->phy_flags & PHY_2_5G_CAPABLE_FLAG)) | ||
1007 | return 0; | ||
1008 | |||
1009 | if (CHIP_NUM(bp) == CHIP_NUM_5709) | ||
1010 | bnx2_write_phy(bp, MII_BNX2_BLK_ADDR, MII_BNX2_BLK_ADDR_OVER1G); | ||
1011 | |||
1012 | bnx2_read_phy(bp, bp->mii_up1, &up1); | ||
1013 | if (up1 & BCM5708S_UP1_2G5) { | ||
1014 | up1 &= ~BCM5708S_UP1_2G5; | ||
1015 | bnx2_write_phy(bp, bp->mii_up1, up1); | ||
1016 | ret = 1; | ||
1017 | } | ||
1018 | |||
1019 | if (CHIP_NUM(bp) == CHIP_NUM_5709) | ||
1020 | bnx2_write_phy(bp, MII_BNX2_BLK_ADDR, | ||
1021 | MII_BNX2_BLK_ADDR_COMBO_IEEEB0); | ||
1022 | |||
1023 | return ret; | ||
1024 | } | ||
1025 | |||
1026 | static void | ||
1027 | bnx2_enable_forced_2g5(struct bnx2 *bp) | ||
1028 | { | ||
1029 | u32 bmcr; | ||
1030 | |||
1031 | if (!(bp->phy_flags & PHY_2_5G_CAPABLE_FLAG)) | ||
1032 | return; | ||
1033 | |||
1034 | if (CHIP_NUM(bp) == CHIP_NUM_5709) { | ||
1035 | u32 val; | ||
1036 | |||
1037 | bnx2_write_phy(bp, MII_BNX2_BLK_ADDR, | ||
1038 | MII_BNX2_BLK_ADDR_SERDES_DIG); | ||
1039 | bnx2_read_phy(bp, MII_BNX2_SERDES_DIG_MISC1, &val); | ||
1040 | val &= ~MII_BNX2_SD_MISC1_FORCE_MSK; | ||
1041 | val |= MII_BNX2_SD_MISC1_FORCE | MII_BNX2_SD_MISC1_FORCE_2_5G; | ||
1042 | bnx2_write_phy(bp, MII_BNX2_SERDES_DIG_MISC1, val); | ||
1043 | |||
1044 | bnx2_write_phy(bp, MII_BNX2_BLK_ADDR, | ||
1045 | MII_BNX2_BLK_ADDR_COMBO_IEEEB0); | ||
1046 | bnx2_read_phy(bp, bp->mii_bmcr, &bmcr); | ||
1047 | |||
1048 | } else if (CHIP_NUM(bp) == CHIP_NUM_5708) { | ||
1049 | bnx2_read_phy(bp, bp->mii_bmcr, &bmcr); | ||
1050 | bmcr |= BCM5708S_BMCR_FORCE_2500; | ||
1051 | } | ||
1052 | |||
1053 | if (bp->autoneg & AUTONEG_SPEED) { | ||
1054 | bmcr &= ~BMCR_ANENABLE; | ||
1055 | if (bp->req_duplex == DUPLEX_FULL) | ||
1056 | bmcr |= BMCR_FULLDPLX; | ||
1057 | } | ||
1058 | bnx2_write_phy(bp, bp->mii_bmcr, bmcr); | ||
1059 | } | ||
1060 | |||
1061 | static void | ||
1062 | bnx2_disable_forced_2g5(struct bnx2 *bp) | ||
1063 | { | ||
1064 | u32 bmcr; | ||
1065 | |||
1066 | if (!(bp->phy_flags & PHY_2_5G_CAPABLE_FLAG)) | ||
1067 | return; | ||
1068 | |||
1069 | if (CHIP_NUM(bp) == CHIP_NUM_5709) { | ||
1070 | u32 val; | ||
1071 | |||
1072 | bnx2_write_phy(bp, MII_BNX2_BLK_ADDR, | ||
1073 | MII_BNX2_BLK_ADDR_SERDES_DIG); | ||
1074 | bnx2_read_phy(bp, MII_BNX2_SERDES_DIG_MISC1, &val); | ||
1075 | val &= ~MII_BNX2_SD_MISC1_FORCE; | ||
1076 | bnx2_write_phy(bp, MII_BNX2_SERDES_DIG_MISC1, val); | ||
1077 | |||
1078 | bnx2_write_phy(bp, MII_BNX2_BLK_ADDR, | ||
1079 | MII_BNX2_BLK_ADDR_COMBO_IEEEB0); | ||
1080 | bnx2_read_phy(bp, bp->mii_bmcr, &bmcr); | ||
1081 | |||
1082 | } else if (CHIP_NUM(bp) == CHIP_NUM_5708) { | ||
1083 | bnx2_read_phy(bp, bp->mii_bmcr, &bmcr); | ||
1084 | bmcr &= ~BCM5708S_BMCR_FORCE_2500; | ||
1085 | } | ||
1086 | |||
1087 | if (bp->autoneg & AUTONEG_SPEED) | ||
1088 | bmcr |= BMCR_SPEED1000 | BMCR_ANENABLE | BMCR_ANRESTART; | ||
1089 | bnx2_write_phy(bp, bp->mii_bmcr, bmcr); | ||
1090 | } | ||
1091 | |||
901 | static int | 1092 | static int |
902 | bnx2_set_link(struct bnx2 *bp) | 1093 | bnx2_set_link(struct bnx2 *bp) |
903 | { | 1094 | { |
@@ -911,8 +1102,10 @@ bnx2_set_link(struct bnx2 *bp) | |||
911 | 1102 | ||
912 | link_up = bp->link_up; | 1103 | link_up = bp->link_up; |
913 | 1104 | ||
914 | bnx2_read_phy(bp, MII_BMSR, &bmsr); | 1105 | bnx2_enable_bmsr1(bp); |
915 | bnx2_read_phy(bp, MII_BMSR, &bmsr); | 1106 | bnx2_read_phy(bp, bp->mii_bmsr1, &bmsr); |
1107 | bnx2_read_phy(bp, bp->mii_bmsr1, &bmsr); | ||
1108 | bnx2_disable_bmsr1(bp); | ||
916 | 1109 | ||
917 | if ((bp->phy_flags & PHY_SERDES_FLAG) && | 1110 | if ((bp->phy_flags & PHY_SERDES_FLAG) && |
918 | (CHIP_NUM(bp) == CHIP_NUM_5706)) { | 1111 | (CHIP_NUM(bp) == CHIP_NUM_5706)) { |
@@ -933,6 +1126,8 @@ bnx2_set_link(struct bnx2 *bp) | |||
933 | bnx2_5706s_linkup(bp); | 1126 | bnx2_5706s_linkup(bp); |
934 | else if (CHIP_NUM(bp) == CHIP_NUM_5708) | 1127 | else if (CHIP_NUM(bp) == CHIP_NUM_5708) |
935 | bnx2_5708s_linkup(bp); | 1128 | bnx2_5708s_linkup(bp); |
1129 | else if (CHIP_NUM(bp) == CHIP_NUM_5709) | ||
1130 | bnx2_5709s_linkup(bp); | ||
936 | } | 1131 | } |
937 | else { | 1132 | else { |
938 | bnx2_copper_linkup(bp); | 1133 | bnx2_copper_linkup(bp); |
@@ -941,17 +1136,9 @@ bnx2_set_link(struct bnx2 *bp) | |||
941 | } | 1136 | } |
942 | else { | 1137 | else { |
943 | if ((bp->phy_flags & PHY_SERDES_FLAG) && | 1138 | if ((bp->phy_flags & PHY_SERDES_FLAG) && |
944 | (bp->autoneg & AUTONEG_SPEED)) { | 1139 | (bp->autoneg & AUTONEG_SPEED)) |
1140 | bnx2_disable_forced_2g5(bp); | ||
945 | 1141 | ||
946 | u32 bmcr; | ||
947 | |||
948 | bnx2_read_phy(bp, MII_BMCR, &bmcr); | ||
949 | bmcr &= ~BCM5708S_BMCR_FORCE_2500; | ||
950 | if (!(bmcr & BMCR_ANENABLE)) { | ||
951 | bnx2_write_phy(bp, MII_BMCR, bmcr | | ||
952 | BMCR_ANENABLE); | ||
953 | } | ||
954 | } | ||
955 | bp->phy_flags &= ~PHY_PARALLEL_DETECT_FLAG; | 1142 | bp->phy_flags &= ~PHY_PARALLEL_DETECT_FLAG; |
956 | bp->link_up = 0; | 1143 | bp->link_up = 0; |
957 | } | 1144 | } |
@@ -971,13 +1158,13 @@ bnx2_reset_phy(struct bnx2 *bp) | |||
971 | int i; | 1158 | int i; |
972 | u32 reg; | 1159 | u32 reg; |
973 | 1160 | ||
974 | bnx2_write_phy(bp, MII_BMCR, BMCR_RESET); | 1161 | bnx2_write_phy(bp, bp->mii_bmcr, BMCR_RESET); |
975 | 1162 | ||
976 | #define PHY_RESET_MAX_WAIT 100 | 1163 | #define PHY_RESET_MAX_WAIT 100 |
977 | for (i = 0; i < PHY_RESET_MAX_WAIT; i++) { | 1164 | for (i = 0; i < PHY_RESET_MAX_WAIT; i++) { |
978 | udelay(10); | 1165 | udelay(10); |
979 | 1166 | ||
980 | bnx2_read_phy(bp, MII_BMCR, ®); | 1167 | bnx2_read_phy(bp, bp->mii_bmcr, ®); |
981 | if (!(reg & BMCR_RESET)) { | 1168 | if (!(reg & BMCR_RESET)) { |
982 | udelay(20); | 1169 | udelay(20); |
983 | break; | 1170 | break; |
@@ -1026,34 +1213,40 @@ bnx2_phy_get_pause_adv(struct bnx2 *bp) | |||
1026 | static int | 1213 | static int |
1027 | bnx2_setup_serdes_phy(struct bnx2 *bp) | 1214 | bnx2_setup_serdes_phy(struct bnx2 *bp) |
1028 | { | 1215 | { |
1029 | u32 adv, bmcr, up1; | 1216 | u32 adv, bmcr; |
1030 | u32 new_adv = 0; | 1217 | u32 new_adv = 0; |
1031 | 1218 | ||
1032 | if (!(bp->autoneg & AUTONEG_SPEED)) { | 1219 | if (!(bp->autoneg & AUTONEG_SPEED)) { |
1033 | u32 new_bmcr; | 1220 | u32 new_bmcr; |
1034 | int force_link_down = 0; | 1221 | int force_link_down = 0; |
1035 | 1222 | ||
1036 | bnx2_read_phy(bp, MII_ADVERTISE, &adv); | 1223 | if (bp->req_line_speed == SPEED_2500) { |
1224 | if (!bnx2_test_and_enable_2g5(bp)) | ||
1225 | force_link_down = 1; | ||
1226 | } else if (bp->req_line_speed == SPEED_1000) { | ||
1227 | if (bnx2_test_and_disable_2g5(bp)) | ||
1228 | force_link_down = 1; | ||
1229 | } | ||
1230 | bnx2_read_phy(bp, bp->mii_adv, &adv); | ||
1037 | adv &= ~(ADVERTISE_1000XFULL | ADVERTISE_1000XHALF); | 1231 | adv &= ~(ADVERTISE_1000XFULL | ADVERTISE_1000XHALF); |
1038 | 1232 | ||
1039 | bnx2_read_phy(bp, MII_BMCR, &bmcr); | 1233 | bnx2_read_phy(bp, bp->mii_bmcr, &bmcr); |
1040 | new_bmcr = bmcr & ~(BMCR_ANENABLE | BCM5708S_BMCR_FORCE_2500); | 1234 | new_bmcr = bmcr & ~BMCR_ANENABLE; |
1041 | new_bmcr |= BMCR_SPEED1000; | 1235 | new_bmcr |= BMCR_SPEED1000; |
1042 | if (bp->req_line_speed == SPEED_2500) { | 1236 | |
1043 | new_bmcr |= BCM5708S_BMCR_FORCE_2500; | 1237 | if (CHIP_NUM(bp) == CHIP_NUM_5709) { |
1044 | bnx2_read_phy(bp, BCM5708S_UP1, &up1); | 1238 | if (bp->req_line_speed == SPEED_2500) |
1045 | if (!(up1 & BCM5708S_UP1_2G5)) { | 1239 | bnx2_enable_forced_2g5(bp); |
1046 | up1 |= BCM5708S_UP1_2G5; | 1240 | else if (bp->req_line_speed == SPEED_1000) { |
1047 | bnx2_write_phy(bp, BCM5708S_UP1, up1); | 1241 | bnx2_disable_forced_2g5(bp); |
1048 | force_link_down = 1; | 1242 | new_bmcr &= ~0x2000; |
1049 | } | 1243 | } |
1244 | |||
1050 | } else if (CHIP_NUM(bp) == CHIP_NUM_5708) { | 1245 | } else if (CHIP_NUM(bp) == CHIP_NUM_5708) { |
1051 | bnx2_read_phy(bp, BCM5708S_UP1, &up1); | 1246 | if (bp->req_line_speed == SPEED_2500) |
1052 | if (up1 & BCM5708S_UP1_2G5) { | 1247 | new_bmcr |= BCM5708S_BMCR_FORCE_2500; |
1053 | up1 &= ~BCM5708S_UP1_2G5; | 1248 | else |
1054 | bnx2_write_phy(bp, BCM5708S_UP1, up1); | 1249 | new_bmcr = bmcr & ~BCM5708S_BMCR_FORCE_2500; |
1055 | force_link_down = 1; | ||
1056 | } | ||
1057 | } | 1250 | } |
1058 | 1251 | ||
1059 | if (bp->req_duplex == DUPLEX_FULL) { | 1252 | if (bp->req_duplex == DUPLEX_FULL) { |
@@ -1067,49 +1260,48 @@ bnx2_setup_serdes_phy(struct bnx2 *bp) | |||
1067 | if ((new_bmcr != bmcr) || (force_link_down)) { | 1260 | if ((new_bmcr != bmcr) || (force_link_down)) { |
1068 | /* Force a link down visible on the other side */ | 1261 | /* Force a link down visible on the other side */ |
1069 | if (bp->link_up) { | 1262 | if (bp->link_up) { |
1070 | bnx2_write_phy(bp, MII_ADVERTISE, adv & | 1263 | bnx2_write_phy(bp, bp->mii_adv, adv & |
1071 | ~(ADVERTISE_1000XFULL | | 1264 | ~(ADVERTISE_1000XFULL | |
1072 | ADVERTISE_1000XHALF)); | 1265 | ADVERTISE_1000XHALF)); |
1073 | bnx2_write_phy(bp, MII_BMCR, bmcr | | 1266 | bnx2_write_phy(bp, bp->mii_bmcr, bmcr | |
1074 | BMCR_ANRESTART | BMCR_ANENABLE); | 1267 | BMCR_ANRESTART | BMCR_ANENABLE); |
1075 | 1268 | ||
1076 | bp->link_up = 0; | 1269 | bp->link_up = 0; |
1077 | netif_carrier_off(bp->dev); | 1270 | netif_carrier_off(bp->dev); |
1078 | bnx2_write_phy(bp, MII_BMCR, new_bmcr); | 1271 | bnx2_write_phy(bp, bp->mii_bmcr, new_bmcr); |
1079 | bnx2_report_link(bp); | 1272 | bnx2_report_link(bp); |
1080 | } | 1273 | } |
1081 | bnx2_write_phy(bp, MII_ADVERTISE, adv); | 1274 | bnx2_write_phy(bp, bp->mii_adv, adv); |
1082 | bnx2_write_phy(bp, MII_BMCR, new_bmcr); | 1275 | bnx2_write_phy(bp, bp->mii_bmcr, new_bmcr); |
1276 | } else { | ||
1277 | bnx2_resolve_flow_ctrl(bp); | ||
1278 | bnx2_set_mac_link(bp); | ||
1083 | } | 1279 | } |
1084 | return 0; | 1280 | return 0; |
1085 | } | 1281 | } |
1086 | 1282 | ||
1087 | if (bp->phy_flags & PHY_2_5G_CAPABLE_FLAG) { | 1283 | bnx2_test_and_enable_2g5(bp); |
1088 | bnx2_read_phy(bp, BCM5708S_UP1, &up1); | ||
1089 | up1 |= BCM5708S_UP1_2G5; | ||
1090 | bnx2_write_phy(bp, BCM5708S_UP1, up1); | ||
1091 | } | ||
1092 | 1284 | ||
1093 | if (bp->advertising & ADVERTISED_1000baseT_Full) | 1285 | if (bp->advertising & ADVERTISED_1000baseT_Full) |
1094 | new_adv |= ADVERTISE_1000XFULL; | 1286 | new_adv |= ADVERTISE_1000XFULL; |
1095 | 1287 | ||
1096 | new_adv |= bnx2_phy_get_pause_adv(bp); | 1288 | new_adv |= bnx2_phy_get_pause_adv(bp); |
1097 | 1289 | ||
1098 | bnx2_read_phy(bp, MII_ADVERTISE, &adv); | 1290 | bnx2_read_phy(bp, bp->mii_adv, &adv); |
1099 | bnx2_read_phy(bp, MII_BMCR, &bmcr); | 1291 | bnx2_read_phy(bp, bp->mii_bmcr, &bmcr); |
1100 | 1292 | ||
1101 | bp->serdes_an_pending = 0; | 1293 | bp->serdes_an_pending = 0; |
1102 | if ((adv != new_adv) || ((bmcr & BMCR_ANENABLE) == 0)) { | 1294 | if ((adv != new_adv) || ((bmcr & BMCR_ANENABLE) == 0)) { |
1103 | /* Force a link down visible on the other side */ | 1295 | /* Force a link down visible on the other side */ |
1104 | if (bp->link_up) { | 1296 | if (bp->link_up) { |
1105 | bnx2_write_phy(bp, MII_BMCR, BMCR_LOOPBACK); | 1297 | bnx2_write_phy(bp, bp->mii_bmcr, BMCR_LOOPBACK); |
1106 | spin_unlock_bh(&bp->phy_lock); | 1298 | spin_unlock_bh(&bp->phy_lock); |
1107 | msleep(20); | 1299 | msleep(20); |
1108 | spin_lock_bh(&bp->phy_lock); | 1300 | spin_lock_bh(&bp->phy_lock); |
1109 | } | 1301 | } |
1110 | 1302 | ||
1111 | bnx2_write_phy(bp, MII_ADVERTISE, new_adv); | 1303 | bnx2_write_phy(bp, bp->mii_adv, new_adv); |
1112 | bnx2_write_phy(bp, MII_BMCR, bmcr | BMCR_ANRESTART | | 1304 | bnx2_write_phy(bp, bp->mii_bmcr, bmcr | BMCR_ANRESTART | |
1113 | BMCR_ANENABLE); | 1305 | BMCR_ANENABLE); |
1114 | /* Speed up link-up time when the link partner | 1306 | /* Speed up link-up time when the link partner |
1115 | * does not autonegotiate which is very common | 1307 | * does not autonegotiate which is very common |
@@ -1122,6 +1314,9 @@ bnx2_setup_serdes_phy(struct bnx2 *bp) | |||
1122 | bp->current_interval = SERDES_AN_TIMEOUT; | 1314 | bp->current_interval = SERDES_AN_TIMEOUT; |
1123 | bp->serdes_an_pending = 1; | 1315 | bp->serdes_an_pending = 1; |
1124 | mod_timer(&bp->timer, jiffies + bp->current_interval); | 1316 | mod_timer(&bp->timer, jiffies + bp->current_interval); |
1317 | } else { | ||
1318 | bnx2_resolve_flow_ctrl(bp); | ||
1319 | bnx2_set_mac_link(bp); | ||
1125 | } | 1320 | } |
1126 | 1321 | ||
1127 | return 0; | 1322 | return 0; |
@@ -1146,14 +1341,14 @@ bnx2_setup_copper_phy(struct bnx2 *bp) | |||
1146 | u32 bmcr; | 1341 | u32 bmcr; |
1147 | u32 new_bmcr; | 1342 | u32 new_bmcr; |
1148 | 1343 | ||
1149 | bnx2_read_phy(bp, MII_BMCR, &bmcr); | 1344 | bnx2_read_phy(bp, bp->mii_bmcr, &bmcr); |
1150 | 1345 | ||
1151 | if (bp->autoneg & AUTONEG_SPEED) { | 1346 | if (bp->autoneg & AUTONEG_SPEED) { |
1152 | u32 adv_reg, adv1000_reg; | 1347 | u32 adv_reg, adv1000_reg; |
1153 | u32 new_adv_reg = 0; | 1348 | u32 new_adv_reg = 0; |
1154 | u32 new_adv1000_reg = 0; | 1349 | u32 new_adv1000_reg = 0; |
1155 | 1350 | ||
1156 | bnx2_read_phy(bp, MII_ADVERTISE, &adv_reg); | 1351 | bnx2_read_phy(bp, bp->mii_adv, &adv_reg); |
1157 | adv_reg &= (PHY_ALL_10_100_SPEED | ADVERTISE_PAUSE_CAP | | 1352 | adv_reg &= (PHY_ALL_10_100_SPEED | ADVERTISE_PAUSE_CAP | |
1158 | ADVERTISE_PAUSE_ASYM); | 1353 | ADVERTISE_PAUSE_ASYM); |
1159 | 1354 | ||
@@ -1179,9 +1374,9 @@ bnx2_setup_copper_phy(struct bnx2 *bp) | |||
1179 | (adv_reg != new_adv_reg) || | 1374 | (adv_reg != new_adv_reg) || |
1180 | ((bmcr & BMCR_ANENABLE) == 0)) { | 1375 | ((bmcr & BMCR_ANENABLE) == 0)) { |
1181 | 1376 | ||
1182 | bnx2_write_phy(bp, MII_ADVERTISE, new_adv_reg); | 1377 | bnx2_write_phy(bp, bp->mii_adv, new_adv_reg); |
1183 | bnx2_write_phy(bp, MII_CTRL1000, new_adv1000_reg); | 1378 | bnx2_write_phy(bp, MII_CTRL1000, new_adv1000_reg); |
1184 | bnx2_write_phy(bp, MII_BMCR, BMCR_ANRESTART | | 1379 | bnx2_write_phy(bp, bp->mii_bmcr, BMCR_ANRESTART | |
1185 | BMCR_ANENABLE); | 1380 | BMCR_ANENABLE); |
1186 | } | 1381 | } |
1187 | else if (bp->link_up) { | 1382 | else if (bp->link_up) { |
@@ -1204,21 +1399,21 @@ bnx2_setup_copper_phy(struct bnx2 *bp) | |||
1204 | if (new_bmcr != bmcr) { | 1399 | if (new_bmcr != bmcr) { |
1205 | u32 bmsr; | 1400 | u32 bmsr; |
1206 | 1401 | ||
1207 | bnx2_read_phy(bp, MII_BMSR, &bmsr); | 1402 | bnx2_read_phy(bp, bp->mii_bmsr, &bmsr); |
1208 | bnx2_read_phy(bp, MII_BMSR, &bmsr); | 1403 | bnx2_read_phy(bp, bp->mii_bmsr, &bmsr); |
1209 | 1404 | ||
1210 | if (bmsr & BMSR_LSTATUS) { | 1405 | if (bmsr & BMSR_LSTATUS) { |
1211 | /* Force link down */ | 1406 | /* Force link down */ |
1212 | bnx2_write_phy(bp, MII_BMCR, BMCR_LOOPBACK); | 1407 | bnx2_write_phy(bp, bp->mii_bmcr, BMCR_LOOPBACK); |
1213 | spin_unlock_bh(&bp->phy_lock); | 1408 | spin_unlock_bh(&bp->phy_lock); |
1214 | msleep(50); | 1409 | msleep(50); |
1215 | spin_lock_bh(&bp->phy_lock); | 1410 | spin_lock_bh(&bp->phy_lock); |
1216 | 1411 | ||
1217 | bnx2_read_phy(bp, MII_BMSR, &bmsr); | 1412 | bnx2_read_phy(bp, bp->mii_bmsr, &bmsr); |
1218 | bnx2_read_phy(bp, MII_BMSR, &bmsr); | 1413 | bnx2_read_phy(bp, bp->mii_bmsr, &bmsr); |
1219 | } | 1414 | } |
1220 | 1415 | ||
1221 | bnx2_write_phy(bp, MII_BMCR, new_bmcr); | 1416 | bnx2_write_phy(bp, bp->mii_bmcr, new_bmcr); |
1222 | 1417 | ||
1223 | /* Normally, the new speed is setup after the link has | 1418 | /* Normally, the new speed is setup after the link has |
1224 | * gone down and up again. In some cases, link will not go | 1419 | * gone down and up again. In some cases, link will not go |
@@ -1230,6 +1425,9 @@ bnx2_setup_copper_phy(struct bnx2 *bp) | |||
1230 | bnx2_resolve_flow_ctrl(bp); | 1425 | bnx2_resolve_flow_ctrl(bp); |
1231 | bnx2_set_mac_link(bp); | 1426 | bnx2_set_mac_link(bp); |
1232 | } | 1427 | } |
1428 | } else { | ||
1429 | bnx2_resolve_flow_ctrl(bp); | ||
1430 | bnx2_set_mac_link(bp); | ||
1233 | } | 1431 | } |
1234 | return 0; | 1432 | return 0; |
1235 | } | 1433 | } |
@@ -1249,10 +1447,63 @@ bnx2_setup_phy(struct bnx2 *bp) | |||
1249 | } | 1447 | } |
1250 | 1448 | ||
1251 | static int | 1449 | static int |
1450 | bnx2_init_5709s_phy(struct bnx2 *bp) | ||
1451 | { | ||
1452 | u32 val; | ||
1453 | |||
1454 | bp->mii_bmcr = MII_BMCR + 0x10; | ||
1455 | bp->mii_bmsr = MII_BMSR + 0x10; | ||
1456 | bp->mii_bmsr1 = MII_BNX2_GP_TOP_AN_STATUS1; | ||
1457 | bp->mii_adv = MII_ADVERTISE + 0x10; | ||
1458 | bp->mii_lpa = MII_LPA + 0x10; | ||
1459 | bp->mii_up1 = MII_BNX2_OVER1G_UP1; | ||
1460 | |||
1461 | bnx2_write_phy(bp, MII_BNX2_BLK_ADDR, MII_BNX2_BLK_ADDR_AER); | ||
1462 | bnx2_write_phy(bp, MII_BNX2_AER_AER, MII_BNX2_AER_AER_AN_MMD); | ||
1463 | |||
1464 | bnx2_write_phy(bp, MII_BNX2_BLK_ADDR, MII_BNX2_BLK_ADDR_COMBO_IEEEB0); | ||
1465 | bnx2_reset_phy(bp); | ||
1466 | |||
1467 | bnx2_write_phy(bp, MII_BNX2_BLK_ADDR, MII_BNX2_BLK_ADDR_SERDES_DIG); | ||
1468 | |||
1469 | bnx2_read_phy(bp, MII_BNX2_SERDES_DIG_1000XCTL1, &val); | ||
1470 | val &= ~MII_BNX2_SD_1000XCTL1_AUTODET; | ||
1471 | val |= MII_BNX2_SD_1000XCTL1_FIBER; | ||
1472 | bnx2_write_phy(bp, MII_BNX2_SERDES_DIG_1000XCTL1, val); | ||
1473 | |||
1474 | bnx2_write_phy(bp, MII_BNX2_BLK_ADDR, MII_BNX2_BLK_ADDR_OVER1G); | ||
1475 | bnx2_read_phy(bp, MII_BNX2_OVER1G_UP1, &val); | ||
1476 | if (bp->phy_flags & PHY_2_5G_CAPABLE_FLAG) | ||
1477 | val |= BCM5708S_UP1_2G5; | ||
1478 | else | ||
1479 | val &= ~BCM5708S_UP1_2G5; | ||
1480 | bnx2_write_phy(bp, MII_BNX2_OVER1G_UP1, val); | ||
1481 | |||
1482 | bnx2_write_phy(bp, MII_BNX2_BLK_ADDR, MII_BNX2_BLK_ADDR_BAM_NXTPG); | ||
1483 | bnx2_read_phy(bp, MII_BNX2_BAM_NXTPG_CTL, &val); | ||
1484 | val |= MII_BNX2_NXTPG_CTL_T2 | MII_BNX2_NXTPG_CTL_BAM; | ||
1485 | bnx2_write_phy(bp, MII_BNX2_BAM_NXTPG_CTL, val); | ||
1486 | |||
1487 | bnx2_write_phy(bp, MII_BNX2_BLK_ADDR, MII_BNX2_BLK_ADDR_CL73_USERB0); | ||
1488 | |||
1489 | val = MII_BNX2_CL73_BAM_EN | MII_BNX2_CL73_BAM_STA_MGR_EN | | ||
1490 | MII_BNX2_CL73_BAM_NP_AFT_BP_EN; | ||
1491 | bnx2_write_phy(bp, MII_BNX2_CL73_BAM_CTL1, val); | ||
1492 | |||
1493 | bnx2_write_phy(bp, MII_BNX2_BLK_ADDR, MII_BNX2_BLK_ADDR_COMBO_IEEEB0); | ||
1494 | |||
1495 | return 0; | ||
1496 | } | ||
1497 | |||
1498 | static int | ||
1252 | bnx2_init_5708s_phy(struct bnx2 *bp) | 1499 | bnx2_init_5708s_phy(struct bnx2 *bp) |
1253 | { | 1500 | { |
1254 | u32 val; | 1501 | u32 val; |
1255 | 1502 | ||
1503 | bnx2_reset_phy(bp); | ||
1504 | |||
1505 | bp->mii_up1 = BCM5708S_UP1; | ||
1506 | |||
1256 | bnx2_write_phy(bp, BCM5708S_BLK_ADDR, BCM5708S_BLK_ADDR_DIG3); | 1507 | bnx2_write_phy(bp, BCM5708S_BLK_ADDR, BCM5708S_BLK_ADDR_DIG3); |
1257 | bnx2_write_phy(bp, BCM5708S_DIG_3_0, BCM5708S_DIG_3_0_USE_IEEE); | 1508 | bnx2_write_phy(bp, BCM5708S_DIG_3_0, BCM5708S_DIG_3_0_USE_IEEE); |
1258 | bnx2_write_phy(bp, BCM5708S_BLK_ADDR, BCM5708S_BLK_ADDR_DIG); | 1509 | bnx2_write_phy(bp, BCM5708S_BLK_ADDR, BCM5708S_BLK_ADDR_DIG); |
@@ -1305,6 +1556,8 @@ bnx2_init_5708s_phy(struct bnx2 *bp) | |||
1305 | static int | 1556 | static int |
1306 | bnx2_init_5706s_phy(struct bnx2 *bp) | 1557 | bnx2_init_5706s_phy(struct bnx2 *bp) |
1307 | { | 1558 | { |
1559 | bnx2_reset_phy(bp); | ||
1560 | |||
1308 | bp->phy_flags &= ~PHY_PARALLEL_DETECT_FLAG; | 1561 | bp->phy_flags &= ~PHY_PARALLEL_DETECT_FLAG; |
1309 | 1562 | ||
1310 | if (CHIP_NUM(bp) == CHIP_NUM_5706) | 1563 | if (CHIP_NUM(bp) == CHIP_NUM_5706) |
@@ -1342,6 +1595,8 @@ bnx2_init_copper_phy(struct bnx2 *bp) | |||
1342 | { | 1595 | { |
1343 | u32 val; | 1596 | u32 val; |
1344 | 1597 | ||
1598 | bnx2_reset_phy(bp); | ||
1599 | |||
1345 | if (bp->phy_flags & PHY_CRC_FIX_FLAG) { | 1600 | if (bp->phy_flags & PHY_CRC_FIX_FLAG) { |
1346 | bnx2_write_phy(bp, 0x18, 0x0c00); | 1601 | bnx2_write_phy(bp, 0x18, 0x0c00); |
1347 | bnx2_write_phy(bp, 0x17, 0x000a); | 1602 | bnx2_write_phy(bp, 0x17, 0x000a); |
@@ -1396,9 +1651,13 @@ bnx2_init_phy(struct bnx2 *bp) | |||
1396 | bp->phy_flags &= ~PHY_INT_MODE_MASK_FLAG; | 1651 | bp->phy_flags &= ~PHY_INT_MODE_MASK_FLAG; |
1397 | bp->phy_flags |= PHY_INT_MODE_LINK_READY_FLAG; | 1652 | bp->phy_flags |= PHY_INT_MODE_LINK_READY_FLAG; |
1398 | 1653 | ||
1399 | REG_WR(bp, BNX2_EMAC_ATTENTION_ENA, BNX2_EMAC_ATTENTION_ENA_LINK); | 1654 | bp->mii_bmcr = MII_BMCR; |
1655 | bp->mii_bmsr = MII_BMSR; | ||
1656 | bp->mii_bmsr1 = MII_BMSR; | ||
1657 | bp->mii_adv = MII_ADVERTISE; | ||
1658 | bp->mii_lpa = MII_LPA; | ||
1400 | 1659 | ||
1401 | bnx2_reset_phy(bp); | 1660 | REG_WR(bp, BNX2_EMAC_ATTENTION_ENA, BNX2_EMAC_ATTENTION_ENA_LINK); |
1402 | 1661 | ||
1403 | bnx2_read_phy(bp, MII_PHYSID1, &val); | 1662 | bnx2_read_phy(bp, MII_PHYSID1, &val); |
1404 | bp->phy_id = val << 16; | 1663 | bp->phy_id = val << 16; |
@@ -1410,6 +1669,8 @@ bnx2_init_phy(struct bnx2 *bp) | |||
1410 | rc = bnx2_init_5706s_phy(bp); | 1669 | rc = bnx2_init_5706s_phy(bp); |
1411 | else if (CHIP_NUM(bp) == CHIP_NUM_5708) | 1670 | else if (CHIP_NUM(bp) == CHIP_NUM_5708) |
1412 | rc = bnx2_init_5708s_phy(bp); | 1671 | rc = bnx2_init_5708s_phy(bp); |
1672 | else if (CHIP_NUM(bp) == CHIP_NUM_5709) | ||
1673 | rc = bnx2_init_5709s_phy(bp); | ||
1413 | } | 1674 | } |
1414 | else { | 1675 | else { |
1415 | rc = bnx2_init_copper_phy(bp); | 1676 | rc = bnx2_init_copper_phy(bp); |
@@ -1442,7 +1703,7 @@ bnx2_set_phy_loopback(struct bnx2 *bp) | |||
1442 | int rc, i; | 1703 | int rc, i; |
1443 | 1704 | ||
1444 | spin_lock_bh(&bp->phy_lock); | 1705 | spin_lock_bh(&bp->phy_lock); |
1445 | rc = bnx2_write_phy(bp, MII_BMCR, BMCR_LOOPBACK | BMCR_FULLDPLX | | 1706 | rc = bnx2_write_phy(bp, bp->mii_bmcr, BMCR_LOOPBACK | BMCR_FULLDPLX | |
1446 | BMCR_SPEED1000); | 1707 | BMCR_SPEED1000); |
1447 | spin_unlock_bh(&bp->phy_lock); | 1708 | spin_unlock_bh(&bp->phy_lock); |
1448 | if (rc) | 1709 | if (rc) |
@@ -1681,25 +1942,33 @@ bnx2_alloc_rx_skb(struct bnx2 *bp, u16 index) | |||
1681 | return 0; | 1942 | return 0; |
1682 | } | 1943 | } |
1683 | 1944 | ||
1684 | static void | 1945 | static int |
1685 | bnx2_phy_int(struct bnx2 *bp) | 1946 | bnx2_phy_event_is_set(struct bnx2 *bp, u32 event) |
1686 | { | 1947 | { |
1948 | struct status_block *sblk = bp->status_blk; | ||
1687 | u32 new_link_state, old_link_state; | 1949 | u32 new_link_state, old_link_state; |
1950 | int is_set = 1; | ||
1688 | 1951 | ||
1689 | new_link_state = bp->status_blk->status_attn_bits & | 1952 | new_link_state = sblk->status_attn_bits & event; |
1690 | STATUS_ATTN_BITS_LINK_STATE; | 1953 | old_link_state = sblk->status_attn_bits_ack & event; |
1691 | old_link_state = bp->status_blk->status_attn_bits_ack & | ||
1692 | STATUS_ATTN_BITS_LINK_STATE; | ||
1693 | if (new_link_state != old_link_state) { | 1954 | if (new_link_state != old_link_state) { |
1694 | if (new_link_state) { | 1955 | if (new_link_state) |
1695 | REG_WR(bp, BNX2_PCICFG_STATUS_BIT_SET_CMD, | 1956 | REG_WR(bp, BNX2_PCICFG_STATUS_BIT_SET_CMD, event); |
1696 | STATUS_ATTN_BITS_LINK_STATE); | 1957 | else |
1697 | } | 1958 | REG_WR(bp, BNX2_PCICFG_STATUS_BIT_CLEAR_CMD, event); |
1698 | else { | 1959 | } else |
1699 | REG_WR(bp, BNX2_PCICFG_STATUS_BIT_CLEAR_CMD, | 1960 | is_set = 0; |
1700 | STATUS_ATTN_BITS_LINK_STATE); | 1961 | |
1701 | } | 1962 | return is_set; |
1963 | } | ||
1964 | |||
1965 | static void | ||
1966 | bnx2_phy_int(struct bnx2 *bp) | ||
1967 | { | ||
1968 | if (bnx2_phy_event_is_set(bp, STATUS_ATTN_BITS_LINK_STATE)) { | ||
1969 | spin_lock(&bp->phy_lock); | ||
1702 | bnx2_set_link(bp); | 1970 | bnx2_set_link(bp); |
1971 | spin_unlock(&bp->phy_lock); | ||
1703 | } | 1972 | } |
1704 | } | 1973 | } |
1705 | 1974 | ||
@@ -1993,6 +2262,23 @@ bnx2_msi(int irq, void *dev_instance) | |||
1993 | } | 2262 | } |
1994 | 2263 | ||
1995 | static irqreturn_t | 2264 | static irqreturn_t |
2265 | bnx2_msi_1shot(int irq, void *dev_instance) | ||
2266 | { | ||
2267 | struct net_device *dev = dev_instance; | ||
2268 | struct bnx2 *bp = netdev_priv(dev); | ||
2269 | |||
2270 | prefetch(bp->status_blk); | ||
2271 | |||
2272 | /* Return here if interrupt is disabled. */ | ||
2273 | if (unlikely(atomic_read(&bp->intr_sem) != 0)) | ||
2274 | return IRQ_HANDLED; | ||
2275 | |||
2276 | netif_rx_schedule(dev); | ||
2277 | |||
2278 | return IRQ_HANDLED; | ||
2279 | } | ||
2280 | |||
2281 | static irqreturn_t | ||
1996 | bnx2_interrupt(int irq, void *dev_instance) | 2282 | bnx2_interrupt(int irq, void *dev_instance) |
1997 | { | 2283 | { |
1998 | struct net_device *dev = dev_instance; | 2284 | struct net_device *dev = dev_instance; |
@@ -2022,6 +2308,8 @@ bnx2_interrupt(int irq, void *dev_instance) | |||
2022 | return IRQ_HANDLED; | 2308 | return IRQ_HANDLED; |
2023 | } | 2309 | } |
2024 | 2310 | ||
2311 | #define STATUS_ATTN_EVENTS STATUS_ATTN_BITS_LINK_STATE | ||
2312 | |||
2025 | static inline int | 2313 | static inline int |
2026 | bnx2_has_work(struct bnx2 *bp) | 2314 | bnx2_has_work(struct bnx2 *bp) |
2027 | { | 2315 | { |
@@ -2031,8 +2319,8 @@ bnx2_has_work(struct bnx2 *bp) | |||
2031 | (sblk->status_tx_quick_consumer_index0 != bp->hw_tx_cons)) | 2319 | (sblk->status_tx_quick_consumer_index0 != bp->hw_tx_cons)) |
2032 | return 1; | 2320 | return 1; |
2033 | 2321 | ||
2034 | if ((sblk->status_attn_bits & STATUS_ATTN_BITS_LINK_STATE) != | 2322 | if ((sblk->status_attn_bits & STATUS_ATTN_EVENTS) != |
2035 | (sblk->status_attn_bits_ack & STATUS_ATTN_BITS_LINK_STATE)) | 2323 | (sblk->status_attn_bits_ack & STATUS_ATTN_EVENTS)) |
2036 | return 1; | 2324 | return 1; |
2037 | 2325 | ||
2038 | return 0; | 2326 | return 0; |
@@ -2042,15 +2330,14 @@ static int | |||
2042 | bnx2_poll(struct net_device *dev, int *budget) | 2330 | bnx2_poll(struct net_device *dev, int *budget) |
2043 | { | 2331 | { |
2044 | struct bnx2 *bp = netdev_priv(dev); | 2332 | struct bnx2 *bp = netdev_priv(dev); |
2333 | struct status_block *sblk = bp->status_blk; | ||
2334 | u32 status_attn_bits = sblk->status_attn_bits; | ||
2335 | u32 status_attn_bits_ack = sblk->status_attn_bits_ack; | ||
2045 | 2336 | ||
2046 | if ((bp->status_blk->status_attn_bits & | 2337 | if ((status_attn_bits & STATUS_ATTN_EVENTS) != |
2047 | STATUS_ATTN_BITS_LINK_STATE) != | 2338 | (status_attn_bits_ack & STATUS_ATTN_EVENTS)) { |
2048 | (bp->status_blk->status_attn_bits_ack & | ||
2049 | STATUS_ATTN_BITS_LINK_STATE)) { | ||
2050 | 2339 | ||
2051 | spin_lock(&bp->phy_lock); | ||
2052 | bnx2_phy_int(bp); | 2340 | bnx2_phy_int(bp); |
2053 | spin_unlock(&bp->phy_lock); | ||
2054 | 2341 | ||
2055 | /* This is needed to take care of transient status | 2342 | /* This is needed to take care of transient status |
2056 | * during link changes. | 2343 | * during link changes. |
@@ -3489,17 +3776,21 @@ bnx2_init_chip(struct bnx2 *bp) | |||
3489 | REG_WR(bp, BNX2_HC_STAT_COLLECT_TICKS, 0xbb8); /* 3ms */ | 3776 | REG_WR(bp, BNX2_HC_STAT_COLLECT_TICKS, 0xbb8); /* 3ms */ |
3490 | 3777 | ||
3491 | if (CHIP_ID(bp) == CHIP_ID_5706_A1) | 3778 | if (CHIP_ID(bp) == CHIP_ID_5706_A1) |
3492 | REG_WR(bp, BNX2_HC_CONFIG, BNX2_HC_CONFIG_COLLECT_STATS); | 3779 | val = BNX2_HC_CONFIG_COLLECT_STATS; |
3493 | else { | 3780 | else { |
3494 | REG_WR(bp, BNX2_HC_CONFIG, BNX2_HC_CONFIG_RX_TMR_MODE | | 3781 | val = BNX2_HC_CONFIG_RX_TMR_MODE | BNX2_HC_CONFIG_TX_TMR_MODE | |
3495 | BNX2_HC_CONFIG_TX_TMR_MODE | | 3782 | BNX2_HC_CONFIG_COLLECT_STATS; |
3496 | BNX2_HC_CONFIG_COLLECT_STATS); | ||
3497 | } | 3783 | } |
3498 | 3784 | ||
3785 | if (bp->flags & ONE_SHOT_MSI_FLAG) | ||
3786 | val |= BNX2_HC_CONFIG_ONE_SHOT; | ||
3787 | |||
3788 | REG_WR(bp, BNX2_HC_CONFIG, val); | ||
3789 | |||
3499 | /* Clear internal stats counters. */ | 3790 | /* Clear internal stats counters. */ |
3500 | REG_WR(bp, BNX2_HC_COMMAND, BNX2_HC_COMMAND_CLR_STAT_NOW); | 3791 | REG_WR(bp, BNX2_HC_COMMAND, BNX2_HC_COMMAND_CLR_STAT_NOW); |
3501 | 3792 | ||
3502 | REG_WR(bp, BNX2_HC_ATTN_BITS_ENABLE, STATUS_ATTN_BITS_LINK_STATE); | 3793 | REG_WR(bp, BNX2_HC_ATTN_BITS_ENABLE, STATUS_ATTN_EVENTS); |
3503 | 3794 | ||
3504 | if (REG_RD_IND(bp, bp->shmem_base + BNX2_PORT_FEATURE) & | 3795 | if (REG_RD_IND(bp, bp->shmem_base + BNX2_PORT_FEATURE) & |
3505 | BNX2_PORT_FEATURE_ASF_ENABLED) | 3796 | BNX2_PORT_FEATURE_ASF_ENABLED) |
@@ -3763,10 +4054,11 @@ static int | |||
3763 | bnx2_test_registers(struct bnx2 *bp) | 4054 | bnx2_test_registers(struct bnx2 *bp) |
3764 | { | 4055 | { |
3765 | int ret; | 4056 | int ret; |
3766 | int i; | 4057 | int i, is_5709; |
3767 | static const struct { | 4058 | static const struct { |
3768 | u16 offset; | 4059 | u16 offset; |
3769 | u16 flags; | 4060 | u16 flags; |
4061 | #define BNX2_FL_NOT_5709 1 | ||
3770 | u32 rw_mask; | 4062 | u32 rw_mask; |
3771 | u32 ro_mask; | 4063 | u32 ro_mask; |
3772 | } reg_tbl[] = { | 4064 | } reg_tbl[] = { |
@@ -3774,26 +4066,26 @@ bnx2_test_registers(struct bnx2 *bp) | |||
3774 | { 0x0090, 0, 0xffffffff, 0x00000000 }, | 4066 | { 0x0090, 0, 0xffffffff, 0x00000000 }, |
3775 | { 0x0094, 0, 0x00000000, 0x00000000 }, | 4067 | { 0x0094, 0, 0x00000000, 0x00000000 }, |
3776 | 4068 | ||
3777 | { 0x0404, 0, 0x00003f00, 0x00000000 }, | 4069 | { 0x0404, BNX2_FL_NOT_5709, 0x00003f00, 0x00000000 }, |
3778 | { 0x0418, 0, 0x00000000, 0xffffffff }, | 4070 | { 0x0418, BNX2_FL_NOT_5709, 0x00000000, 0xffffffff }, |
3779 | { 0x041c, 0, 0x00000000, 0xffffffff }, | 4071 | { 0x041c, BNX2_FL_NOT_5709, 0x00000000, 0xffffffff }, |
3780 | { 0x0420, 0, 0x00000000, 0x80ffffff }, | 4072 | { 0x0420, BNX2_FL_NOT_5709, 0x00000000, 0x80ffffff }, |
3781 | { 0x0424, 0, 0x00000000, 0x00000000 }, | 4073 | { 0x0424, BNX2_FL_NOT_5709, 0x00000000, 0x00000000 }, |
3782 | { 0x0428, 0, 0x00000000, 0x00000001 }, | 4074 | { 0x0428, BNX2_FL_NOT_5709, 0x00000000, 0x00000001 }, |
3783 | { 0x0450, 0, 0x00000000, 0x0000ffff }, | 4075 | { 0x0450, BNX2_FL_NOT_5709, 0x00000000, 0x0000ffff }, |
3784 | { 0x0454, 0, 0x00000000, 0xffffffff }, | 4076 | { 0x0454, BNX2_FL_NOT_5709, 0x00000000, 0xffffffff }, |
3785 | { 0x0458, 0, 0x00000000, 0xffffffff }, | 4077 | { 0x0458, BNX2_FL_NOT_5709, 0x00000000, 0xffffffff }, |
3786 | 4078 | ||
3787 | { 0x0808, 0, 0x00000000, 0xffffffff }, | 4079 | { 0x0808, BNX2_FL_NOT_5709, 0x00000000, 0xffffffff }, |
3788 | { 0x0854, 0, 0x00000000, 0xffffffff }, | 4080 | { 0x0854, BNX2_FL_NOT_5709, 0x00000000, 0xffffffff }, |
3789 | { 0x0868, 0, 0x00000000, 0x77777777 }, | 4081 | { 0x0868, BNX2_FL_NOT_5709, 0x00000000, 0x77777777 }, |
3790 | { 0x086c, 0, 0x00000000, 0x77777777 }, | 4082 | { 0x086c, BNX2_FL_NOT_5709, 0x00000000, 0x77777777 }, |
3791 | { 0x0870, 0, 0x00000000, 0x77777777 }, | 4083 | { 0x0870, BNX2_FL_NOT_5709, 0x00000000, 0x77777777 }, |
3792 | { 0x0874, 0, 0x00000000, 0x77777777 }, | 4084 | { 0x0874, BNX2_FL_NOT_5709, 0x00000000, 0x77777777 }, |
3793 | 4085 | ||
3794 | { 0x0c00, 0, 0x00000000, 0x00000001 }, | 4086 | { 0x0c00, BNX2_FL_NOT_5709, 0x00000000, 0x00000001 }, |
3795 | { 0x0c04, 0, 0x00000000, 0x03ff0001 }, | 4087 | { 0x0c04, BNX2_FL_NOT_5709, 0x00000000, 0x03ff0001 }, |
3796 | { 0x0c08, 0, 0x0f0ff073, 0x00000000 }, | 4088 | { 0x0c08, BNX2_FL_NOT_5709, 0x0f0ff073, 0x00000000 }, |
3797 | 4089 | ||
3798 | { 0x1000, 0, 0x00000000, 0x00000001 }, | 4090 | { 0x1000, 0, 0x00000000, 0x00000001 }, |
3799 | { 0x1004, 0, 0x00000000, 0x000f0001 }, | 4091 | { 0x1004, 0, 0x00000000, 0x000f0001 }, |
@@ -3840,7 +4132,6 @@ bnx2_test_registers(struct bnx2 *bp) | |||
3840 | 4132 | ||
3841 | { 0x5004, 0, 0x00000000, 0x0000007f }, | 4133 | { 0x5004, 0, 0x00000000, 0x0000007f }, |
3842 | { 0x5008, 0, 0x0f0007ff, 0x00000000 }, | 4134 | { 0x5008, 0, 0x0f0007ff, 0x00000000 }, |
3843 | { 0x500c, 0, 0xf800f800, 0x07ff07ff }, | ||
3844 | 4135 | ||
3845 | { 0x5c00, 0, 0x00000000, 0x00000001 }, | 4136 | { 0x5c00, 0, 0x00000000, 0x00000001 }, |
3846 | { 0x5c04, 0, 0x00000000, 0x0003000f }, | 4137 | { 0x5c04, 0, 0x00000000, 0x0003000f }, |
@@ -3880,8 +4171,16 @@ bnx2_test_registers(struct bnx2 *bp) | |||
3880 | }; | 4171 | }; |
3881 | 4172 | ||
3882 | ret = 0; | 4173 | ret = 0; |
4174 | is_5709 = 0; | ||
4175 | if (CHIP_NUM(bp) == CHIP_NUM_5709) | ||
4176 | is_5709 = 1; | ||
4177 | |||
3883 | for (i = 0; reg_tbl[i].offset != 0xffff; i++) { | 4178 | for (i = 0; reg_tbl[i].offset != 0xffff; i++) { |
3884 | u32 offset, rw_mask, ro_mask, save_val, val; | 4179 | u32 offset, rw_mask, ro_mask, save_val, val; |
4180 | u16 flags = reg_tbl[i].flags; | ||
4181 | |||
4182 | if (is_5709 && (flags & BNX2_FL_NOT_5709)) | ||
4183 | continue; | ||
3885 | 4184 | ||
3886 | offset = (u32) reg_tbl[i].offset; | 4185 | offset = (u32) reg_tbl[i].offset; |
3887 | rw_mask = reg_tbl[i].rw_mask; | 4186 | rw_mask = reg_tbl[i].rw_mask; |
@@ -3950,10 +4249,10 @@ bnx2_test_memory(struct bnx2 *bp) | |||
3950 | { | 4249 | { |
3951 | int ret = 0; | 4250 | int ret = 0; |
3952 | int i; | 4251 | int i; |
3953 | static const struct { | 4252 | static struct mem_entry { |
3954 | u32 offset; | 4253 | u32 offset; |
3955 | u32 len; | 4254 | u32 len; |
3956 | } mem_tbl[] = { | 4255 | } mem_tbl_5706[] = { |
3957 | { 0x60000, 0x4000 }, | 4256 | { 0x60000, 0x4000 }, |
3958 | { 0xa0000, 0x3000 }, | 4257 | { 0xa0000, 0x3000 }, |
3959 | { 0xe0000, 0x4000 }, | 4258 | { 0xe0000, 0x4000 }, |
@@ -3961,7 +4260,21 @@ bnx2_test_memory(struct bnx2 *bp) | |||
3961 | { 0x1a0000, 0x4000 }, | 4260 | { 0x1a0000, 0x4000 }, |
3962 | { 0x160000, 0x4000 }, | 4261 | { 0x160000, 0x4000 }, |
3963 | { 0xffffffff, 0 }, | 4262 | { 0xffffffff, 0 }, |
4263 | }, | ||
4264 | mem_tbl_5709[] = { | ||
4265 | { 0x60000, 0x4000 }, | ||
4266 | { 0xa0000, 0x3000 }, | ||
4267 | { 0xe0000, 0x4000 }, | ||
4268 | { 0x120000, 0x4000 }, | ||
4269 | { 0x1a0000, 0x4000 }, | ||
4270 | { 0xffffffff, 0 }, | ||
3964 | }; | 4271 | }; |
4272 | struct mem_entry *mem_tbl; | ||
4273 | |||
4274 | if (CHIP_NUM(bp) == CHIP_NUM_5709) | ||
4275 | mem_tbl = mem_tbl_5709; | ||
4276 | else | ||
4277 | mem_tbl = mem_tbl_5706; | ||
3965 | 4278 | ||
3966 | for (i = 0; mem_tbl[i].offset != 0xffffffff; i++) { | 4279 | for (i = 0; mem_tbl[i].offset != 0xffffffff; i++) { |
3967 | if ((ret = bnx2_do_mem_test(bp, mem_tbl[i].offset, | 4280 | if ((ret = bnx2_do_mem_test(bp, mem_tbl[i].offset, |
@@ -4163,8 +4476,10 @@ bnx2_test_link(struct bnx2 *bp) | |||
4163 | u32 bmsr; | 4476 | u32 bmsr; |
4164 | 4477 | ||
4165 | spin_lock_bh(&bp->phy_lock); | 4478 | spin_lock_bh(&bp->phy_lock); |
4166 | bnx2_read_phy(bp, MII_BMSR, &bmsr); | 4479 | bnx2_enable_bmsr1(bp); |
4167 | bnx2_read_phy(bp, MII_BMSR, &bmsr); | 4480 | bnx2_read_phy(bp, bp->mii_bmsr1, &bmsr); |
4481 | bnx2_read_phy(bp, bp->mii_bmsr1, &bmsr); | ||
4482 | bnx2_disable_bmsr1(bp); | ||
4168 | spin_unlock_bh(&bp->phy_lock); | 4483 | spin_unlock_bh(&bp->phy_lock); |
4169 | 4484 | ||
4170 | if (bmsr & BMSR_LSTATUS) { | 4485 | if (bmsr & BMSR_LSTATUS) { |
@@ -4214,7 +4529,7 @@ bnx2_5706_serdes_timer(struct bnx2 *bp) | |||
4214 | 4529 | ||
4215 | bp->current_interval = bp->timer_interval; | 4530 | bp->current_interval = bp->timer_interval; |
4216 | 4531 | ||
4217 | bnx2_read_phy(bp, MII_BMCR, &bmcr); | 4532 | bnx2_read_phy(bp, bp->mii_bmcr, &bmcr); |
4218 | 4533 | ||
4219 | if (bmcr & BMCR_ANENABLE) { | 4534 | if (bmcr & BMCR_ANENABLE) { |
4220 | u32 phy1, phy2; | 4535 | u32 phy1, phy2; |
@@ -4232,7 +4547,7 @@ bnx2_5706_serdes_timer(struct bnx2 *bp) | |||
4232 | 4547 | ||
4233 | bmcr &= ~BMCR_ANENABLE; | 4548 | bmcr &= ~BMCR_ANENABLE; |
4234 | bmcr |= BMCR_SPEED1000 | BMCR_FULLDPLX; | 4549 | bmcr |= BMCR_SPEED1000 | BMCR_FULLDPLX; |
4235 | bnx2_write_phy(bp, MII_BMCR, bmcr); | 4550 | bnx2_write_phy(bp, bp->mii_bmcr, bmcr); |
4236 | bp->phy_flags |= PHY_PARALLEL_DETECT_FLAG; | 4551 | bp->phy_flags |= PHY_PARALLEL_DETECT_FLAG; |
4237 | } | 4552 | } |
4238 | } | 4553 | } |
@@ -4246,9 +4561,9 @@ bnx2_5706_serdes_timer(struct bnx2 *bp) | |||
4246 | if (phy2 & 0x20) { | 4561 | if (phy2 & 0x20) { |
4247 | u32 bmcr; | 4562 | u32 bmcr; |
4248 | 4563 | ||
4249 | bnx2_read_phy(bp, MII_BMCR, &bmcr); | 4564 | bnx2_read_phy(bp, bp->mii_bmcr, &bmcr); |
4250 | bmcr |= BMCR_ANENABLE; | 4565 | bmcr |= BMCR_ANENABLE; |
4251 | bnx2_write_phy(bp, MII_BMCR, bmcr); | 4566 | bnx2_write_phy(bp, bp->mii_bmcr, bmcr); |
4252 | 4567 | ||
4253 | bp->phy_flags &= ~PHY_PARALLEL_DETECT_FLAG; | 4568 | bp->phy_flags &= ~PHY_PARALLEL_DETECT_FLAG; |
4254 | } | 4569 | } |
@@ -4272,17 +4587,12 @@ bnx2_5708_serdes_timer(struct bnx2 *bp) | |||
4272 | else if ((bp->link_up == 0) && (bp->autoneg & AUTONEG_SPEED)) { | 4587 | else if ((bp->link_up == 0) && (bp->autoneg & AUTONEG_SPEED)) { |
4273 | u32 bmcr; | 4588 | u32 bmcr; |
4274 | 4589 | ||
4275 | bnx2_read_phy(bp, MII_BMCR, &bmcr); | 4590 | bnx2_read_phy(bp, bp->mii_bmcr, &bmcr); |
4276 | |||
4277 | if (bmcr & BMCR_ANENABLE) { | 4591 | if (bmcr & BMCR_ANENABLE) { |
4278 | bmcr &= ~BMCR_ANENABLE; | 4592 | bnx2_enable_forced_2g5(bp); |
4279 | bmcr |= BMCR_FULLDPLX | BCM5708S_BMCR_FORCE_2500; | ||
4280 | bnx2_write_phy(bp, MII_BMCR, bmcr); | ||
4281 | bp->current_interval = SERDES_FORCED_TIMEOUT; | 4593 | bp->current_interval = SERDES_FORCED_TIMEOUT; |
4282 | } else { | 4594 | } else { |
4283 | bmcr &= ~(BMCR_FULLDPLX | BCM5708S_BMCR_FORCE_2500); | 4595 | bnx2_disable_forced_2g5(bp); |
4284 | bmcr |= BMCR_ANENABLE; | ||
4285 | bnx2_write_phy(bp, MII_BMCR, bmcr); | ||
4286 | bp->serdes_an_pending = 2; | 4596 | bp->serdes_an_pending = 2; |
4287 | bp->current_interval = bp->timer_interval; | 4597 | bp->current_interval = bp->timer_interval; |
4288 | } | 4598 | } |
@@ -4313,7 +4623,7 @@ bnx2_timer(unsigned long data) | |||
4313 | if (bp->phy_flags & PHY_SERDES_FLAG) { | 4623 | if (bp->phy_flags & PHY_SERDES_FLAG) { |
4314 | if (CHIP_NUM(bp) == CHIP_NUM_5706) | 4624 | if (CHIP_NUM(bp) == CHIP_NUM_5706) |
4315 | bnx2_5706_serdes_timer(bp); | 4625 | bnx2_5706_serdes_timer(bp); |
4316 | else if (CHIP_NUM(bp) == CHIP_NUM_5708) | 4626 | else |
4317 | bnx2_5708_serdes_timer(bp); | 4627 | bnx2_5708_serdes_timer(bp); |
4318 | } | 4628 | } |
4319 | 4629 | ||
@@ -4321,6 +4631,38 @@ bnx2_restart_timer: | |||
4321 | mod_timer(&bp->timer, jiffies + bp->current_interval); | 4631 | mod_timer(&bp->timer, jiffies + bp->current_interval); |
4322 | } | 4632 | } |
4323 | 4633 | ||
4634 | static int | ||
4635 | bnx2_request_irq(struct bnx2 *bp) | ||
4636 | { | ||
4637 | struct net_device *dev = bp->dev; | ||
4638 | int rc = 0; | ||
4639 | |||
4640 | if (bp->flags & USING_MSI_FLAG) { | ||
4641 | irq_handler_t fn = bnx2_msi; | ||
4642 | |||
4643 | if (bp->flags & ONE_SHOT_MSI_FLAG) | ||
4644 | fn = bnx2_msi_1shot; | ||
4645 | |||
4646 | rc = request_irq(bp->pdev->irq, fn, 0, dev->name, dev); | ||
4647 | } else | ||
4648 | rc = request_irq(bp->pdev->irq, bnx2_interrupt, | ||
4649 | IRQF_SHARED, dev->name, dev); | ||
4650 | return rc; | ||
4651 | } | ||
4652 | |||
4653 | static void | ||
4654 | bnx2_free_irq(struct bnx2 *bp) | ||
4655 | { | ||
4656 | struct net_device *dev = bp->dev; | ||
4657 | |||
4658 | if (bp->flags & USING_MSI_FLAG) { | ||
4659 | free_irq(bp->pdev->irq, dev); | ||
4660 | pci_disable_msi(bp->pdev); | ||
4661 | bp->flags &= ~(USING_MSI_FLAG | ONE_SHOT_MSI_FLAG); | ||
4662 | } else | ||
4663 | free_irq(bp->pdev->irq, dev); | ||
4664 | } | ||
4665 | |||
4324 | /* Called with rtnl_lock */ | 4666 | /* Called with rtnl_lock */ |
4325 | static int | 4667 | static int |
4326 | bnx2_open(struct net_device *dev) | 4668 | bnx2_open(struct net_device *dev) |
@@ -4328,6 +4670,8 @@ bnx2_open(struct net_device *dev) | |||
4328 | struct bnx2 *bp = netdev_priv(dev); | 4670 | struct bnx2 *bp = netdev_priv(dev); |
4329 | int rc; | 4671 | int rc; |
4330 | 4672 | ||
4673 | netif_carrier_off(dev); | ||
4674 | |||
4331 | bnx2_set_power_state(bp, PCI_D0); | 4675 | bnx2_set_power_state(bp, PCI_D0); |
4332 | bnx2_disable_int(bp); | 4676 | bnx2_disable_int(bp); |
4333 | 4677 | ||
@@ -4335,24 +4679,15 @@ bnx2_open(struct net_device *dev) | |||
4335 | if (rc) | 4679 | if (rc) |
4336 | return rc; | 4680 | return rc; |
4337 | 4681 | ||
4338 | if ((CHIP_ID(bp) != CHIP_ID_5706_A0) && | 4682 | if ((bp->flags & MSI_CAP_FLAG) && !disable_msi) { |
4339 | (CHIP_ID(bp) != CHIP_ID_5706_A1) && | ||
4340 | !disable_msi) { | ||
4341 | |||
4342 | if (pci_enable_msi(bp->pdev) == 0) { | 4683 | if (pci_enable_msi(bp->pdev) == 0) { |
4343 | bp->flags |= USING_MSI_FLAG; | 4684 | bp->flags |= USING_MSI_FLAG; |
4344 | rc = request_irq(bp->pdev->irq, bnx2_msi, 0, dev->name, | 4685 | if (CHIP_NUM(bp) == CHIP_NUM_5709) |
4345 | dev); | 4686 | bp->flags |= ONE_SHOT_MSI_FLAG; |
4346 | } | ||
4347 | else { | ||
4348 | rc = request_irq(bp->pdev->irq, bnx2_interrupt, | ||
4349 | IRQF_SHARED, dev->name, dev); | ||
4350 | } | 4687 | } |
4351 | } | 4688 | } |
4352 | else { | 4689 | rc = bnx2_request_irq(bp); |
4353 | rc = request_irq(bp->pdev->irq, bnx2_interrupt, IRQF_SHARED, | 4690 | |
4354 | dev->name, dev); | ||
4355 | } | ||
4356 | if (rc) { | 4691 | if (rc) { |
4357 | bnx2_free_mem(bp); | 4692 | bnx2_free_mem(bp); |
4358 | return rc; | 4693 | return rc; |
@@ -4361,11 +4696,7 @@ bnx2_open(struct net_device *dev) | |||
4361 | rc = bnx2_init_nic(bp); | 4696 | rc = bnx2_init_nic(bp); |
4362 | 4697 | ||
4363 | if (rc) { | 4698 | if (rc) { |
4364 | free_irq(bp->pdev->irq, dev); | 4699 | bnx2_free_irq(bp); |
4365 | if (bp->flags & USING_MSI_FLAG) { | ||
4366 | pci_disable_msi(bp->pdev); | ||
4367 | bp->flags &= ~USING_MSI_FLAG; | ||
4368 | } | ||
4369 | bnx2_free_skbs(bp); | 4700 | bnx2_free_skbs(bp); |
4370 | bnx2_free_mem(bp); | 4701 | bnx2_free_mem(bp); |
4371 | return rc; | 4702 | return rc; |
@@ -4389,16 +4720,13 @@ bnx2_open(struct net_device *dev) | |||
4389 | bp->dev->name); | 4720 | bp->dev->name); |
4390 | 4721 | ||
4391 | bnx2_disable_int(bp); | 4722 | bnx2_disable_int(bp); |
4392 | free_irq(bp->pdev->irq, dev); | 4723 | bnx2_free_irq(bp); |
4393 | pci_disable_msi(bp->pdev); | ||
4394 | bp->flags &= ~USING_MSI_FLAG; | ||
4395 | 4724 | ||
4396 | rc = bnx2_init_nic(bp); | 4725 | rc = bnx2_init_nic(bp); |
4397 | 4726 | ||
4398 | if (!rc) { | 4727 | if (!rc) |
4399 | rc = request_irq(bp->pdev->irq, bnx2_interrupt, | 4728 | rc = bnx2_request_irq(bp); |
4400 | IRQF_SHARED, dev->name, dev); | 4729 | |
4401 | } | ||
4402 | if (rc) { | 4730 | if (rc) { |
4403 | bnx2_free_skbs(bp); | 4731 | bnx2_free_skbs(bp); |
4404 | bnx2_free_mem(bp); | 4732 | bnx2_free_mem(bp); |
@@ -4508,40 +4836,53 @@ bnx2_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
4508 | vlan_tag_flags |= | 4836 | vlan_tag_flags |= |
4509 | (TX_BD_FLAGS_VLAN_TAG | (vlan_tx_tag_get(skb) << 16)); | 4837 | (TX_BD_FLAGS_VLAN_TAG | (vlan_tx_tag_get(skb) << 16)); |
4510 | } | 4838 | } |
4511 | if ((mss = skb_shinfo(skb)->gso_size) && | 4839 | if ((mss = skb_shinfo(skb)->gso_size)) { |
4512 | (skb->len > (bp->dev->mtu + ETH_HLEN))) { | ||
4513 | u32 tcp_opt_len, ip_tcp_len; | 4840 | u32 tcp_opt_len, ip_tcp_len; |
4514 | struct iphdr *iph; | 4841 | struct iphdr *iph; |
4515 | 4842 | ||
4516 | if (skb_header_cloned(skb) && | ||
4517 | pskb_expand_head(skb, 0, 0, GFP_ATOMIC)) { | ||
4518 | dev_kfree_skb(skb); | ||
4519 | return NETDEV_TX_OK; | ||
4520 | } | ||
4521 | |||
4522 | vlan_tag_flags |= TX_BD_FLAGS_SW_LSO; | 4843 | vlan_tag_flags |= TX_BD_FLAGS_SW_LSO; |
4523 | 4844 | ||
4524 | tcp_opt_len = 0; | 4845 | tcp_opt_len = tcp_optlen(skb); |
4525 | if (tcp_hdr(skb)->doff > 5) | 4846 | |
4526 | tcp_opt_len = tcp_optlen(skb); | 4847 | if (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV6) { |
4848 | u32 tcp_off = skb_transport_offset(skb) - | ||
4849 | sizeof(struct ipv6hdr) - ETH_HLEN; | ||
4527 | 4850 | ||
4528 | ip_tcp_len = ip_hdrlen(skb) + sizeof(struct tcphdr); | 4851 | vlan_tag_flags |= ((tcp_opt_len >> 2) << 8) | |
4852 | TX_BD_FLAGS_SW_FLAGS; | ||
4853 | if (likely(tcp_off == 0)) | ||
4854 | vlan_tag_flags &= ~TX_BD_FLAGS_TCP6_OFF0_MSK; | ||
4855 | else { | ||
4856 | tcp_off >>= 3; | ||
4857 | vlan_tag_flags |= ((tcp_off & 0x3) << | ||
4858 | TX_BD_FLAGS_TCP6_OFF0_SHL) | | ||
4859 | ((tcp_off & 0x10) << | ||
4860 | TX_BD_FLAGS_TCP6_OFF4_SHL); | ||
4861 | mss |= (tcp_off & 0xc) << TX_BD_TCP6_OFF2_SHL; | ||
4862 | } | ||
4863 | } else { | ||
4864 | if (skb_header_cloned(skb) && | ||
4865 | pskb_expand_head(skb, 0, 0, GFP_ATOMIC)) { | ||
4866 | dev_kfree_skb(skb); | ||
4867 | return NETDEV_TX_OK; | ||
4868 | } | ||
4529 | 4869 | ||
4530 | iph = ip_hdr(skb); | 4870 | ip_tcp_len = ip_hdrlen(skb) + sizeof(struct tcphdr); |
4531 | iph->check = 0; | 4871 | |
4532 | iph->tot_len = htons(mss + ip_tcp_len + tcp_opt_len); | 4872 | iph = ip_hdr(skb); |
4533 | tcp_hdr(skb)->check = ~csum_tcpudp_magic(iph->saddr, | 4873 | iph->check = 0; |
4534 | iph->daddr, 0, | 4874 | iph->tot_len = htons(mss + ip_tcp_len + tcp_opt_len); |
4535 | IPPROTO_TCP, 0); | 4875 | tcp_hdr(skb)->check = ~csum_tcpudp_magic(iph->saddr, |
4536 | if (tcp_opt_len || (iph->ihl > 5)) { | 4876 | iph->daddr, 0, |
4537 | vlan_tag_flags |= ((iph->ihl - 5) + | 4877 | IPPROTO_TCP, |
4538 | (tcp_opt_len >> 2)) << 8; | 4878 | 0); |
4879 | if (tcp_opt_len || (iph->ihl > 5)) { | ||
4880 | vlan_tag_flags |= ((iph->ihl - 5) + | ||
4881 | (tcp_opt_len >> 2)) << 8; | ||
4882 | } | ||
4539 | } | 4883 | } |
4540 | } | 4884 | } else |
4541 | else | ||
4542 | { | ||
4543 | mss = 0; | 4885 | mss = 0; |
4544 | } | ||
4545 | 4886 | ||
4546 | mapping = pci_map_single(bp->pdev, skb->data, len, PCI_DMA_TODEVICE); | 4887 | mapping = pci_map_single(bp->pdev, skb->data, len, PCI_DMA_TODEVICE); |
4547 | 4888 | ||
@@ -4622,11 +4963,7 @@ bnx2_close(struct net_device *dev) | |||
4622 | else | 4963 | else |
4623 | reset_code = BNX2_DRV_MSG_CODE_SUSPEND_NO_WOL; | 4964 | reset_code = BNX2_DRV_MSG_CODE_SUSPEND_NO_WOL; |
4624 | bnx2_reset_chip(bp, reset_code); | 4965 | bnx2_reset_chip(bp, reset_code); |
4625 | free_irq(bp->pdev->irq, dev); | 4966 | bnx2_free_irq(bp); |
4626 | if (bp->flags & USING_MSI_FLAG) { | ||
4627 | pci_disable_msi(bp->pdev); | ||
4628 | bp->flags &= ~USING_MSI_FLAG; | ||
4629 | } | ||
4630 | bnx2_free_skbs(bp); | 4967 | bnx2_free_skbs(bp); |
4631 | bnx2_free_mem(bp); | 4968 | bnx2_free_mem(bp); |
4632 | bp->link_up = 0; | 4969 | bp->link_up = 0; |
@@ -4735,6 +5072,8 @@ bnx2_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) | |||
4735 | if (bp->phy_flags & PHY_SERDES_FLAG) { | 5072 | if (bp->phy_flags & PHY_SERDES_FLAG) { |
4736 | cmd->supported |= SUPPORTED_1000baseT_Full | | 5073 | cmd->supported |= SUPPORTED_1000baseT_Full | |
4737 | SUPPORTED_FIBRE; | 5074 | SUPPORTED_FIBRE; |
5075 | if (bp->phy_flags & PHY_2_5G_CAPABLE_FLAG) | ||
5076 | cmd->supported |= SUPPORTED_2500baseX_Full; | ||
4738 | 5077 | ||
4739 | cmd->port = PORT_FIBRE; | 5078 | cmd->port = PORT_FIBRE; |
4740 | } | 5079 | } |
@@ -4798,8 +5137,10 @@ bnx2_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) | |||
4798 | 5137 | ||
4799 | advertising = cmd->advertising; | 5138 | advertising = cmd->advertising; |
4800 | 5139 | ||
4801 | } | 5140 | } else if (cmd->advertising == ADVERTISED_2500baseX_Full) { |
4802 | else if (cmd->advertising == ADVERTISED_1000baseT_Full) { | 5141 | if (!(bp->phy_flags & PHY_2_5G_CAPABLE_FLAG)) |
5142 | return -EINVAL; | ||
5143 | } else if (cmd->advertising == ADVERTISED_1000baseT_Full) { | ||
4803 | advertising = cmd->advertising; | 5144 | advertising = cmd->advertising; |
4804 | } | 5145 | } |
4805 | else if (cmd->advertising == ADVERTISED_1000baseT_Half) { | 5146 | else if (cmd->advertising == ADVERTISED_1000baseT_Half) { |
@@ -4975,7 +5316,7 @@ bnx2_nway_reset(struct net_device *dev) | |||
4975 | 5316 | ||
4976 | /* Force a link down visible on the other side */ | 5317 | /* Force a link down visible on the other side */ |
4977 | if (bp->phy_flags & PHY_SERDES_FLAG) { | 5318 | if (bp->phy_flags & PHY_SERDES_FLAG) { |
4978 | bnx2_write_phy(bp, MII_BMCR, BMCR_LOOPBACK); | 5319 | bnx2_write_phy(bp, bp->mii_bmcr, BMCR_LOOPBACK); |
4979 | spin_unlock_bh(&bp->phy_lock); | 5320 | spin_unlock_bh(&bp->phy_lock); |
4980 | 5321 | ||
4981 | msleep(20); | 5322 | msleep(20); |
@@ -4987,9 +5328,9 @@ bnx2_nway_reset(struct net_device *dev) | |||
4987 | mod_timer(&bp->timer, jiffies + bp->current_interval); | 5328 | mod_timer(&bp->timer, jiffies + bp->current_interval); |
4988 | } | 5329 | } |
4989 | 5330 | ||
4990 | bnx2_read_phy(bp, MII_BMCR, &bmcr); | 5331 | bnx2_read_phy(bp, bp->mii_bmcr, &bmcr); |
4991 | bmcr &= ~BMCR_LOOPBACK; | 5332 | bmcr &= ~BMCR_LOOPBACK; |
4992 | bnx2_write_phy(bp, MII_BMCR, bmcr | BMCR_ANRESTART | BMCR_ANENABLE); | 5333 | bnx2_write_phy(bp, bp->mii_bmcr, bmcr | BMCR_ANRESTART | BMCR_ANENABLE); |
4993 | 5334 | ||
4994 | spin_unlock_bh(&bp->phy_lock); | 5335 | spin_unlock_bh(&bp->phy_lock); |
4995 | 5336 | ||
@@ -5209,10 +5550,15 @@ bnx2_set_rx_csum(struct net_device *dev, u32 data) | |||
5209 | static int | 5550 | static int |
5210 | bnx2_set_tso(struct net_device *dev, u32 data) | 5551 | bnx2_set_tso(struct net_device *dev, u32 data) |
5211 | { | 5552 | { |
5212 | if (data) | 5553 | struct bnx2 *bp = netdev_priv(dev); |
5554 | |||
5555 | if (data) { | ||
5213 | dev->features |= NETIF_F_TSO | NETIF_F_TSO_ECN; | 5556 | dev->features |= NETIF_F_TSO | NETIF_F_TSO_ECN; |
5214 | else | 5557 | if (CHIP_NUM(bp) == CHIP_NUM_5709) |
5215 | dev->features &= ~(NETIF_F_TSO | NETIF_F_TSO_ECN); | 5558 | dev->features |= NETIF_F_TSO6; |
5559 | } else | ||
5560 | dev->features &= ~(NETIF_F_TSO | NETIF_F_TSO6 | | ||
5561 | NETIF_F_TSO_ECN); | ||
5216 | return 0; | 5562 | return 0; |
5217 | } | 5563 | } |
5218 | 5564 | ||
@@ -5510,6 +5856,17 @@ bnx2_phys_id(struct net_device *dev, u32 data) | |||
5510 | return 0; | 5856 | return 0; |
5511 | } | 5857 | } |
5512 | 5858 | ||
5859 | static int | ||
5860 | bnx2_set_tx_csum(struct net_device *dev, u32 data) | ||
5861 | { | ||
5862 | struct bnx2 *bp = netdev_priv(dev); | ||
5863 | |||
5864 | if (CHIP_NUM(bp) == CHIP_NUM_5709) | ||
5865 | return (ethtool_op_set_tx_hw_csum(dev, data)); | ||
5866 | else | ||
5867 | return (ethtool_op_set_tx_csum(dev, data)); | ||
5868 | } | ||
5869 | |||
5513 | static const struct ethtool_ops bnx2_ethtool_ops = { | 5870 | static const struct ethtool_ops bnx2_ethtool_ops = { |
5514 | .get_settings = bnx2_get_settings, | 5871 | .get_settings = bnx2_get_settings, |
5515 | .set_settings = bnx2_set_settings, | 5872 | .set_settings = bnx2_set_settings, |
@@ -5532,7 +5889,7 @@ static const struct ethtool_ops bnx2_ethtool_ops = { | |||
5532 | .get_rx_csum = bnx2_get_rx_csum, | 5889 | .get_rx_csum = bnx2_get_rx_csum, |
5533 | .set_rx_csum = bnx2_set_rx_csum, | 5890 | .set_rx_csum = bnx2_set_rx_csum, |
5534 | .get_tx_csum = ethtool_op_get_tx_csum, | 5891 | .get_tx_csum = ethtool_op_get_tx_csum, |
5535 | .set_tx_csum = ethtool_op_set_tx_csum, | 5892 | .set_tx_csum = bnx2_set_tx_csum, |
5536 | .get_sg = ethtool_op_get_sg, | 5893 | .get_sg = ethtool_op_get_sg, |
5537 | .set_sg = ethtool_op_set_sg, | 5894 | .set_sg = ethtool_op_set_sg, |
5538 | .get_tso = ethtool_op_get_tso, | 5895 | .get_tso = ethtool_op_get_tso, |
@@ -5562,6 +5919,9 @@ bnx2_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) | |||
5562 | case SIOCGMIIREG: { | 5919 | case SIOCGMIIREG: { |
5563 | u32 mii_regval; | 5920 | u32 mii_regval; |
5564 | 5921 | ||
5922 | if (!netif_running(dev)) | ||
5923 | return -EAGAIN; | ||
5924 | |||
5565 | spin_lock_bh(&bp->phy_lock); | 5925 | spin_lock_bh(&bp->phy_lock); |
5566 | err = bnx2_read_phy(bp, data->reg_num & 0x1f, &mii_regval); | 5926 | err = bnx2_read_phy(bp, data->reg_num & 0x1f, &mii_regval); |
5567 | spin_unlock_bh(&bp->phy_lock); | 5927 | spin_unlock_bh(&bp->phy_lock); |
@@ -5575,6 +5935,9 @@ bnx2_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) | |||
5575 | if (!capable(CAP_NET_ADMIN)) | 5935 | if (!capable(CAP_NET_ADMIN)) |
5576 | return -EPERM; | 5936 | return -EPERM; |
5577 | 5937 | ||
5938 | if (!netif_running(dev)) | ||
5939 | return -EAGAIN; | ||
5940 | |||
5578 | spin_lock_bh(&bp->phy_lock); | 5941 | spin_lock_bh(&bp->phy_lock); |
5579 | err = bnx2_write_phy(bp, data->reg_num & 0x1f, data->val_in); | 5942 | err = bnx2_write_phy(bp, data->reg_num & 0x1f, data->val_in); |
5580 | spin_unlock_bh(&bp->phy_lock); | 5943 | spin_unlock_bh(&bp->phy_lock); |
@@ -5676,6 +6039,58 @@ bnx2_get_5709_media(struct bnx2 *bp) | |||
5676 | } | 6039 | } |
5677 | } | 6040 | } |
5678 | 6041 | ||
6042 | static void __devinit | ||
6043 | bnx2_get_pci_speed(struct bnx2 *bp) | ||
6044 | { | ||
6045 | u32 reg; | ||
6046 | |||
6047 | reg = REG_RD(bp, BNX2_PCICFG_MISC_STATUS); | ||
6048 | if (reg & BNX2_PCICFG_MISC_STATUS_PCIX_DET) { | ||
6049 | u32 clkreg; | ||
6050 | |||
6051 | bp->flags |= PCIX_FLAG; | ||
6052 | |||
6053 | clkreg = REG_RD(bp, BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS); | ||
6054 | |||
6055 | clkreg &= BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET; | ||
6056 | switch (clkreg) { | ||
6057 | case BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_133MHZ: | ||
6058 | bp->bus_speed_mhz = 133; | ||
6059 | break; | ||
6060 | |||
6061 | case BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_95MHZ: | ||
6062 | bp->bus_speed_mhz = 100; | ||
6063 | break; | ||
6064 | |||
6065 | case BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_66MHZ: | ||
6066 | case BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_80MHZ: | ||
6067 | bp->bus_speed_mhz = 66; | ||
6068 | break; | ||
6069 | |||
6070 | case BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_48MHZ: | ||
6071 | case BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_55MHZ: | ||
6072 | bp->bus_speed_mhz = 50; | ||
6073 | break; | ||
6074 | |||
6075 | case BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_LOW: | ||
6076 | case BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_32MHZ: | ||
6077 | case BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_38MHZ: | ||
6078 | bp->bus_speed_mhz = 33; | ||
6079 | break; | ||
6080 | } | ||
6081 | } | ||
6082 | else { | ||
6083 | if (reg & BNX2_PCICFG_MISC_STATUS_M66EN) | ||
6084 | bp->bus_speed_mhz = 66; | ||
6085 | else | ||
6086 | bp->bus_speed_mhz = 33; | ||
6087 | } | ||
6088 | |||
6089 | if (reg & BNX2_PCICFG_MISC_STATUS_32BIT_DET) | ||
6090 | bp->flags |= PCI_32BIT_FLAG; | ||
6091 | |||
6092 | } | ||
6093 | |||
5679 | static int __devinit | 6094 | static int __devinit |
5680 | bnx2_init_board(struct pci_dev *pdev, struct net_device *dev) | 6095 | bnx2_init_board(struct pci_dev *pdev, struct net_device *dev) |
5681 | { | 6096 | { |
@@ -5683,6 +6098,7 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev) | |||
5683 | unsigned long mem_len; | 6098 | unsigned long mem_len; |
5684 | int rc; | 6099 | int rc; |
5685 | u32 reg; | 6100 | u32 reg; |
6101 | u64 dma_mask, persist_dma_mask; | ||
5686 | 6102 | ||
5687 | SET_MODULE_OWNER(dev); | 6103 | SET_MODULE_OWNER(dev); |
5688 | SET_NETDEV_DEV(dev, &pdev->dev); | 6104 | SET_NETDEV_DEV(dev, &pdev->dev); |
@@ -5721,25 +6137,11 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev) | |||
5721 | goto err_out_release; | 6137 | goto err_out_release; |
5722 | } | 6138 | } |
5723 | 6139 | ||
5724 | if (pci_set_dma_mask(pdev, DMA_64BIT_MASK) == 0) { | ||
5725 | bp->flags |= USING_DAC_FLAG; | ||
5726 | if (pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK) != 0) { | ||
5727 | dev_err(&pdev->dev, | ||
5728 | "pci_set_consistent_dma_mask failed, aborting.\n"); | ||
5729 | rc = -EIO; | ||
5730 | goto err_out_release; | ||
5731 | } | ||
5732 | } | ||
5733 | else if (pci_set_dma_mask(pdev, DMA_32BIT_MASK) != 0) { | ||
5734 | dev_err(&pdev->dev, "System does not support DMA, aborting.\n"); | ||
5735 | rc = -EIO; | ||
5736 | goto err_out_release; | ||
5737 | } | ||
5738 | |||
5739 | bp->dev = dev; | 6140 | bp->dev = dev; |
5740 | bp->pdev = pdev; | 6141 | bp->pdev = pdev; |
5741 | 6142 | ||
5742 | spin_lock_init(&bp->phy_lock); | 6143 | spin_lock_init(&bp->phy_lock); |
6144 | spin_lock_init(&bp->indirect_lock); | ||
5743 | INIT_WORK(&bp->reset_task, bnx2_reset_task); | 6145 | INIT_WORK(&bp->reset_task, bnx2_reset_task); |
5744 | 6146 | ||
5745 | dev->base_addr = dev->mem_start = pci_resource_start(pdev, 0); | 6147 | dev->base_addr = dev->mem_start = pci_resource_start(pdev, 0); |
@@ -5767,7 +6169,15 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev) | |||
5767 | 6169 | ||
5768 | bp->chip_id = REG_RD(bp, BNX2_MISC_ID); | 6170 | bp->chip_id = REG_RD(bp, BNX2_MISC_ID); |
5769 | 6171 | ||
5770 | if (CHIP_NUM(bp) != CHIP_NUM_5709) { | 6172 | if (CHIP_NUM(bp) == CHIP_NUM_5709) { |
6173 | if (pci_find_capability(pdev, PCI_CAP_ID_EXP) == 0) { | ||
6174 | dev_err(&pdev->dev, | ||
6175 | "Cannot find PCIE capability, aborting.\n"); | ||
6176 | rc = -EIO; | ||
6177 | goto err_out_unmap; | ||
6178 | } | ||
6179 | bp->flags |= PCIE_FLAG; | ||
6180 | } else { | ||
5771 | bp->pcix_cap = pci_find_capability(pdev, PCI_CAP_ID_PCIX); | 6181 | bp->pcix_cap = pci_find_capability(pdev, PCI_CAP_ID_PCIX); |
5772 | if (bp->pcix_cap == 0) { | 6182 | if (bp->pcix_cap == 0) { |
5773 | dev_err(&pdev->dev, | 6183 | dev_err(&pdev->dev, |
@@ -5777,51 +6187,33 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev) | |||
5777 | } | 6187 | } |
5778 | } | 6188 | } |
5779 | 6189 | ||
5780 | /* Get bus information. */ | 6190 | if (CHIP_ID(bp) != CHIP_ID_5706_A0 && CHIP_ID(bp) != CHIP_ID_5706_A1) { |
5781 | reg = REG_RD(bp, BNX2_PCICFG_MISC_STATUS); | 6191 | if (pci_find_capability(pdev, PCI_CAP_ID_MSI)) |
5782 | if (reg & BNX2_PCICFG_MISC_STATUS_PCIX_DET) { | 6192 | bp->flags |= MSI_CAP_FLAG; |
5783 | u32 clkreg; | 6193 | } |
5784 | |||
5785 | bp->flags |= PCIX_FLAG; | ||
5786 | |||
5787 | clkreg = REG_RD(bp, BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS); | ||
5788 | |||
5789 | clkreg &= BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET; | ||
5790 | switch (clkreg) { | ||
5791 | case BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_133MHZ: | ||
5792 | bp->bus_speed_mhz = 133; | ||
5793 | break; | ||
5794 | |||
5795 | case BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_95MHZ: | ||
5796 | bp->bus_speed_mhz = 100; | ||
5797 | break; | ||
5798 | |||
5799 | case BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_66MHZ: | ||
5800 | case BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_80MHZ: | ||
5801 | bp->bus_speed_mhz = 66; | ||
5802 | break; | ||
5803 | 6194 | ||
5804 | case BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_48MHZ: | 6195 | /* 5708 cannot support DMA addresses > 40-bit. */ |
5805 | case BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_55MHZ: | 6196 | if (CHIP_NUM(bp) == CHIP_NUM_5708) |
5806 | bp->bus_speed_mhz = 50; | 6197 | persist_dma_mask = dma_mask = DMA_40BIT_MASK; |
5807 | break; | 6198 | else |
6199 | persist_dma_mask = dma_mask = DMA_64BIT_MASK; | ||
5808 | 6200 | ||
5809 | case BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_LOW: | 6201 | /* Configure DMA attributes. */ |
5810 | case BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_32MHZ: | 6202 | if (pci_set_dma_mask(pdev, dma_mask) == 0) { |
5811 | case BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_38MHZ: | 6203 | dev->features |= NETIF_F_HIGHDMA; |
5812 | bp->bus_speed_mhz = 33; | 6204 | rc = pci_set_consistent_dma_mask(pdev, persist_dma_mask); |
5813 | break; | 6205 | if (rc) { |
6206 | dev_err(&pdev->dev, | ||
6207 | "pci_set_consistent_dma_mask failed, aborting.\n"); | ||
6208 | goto err_out_unmap; | ||
5814 | } | 6209 | } |
5815 | } | 6210 | } else if ((rc = pci_set_dma_mask(pdev, DMA_32BIT_MASK)) != 0) { |
5816 | else { | 6211 | dev_err(&pdev->dev, "System does not support DMA, aborting.\n"); |
5817 | if (reg & BNX2_PCICFG_MISC_STATUS_M66EN) | 6212 | goto err_out_unmap; |
5818 | bp->bus_speed_mhz = 66; | ||
5819 | else | ||
5820 | bp->bus_speed_mhz = 33; | ||
5821 | } | 6213 | } |
5822 | 6214 | ||
5823 | if (reg & BNX2_PCICFG_MISC_STATUS_32BIT_DET) | 6215 | if (!(bp->flags & PCIE_FLAG)) |
5824 | bp->flags |= PCI_32BIT_FLAG; | 6216 | bnx2_get_pci_speed(bp); |
5825 | 6217 | ||
5826 | /* 5706A0 may falsely detect SERR and PERR. */ | 6218 | /* 5706A0 may falsely detect SERR and PERR. */ |
5827 | if (CHIP_ID(bp) == CHIP_ID_5706_A0) { | 6219 | if (CHIP_ID(bp) == CHIP_ID_5706_A0) { |
@@ -6005,6 +6397,26 @@ err_out: | |||
6005 | return rc; | 6397 | return rc; |
6006 | } | 6398 | } |
6007 | 6399 | ||
6400 | static char * __devinit | ||
6401 | bnx2_bus_string(struct bnx2 *bp, char *str) | ||
6402 | { | ||
6403 | char *s = str; | ||
6404 | |||
6405 | if (bp->flags & PCIE_FLAG) { | ||
6406 | s += sprintf(s, "PCI Express"); | ||
6407 | } else { | ||
6408 | s += sprintf(s, "PCI"); | ||
6409 | if (bp->flags & PCIX_FLAG) | ||
6410 | s += sprintf(s, "-X"); | ||
6411 | if (bp->flags & PCI_32BIT_FLAG) | ||
6412 | s += sprintf(s, " 32-bit"); | ||
6413 | else | ||
6414 | s += sprintf(s, " 64-bit"); | ||
6415 | s += sprintf(s, " %dMHz", bp->bus_speed_mhz); | ||
6416 | } | ||
6417 | return str; | ||
6418 | } | ||
6419 | |||
6008 | static int __devinit | 6420 | static int __devinit |
6009 | bnx2_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) | 6421 | bnx2_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) |
6010 | { | 6422 | { |
@@ -6012,6 +6424,7 @@ bnx2_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
6012 | struct net_device *dev = NULL; | 6424 | struct net_device *dev = NULL; |
6013 | struct bnx2 *bp; | 6425 | struct bnx2 *bp; |
6014 | int rc, i; | 6426 | int rc, i; |
6427 | char str[40]; | ||
6015 | 6428 | ||
6016 | if (version_printed++ == 0) | 6429 | if (version_printed++ == 0) |
6017 | printk(KERN_INFO "%s", version); | 6430 | printk(KERN_INFO "%s", version); |
@@ -6052,6 +6465,23 @@ bnx2_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
6052 | dev->poll_controller = poll_bnx2; | 6465 | dev->poll_controller = poll_bnx2; |
6053 | #endif | 6466 | #endif |
6054 | 6467 | ||
6468 | pci_set_drvdata(pdev, dev); | ||
6469 | |||
6470 | memcpy(dev->dev_addr, bp->mac_addr, 6); | ||
6471 | memcpy(dev->perm_addr, bp->mac_addr, 6); | ||
6472 | bp->name = board_info[ent->driver_data].name; | ||
6473 | |||
6474 | if (CHIP_NUM(bp) == CHIP_NUM_5709) | ||
6475 | dev->features |= NETIF_F_HW_CSUM | NETIF_F_SG; | ||
6476 | else | ||
6477 | dev->features |= NETIF_F_IP_CSUM | NETIF_F_SG; | ||
6478 | #ifdef BCM_VLAN | ||
6479 | dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX; | ||
6480 | #endif | ||
6481 | dev->features |= NETIF_F_TSO | NETIF_F_TSO_ECN; | ||
6482 | if (CHIP_NUM(bp) == CHIP_NUM_5709) | ||
6483 | dev->features |= NETIF_F_TSO6; | ||
6484 | |||
6055 | if ((rc = register_netdev(dev))) { | 6485 | if ((rc = register_netdev(dev))) { |
6056 | dev_err(&pdev->dev, "Cannot register net device\n"); | 6486 | dev_err(&pdev->dev, "Cannot register net device\n"); |
6057 | if (bp->regview) | 6487 | if (bp->regview) |
@@ -6063,20 +6493,13 @@ bnx2_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
6063 | return rc; | 6493 | return rc; |
6064 | } | 6494 | } |
6065 | 6495 | ||
6066 | pci_set_drvdata(pdev, dev); | 6496 | printk(KERN_INFO "%s: %s (%c%d) %s found at mem %lx, " |
6067 | |||
6068 | memcpy(dev->dev_addr, bp->mac_addr, 6); | ||
6069 | memcpy(dev->perm_addr, bp->mac_addr, 6); | ||
6070 | bp->name = board_info[ent->driver_data].name, | ||
6071 | printk(KERN_INFO "%s: %s (%c%d) PCI%s %s %dMHz found at mem %lx, " | ||
6072 | "IRQ %d, ", | 6497 | "IRQ %d, ", |
6073 | dev->name, | 6498 | dev->name, |
6074 | bp->name, | 6499 | bp->name, |
6075 | ((CHIP_ID(bp) & 0xf000) >> 12) + 'A', | 6500 | ((CHIP_ID(bp) & 0xf000) >> 12) + 'A', |
6076 | ((CHIP_ID(bp) & 0x0ff0) >> 4), | 6501 | ((CHIP_ID(bp) & 0x0ff0) >> 4), |
6077 | ((bp->flags & PCIX_FLAG) ? "-X" : ""), | 6502 | bnx2_bus_string(bp, str), |
6078 | ((bp->flags & PCI_32BIT_FLAG) ? "32-bit" : "64-bit"), | ||
6079 | bp->bus_speed_mhz, | ||
6080 | dev->base_addr, | 6503 | dev->base_addr, |
6081 | bp->pdev->irq); | 6504 | bp->pdev->irq); |
6082 | 6505 | ||
@@ -6085,17 +6508,6 @@ bnx2_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
6085 | printk("%2.2x", dev->dev_addr[i]); | 6508 | printk("%2.2x", dev->dev_addr[i]); |
6086 | printk("\n"); | 6509 | printk("\n"); |
6087 | 6510 | ||
6088 | dev->features |= NETIF_F_SG; | ||
6089 | if (bp->flags & USING_DAC_FLAG) | ||
6090 | dev->features |= NETIF_F_HIGHDMA; | ||
6091 | dev->features |= NETIF_F_IP_CSUM; | ||
6092 | #ifdef BCM_VLAN | ||
6093 | dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX; | ||
6094 | #endif | ||
6095 | dev->features |= NETIF_F_TSO | NETIF_F_TSO_ECN; | ||
6096 | |||
6097 | netif_carrier_off(bp->dev); | ||
6098 | |||
6099 | return 0; | 6511 | return 0; |
6100 | } | 6512 | } |
6101 | 6513 | ||
@@ -6140,6 +6552,7 @@ bnx2_suspend(struct pci_dev *pdev, pm_message_t state) | |||
6140 | reset_code = BNX2_DRV_MSG_CODE_SUSPEND_NO_WOL; | 6552 | reset_code = BNX2_DRV_MSG_CODE_SUSPEND_NO_WOL; |
6141 | bnx2_reset_chip(bp, reset_code); | 6553 | bnx2_reset_chip(bp, reset_code); |
6142 | bnx2_free_skbs(bp); | 6554 | bnx2_free_skbs(bp); |
6555 | pci_save_state(pdev); | ||
6143 | bnx2_set_power_state(bp, pci_choose_state(pdev, state)); | 6556 | bnx2_set_power_state(bp, pci_choose_state(pdev, state)); |
6144 | return 0; | 6557 | return 0; |
6145 | } | 6558 | } |
@@ -6153,6 +6566,7 @@ bnx2_resume(struct pci_dev *pdev) | |||
6153 | if (!netif_running(dev)) | 6566 | if (!netif_running(dev)) |
6154 | return 0; | 6567 | return 0; |
6155 | 6568 | ||
6569 | pci_restore_state(pdev); | ||
6156 | bnx2_set_power_state(bp, PCI_D0); | 6570 | bnx2_set_power_state(bp, PCI_D0); |
6157 | netif_device_attach(dev); | 6571 | netif_device_attach(dev); |
6158 | bnx2_init_nic(bp); | 6572 | bnx2_init_nic(bp); |