diff options
author | Yaniv Rosner <yaniv.rosner@broadcom.com> | 2010-09-07 07:41:20 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2010-09-07 16:15:42 -0400 |
commit | a22f078867ef362e35c54055878168e6613ff743 (patch) | |
tree | 2cf683f3057b7ed5dcaaaad16192f3a267dcf0f8 /drivers/net/bnx2x | |
parent | de6eae1f42eae736548f293570fd867bd37c3bdd (diff) |
bnx2x: Add dual-media changes
Add required changes in order to support dual-media boards.
Signed-off-by: Yaniv Rosner <yanivr@broadcom.com>
Signed-off-by: Eilon Greenstein <eilong@broadcom.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/bnx2x')
-rw-r--r-- | drivers/net/bnx2x/bnx2x.h | 10 | ||||
-rw-r--r-- | drivers/net/bnx2x/bnx2x_cmn.c | 14 | ||||
-rw-r--r-- | drivers/net/bnx2x/bnx2x_cmn.h | 3 | ||||
-rw-r--r-- | drivers/net/bnx2x/bnx2x_ethtool.c | 176 | ||||
-rw-r--r-- | drivers/net/bnx2x/bnx2x_hsi.h | 111 | ||||
-rw-r--r-- | drivers/net/bnx2x/bnx2x_link.c | 695 | ||||
-rw-r--r-- | drivers/net/bnx2x/bnx2x_link.h | 62 | ||||
-rw-r--r-- | drivers/net/bnx2x/bnx2x_main.c | 354 | ||||
-rw-r--r-- | drivers/net/bnx2x/bnx2x_reg.h | 25 |
9 files changed, 1074 insertions, 376 deletions
diff --git a/drivers/net/bnx2x/bnx2x.h b/drivers/net/bnx2x/bnx2x.h index a019c67d2995..137187684f27 100644 --- a/drivers/net/bnx2x/bnx2x.h +++ b/drivers/net/bnx2x/bnx2x.h | |||
@@ -566,13 +566,13 @@ struct bnx2x_common { | |||
566 | struct bnx2x_port { | 566 | struct bnx2x_port { |
567 | u32 pmf; | 567 | u32 pmf; |
568 | 568 | ||
569 | u32 link_config; | 569 | u32 link_config[LINK_CONFIG_SIZE]; |
570 | 570 | ||
571 | u32 supported; | 571 | u32 supported[LINK_CONFIG_SIZE]; |
572 | /* link settings - missing defines */ | 572 | /* link settings - missing defines */ |
573 | #define SUPPORTED_2500baseX_Full (1 << 15) | 573 | #define SUPPORTED_2500baseX_Full (1 << 15) |
574 | 574 | ||
575 | u32 advertising; | 575 | u32 advertising[LINK_CONFIG_SIZE]; |
576 | /* link settings - missing defines */ | 576 | /* link settings - missing defines */ |
577 | #define ADVERTISED_2500baseX_Full (1 << 15) | 577 | #define ADVERTISED_2500baseX_Full (1 << 15) |
578 | 578 | ||
@@ -931,7 +931,7 @@ void bnx2x_write_dmae(struct bnx2x *bp, dma_addr_t dma_addr, u32 dst_addr, | |||
931 | int bnx2x_get_gpio(struct bnx2x *bp, int gpio_num, u8 port); | 931 | int bnx2x_get_gpio(struct bnx2x *bp, int gpio_num, u8 port); |
932 | int bnx2x_set_gpio(struct bnx2x *bp, int gpio_num, u32 mode, u8 port); | 932 | int bnx2x_set_gpio(struct bnx2x *bp, int gpio_num, u32 mode, u8 port); |
933 | int bnx2x_set_gpio_int(struct bnx2x *bp, int gpio_num, u32 mode, u8 port); | 933 | int bnx2x_set_gpio_int(struct bnx2x *bp, int gpio_num, u32 mode, u8 port); |
934 | u32 bnx2x_fw_command(struct bnx2x *bp, u32 command); | 934 | u32 bnx2x_fw_command(struct bnx2x *bp, u32 command, u32 param); |
935 | void bnx2x_reg_wr_ind(struct bnx2x *bp, u32 addr, u32 val); | 935 | void bnx2x_reg_wr_ind(struct bnx2x *bp, u32 addr, u32 val); |
936 | void bnx2x_write_dmae_phys_len(struct bnx2x *bp, dma_addr_t phys_addr, | 936 | void bnx2x_write_dmae_phys_len(struct bnx2x *bp, dma_addr_t phys_addr, |
937 | u32 addr, u32 len); | 937 | u32 addr, u32 len); |
@@ -939,7 +939,7 @@ void bnx2x_calc_fc_adv(struct bnx2x *bp); | |||
939 | int bnx2x_sp_post(struct bnx2x *bp, int command, int cid, | 939 | int bnx2x_sp_post(struct bnx2x *bp, int command, int cid, |
940 | u32 data_hi, u32 data_lo, int common); | 940 | u32 data_hi, u32 data_lo, int common); |
941 | void bnx2x_update_coalesce(struct bnx2x *bp); | 941 | void bnx2x_update_coalesce(struct bnx2x *bp); |
942 | 942 | int bnx2x_get_link_cfg_idx(struct bnx2x *bp); | |
943 | static inline u32 reg_poll(struct bnx2x *bp, u32 reg, u32 expected, int ms, | 943 | static inline u32 reg_poll(struct bnx2x *bp, u32 reg, u32 expected, int ms, |
944 | int wait) | 944 | int wait) |
945 | { | 945 | { |
diff --git a/drivers/net/bnx2x/bnx2x_cmn.c b/drivers/net/bnx2x/bnx2x_cmn.c index 0e4caf411905..7f1d291eaaa5 100644 --- a/drivers/net/bnx2x/bnx2x_cmn.c +++ b/drivers/net/bnx2x/bnx2x_cmn.c | |||
@@ -1283,7 +1283,7 @@ int bnx2x_nic_load(struct bnx2x *bp, int load_mode) | |||
1283 | common blocks should be initialized, otherwise - not | 1283 | common blocks should be initialized, otherwise - not |
1284 | */ | 1284 | */ |
1285 | if (!BP_NOMCP(bp)) { | 1285 | if (!BP_NOMCP(bp)) { |
1286 | load_code = bnx2x_fw_command(bp, DRV_MSG_CODE_LOAD_REQ); | 1286 | load_code = bnx2x_fw_command(bp, DRV_MSG_CODE_LOAD_REQ, 0); |
1287 | if (!load_code) { | 1287 | if (!load_code) { |
1288 | BNX2X_ERR("MCP response failure, aborting\n"); | 1288 | BNX2X_ERR("MCP response failure, aborting\n"); |
1289 | rc = -EBUSY; | 1289 | rc = -EBUSY; |
@@ -1322,9 +1322,9 @@ int bnx2x_nic_load(struct bnx2x *bp, int load_mode) | |||
1322 | rc = bnx2x_init_hw(bp, load_code); | 1322 | rc = bnx2x_init_hw(bp, load_code); |
1323 | if (rc) { | 1323 | if (rc) { |
1324 | BNX2X_ERR("HW init failed, aborting\n"); | 1324 | BNX2X_ERR("HW init failed, aborting\n"); |
1325 | bnx2x_fw_command(bp, DRV_MSG_CODE_LOAD_DONE); | 1325 | bnx2x_fw_command(bp, DRV_MSG_CODE_LOAD_DONE, 0); |
1326 | bnx2x_fw_command(bp, DRV_MSG_CODE_UNLOAD_REQ_WOL_MCP); | 1326 | bnx2x_fw_command(bp, DRV_MSG_CODE_UNLOAD_REQ_WOL_MCP, 0); |
1327 | bnx2x_fw_command(bp, DRV_MSG_CODE_UNLOAD_DONE); | 1327 | bnx2x_fw_command(bp, DRV_MSG_CODE_UNLOAD_DONE, 0); |
1328 | goto load_error2; | 1328 | goto load_error2; |
1329 | } | 1329 | } |
1330 | 1330 | ||
@@ -1339,7 +1339,7 @@ int bnx2x_nic_load(struct bnx2x *bp, int load_mode) | |||
1339 | 1339 | ||
1340 | /* Send LOAD_DONE command to MCP */ | 1340 | /* Send LOAD_DONE command to MCP */ |
1341 | if (!BP_NOMCP(bp)) { | 1341 | if (!BP_NOMCP(bp)) { |
1342 | load_code = bnx2x_fw_command(bp, DRV_MSG_CODE_LOAD_DONE); | 1342 | load_code = bnx2x_fw_command(bp, DRV_MSG_CODE_LOAD_DONE, 0); |
1343 | if (!load_code) { | 1343 | if (!load_code) { |
1344 | BNX2X_ERR("MCP response failure, aborting\n"); | 1344 | BNX2X_ERR("MCP response failure, aborting\n"); |
1345 | rc = -EBUSY; | 1345 | rc = -EBUSY; |
@@ -1455,8 +1455,8 @@ load_error4: | |||
1455 | load_error3: | 1455 | load_error3: |
1456 | bnx2x_int_disable_sync(bp, 1); | 1456 | bnx2x_int_disable_sync(bp, 1); |
1457 | if (!BP_NOMCP(bp)) { | 1457 | if (!BP_NOMCP(bp)) { |
1458 | bnx2x_fw_command(bp, DRV_MSG_CODE_UNLOAD_REQ_WOL_MCP); | 1458 | bnx2x_fw_command(bp, DRV_MSG_CODE_UNLOAD_REQ_WOL_MCP, 0); |
1459 | bnx2x_fw_command(bp, DRV_MSG_CODE_UNLOAD_DONE); | 1459 | bnx2x_fw_command(bp, DRV_MSG_CODE_UNLOAD_DONE, 0); |
1460 | } | 1460 | } |
1461 | bp->port.pmf = 0; | 1461 | bp->port.pmf = 0; |
1462 | /* Free SKBs, SGEs, TPA pool and driver internals */ | 1462 | /* Free SKBs, SGEs, TPA pool and driver internals */ |
diff --git a/drivers/net/bnx2x/bnx2x_cmn.h b/drivers/net/bnx2x/bnx2x_cmn.h index 32543c32805c..d1e6a8c977d1 100644 --- a/drivers/net/bnx2x/bnx2x_cmn.h +++ b/drivers/net/bnx2x/bnx2x_cmn.h | |||
@@ -49,10 +49,11 @@ void bnx2x_link_set(struct bnx2x *bp); | |||
49 | * Query link status | 49 | * Query link status |
50 | * | 50 | * |
51 | * @param bp | 51 | * @param bp |
52 | * @param is_serdes | ||
52 | * | 53 | * |
53 | * @return 0 - link is UP | 54 | * @return 0 - link is UP |
54 | */ | 55 | */ |
55 | u8 bnx2x_link_test(struct bnx2x *bp); | 56 | u8 bnx2x_link_test(struct bnx2x *bp, u8 is_serdes); |
56 | 57 | ||
57 | /** | 58 | /** |
58 | * Handles link status change | 59 | * Handles link status change |
diff --git a/drivers/net/bnx2x/bnx2x_ethtool.c b/drivers/net/bnx2x/bnx2x_ethtool.c index dbcfa7a5618f..d058f9716785 100644 --- a/drivers/net/bnx2x/bnx2x_ethtool.c +++ b/drivers/net/bnx2x/bnx2x_ethtool.c | |||
@@ -29,9 +29,12 @@ | |||
29 | static int bnx2x_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) | 29 | static int bnx2x_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) |
30 | { | 30 | { |
31 | struct bnx2x *bp = netdev_priv(dev); | 31 | struct bnx2x *bp = netdev_priv(dev); |
32 | 32 | int cfg_idx = bnx2x_get_link_cfg_idx(bp); | |
33 | cmd->supported = bp->port.supported; | 33 | /* Dual Media boards present all available port types */ |
34 | cmd->advertising = bp->port.advertising; | 34 | cmd->supported = bp->port.supported[cfg_idx] | |
35 | (bp->port.supported[cfg_idx ^ 1] & | ||
36 | (SUPPORTED_TP | SUPPORTED_FIBRE)); | ||
37 | cmd->advertising = bp->port.advertising[cfg_idx]; | ||
35 | 38 | ||
36 | if ((bp->state == BNX2X_STATE_OPEN) && | 39 | if ((bp->state == BNX2X_STATE_OPEN) && |
37 | !(bp->flags & MF_FUNC_DIS) && | 40 | !(bp->flags & MF_FUNC_DIS) && |
@@ -48,22 +51,21 @@ static int bnx2x_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) | |||
48 | cmd->speed = vn_max_rate; | 51 | cmd->speed = vn_max_rate; |
49 | } | 52 | } |
50 | } else { | 53 | } else { |
51 | cmd->speed = -1; | 54 | cmd->speed = bp->link_params.req_line_speed[cfg_idx]; |
52 | cmd->duplex = -1; | 55 | cmd->duplex = bp->link_params.req_duplex[cfg_idx]; |
53 | } | 56 | } |
54 | 57 | ||
55 | if (bp->link_params.num_phys > 0) { | 58 | if (bp->port.supported[cfg_idx] & SUPPORTED_TP) |
56 | if (bp->link_params.phy[bp->link_params.num_phys - 1]. | 59 | cmd->port = PORT_TP; |
57 | supported & SUPPORTED_FIBRE) | 60 | else if (bp->port.supported[cfg_idx] & SUPPORTED_FIBRE) |
58 | cmd->port = PORT_FIBRE; | 61 | cmd->port = PORT_FIBRE; |
59 | else | 62 | else |
60 | cmd->port = PORT_TP; | 63 | BNX2X_ERR("XGXS PHY Failure detected\n"); |
61 | } else | 64 | |
62 | DP(NETIF_MSG_LINK, "No media found\n"); | ||
63 | cmd->phy_address = bp->mdio.prtad; | 65 | cmd->phy_address = bp->mdio.prtad; |
64 | cmd->transceiver = XCVR_INTERNAL; | 66 | cmd->transceiver = XCVR_INTERNAL; |
65 | 67 | ||
66 | if (bp->link_params.req_line_speed == SPEED_AUTO_NEG) | 68 | if (bp->link_params.req_line_speed[cfg_idx] == SPEED_AUTO_NEG) |
67 | cmd->autoneg = AUTONEG_ENABLE; | 69 | cmd->autoneg = AUTONEG_ENABLE; |
68 | else | 70 | else |
69 | cmd->autoneg = AUTONEG_DISABLE; | 71 | cmd->autoneg = AUTONEG_DISABLE; |
@@ -85,7 +87,7 @@ static int bnx2x_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) | |||
85 | static int bnx2x_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) | 87 | static int bnx2x_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) |
86 | { | 88 | { |
87 | struct bnx2x *bp = netdev_priv(dev); | 89 | struct bnx2x *bp = netdev_priv(dev); |
88 | u32 advertising; | 90 | u32 advertising, cfg_idx, old_multi_phy_config, new_multi_phy_config; |
89 | 91 | ||
90 | if (IS_E1HMF(bp)) | 92 | if (IS_E1HMF(bp)) |
91 | return 0; | 93 | return 0; |
@@ -98,26 +100,81 @@ static int bnx2x_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) | |||
98 | cmd->duplex, cmd->port, cmd->phy_address, cmd->transceiver, | 100 | cmd->duplex, cmd->port, cmd->phy_address, cmd->transceiver, |
99 | cmd->autoneg, cmd->maxtxpkt, cmd->maxrxpkt); | 101 | cmd->autoneg, cmd->maxtxpkt, cmd->maxrxpkt); |
100 | 102 | ||
103 | cfg_idx = bnx2x_get_link_cfg_idx(bp); | ||
104 | old_multi_phy_config = bp->link_params.multi_phy_config; | ||
105 | switch (cmd->port) { | ||
106 | case PORT_TP: | ||
107 | if (bp->port.supported[cfg_idx] & SUPPORTED_TP) | ||
108 | break; /* no port change */ | ||
109 | |||
110 | if (!(bp->port.supported[0] & SUPPORTED_TP || | ||
111 | bp->port.supported[1] & SUPPORTED_TP)) { | ||
112 | DP(NETIF_MSG_LINK, "Unsupported port type\n"); | ||
113 | return -EINVAL; | ||
114 | } | ||
115 | bp->link_params.multi_phy_config &= | ||
116 | ~PORT_HW_CFG_PHY_SELECTION_MASK; | ||
117 | if (bp->link_params.multi_phy_config & | ||
118 | PORT_HW_CFG_PHY_SWAPPED_ENABLED) | ||
119 | bp->link_params.multi_phy_config |= | ||
120 | PORT_HW_CFG_PHY_SELECTION_SECOND_PHY; | ||
121 | else | ||
122 | bp->link_params.multi_phy_config |= | ||
123 | PORT_HW_CFG_PHY_SELECTION_FIRST_PHY; | ||
124 | break; | ||
125 | case PORT_FIBRE: | ||
126 | if (bp->port.supported[cfg_idx] & SUPPORTED_FIBRE) | ||
127 | break; /* no port change */ | ||
128 | |||
129 | if (!(bp->port.supported[0] & SUPPORTED_FIBRE || | ||
130 | bp->port.supported[1] & SUPPORTED_FIBRE)) { | ||
131 | DP(NETIF_MSG_LINK, "Unsupported port type\n"); | ||
132 | return -EINVAL; | ||
133 | } | ||
134 | bp->link_params.multi_phy_config &= | ||
135 | ~PORT_HW_CFG_PHY_SELECTION_MASK; | ||
136 | if (bp->link_params.multi_phy_config & | ||
137 | PORT_HW_CFG_PHY_SWAPPED_ENABLED) | ||
138 | bp->link_params.multi_phy_config |= | ||
139 | PORT_HW_CFG_PHY_SELECTION_FIRST_PHY; | ||
140 | else | ||
141 | bp->link_params.multi_phy_config |= | ||
142 | PORT_HW_CFG_PHY_SELECTION_SECOND_PHY; | ||
143 | break; | ||
144 | default: | ||
145 | DP(NETIF_MSG_LINK, "Unsupported port type\n"); | ||
146 | return -EINVAL; | ||
147 | } | ||
148 | /* Save new config in case command complete successuly */ | ||
149 | new_multi_phy_config = bp->link_params.multi_phy_config; | ||
150 | /* Get the new cfg_idx */ | ||
151 | cfg_idx = bnx2x_get_link_cfg_idx(bp); | ||
152 | /* Restore old config in case command failed */ | ||
153 | bp->link_params.multi_phy_config = old_multi_phy_config; | ||
154 | DP(NETIF_MSG_LINK, "cfg_idx = %x\n", cfg_idx); | ||
155 | |||
101 | if (cmd->autoneg == AUTONEG_ENABLE) { | 156 | if (cmd->autoneg == AUTONEG_ENABLE) { |
102 | if (!(bp->port.supported & SUPPORTED_Autoneg)) { | 157 | if (!(bp->port.supported[cfg_idx] & SUPPORTED_Autoneg)) { |
103 | DP(NETIF_MSG_LINK, "Autoneg not supported\n"); | 158 | DP(NETIF_MSG_LINK, "Autoneg not supported\n"); |
104 | return -EINVAL; | 159 | return -EINVAL; |
105 | } | 160 | } |
106 | 161 | ||
107 | /* advertise the requested speed and duplex if supported */ | 162 | /* advertise the requested speed and duplex if supported */ |
108 | cmd->advertising &= bp->port.supported; | 163 | cmd->advertising &= bp->port.supported[cfg_idx]; |
109 | 164 | ||
110 | bp->link_params.req_line_speed = SPEED_AUTO_NEG; | 165 | bp->link_params.req_line_speed[cfg_idx] = SPEED_AUTO_NEG; |
111 | bp->link_params.req_duplex = DUPLEX_FULL; | 166 | bp->link_params.req_duplex[cfg_idx] = DUPLEX_FULL; |
112 | bp->port.advertising |= (ADVERTISED_Autoneg | | 167 | bp->port.advertising[cfg_idx] |= (ADVERTISED_Autoneg | |
113 | cmd->advertising); | 168 | cmd->advertising); |
114 | 169 | ||
115 | } else { /* forced speed */ | 170 | } else { /* forced speed */ |
116 | /* advertise the requested speed and duplex if supported */ | 171 | /* advertise the requested speed and duplex if supported */ |
117 | switch (cmd->speed) { | 172 | u32 speed = cmd->speed; |
173 | speed |= (cmd->speed_hi << 16); | ||
174 | switch (speed) { | ||
118 | case SPEED_10: | 175 | case SPEED_10: |
119 | if (cmd->duplex == DUPLEX_FULL) { | 176 | if (cmd->duplex == DUPLEX_FULL) { |
120 | if (!(bp->port.supported & | 177 | if (!(bp->port.supported[cfg_idx] & |
121 | SUPPORTED_10baseT_Full)) { | 178 | SUPPORTED_10baseT_Full)) { |
122 | DP(NETIF_MSG_LINK, | 179 | DP(NETIF_MSG_LINK, |
123 | "10M full not supported\n"); | 180 | "10M full not supported\n"); |
@@ -127,7 +184,7 @@ static int bnx2x_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) | |||
127 | advertising = (ADVERTISED_10baseT_Full | | 184 | advertising = (ADVERTISED_10baseT_Full | |
128 | ADVERTISED_TP); | 185 | ADVERTISED_TP); |
129 | } else { | 186 | } else { |
130 | if (!(bp->port.supported & | 187 | if (!(bp->port.supported[cfg_idx] & |
131 | SUPPORTED_10baseT_Half)) { | 188 | SUPPORTED_10baseT_Half)) { |
132 | DP(NETIF_MSG_LINK, | 189 | DP(NETIF_MSG_LINK, |
133 | "10M half not supported\n"); | 190 | "10M half not supported\n"); |
@@ -141,7 +198,7 @@ static int bnx2x_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) | |||
141 | 198 | ||
142 | case SPEED_100: | 199 | case SPEED_100: |
143 | if (cmd->duplex == DUPLEX_FULL) { | 200 | if (cmd->duplex == DUPLEX_FULL) { |
144 | if (!(bp->port.supported & | 201 | if (!(bp->port.supported[cfg_idx] & |
145 | SUPPORTED_100baseT_Full)) { | 202 | SUPPORTED_100baseT_Full)) { |
146 | DP(NETIF_MSG_LINK, | 203 | DP(NETIF_MSG_LINK, |
147 | "100M full not supported\n"); | 204 | "100M full not supported\n"); |
@@ -151,7 +208,7 @@ static int bnx2x_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) | |||
151 | advertising = (ADVERTISED_100baseT_Full | | 208 | advertising = (ADVERTISED_100baseT_Full | |
152 | ADVERTISED_TP); | 209 | ADVERTISED_TP); |
153 | } else { | 210 | } else { |
154 | if (!(bp->port.supported & | 211 | if (!(bp->port.supported[cfg_idx] & |
155 | SUPPORTED_100baseT_Half)) { | 212 | SUPPORTED_100baseT_Half)) { |
156 | DP(NETIF_MSG_LINK, | 213 | DP(NETIF_MSG_LINK, |
157 | "100M half not supported\n"); | 214 | "100M half not supported\n"); |
@@ -169,7 +226,8 @@ static int bnx2x_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) | |||
169 | return -EINVAL; | 226 | return -EINVAL; |
170 | } | 227 | } |
171 | 228 | ||
172 | if (!(bp->port.supported & SUPPORTED_1000baseT_Full)) { | 229 | if (!(bp->port.supported[cfg_idx] & |
230 | SUPPORTED_1000baseT_Full)) { | ||
173 | DP(NETIF_MSG_LINK, "1G full not supported\n"); | 231 | DP(NETIF_MSG_LINK, "1G full not supported\n"); |
174 | return -EINVAL; | 232 | return -EINVAL; |
175 | } | 233 | } |
@@ -185,7 +243,8 @@ static int bnx2x_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) | |||
185 | return -EINVAL; | 243 | return -EINVAL; |
186 | } | 244 | } |
187 | 245 | ||
188 | if (!(bp->port.supported & SUPPORTED_2500baseX_Full)) { | 246 | if (!(bp->port.supported[cfg_idx] |
247 | & SUPPORTED_2500baseX_Full)) { | ||
189 | DP(NETIF_MSG_LINK, | 248 | DP(NETIF_MSG_LINK, |
190 | "2.5G full not supported\n"); | 249 | "2.5G full not supported\n"); |
191 | return -EINVAL; | 250 | return -EINVAL; |
@@ -201,7 +260,8 @@ static int bnx2x_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) | |||
201 | return -EINVAL; | 260 | return -EINVAL; |
202 | } | 261 | } |
203 | 262 | ||
204 | if (!(bp->port.supported & SUPPORTED_10000baseT_Full)) { | 263 | if (!(bp->port.supported[cfg_idx] |
264 | & SUPPORTED_10000baseT_Full)) { | ||
205 | DP(NETIF_MSG_LINK, "10G full not supported\n"); | 265 | DP(NETIF_MSG_LINK, "10G full not supported\n"); |
206 | return -EINVAL; | 266 | return -EINVAL; |
207 | } | 267 | } |
@@ -211,20 +271,23 @@ static int bnx2x_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) | |||
211 | break; | 271 | break; |
212 | 272 | ||
213 | default: | 273 | default: |
214 | DP(NETIF_MSG_LINK, "Unsupported speed\n"); | 274 | DP(NETIF_MSG_LINK, "Unsupported speed %d\n", speed); |
215 | return -EINVAL; | 275 | return -EINVAL; |
216 | } | 276 | } |
217 | 277 | ||
218 | bp->link_params.req_line_speed = cmd->speed; | 278 | bp->link_params.req_line_speed[cfg_idx] = speed; |
219 | bp->link_params.req_duplex = cmd->duplex; | 279 | bp->link_params.req_duplex[cfg_idx] = cmd->duplex; |
220 | bp->port.advertising = advertising; | 280 | bp->port.advertising[cfg_idx] = advertising; |
221 | } | 281 | } |
222 | 282 | ||
223 | DP(NETIF_MSG_LINK, "req_line_speed %d\n" | 283 | DP(NETIF_MSG_LINK, "req_line_speed %d\n" |
224 | DP_LEVEL " req_duplex %d advertising 0x%x\n", | 284 | DP_LEVEL " req_duplex %d advertising 0x%x\n", |
225 | bp->link_params.req_line_speed, bp->link_params.req_duplex, | 285 | bp->link_params.req_line_speed[cfg_idx], |
226 | bp->port.advertising); | 286 | bp->link_params.req_duplex[cfg_idx], |
287 | bp->port.advertising[cfg_idx]); | ||
227 | 288 | ||
289 | /* Set new config */ | ||
290 | bp->link_params.multi_phy_config = new_multi_phy_config; | ||
228 | if (netif_running(dev)) { | 291 | if (netif_running(dev)) { |
229 | bnx2x_stats_handle(bp, STATS_EVENT_STOP); | 292 | bnx2x_stats_handle(bp, STATS_EVENT_STOP); |
230 | bnx2x_link_set(bp); | 293 | bnx2x_link_set(bp); |
@@ -937,10 +1000,9 @@ static void bnx2x_get_pauseparam(struct net_device *dev, | |||
937 | struct ethtool_pauseparam *epause) | 1000 | struct ethtool_pauseparam *epause) |
938 | { | 1001 | { |
939 | struct bnx2x *bp = netdev_priv(dev); | 1002 | struct bnx2x *bp = netdev_priv(dev); |
940 | 1003 | int cfg_idx = bnx2x_get_link_cfg_idx(bp); | |
941 | epause->autoneg = (bp->link_params.req_flow_ctrl == | 1004 | epause->autoneg = (bp->link_params.req_flow_ctrl[cfg_idx] == |
942 | BNX2X_FLOW_CTRL_AUTO) && | 1005 | BNX2X_FLOW_CTRL_AUTO); |
943 | (bp->link_params.req_line_speed == SPEED_AUTO_NEG); | ||
944 | 1006 | ||
945 | epause->rx_pause = ((bp->link_vars.flow_ctrl & BNX2X_FLOW_CTRL_RX) == | 1007 | epause->rx_pause = ((bp->link_vars.flow_ctrl & BNX2X_FLOW_CTRL_RX) == |
946 | BNX2X_FLOW_CTRL_RX); | 1008 | BNX2X_FLOW_CTRL_RX); |
@@ -956,7 +1018,7 @@ static int bnx2x_set_pauseparam(struct net_device *dev, | |||
956 | struct ethtool_pauseparam *epause) | 1018 | struct ethtool_pauseparam *epause) |
957 | { | 1019 | { |
958 | struct bnx2x *bp = netdev_priv(dev); | 1020 | struct bnx2x *bp = netdev_priv(dev); |
959 | 1021 | u32 cfg_idx = bnx2x_get_link_cfg_idx(bp); | |
960 | if (IS_E1HMF(bp)) | 1022 | if (IS_E1HMF(bp)) |
961 | return 0; | 1023 | return 0; |
962 | 1024 | ||
@@ -964,29 +1026,31 @@ static int bnx2x_set_pauseparam(struct net_device *dev, | |||
964 | DP_LEVEL " autoneg %d rx_pause %d tx_pause %d\n", | 1026 | DP_LEVEL " autoneg %d rx_pause %d tx_pause %d\n", |
965 | epause->cmd, epause->autoneg, epause->rx_pause, epause->tx_pause); | 1027 | epause->cmd, epause->autoneg, epause->rx_pause, epause->tx_pause); |
966 | 1028 | ||
967 | bp->link_params.req_flow_ctrl = BNX2X_FLOW_CTRL_AUTO; | 1029 | bp->link_params.req_flow_ctrl[cfg_idx] = BNX2X_FLOW_CTRL_AUTO; |
968 | 1030 | ||
969 | if (epause->rx_pause) | 1031 | if (epause->rx_pause) |
970 | bp->link_params.req_flow_ctrl |= BNX2X_FLOW_CTRL_RX; | 1032 | bp->link_params.req_flow_ctrl[cfg_idx] |= BNX2X_FLOW_CTRL_RX; |
971 | 1033 | ||
972 | if (epause->tx_pause) | 1034 | if (epause->tx_pause) |
973 | bp->link_params.req_flow_ctrl |= BNX2X_FLOW_CTRL_TX; | 1035 | bp->link_params.req_flow_ctrl[cfg_idx] |= BNX2X_FLOW_CTRL_TX; |
974 | 1036 | ||
975 | if (bp->link_params.req_flow_ctrl == BNX2X_FLOW_CTRL_AUTO) | 1037 | if (bp->link_params.req_flow_ctrl[cfg_idx] == BNX2X_FLOW_CTRL_AUTO) |
976 | bp->link_params.req_flow_ctrl = BNX2X_FLOW_CTRL_NONE; | 1038 | bp->link_params.req_flow_ctrl[cfg_idx] = BNX2X_FLOW_CTRL_NONE; |
977 | 1039 | ||
978 | if (epause->autoneg) { | 1040 | if (epause->autoneg) { |
979 | if (!(bp->port.supported & SUPPORTED_Autoneg)) { | 1041 | if (!(bp->port.supported[cfg_idx] & SUPPORTED_Autoneg)) { |
980 | DP(NETIF_MSG_LINK, "autoneg not supported\n"); | 1042 | DP(NETIF_MSG_LINK, "autoneg not supported\n"); |
981 | return -EINVAL; | 1043 | return -EINVAL; |
982 | } | 1044 | } |
983 | 1045 | ||
984 | if (bp->link_params.req_line_speed == SPEED_AUTO_NEG) | 1046 | if (bp->link_params.req_line_speed[cfg_idx] == SPEED_AUTO_NEG) { |
985 | bp->link_params.req_flow_ctrl = BNX2X_FLOW_CTRL_AUTO; | 1047 | bp->link_params.req_flow_ctrl[cfg_idx] = |
1048 | BNX2X_FLOW_CTRL_AUTO; | ||
1049 | } | ||
986 | } | 1050 | } |
987 | 1051 | ||
988 | DP(NETIF_MSG_LINK, | 1052 | DP(NETIF_MSG_LINK, |
989 | "req_flow_ctrl 0x%x\n", bp->link_params.req_flow_ctrl); | 1053 | "req_flow_ctrl 0x%x\n", bp->link_params.req_flow_ctrl[cfg_idx]); |
990 | 1054 | ||
991 | if (netif_running(dev)) { | 1055 | if (netif_running(dev)) { |
992 | bnx2x_stats_handle(bp, STATS_EVENT_STOP); | 1056 | bnx2x_stats_handle(bp, STATS_EVENT_STOP); |
@@ -1250,12 +1314,12 @@ test_mem_exit: | |||
1250 | return rc; | 1314 | return rc; |
1251 | } | 1315 | } |
1252 | 1316 | ||
1253 | static void bnx2x_wait_for_link(struct bnx2x *bp, u8 link_up) | 1317 | static void bnx2x_wait_for_link(struct bnx2x *bp, u8 link_up, u8 is_serdes) |
1254 | { | 1318 | { |
1255 | int cnt = 1000; | 1319 | int cnt = 1000; |
1256 | 1320 | ||
1257 | if (link_up) | 1321 | if (link_up) |
1258 | while (bnx2x_link_test(bp) && cnt--) | 1322 | while (bnx2x_link_test(bp, is_serdes) && cnt--) |
1259 | msleep(10); | 1323 | msleep(10); |
1260 | } | 1324 | } |
1261 | 1325 | ||
@@ -1527,7 +1591,7 @@ static void bnx2x_self_test(struct net_device *dev, | |||
1527 | struct ethtool_test *etest, u64 *buf) | 1591 | struct ethtool_test *etest, u64 *buf) |
1528 | { | 1592 | { |
1529 | struct bnx2x *bp = netdev_priv(dev); | 1593 | struct bnx2x *bp = netdev_priv(dev); |
1530 | 1594 | u8 is_serdes; | |
1531 | if (bp->recovery_state != BNX2X_RECOVERY_DONE) { | 1595 | if (bp->recovery_state != BNX2X_RECOVERY_DONE) { |
1532 | printk(KERN_ERR "Handling parity error recovery. Try again later\n"); | 1596 | printk(KERN_ERR "Handling parity error recovery. Try again later\n"); |
1533 | etest->flags |= ETH_TEST_FL_FAILED; | 1597 | etest->flags |= ETH_TEST_FL_FAILED; |
@@ -1542,6 +1606,7 @@ static void bnx2x_self_test(struct net_device *dev, | |||
1542 | /* offline tests are not supported in MF mode */ | 1606 | /* offline tests are not supported in MF mode */ |
1543 | if (IS_E1HMF(bp)) | 1607 | if (IS_E1HMF(bp)) |
1544 | etest->flags &= ~ETH_TEST_FL_OFFLINE; | 1608 | etest->flags &= ~ETH_TEST_FL_OFFLINE; |
1609 | is_serdes = (bp->link_vars.link_status & LINK_STATUS_SERDES_LINK) > 0; | ||
1545 | 1610 | ||
1546 | if (etest->flags & ETH_TEST_FL_OFFLINE) { | 1611 | if (etest->flags & ETH_TEST_FL_OFFLINE) { |
1547 | int port = BP_PORT(bp); | 1612 | int port = BP_PORT(bp); |
@@ -1553,11 +1618,12 @@ static void bnx2x_self_test(struct net_device *dev, | |||
1553 | /* disable input for TX port IF */ | 1618 | /* disable input for TX port IF */ |
1554 | REG_WR(bp, NIG_REG_EGRESS_UMP0_IN_EN + port*4, 0); | 1619 | REG_WR(bp, NIG_REG_EGRESS_UMP0_IN_EN + port*4, 0); |
1555 | 1620 | ||
1556 | link_up = (bnx2x_link_test(bp) == 0); | 1621 | link_up = bp->link_vars.link_up; |
1622 | |||
1557 | bnx2x_nic_unload(bp, UNLOAD_NORMAL); | 1623 | bnx2x_nic_unload(bp, UNLOAD_NORMAL); |
1558 | bnx2x_nic_load(bp, LOAD_DIAG); | 1624 | bnx2x_nic_load(bp, LOAD_DIAG); |
1559 | /* wait until link state is restored */ | 1625 | /* wait until link state is restored */ |
1560 | bnx2x_wait_for_link(bp, link_up); | 1626 | bnx2x_wait_for_link(bp, link_up, is_serdes); |
1561 | 1627 | ||
1562 | if (bnx2x_test_registers(bp) != 0) { | 1628 | if (bnx2x_test_registers(bp) != 0) { |
1563 | buf[0] = 1; | 1629 | buf[0] = 1; |
@@ -1578,7 +1644,7 @@ static void bnx2x_self_test(struct net_device *dev, | |||
1578 | 1644 | ||
1579 | bnx2x_nic_load(bp, LOAD_NORMAL); | 1645 | bnx2x_nic_load(bp, LOAD_NORMAL); |
1580 | /* wait until link state is restored */ | 1646 | /* wait until link state is restored */ |
1581 | bnx2x_wait_for_link(bp, link_up); | 1647 | bnx2x_wait_for_link(bp, link_up, is_serdes); |
1582 | } | 1648 | } |
1583 | if (bnx2x_test_nvram(bp) != 0) { | 1649 | if (bnx2x_test_nvram(bp) != 0) { |
1584 | buf[3] = 1; | 1650 | buf[3] = 1; |
@@ -1589,7 +1655,7 @@ static void bnx2x_self_test(struct net_device *dev, | |||
1589 | etest->flags |= ETH_TEST_FL_FAILED; | 1655 | etest->flags |= ETH_TEST_FL_FAILED; |
1590 | } | 1656 | } |
1591 | if (bp->port.pmf) | 1657 | if (bp->port.pmf) |
1592 | if (bnx2x_link_test(bp) != 0) { | 1658 | if (bnx2x_link_test(bp, is_serdes) != 0) { |
1593 | buf[5] = 1; | 1659 | buf[5] = 1; |
1594 | etest->flags |= ETH_TEST_FL_FAILED; | 1660 | etest->flags |= ETH_TEST_FL_FAILED; |
1595 | } | 1661 | } |
diff --git a/drivers/net/bnx2x/bnx2x_hsi.h b/drivers/net/bnx2x/bnx2x_hsi.h index f494bc333f52..bab3b2d8cc7a 100644 --- a/drivers/net/bnx2x/bnx2x_hsi.h +++ b/drivers/net/bnx2x/bnx2x_hsi.h | |||
@@ -238,7 +238,88 @@ struct port_hw_cfg { /* port 0: 0x12c port 1: 0x2bc */ | |||
238 | 238 | ||
239 | u16 xgxs_config_tx[4]; /* 0x1A0 */ | 239 | u16 xgxs_config_tx[4]; /* 0x1A0 */ |
240 | 240 | ||
241 | u32 Reserved1[64]; /* 0x1A8 */ | 241 | u32 Reserved1[57]; /* 0x1A8 */ |
242 | u32 speed_capability_mask2; /* 0x28C */ | ||
243 | #define PORT_HW_CFG_SPEED_CAPABILITY2_D3_MASK 0x0000FFFF | ||
244 | #define PORT_HW_CFG_SPEED_CAPABILITY2_D3_SHIFT 0 | ||
245 | #define PORT_HW_CFG_SPEED_CAPABILITY2_D3_10M_FULL 0x00000001 | ||
246 | #define PORT_HW_CFG_SPEED_CAPABILITY2_D3__ 0x00000002 | ||
247 | #define PORT_HW_CFG_SPEED_CAPABILITY2_D3___ 0x00000004 | ||
248 | #define PORT_HW_CFG_SPEED_CAPABILITY2_D3_100M_FULL 0x00000008 | ||
249 | #define PORT_HW_CFG_SPEED_CAPABILITY2_D3_1G 0x00000010 | ||
250 | #define PORT_HW_CFG_SPEED_CAPABILITY2_D3_2_DOT_5G 0x00000020 | ||
251 | #define PORT_HW_CFG_SPEED_CAPABILITY2_D3_10G 0x00000040 | ||
252 | #define PORT_HW_CFG_SPEED_CAPABILITY2_D3_12G 0x00000080 | ||
253 | #define PORT_HW_CFG_SPEED_CAPABILITY2_D3_12_DOT_5G 0x00000100 | ||
254 | #define PORT_HW_CFG_SPEED_CAPABILITY2_D3_13G 0x00000200 | ||
255 | #define PORT_HW_CFG_SPEED_CAPABILITY2_D3_15G 0x00000400 | ||
256 | #define PORT_HW_CFG_SPEED_CAPABILITY2_D3_16G 0x00000800 | ||
257 | |||
258 | #define PORT_HW_CFG_SPEED_CAPABILITY2_D0_MASK 0xFFFF0000 | ||
259 | #define PORT_HW_CFG_SPEED_CAPABILITY2_D0_SHIFT 16 | ||
260 | #define PORT_HW_CFG_SPEED_CAPABILITY2_D0_10M_FULL 0x00010000 | ||
261 | #define PORT_HW_CFG_SPEED_CAPABILITY2_D0__ 0x00020000 | ||
262 | #define PORT_HW_CFG_SPEED_CAPABILITY2_D0___ 0x00040000 | ||
263 | #define PORT_HW_CFG_SPEED_CAPABILITY2_D0_100M_FULL 0x00080000 | ||
264 | #define PORT_HW_CFG_SPEED_CAPABILITY2_D0_1G 0x00100000 | ||
265 | #define PORT_HW_CFG_SPEED_CAPABILITY2_D0_2_DOT_5G 0x00200000 | ||
266 | #define PORT_HW_CFG_SPEED_CAPABILITY2_D0_10G 0x00400000 | ||
267 | #define PORT_HW_CFG_SPEED_CAPABILITY2_D0_12G 0x00800000 | ||
268 | #define PORT_HW_CFG_SPEED_CAPABILITY2_D0_12_DOT_5G 0x01000000 | ||
269 | #define PORT_HW_CFG_SPEED_CAPABILITY2_D0_13G 0x02000000 | ||
270 | #define PORT_HW_CFG_SPEED_CAPABILITY2_D0_15G 0x04000000 | ||
271 | #define PORT_HW_CFG_SPEED_CAPABILITY2_D0_16G 0x08000000 | ||
272 | |||
273 | /* In the case where two media types (e.g. copper and fiber) are | ||
274 | present and electrically active at the same time, PHY Selection | ||
275 | will determine which of the two PHYs will be designated as the | ||
276 | Active PHY and used for a connection to the network. */ | ||
277 | u32 multi_phy_config; /* 0x290 */ | ||
278 | #define PORT_HW_CFG_PHY_SELECTION_MASK 0x00000007 | ||
279 | #define PORT_HW_CFG_PHY_SELECTION_SHIFT 0 | ||
280 | #define PORT_HW_CFG_PHY_SELECTION_HARDWARE_DEFAULT 0x00000000 | ||
281 | #define PORT_HW_CFG_PHY_SELECTION_FIRST_PHY 0x00000001 | ||
282 | #define PORT_HW_CFG_PHY_SELECTION_SECOND_PHY 0x00000002 | ||
283 | #define PORT_HW_CFG_PHY_SELECTION_FIRST_PHY_PRIORITY 0x00000003 | ||
284 | #define PORT_HW_CFG_PHY_SELECTION_SECOND_PHY_PRIORITY 0x00000004 | ||
285 | |||
286 | /* When enabled, all second phy nvram parameters will be swapped | ||
287 | with the first phy parameters */ | ||
288 | #define PORT_HW_CFG_PHY_SWAPPED_MASK 0x00000008 | ||
289 | #define PORT_HW_CFG_PHY_SWAPPED_SHIFT 3 | ||
290 | #define PORT_HW_CFG_PHY_SWAPPED_DISABLED 0x00000000 | ||
291 | #define PORT_HW_CFG_PHY_SWAPPED_ENABLED 0x00000008 | ||
292 | |||
293 | |||
294 | /* Address of the second external phy */ | ||
295 | u32 external_phy_config2; /* 0x294 */ | ||
296 | #define PORT_HW_CFG_XGXS_EXT_PHY2_ADDR_MASK 0x000000FF | ||
297 | #define PORT_HW_CFG_XGXS_EXT_PHY2_ADDR_SHIFT 0 | ||
298 | |||
299 | /* The second XGXS external PHY type */ | ||
300 | #define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_MASK 0x0000FF00 | ||
301 | #define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_SHIFT 8 | ||
302 | #define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_DIRECT 0x00000000 | ||
303 | #define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BCM8071 0x00000100 | ||
304 | #define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BCM8072 0x00000200 | ||
305 | #define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BCM8073 0x00000300 | ||
306 | #define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BCM8705 0x00000400 | ||
307 | #define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BCM8706 0x00000500 | ||
308 | #define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BCM8726 0x00000600 | ||
309 | #define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BCM8481 0x00000700 | ||
310 | #define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_SFX7101 0x00000800 | ||
311 | #define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BCM8727 0x00000900 | ||
312 | #define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BCM8727_NOC 0x00000a00 | ||
313 | #define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BCM84823 0x00000b00 | ||
314 | #define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BCM54640 0x00000c00 | ||
315 | #define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BCM84833 0x00000d00 | ||
316 | #define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_FAILURE 0x0000fd00 | ||
317 | #define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_NOT_CONN 0x0000ff00 | ||
318 | |||
319 | /* 4 times 16 bits for all 4 lanes. For some external PHYs (such as | ||
320 | 8706, 8726 and 8727) not all 4 values are needed. */ | ||
321 | u16 xgxs_config2_rx[4]; /* 0x296 */ | ||
322 | u16 xgxs_config2_tx[4]; /* 0x2A0 */ | ||
242 | 323 | ||
243 | u32 lane_config; | 324 | u32 lane_config; |
244 | #define PORT_HW_CFG_LANE_SWAP_CFG_MASK 0x0000ffff | 325 | #define PORT_HW_CFG_LANE_SWAP_CFG_MASK 0x0000ffff |
@@ -532,10 +613,17 @@ struct port_feat_cfg { /* port 0: 0x454 port 1: 0x4c8 */ | |||
532 | #define PORT_FEATURE_FLOW_CONTROL_NONE 0x00000400 | 613 | #define PORT_FEATURE_FLOW_CONTROL_NONE 0x00000400 |
533 | 614 | ||
534 | /* The default for MCP link configuration, | 615 | /* The default for MCP link configuration, |
535 | uses the same defines as link_config */ | 616 | uses the same defines as link_config */ |
536 | u32 mfw_wol_link_cfg; | 617 | u32 mfw_wol_link_cfg; |
618 | /* The default for the driver of the second external phy, | ||
619 | uses the same defines as link_config */ | ||
620 | u32 link_config2; /* 0x47C */ | ||
537 | 621 | ||
538 | u32 reserved[19]; | 622 | /* The default for MCP of the second external phy, |
623 | uses the same defines as link_config */ | ||
624 | u32 mfw_wol_link_cfg2; /* 0x480 */ | ||
625 | |||
626 | u32 Reserved2[17]; /* 0x484 */ | ||
539 | 627 | ||
540 | }; | 628 | }; |
541 | 629 | ||
@@ -703,8 +791,14 @@ struct drv_func_mb { | |||
703 | * The optic module verification commands require bootcode | 791 | * The optic module verification commands require bootcode |
704 | * v5.0.6 or later | 792 | * v5.0.6 or later |
705 | */ | 793 | */ |
706 | #define DRV_MSG_CODE_VRFY_OPT_MDL 0xa0000000 | 794 | #define DRV_MSG_CODE_VRFY_FIRST_PHY_OPT_MDL 0xa0000000 |
707 | #define REQ_BC_VER_4_VRFY_OPT_MDL 0x00050006 | 795 | #define REQ_BC_VER_4_VRFY_FIRST_PHY_OPT_MDL 0x00050006 |
796 | /* | ||
797 | * The specific optic module verification command requires bootcode | ||
798 | * v5.2.12 or later | ||
799 | */ | ||
800 | #define DRV_MSG_CODE_VRFY_SPECIFIC_PHY_OPT_MDL 0xa1000000 | ||
801 | #define REQ_BC_VER_4_VRFY_SPECIFIC_PHY_OPT_MDL 0x00050234 | ||
708 | 802 | ||
709 | #define BIOS_MSG_CODE_LIC_CHALLENGE 0xff010000 | 803 | #define BIOS_MSG_CODE_LIC_CHALLENGE 0xff010000 |
710 | #define BIOS_MSG_CODE_LIC_RESPONSE 0xff020000 | 804 | #define BIOS_MSG_CODE_LIC_RESPONSE 0xff020000 |
@@ -939,7 +1033,12 @@ struct shmem2_region { | |||
939 | #define SHMEM_DCC_SUPPORT_SET_PROTOCOL_TLV 0x00000040 | 1033 | #define SHMEM_DCC_SUPPORT_SET_PROTOCOL_TLV 0x00000040 |
940 | #define SHMEM_DCC_SUPPORT_SET_PRIORITY_TLV 0x00000080 | 1034 | #define SHMEM_DCC_SUPPORT_SET_PRIORITY_TLV 0x00000080 |
941 | #define SHMEM_DCC_SUPPORT_DEFAULT SHMEM_DCC_SUPPORT_NONE | 1035 | #define SHMEM_DCC_SUPPORT_DEFAULT SHMEM_DCC_SUPPORT_NONE |
942 | 1036 | u32 ext_phy_fw_version2[PORT_MAX]; | |
1037 | /* | ||
1038 | * For backwards compatibility, if the mf_cfg_addr does not exist | ||
1039 | * (the size filed is smaller than 0xc) the mf_cfg resides at the | ||
1040 | * end of struct shmem_region | ||
1041 | */ | ||
943 | }; | 1042 | }; |
944 | 1043 | ||
945 | 1044 | ||
diff --git a/drivers/net/bnx2x/bnx2x_link.c b/drivers/net/bnx2x/bnx2x_link.c index e2509aab9f0d..571785898970 100644 --- a/drivers/net/bnx2x/bnx2x_link.c +++ b/drivers/net/bnx2x/bnx2x_link.c | |||
@@ -899,6 +899,7 @@ static void bnx2x_xgxs_deassert(struct link_params *params) | |||
899 | params->phy[INT_PHY].def_md_devad); | 899 | params->phy[INT_PHY].def_md_devad); |
900 | } | 900 | } |
901 | 901 | ||
902 | |||
902 | void bnx2x_link_status_update(struct link_params *params, | 903 | void bnx2x_link_status_update(struct link_params *params, |
903 | struct link_vars *vars) | 904 | struct link_vars *vars) |
904 | { | 905 | { |
@@ -906,10 +907,6 @@ void bnx2x_link_status_update(struct link_params *params, | |||
906 | u8 link_10g; | 907 | u8 link_10g; |
907 | u8 port = params->port; | 908 | u8 port = params->port; |
908 | 909 | ||
909 | if (params->switch_cfg == SWITCH_CFG_1G) | ||
910 | vars->phy_flags = PHY_SERDES_FLAG; | ||
911 | else | ||
912 | vars->phy_flags = PHY_XGXS_FLAG; | ||
913 | vars->link_status = REG_RD(bp, params->shmem_base + | 910 | vars->link_status = REG_RD(bp, params->shmem_base + |
914 | offsetof(struct shmem_region, | 911 | offsetof(struct shmem_region, |
915 | port_mb[port].link_status)); | 912 | port_mb[port].link_status)); |
@@ -1880,12 +1877,8 @@ static u8 bnx2x_link_settings_status(struct bnx2x_phy *phy, | |||
1880 | 1877 | ||
1881 | DP(NETIF_MSG_LINK, "gp_status 0x%x phy_link_up %x line_speed %x\n", | 1878 | DP(NETIF_MSG_LINK, "gp_status 0x%x phy_link_up %x line_speed %x\n", |
1882 | gp_status, vars->phy_link_up, vars->line_speed); | 1879 | gp_status, vars->phy_link_up, vars->line_speed); |
1883 | DP(NETIF_MSG_LINK, "duplex %x flow_ctrl 0x%x" | 1880 | DP(NETIF_MSG_LINK, "duplex %x flow_ctrl 0x%x link_status 0x%x\n", |
1884 | " autoneg 0x%x\n", | 1881 | vars->duplex, vars->flow_ctrl, vars->link_status); |
1885 | vars->duplex, | ||
1886 | vars->flow_ctrl, vars->autoneg); | ||
1887 | DP(NETIF_MSG_LINK, "link_status 0x%x\n", vars->link_status); | ||
1888 | |||
1889 | return rc; | 1882 | return rc; |
1890 | } | 1883 | } |
1891 | 1884 | ||
@@ -2164,45 +2157,43 @@ static void bnx2x_link_int_enable(struct link_params *params) | |||
2164 | REG_RD(bp, NIG_REG_XGXS0_STATUS_LINK_STATUS + port*0x68)); | 2157 | REG_RD(bp, NIG_REG_XGXS0_STATUS_LINK_STATUS + port*0x68)); |
2165 | } | 2158 | } |
2166 | 2159 | ||
2167 | static void bnx2x_8481_rearm_latch_signal(struct bnx2x *bp, u8 port, | 2160 | static void bnx2x_rearm_latch_signal(struct bnx2x *bp, u8 port, |
2168 | u8 is_mi_int) | 2161 | u8 exp_mi_int) |
2169 | { | 2162 | { |
2170 | u32 latch_status = 0, is_mi_int_status; | 2163 | u32 latch_status = 0; |
2171 | /* Disable the MI INT ( external phy int ) | 2164 | |
2172 | * by writing 1 to the status register. Link down indication | 2165 | /** |
2173 | * is high-active-signal, so in this case we need to write the | 2166 | * Disable the MI INT ( external phy int ) by writing 1 to the |
2174 | * status to clear the XOR | 2167 | * status register. Link down indication is high-active-signal, |
2168 | * so in this case we need to write the status to clear the XOR | ||
2175 | */ | 2169 | */ |
2176 | /* Read Latched signals */ | 2170 | /* Read Latched signals */ |
2177 | latch_status = REG_RD(bp, | 2171 | latch_status = REG_RD(bp, |
2178 | NIG_REG_LATCH_STATUS_0 + port*8); | 2172 | NIG_REG_LATCH_STATUS_0 + port*8); |
2179 | is_mi_int_status = REG_RD(bp, | 2173 | DP(NETIF_MSG_LINK, "latch_status = 0x%x\n", latch_status); |
2180 | NIG_REG_STATUS_INTERRUPT_PORT0 + port*4); | ||
2181 | DP(NETIF_MSG_LINK, "original_signal = 0x%x, nig_status = 0x%x," | ||
2182 | "latch_status = 0x%x\n", | ||
2183 | is_mi_int, is_mi_int_status, latch_status); | ||
2184 | /* Handle only those with latched-signal=up.*/ | 2174 | /* Handle only those with latched-signal=up.*/ |
2175 | if (exp_mi_int) | ||
2176 | bnx2x_bits_en(bp, | ||
2177 | NIG_REG_STATUS_INTERRUPT_PORT0 | ||
2178 | + port*4, | ||
2179 | NIG_STATUS_EMAC0_MI_INT); | ||
2180 | else | ||
2181 | bnx2x_bits_dis(bp, | ||
2182 | NIG_REG_STATUS_INTERRUPT_PORT0 | ||
2183 | + port*4, | ||
2184 | NIG_STATUS_EMAC0_MI_INT); | ||
2185 | |||
2185 | if (latch_status & 1) { | 2186 | if (latch_status & 1) { |
2186 | /* For all latched-signal=up,Write original_signal to status */ | 2187 | |
2187 | if (is_mi_int) | ||
2188 | bnx2x_bits_en(bp, | ||
2189 | NIG_REG_STATUS_INTERRUPT_PORT0 | ||
2190 | + port*4, | ||
2191 | NIG_STATUS_EMAC0_MI_INT); | ||
2192 | else | ||
2193 | bnx2x_bits_dis(bp, | ||
2194 | NIG_REG_STATUS_INTERRUPT_PORT0 | ||
2195 | + port*4, | ||
2196 | NIG_STATUS_EMAC0_MI_INT); | ||
2197 | /* For all latched-signal=up : Re-Arm Latch signals */ | 2188 | /* For all latched-signal=up : Re-Arm Latch signals */ |
2198 | REG_WR(bp, NIG_REG_LATCH_STATUS_0 + port*8, | 2189 | REG_WR(bp, NIG_REG_LATCH_STATUS_0 + port*8, |
2199 | (latch_status & 0xfffe) | (latch_status & 1)); | 2190 | (latch_status & 0xfffe) | (latch_status & 1)); |
2200 | } | 2191 | } |
2192 | /* For all latched-signal=up,Write original_signal to status */ | ||
2201 | } | 2193 | } |
2202 | 2194 | ||
2203 | static void bnx2x_link_int_ack(struct link_params *params, | 2195 | static void bnx2x_link_int_ack(struct link_params *params, |
2204 | struct link_vars *vars, u8 is_10g, | 2196 | struct link_vars *vars, u8 is_10g) |
2205 | u8 is_mi_int) | ||
2206 | { | 2197 | { |
2207 | struct bnx2x *bp = params->bp; | 2198 | struct bnx2x *bp = params->bp; |
2208 | u8 port = params->port; | 2199 | u8 port = params->port; |
@@ -2213,12 +2204,6 @@ static void bnx2x_link_int_ack(struct link_params *params, | |||
2213 | (NIG_STATUS_XGXS0_LINK10G | | 2204 | (NIG_STATUS_XGXS0_LINK10G | |
2214 | NIG_STATUS_XGXS0_LINK_STATUS | | 2205 | NIG_STATUS_XGXS0_LINK_STATUS | |
2215 | NIG_STATUS_SERDES0_LINK_STATUS)); | 2206 | NIG_STATUS_SERDES0_LINK_STATUS)); |
2216 | if ((params->phy[EXT_PHY1].type | ||
2217 | == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8481) || | ||
2218 | (params->phy[EXT_PHY1].type | ||
2219 | == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84823)) { | ||
2220 | bnx2x_8481_rearm_latch_signal(bp, port, is_mi_int); | ||
2221 | } | ||
2222 | if (vars->phy_link_up) { | 2207 | if (vars->phy_link_up) { |
2223 | if (is_10g) { | 2208 | if (is_10g) { |
2224 | /* Disable the 10G link interrupt | 2209 | /* Disable the 10G link interrupt |
@@ -2264,30 +2249,39 @@ static u8 bnx2x_format_ver(u32 num, u8 *str, u16 *len) | |||
2264 | u32 mask = 0xf0000000; | 2249 | u32 mask = 0xf0000000; |
2265 | u8 shift = 8*4; | 2250 | u8 shift = 8*4; |
2266 | u8 digit; | 2251 | u8 digit; |
2252 | u8 remove_leading_zeros = 1; | ||
2267 | if (*len < 10) { | 2253 | if (*len < 10) { |
2268 | /* Need more than 10chars for this format */ | 2254 | /* Need more than 10chars for this format */ |
2269 | *str_ptr = '\0'; | 2255 | *str_ptr = '\0'; |
2256 | (*len)--; | ||
2270 | return -EINVAL; | 2257 | return -EINVAL; |
2271 | } | 2258 | } |
2272 | while (shift > 0) { | 2259 | while (shift > 0) { |
2273 | 2260 | ||
2274 | shift -= 4; | 2261 | shift -= 4; |
2275 | digit = ((num & mask) >> shift); | 2262 | digit = ((num & mask) >> shift); |
2276 | if (digit < 0xa) | 2263 | if (digit == 0 && remove_leading_zeros) { |
2264 | mask = mask >> 4; | ||
2265 | continue; | ||
2266 | } else if (digit < 0xa) | ||
2277 | *str_ptr = digit + '0'; | 2267 | *str_ptr = digit + '0'; |
2278 | else | 2268 | else |
2279 | *str_ptr = digit - 0xa + 'a'; | 2269 | *str_ptr = digit - 0xa + 'a'; |
2270 | remove_leading_zeros = 0; | ||
2280 | str_ptr++; | 2271 | str_ptr++; |
2272 | (*len)--; | ||
2281 | mask = mask >> 4; | 2273 | mask = mask >> 4; |
2282 | if (shift == 4*4) { | 2274 | if (shift == 4*4) { |
2283 | *str_ptr = ':'; | 2275 | *str_ptr = '.'; |
2284 | str_ptr++; | 2276 | str_ptr++; |
2277 | (*len)--; | ||
2278 | remove_leading_zeros = 1; | ||
2285 | } | 2279 | } |
2286 | } | 2280 | } |
2287 | *str_ptr = '\0'; | ||
2288 | return 0; | 2281 | return 0; |
2289 | } | 2282 | } |
2290 | 2283 | ||
2284 | |||
2291 | static u8 bnx2x_null_format_ver(u32 spirom_ver, u8 *str, u16 *len) | 2285 | static u8 bnx2x_null_format_ver(u32 spirom_ver, u8 *str, u16 *len) |
2292 | { | 2286 | { |
2293 | str[0] = '\0'; | 2287 | str[0] = '\0'; |
@@ -2302,6 +2296,7 @@ u8 bnx2x_get_ext_phy_fw_version(struct link_params *params, u8 driver_loaded, | |||
2302 | u32 spirom_ver = 0; | 2296 | u32 spirom_ver = 0; |
2303 | u8 status = 0; | 2297 | u8 status = 0; |
2304 | u8 *ver_p = version; | 2298 | u8 *ver_p = version; |
2299 | u16 remain_len = len; | ||
2305 | if (version == NULL || params == NULL) | 2300 | if (version == NULL || params == NULL) |
2306 | return -EINVAL; | 2301 | return -EINVAL; |
2307 | bp = params->bp; | 2302 | bp = params->bp; |
@@ -2310,10 +2305,28 @@ u8 bnx2x_get_ext_phy_fw_version(struct link_params *params, u8 driver_loaded, | |||
2310 | version[0] = '\0'; | 2305 | version[0] = '\0'; |
2311 | spirom_ver = REG_RD(bp, params->phy[EXT_PHY1].ver_addr); | 2306 | spirom_ver = REG_RD(bp, params->phy[EXT_PHY1].ver_addr); |
2312 | 2307 | ||
2313 | if (params->phy[EXT_PHY1].format_fw_ver) | 2308 | if (params->phy[EXT_PHY1].format_fw_ver) { |
2314 | status |= params->phy[EXT_PHY1].format_fw_ver(spirom_ver, | 2309 | status |= params->phy[EXT_PHY1].format_fw_ver(spirom_ver, |
2315 | ver_p, | 2310 | ver_p, |
2316 | &len); | 2311 | &remain_len); |
2312 | ver_p += (len - remain_len); | ||
2313 | } | ||
2314 | if ((params->num_phys == MAX_PHYS) && | ||
2315 | (params->phy[EXT_PHY2].ver_addr != 0)) { | ||
2316 | spirom_ver = REG_RD(bp, | ||
2317 | params->phy[EXT_PHY2].ver_addr); | ||
2318 | if (params->phy[EXT_PHY2].format_fw_ver) { | ||
2319 | *ver_p = '/'; | ||
2320 | ver_p++; | ||
2321 | remain_len--; | ||
2322 | status |= params->phy[EXT_PHY2].format_fw_ver( | ||
2323 | spirom_ver, | ||
2324 | ver_p, | ||
2325 | &remain_len); | ||
2326 | ver_p = version + (len - remain_len); | ||
2327 | } | ||
2328 | } | ||
2329 | *ver_p = '\0'; | ||
2317 | return status; | 2330 | return status; |
2318 | } | 2331 | } |
2319 | 2332 | ||
@@ -2550,30 +2563,56 @@ u8 bnx2x_set_led(struct link_params *params, u8 mode, u32 speed) | |||
2550 | 2563 | ||
2551 | } | 2564 | } |
2552 | 2565 | ||
2553 | u8 bnx2x_test_link(struct link_params *params, struct link_vars *vars) | 2566 | /** |
2567 | * This function comes to reflect the actual link state read DIRECTLY from the | ||
2568 | * HW | ||
2569 | */ | ||
2570 | u8 bnx2x_test_link(struct link_params *params, struct link_vars *vars, | ||
2571 | u8 is_serdes) | ||
2554 | { | 2572 | { |
2555 | struct bnx2x *bp = params->bp; | 2573 | struct bnx2x *bp = params->bp; |
2556 | u16 gp_status = 0, phy_index = 0; | 2574 | u16 gp_status = 0, phy_index = 0; |
2575 | u8 ext_phy_link_up = 0, serdes_phy_type; | ||
2576 | struct link_vars temp_vars; | ||
2557 | 2577 | ||
2558 | CL45_RD_OVER_CL22(bp, ¶ms->phy[INT_PHY], | 2578 | CL45_RD_OVER_CL22(bp, ¶ms->phy[INT_PHY], |
2559 | MDIO_REG_BANK_GP_STATUS, | 2579 | MDIO_REG_BANK_GP_STATUS, |
2560 | MDIO_GP_STATUS_TOP_AN_STATUS1, | 2580 | MDIO_GP_STATUS_TOP_AN_STATUS1, |
2561 | &gp_status); | 2581 | &gp_status); |
2562 | /* link is up only if both local phy and external phy are up */ | 2582 | /* link is up only if both local phy and external phy are up */ |
2563 | if (gp_status & MDIO_GP_STATUS_TOP_AN_STATUS1_LINK_STATUS) { | 2583 | if (!(gp_status & MDIO_GP_STATUS_TOP_AN_STATUS1_LINK_STATUS)) |
2564 | u8 ext_phy_link_up = 1; | 2584 | return -ESRCH; |
2565 | struct link_vars temp_vars; | 2585 | |
2586 | switch (params->num_phys) { | ||
2587 | case 1: | ||
2588 | /* No external PHY */ | ||
2589 | return 0; | ||
2590 | case 2: | ||
2591 | ext_phy_link_up = params->phy[EXT_PHY1].read_status( | ||
2592 | ¶ms->phy[EXT_PHY1], | ||
2593 | params, &temp_vars); | ||
2594 | break; | ||
2595 | case 3: /* Dual Media */ | ||
2566 | for (phy_index = EXT_PHY1; phy_index < params->num_phys; | 2596 | for (phy_index = EXT_PHY1; phy_index < params->num_phys; |
2567 | phy_index++) { | 2597 | phy_index++) { |
2568 | if (params->phy[phy_index].read_status) | 2598 | serdes_phy_type = ((params->phy[phy_index].media_type == |
2569 | ext_phy_link_up &= | 2599 | ETH_PHY_SFP_FIBER) || |
2600 | (params->phy[phy_index].media_type == | ||
2601 | ETH_PHY_XFP_FIBER)); | ||
2602 | |||
2603 | if (is_serdes != serdes_phy_type) | ||
2604 | continue; | ||
2605 | if (params->phy[phy_index].read_status) { | ||
2606 | ext_phy_link_up |= | ||
2570 | params->phy[phy_index].read_status( | 2607 | params->phy[phy_index].read_status( |
2571 | ¶ms->phy[phy_index], | 2608 | ¶ms->phy[phy_index], |
2572 | params, &temp_vars); | 2609 | params, &temp_vars); |
2610 | } | ||
2573 | } | 2611 | } |
2574 | if (ext_phy_link_up) | 2612 | break; |
2575 | return 0; | ||
2576 | } | 2613 | } |
2614 | if (ext_phy_link_up) | ||
2615 | return 0; | ||
2577 | return -ESRCH; | 2616 | return -ESRCH; |
2578 | } | 2617 | } |
2579 | 2618 | ||
@@ -2619,6 +2658,19 @@ static u8 bnx2x_link_initialize(struct link_params *params, | |||
2619 | if (!non_ext_phy) | 2658 | if (!non_ext_phy) |
2620 | for (phy_index = EXT_PHY1; phy_index < params->num_phys; | 2659 | for (phy_index = EXT_PHY1; phy_index < params->num_phys; |
2621 | phy_index++) { | 2660 | phy_index++) { |
2661 | /** | ||
2662 | * No need to initialize second phy in case of first | ||
2663 | * phy only selection. In case of second phy, we do | ||
2664 | * need to initialize the first phy, since they are | ||
2665 | * connected. | ||
2666 | **/ | ||
2667 | if (phy_index == EXT_PHY2 && | ||
2668 | (bnx2x_phy_selection(params) == | ||
2669 | PORT_HW_CFG_PHY_SELECTION_FIRST_PHY)) { | ||
2670 | DP(NETIF_MSG_LINK, "Not initializing" | ||
2671 | "second phy\n"); | ||
2672 | continue; | ||
2673 | } | ||
2622 | params->phy[phy_index].config_init( | 2674 | params->phy[phy_index].config_init( |
2623 | ¶ms->phy[phy_index], | 2675 | ¶ms->phy[phy_index], |
2624 | params, vars); | 2676 | params, vars); |
@@ -2816,6 +2868,40 @@ u8 bnx2x_link_update(struct link_params *params, struct link_vars *vars) | |||
2816 | if (!ext_phy_link_up) { | 2868 | if (!ext_phy_link_up) { |
2817 | ext_phy_link_up = 1; | 2869 | ext_phy_link_up = 1; |
2818 | active_external_phy = phy_index; | 2870 | active_external_phy = phy_index; |
2871 | } else { | ||
2872 | switch (bnx2x_phy_selection(params)) { | ||
2873 | case PORT_HW_CFG_PHY_SELECTION_HARDWARE_DEFAULT: | ||
2874 | case PORT_HW_CFG_PHY_SELECTION_FIRST_PHY_PRIORITY: | ||
2875 | /** | ||
2876 | * In this option, the first PHY makes sure to pass the | ||
2877 | * traffic through itself only. | ||
2878 | * Its not clear how to reset the link on the second phy | ||
2879 | **/ | ||
2880 | active_external_phy = EXT_PHY1; | ||
2881 | break; | ||
2882 | case PORT_HW_CFG_PHY_SELECTION_SECOND_PHY_PRIORITY: | ||
2883 | /** | ||
2884 | * In this option, the first PHY makes sure to pass the | ||
2885 | * traffic through the second PHY. | ||
2886 | **/ | ||
2887 | active_external_phy = EXT_PHY2; | ||
2888 | break; | ||
2889 | default: | ||
2890 | /** | ||
2891 | * Link indication on both PHYs with the following cases | ||
2892 | * is invalid: | ||
2893 | * - FIRST_PHY means that second phy wasn't initialized, | ||
2894 | * hence its link is expected to be down | ||
2895 | * - SECOND_PHY means that first phy should not be able | ||
2896 | * to link up by itself (using configuration) | ||
2897 | * - DEFAULT should be overriden during initialiazation | ||
2898 | **/ | ||
2899 | DP(NETIF_MSG_LINK, "Invalid link indication" | ||
2900 | "mpc=0x%x. DISABLING LINK !!!\n", | ||
2901 | params->multi_phy_config); | ||
2902 | ext_phy_link_up = 0; | ||
2903 | break; | ||
2904 | } | ||
2819 | } | 2905 | } |
2820 | } | 2906 | } |
2821 | prev_line_speed = vars->line_speed; | 2907 | prev_line_speed = vars->line_speed; |
@@ -2845,6 +2931,21 @@ u8 bnx2x_link_update(struct link_params *params, struct link_vars *vars) | |||
2845 | * the external phy. | 2931 | * the external phy. |
2846 | */ | 2932 | */ |
2847 | vars->link_status |= phy_vars[active_external_phy].link_status; | 2933 | vars->link_status |= phy_vars[active_external_phy].link_status; |
2934 | |||
2935 | /** | ||
2936 | * if active_external_phy is first PHY and link is up - disable | ||
2937 | * disable TX on second external PHY | ||
2938 | */ | ||
2939 | if (active_external_phy == EXT_PHY1) { | ||
2940 | if (params->phy[EXT_PHY2].phy_specific_func) { | ||
2941 | DP(NETIF_MSG_LINK, "Disabling TX on" | ||
2942 | " EXT_PHY2\n"); | ||
2943 | params->phy[EXT_PHY2].phy_specific_func( | ||
2944 | ¶ms->phy[EXT_PHY2], | ||
2945 | params, DISABLE_TX); | ||
2946 | } | ||
2947 | } | ||
2948 | |||
2848 | ext_phy_line_speed = phy_vars[active_external_phy].line_speed; | 2949 | ext_phy_line_speed = phy_vars[active_external_phy].line_speed; |
2849 | vars->duplex = phy_vars[active_external_phy].duplex; | 2950 | vars->duplex = phy_vars[active_external_phy].duplex; |
2850 | if (params->phy[active_external_phy].supported & | 2951 | if (params->phy[active_external_phy].supported & |
@@ -2853,6 +2954,17 @@ u8 bnx2x_link_update(struct link_params *params, struct link_vars *vars) | |||
2853 | DP(NETIF_MSG_LINK, "Active external phy selected: %x\n", | 2954 | DP(NETIF_MSG_LINK, "Active external phy selected: %x\n", |
2854 | active_external_phy); | 2955 | active_external_phy); |
2855 | } | 2956 | } |
2957 | |||
2958 | for (phy_index = EXT_PHY1; phy_index < params->num_phys; | ||
2959 | phy_index++) { | ||
2960 | if (params->phy[phy_index].flags & | ||
2961 | FLAGS_REARM_LATCH_SIGNAL) { | ||
2962 | bnx2x_rearm_latch_signal(bp, port, | ||
2963 | phy_index == | ||
2964 | active_external_phy); | ||
2965 | break; | ||
2966 | } | ||
2967 | } | ||
2856 | DP(NETIF_MSG_LINK, "vars->flow_ctrl = 0x%x, vars->link_status = 0x%x," | 2968 | DP(NETIF_MSG_LINK, "vars->flow_ctrl = 0x%x, vars->link_status = 0x%x," |
2857 | " ext_phy_line_speed = %d\n", vars->flow_ctrl, | 2969 | " ext_phy_line_speed = %d\n", vars->flow_ctrl, |
2858 | vars->link_status, ext_phy_line_speed); | 2970 | vars->link_status, ext_phy_line_speed); |
@@ -2885,7 +2997,7 @@ u8 bnx2x_link_update(struct link_params *params, struct link_vars *vars) | |||
2885 | (vars->line_speed == SPEED_15000) || | 2997 | (vars->line_speed == SPEED_15000) || |
2886 | (vars->line_speed == SPEED_16000)); | 2998 | (vars->line_speed == SPEED_16000)); |
2887 | 2999 | ||
2888 | bnx2x_link_int_ack(params, vars, link_10g, is_mi_int); | 3000 | bnx2x_link_int_ack(params, vars, link_10g); |
2889 | 3001 | ||
2890 | /** | 3002 | /** |
2891 | * In case external phy link is up, and internal link is down | 3003 | * In case external phy link is up, and internal link is down |
@@ -3898,11 +4010,11 @@ static u8 bnx2x_verify_sfp_module(struct bnx2x_phy *phy, | |||
3898 | struct link_params *params) | 4010 | struct link_params *params) |
3899 | { | 4011 | { |
3900 | struct bnx2x *bp = params->bp; | 4012 | struct bnx2x *bp = params->bp; |
3901 | u32 val; | 4013 | u32 val, cmd; |
3902 | u32 fw_resp; | 4014 | u32 fw_resp, fw_cmd_param; |
3903 | char vendor_name[SFP_EEPROM_VENDOR_NAME_SIZE+1]; | 4015 | char vendor_name[SFP_EEPROM_VENDOR_NAME_SIZE+1]; |
3904 | char vendor_pn[SFP_EEPROM_PART_NO_SIZE+1]; | 4016 | char vendor_pn[SFP_EEPROM_PART_NO_SIZE+1]; |
3905 | 4017 | phy->flags &= ~FLAGS_SFP_NOT_APPROVED; | |
3906 | val = REG_RD(bp, params->shmem_base + | 4018 | val = REG_RD(bp, params->shmem_base + |
3907 | offsetof(struct shmem_region, dev_info. | 4019 | offsetof(struct shmem_region, dev_info. |
3908 | port_feature_config[params->port].config)); | 4020 | port_feature_config[params->port].config)); |
@@ -3912,15 +4024,27 @@ static u8 bnx2x_verify_sfp_module(struct bnx2x_phy *phy, | |||
3912 | return 0; | 4024 | return 0; |
3913 | } | 4025 | } |
3914 | 4026 | ||
3915 | /* Ask the FW to validate the module */ | 4027 | if (params->feature_config_flags & |
3916 | if (!(params->feature_config_flags & | 4028 | FEATURE_CONFIG_BC_SUPPORTS_DUAL_PHY_OPT_MDL_VRFY) { |
3917 | FEATURE_CONFIG_BC_SUPPORTS_OPT_MDL_VRFY)) { | 4029 | /* Use specific phy request */ |
4030 | cmd = DRV_MSG_CODE_VRFY_SPECIFIC_PHY_OPT_MDL; | ||
4031 | } else if (params->feature_config_flags & | ||
4032 | FEATURE_CONFIG_BC_SUPPORTS_OPT_MDL_VRFY) { | ||
4033 | /* Use first phy request only in case of non-dual media*/ | ||
4034 | if (DUAL_MEDIA(params)) { | ||
4035 | DP(NETIF_MSG_LINK, "FW does not support OPT MDL " | ||
4036 | "verification\n"); | ||
4037 | return -EINVAL; | ||
4038 | } | ||
4039 | cmd = DRV_MSG_CODE_VRFY_FIRST_PHY_OPT_MDL; | ||
4040 | } else { | ||
4041 | /* No support in OPT MDL detection */ | ||
3918 | DP(NETIF_MSG_LINK, "FW does not support OPT MDL " | 4042 | DP(NETIF_MSG_LINK, "FW does not support OPT MDL " |
3919 | "verification\n"); | 4043 | "verification\n"); |
3920 | return -EINVAL; | 4044 | return -EINVAL; |
3921 | } | 4045 | } |
3922 | 4046 | fw_cmd_param = FW_PARAM_SET(phy->addr, phy->type, phy->mdio_ctrl); | |
3923 | fw_resp = bnx2x_fw_command(bp, DRV_MSG_CODE_VRFY_OPT_MDL); | 4047 | fw_resp = bnx2x_fw_command(bp, cmd, fw_cmd_param); |
3924 | if (fw_resp == FW_MSG_CODE_VRFY_OPT_MDL_SUCCESS) { | 4048 | if (fw_resp == FW_MSG_CODE_VRFY_OPT_MDL_SUCCESS) { |
3925 | DP(NETIF_MSG_LINK, "Approved module\n"); | 4049 | DP(NETIF_MSG_LINK, "Approved module\n"); |
3926 | return 0; | 4050 | return 0; |
@@ -3947,6 +4071,7 @@ static u8 bnx2x_verify_sfp_module(struct bnx2x_phy *phy, | |||
3947 | netdev_info(bp->dev, "Warning: Unqualified SFP+ module detected," | 4071 | netdev_info(bp->dev, "Warning: Unqualified SFP+ module detected," |
3948 | " Port %d from %s part number %s\n", | 4072 | " Port %d from %s part number %s\n", |
3949 | params->port, vendor_name, vendor_pn); | 4073 | params->port, vendor_name, vendor_pn); |
4074 | phy->flags |= FLAGS_SFP_NOT_APPROVED; | ||
3950 | return -EINVAL; | 4075 | return -EINVAL; |
3951 | } | 4076 | } |
3952 | 4077 | ||
@@ -4092,6 +4217,27 @@ static u8 bnx2x_8727_set_limiting_mode(struct bnx2x *bp, | |||
4092 | return 0; | 4217 | return 0; |
4093 | } | 4218 | } |
4094 | 4219 | ||
4220 | static void bnx2x_8727_specific_func(struct bnx2x_phy *phy, | ||
4221 | struct link_params *params, | ||
4222 | u32 action) | ||
4223 | { | ||
4224 | struct bnx2x *bp = params->bp; | ||
4225 | |||
4226 | switch (action) { | ||
4227 | case DISABLE_TX: | ||
4228 | bnx2x_sfp_set_transmitter(bp, phy, params->port, 0); | ||
4229 | break; | ||
4230 | case ENABLE_TX: | ||
4231 | if (!(phy->flags & FLAGS_SFP_NOT_APPROVED)) | ||
4232 | bnx2x_sfp_set_transmitter(bp, phy, params->port, 1); | ||
4233 | break; | ||
4234 | default: | ||
4235 | DP(NETIF_MSG_LINK, "Function 0x%x not supported by 8727\n", | ||
4236 | action); | ||
4237 | return; | ||
4238 | } | ||
4239 | } | ||
4240 | |||
4095 | static u8 bnx2x_sfp_module_detection(struct bnx2x_phy *phy, | 4241 | static u8 bnx2x_sfp_module_detection(struct bnx2x_phy *phy, |
4096 | struct link_params *params) | 4242 | struct link_params *params) |
4097 | { | 4243 | { |
@@ -4625,6 +4771,19 @@ static u8 bnx2x_8727_config_init(struct bnx2x_phy *phy, | |||
4625 | bnx2x_cl45_read(bp, phy, | 4771 | bnx2x_cl45_read(bp, phy, |
4626 | MDIO_PMA_DEVAD, MDIO_PMA_REG_10G_CTRL2, &tmp1); | 4772 | MDIO_PMA_DEVAD, MDIO_PMA_REG_10G_CTRL2, &tmp1); |
4627 | DP(NETIF_MSG_LINK, "1.7 = 0x%x\n", tmp1); | 4773 | DP(NETIF_MSG_LINK, "1.7 = 0x%x\n", tmp1); |
4774 | /** | ||
4775 | * Power down the XAUI until link is up in case of dual-media | ||
4776 | * and 1G | ||
4777 | */ | ||
4778 | if (DUAL_MEDIA(params)) { | ||
4779 | bnx2x_cl45_read(bp, phy, | ||
4780 | MDIO_PMA_DEVAD, | ||
4781 | MDIO_PMA_REG_8727_PCS_GP, &val); | ||
4782 | val |= (3<<10); | ||
4783 | bnx2x_cl45_write(bp, phy, | ||
4784 | MDIO_PMA_DEVAD, | ||
4785 | MDIO_PMA_REG_8727_PCS_GP, val); | ||
4786 | } | ||
4628 | } else if ((phy->req_line_speed == SPEED_AUTO_NEG) && | 4787 | } else if ((phy->req_line_speed == SPEED_AUTO_NEG) && |
4629 | ((phy->speed_cap_mask & | 4788 | ((phy->speed_cap_mask & |
4630 | PORT_HW_CFG_SPEED_CAPABILITY_D0_1G)) && | 4789 | PORT_HW_CFG_SPEED_CAPABILITY_D0_1G)) && |
@@ -4766,7 +4925,15 @@ static u8 bnx2x_8727_read_status(struct bnx2x_phy *phy, | |||
4766 | struct bnx2x *bp = params->bp; | 4925 | struct bnx2x *bp = params->bp; |
4767 | u8 link_up = 0; | 4926 | u8 link_up = 0; |
4768 | u16 link_status = 0; | 4927 | u16 link_status = 0; |
4769 | u16 rx_alarm_status, val1; | 4928 | u16 rx_alarm_status, lasi_ctrl, val1; |
4929 | |||
4930 | /* If PHY is not initialized, do not check link status */ | ||
4931 | bnx2x_cl45_read(bp, phy, | ||
4932 | MDIO_PMA_DEVAD, MDIO_PMA_REG_LASI_CTRL, | ||
4933 | &lasi_ctrl); | ||
4934 | if (!lasi_ctrl) | ||
4935 | return 0; | ||
4936 | |||
4770 | /* Check the LASI */ | 4937 | /* Check the LASI */ |
4771 | bnx2x_cl45_read(bp, phy, | 4938 | bnx2x_cl45_read(bp, phy, |
4772 | MDIO_PMA_DEVAD, MDIO_PMA_REG_RX_ALARM, | 4939 | MDIO_PMA_DEVAD, MDIO_PMA_REG_RX_ALARM, |
@@ -4837,7 +5004,8 @@ static u8 bnx2x_8727_read_status(struct bnx2x_phy *phy, | |||
4837 | MDIO_PMA_DEVAD, MDIO_PMA_REG_RX_ALARM_CTRL, | 5004 | MDIO_PMA_DEVAD, MDIO_PMA_REG_RX_ALARM_CTRL, |
4838 | ((1<<5) | (1<<2))); | 5005 | ((1<<5) | (1<<2))); |
4839 | } | 5006 | } |
4840 | 5007 | DP(NETIF_MSG_LINK, "Enabling 8727 TX laser if SFP is approved\n"); | |
5008 | bnx2x_8727_specific_func(phy, params, ENABLE_TX); | ||
4841 | /* If transmitter is disabled, ignore false link up indication */ | 5009 | /* If transmitter is disabled, ignore false link up indication */ |
4842 | bnx2x_cl45_read(bp, phy, | 5010 | bnx2x_cl45_read(bp, phy, |
4843 | MDIO_PMA_DEVAD, MDIO_PMA_REG_PHY_IDENTIFIER, &val1); | 5011 | MDIO_PMA_DEVAD, MDIO_PMA_REG_PHY_IDENTIFIER, &val1); |
@@ -4867,6 +5035,24 @@ static u8 bnx2x_8727_read_status(struct bnx2x_phy *phy, | |||
4867 | } | 5035 | } |
4868 | if (link_up) | 5036 | if (link_up) |
4869 | bnx2x_ext_phy_resolve_fc(phy, params, vars); | 5037 | bnx2x_ext_phy_resolve_fc(phy, params, vars); |
5038 | |||
5039 | if ((DUAL_MEDIA(params)) && | ||
5040 | (phy->req_line_speed == SPEED_1000)) { | ||
5041 | bnx2x_cl45_read(bp, phy, | ||
5042 | MDIO_PMA_DEVAD, | ||
5043 | MDIO_PMA_REG_8727_PCS_GP, &val1); | ||
5044 | /** | ||
5045 | * In case of dual-media board and 1G, power up the XAUI side, | ||
5046 | * otherwise power it down. For 10G it is done automatically | ||
5047 | */ | ||
5048 | if (link_up) | ||
5049 | val1 &= ~(3<<10); | ||
5050 | else | ||
5051 | val1 |= (3<<10); | ||
5052 | bnx2x_cl45_write(bp, phy, | ||
5053 | MDIO_PMA_DEVAD, | ||
5054 | MDIO_PMA_REG_8727_PCS_GP, val1); | ||
5055 | } | ||
4870 | return link_up; | 5056 | return link_up; |
4871 | } | 5057 | } |
4872 | 5058 | ||
@@ -4876,6 +5062,9 @@ static void bnx2x_8727_link_reset(struct bnx2x_phy *phy, | |||
4876 | struct bnx2x *bp = params->bp; | 5062 | struct bnx2x *bp = params->bp; |
4877 | /* Disable Transmitter */ | 5063 | /* Disable Transmitter */ |
4878 | bnx2x_sfp_set_transmitter(bp, phy, params->port, 0); | 5064 | bnx2x_sfp_set_transmitter(bp, phy, params->port, 0); |
5065 | /* Clear LASI */ | ||
5066 | bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_LASI_CTRL, 0); | ||
5067 | |||
4879 | } | 5068 | } |
4880 | 5069 | ||
4881 | /******************************************************************/ | 5070 | /******************************************************************/ |
@@ -4973,16 +5162,11 @@ static void bnx2x_848xx_set_led(struct bnx2x *bp, | |||
4973 | } | 5162 | } |
4974 | 5163 | ||
4975 | static u8 bnx2x_848xx_cmn_config_init(struct bnx2x_phy *phy, | 5164 | static u8 bnx2x_848xx_cmn_config_init(struct bnx2x_phy *phy, |
4976 | struct link_params *params, | 5165 | struct link_params *params, |
4977 | struct link_vars *vars) | 5166 | struct link_vars *vars) |
4978 | { | 5167 | { |
4979 | struct bnx2x *bp = params->bp; | 5168 | struct bnx2x *bp = params->bp; |
4980 | u16 autoneg_val, an_1000_val, an_10_100_val; | 5169 | u16 autoneg_val, an_1000_val, an_10_100_val; |
4981 | /** | ||
4982 | * This phy uses the NIG latch mechanism since link indication | ||
4983 | * arrives through its LED4 and not via its LASI signal, so we | ||
4984 | * get steady signal instead of clear on read | ||
4985 | */ | ||
4986 | bnx2x_wait_reset_complete(bp, phy); | 5170 | bnx2x_wait_reset_complete(bp, phy); |
4987 | bnx2x_bits_en(bp, NIG_REG_LATCH_BC_0 + params->port*4, | 5171 | bnx2x_bits_en(bp, NIG_REG_LATCH_BC_0 + params->port*4, |
4988 | 1 << NIG_LATCH_BC_ENABLE_MI_INT); | 5172 | 1 << NIG_LATCH_BC_ENABLE_MI_INT); |
@@ -5122,7 +5306,11 @@ static u8 bnx2x_848x3_config_init(struct bnx2x_phy *phy, | |||
5122 | struct link_vars *vars) | 5306 | struct link_vars *vars) |
5123 | { | 5307 | { |
5124 | struct bnx2x *bp = params->bp; | 5308 | struct bnx2x *bp = params->bp; |
5309 | u8 initialize = 1; | ||
5310 | u16 val; | ||
5125 | u16 temp; | 5311 | u16 temp; |
5312 | u32 actual_phy_selection; | ||
5313 | u8 rc = 0; | ||
5126 | msleep(1); | 5314 | msleep(1); |
5127 | bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_3, | 5315 | bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_3, |
5128 | MISC_REGISTERS_GPIO_OUTPUT_HIGH, | 5316 | MISC_REGISTERS_GPIO_OUTPUT_HIGH, |
@@ -5135,10 +5323,55 @@ static u8 bnx2x_848x3_config_init(struct bnx2x_phy *phy, | |||
5135 | */ | 5323 | */ |
5136 | temp = vars->line_speed; | 5324 | temp = vars->line_speed; |
5137 | vars->line_speed = SPEED_10000; | 5325 | vars->line_speed = SPEED_10000; |
5138 | bnx2x_set_autoneg(phy, params, vars, 0); | 5326 | bnx2x_set_autoneg(¶ms->phy[INT_PHY], params, vars, 0); |
5139 | bnx2x_program_serdes(phy, params, vars); | 5327 | bnx2x_program_serdes(¶ms->phy[INT_PHY], params, vars); |
5140 | vars->line_speed = temp; | 5328 | vars->line_speed = temp; |
5141 | return bnx2x_848xx_cmn_config_init(phy, params, vars); | 5329 | |
5330 | /* Set dual-media configuration according to configuration */ | ||
5331 | |||
5332 | bnx2x_cl45_read(bp, phy, MDIO_CTL_DEVAD, | ||
5333 | MDIO_CTL_REG_84823_MEDIA, &val); | ||
5334 | val &= ~(MDIO_CTL_REG_84823_MEDIA_MAC_MASK | | ||
5335 | MDIO_CTL_REG_84823_MEDIA_LINE_MASK | | ||
5336 | MDIO_CTL_REG_84823_MEDIA_COPPER_CORE_DOWN | | ||
5337 | MDIO_CTL_REG_84823_MEDIA_PRIORITY_MASK | | ||
5338 | MDIO_CTL_REG_84823_MEDIA_FIBER_1G); | ||
5339 | val |= MDIO_CTL_REG_84823_CTRL_MAC_XFI | | ||
5340 | MDIO_CTL_REG_84823_MEDIA_LINE_XAUI_L; | ||
5341 | |||
5342 | actual_phy_selection = bnx2x_phy_selection(params); | ||
5343 | |||
5344 | switch (actual_phy_selection) { | ||
5345 | case PORT_HW_CFG_PHY_SELECTION_HARDWARE_DEFAULT: | ||
5346 | /* Do nothing. Essentialy this is like the priority copper */ | ||
5347 | break; | ||
5348 | case PORT_HW_CFG_PHY_SELECTION_FIRST_PHY_PRIORITY: | ||
5349 | val |= MDIO_CTL_REG_84823_MEDIA_PRIORITY_COPPER; | ||
5350 | break; | ||
5351 | case PORT_HW_CFG_PHY_SELECTION_SECOND_PHY_PRIORITY: | ||
5352 | val |= MDIO_CTL_REG_84823_MEDIA_PRIORITY_FIBER; | ||
5353 | break; | ||
5354 | case PORT_HW_CFG_PHY_SELECTION_FIRST_PHY: | ||
5355 | /* Do nothing here. The first PHY won't be initialized at all */ | ||
5356 | break; | ||
5357 | case PORT_HW_CFG_PHY_SELECTION_SECOND_PHY: | ||
5358 | val |= MDIO_CTL_REG_84823_MEDIA_COPPER_CORE_DOWN; | ||
5359 | initialize = 0; | ||
5360 | break; | ||
5361 | } | ||
5362 | if (params->phy[EXT_PHY2].req_line_speed == SPEED_1000) | ||
5363 | val |= MDIO_CTL_REG_84823_MEDIA_FIBER_1G; | ||
5364 | |||
5365 | bnx2x_cl45_write(bp, phy, MDIO_CTL_DEVAD, | ||
5366 | MDIO_CTL_REG_84823_MEDIA, val); | ||
5367 | DP(NETIF_MSG_LINK, "Multi_phy config = 0x%x, Media control = 0x%x\n", | ||
5368 | params->multi_phy_config, val); | ||
5369 | |||
5370 | if (initialize) | ||
5371 | rc = bnx2x_848xx_cmn_config_init(phy, params, vars); | ||
5372 | else | ||
5373 | bnx2x_save_848xx_spirom_version(phy, params); | ||
5374 | return rc; | ||
5142 | } | 5375 | } |
5143 | 5376 | ||
5144 | static u8 bnx2x_848xx_read_status(struct bnx2x_phy *phy, | 5377 | static u8 bnx2x_848xx_read_status(struct bnx2x_phy *phy, |
@@ -5426,7 +5659,8 @@ static struct bnx2x_phy phy_null = { | |||
5426 | .config_loopback = (config_loopback_t)NULL, | 5659 | .config_loopback = (config_loopback_t)NULL, |
5427 | .format_fw_ver = (format_fw_ver_t)NULL, | 5660 | .format_fw_ver = (format_fw_ver_t)NULL, |
5428 | .hw_reset = (hw_reset_t)NULL, | 5661 | .hw_reset = (hw_reset_t)NULL, |
5429 | .set_link_led = (set_link_led_t)NULL | 5662 | .set_link_led = (set_link_led_t)NULL, |
5663 | .phy_specific_func = (phy_specific_func_t)NULL | ||
5430 | }; | 5664 | }; |
5431 | 5665 | ||
5432 | static struct bnx2x_phy phy_serdes = { | 5666 | static struct bnx2x_phy phy_serdes = { |
@@ -5461,7 +5695,8 @@ static struct bnx2x_phy phy_serdes = { | |||
5461 | .config_loopback = (config_loopback_t)NULL, | 5695 | .config_loopback = (config_loopback_t)NULL, |
5462 | .format_fw_ver = (format_fw_ver_t)NULL, | 5696 | .format_fw_ver = (format_fw_ver_t)NULL, |
5463 | .hw_reset = (hw_reset_t)NULL, | 5697 | .hw_reset = (hw_reset_t)NULL, |
5464 | .set_link_led = (set_link_led_t)NULL | 5698 | .set_link_led = (set_link_led_t)NULL, |
5699 | .phy_specific_func = (phy_specific_func_t)NULL | ||
5465 | }; | 5700 | }; |
5466 | 5701 | ||
5467 | static struct bnx2x_phy phy_xgxs = { | 5702 | static struct bnx2x_phy phy_xgxs = { |
@@ -5497,7 +5732,8 @@ static struct bnx2x_phy phy_xgxs = { | |||
5497 | .config_loopback = (config_loopback_t)bnx2x_set_xgxs_loopback, | 5732 | .config_loopback = (config_loopback_t)bnx2x_set_xgxs_loopback, |
5498 | .format_fw_ver = (format_fw_ver_t)NULL, | 5733 | .format_fw_ver = (format_fw_ver_t)NULL, |
5499 | .hw_reset = (hw_reset_t)NULL, | 5734 | .hw_reset = (hw_reset_t)NULL, |
5500 | .set_link_led = (set_link_led_t)NULL | 5735 | .set_link_led = (set_link_led_t)NULL, |
5736 | .phy_specific_func = (phy_specific_func_t)NULL | ||
5501 | }; | 5737 | }; |
5502 | 5738 | ||
5503 | static struct bnx2x_phy phy_7101 = { | 5739 | static struct bnx2x_phy phy_7101 = { |
@@ -5527,7 +5763,8 @@ static struct bnx2x_phy phy_7101 = { | |||
5527 | .config_loopback = (config_loopback_t)bnx2x_7101_config_loopback, | 5763 | .config_loopback = (config_loopback_t)bnx2x_7101_config_loopback, |
5528 | .format_fw_ver = (format_fw_ver_t)bnx2x_7101_format_ver, | 5764 | .format_fw_ver = (format_fw_ver_t)bnx2x_7101_format_ver, |
5529 | .hw_reset = (hw_reset_t)bnx2x_7101_hw_reset, | 5765 | .hw_reset = (hw_reset_t)bnx2x_7101_hw_reset, |
5530 | .set_link_led = (set_link_led_t)NULL | 5766 | .set_link_led = (set_link_led_t)NULL, |
5767 | .phy_specific_func = (phy_specific_func_t)NULL | ||
5531 | }; | 5768 | }; |
5532 | static struct bnx2x_phy phy_8073 = { | 5769 | static struct bnx2x_phy phy_8073 = { |
5533 | .type = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073, | 5770 | .type = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073, |
@@ -5558,7 +5795,8 @@ static struct bnx2x_phy phy_8073 = { | |||
5558 | .config_loopback = (config_loopback_t)NULL, | 5795 | .config_loopback = (config_loopback_t)NULL, |
5559 | .format_fw_ver = (format_fw_ver_t)bnx2x_format_ver, | 5796 | .format_fw_ver = (format_fw_ver_t)bnx2x_format_ver, |
5560 | .hw_reset = (hw_reset_t)NULL, | 5797 | .hw_reset = (hw_reset_t)NULL, |
5561 | .set_link_led = (set_link_led_t)NULL | 5798 | .set_link_led = (set_link_led_t)NULL, |
5799 | .phy_specific_func = (phy_specific_func_t)NULL | ||
5562 | }; | 5800 | }; |
5563 | static struct bnx2x_phy phy_8705 = { | 5801 | static struct bnx2x_phy phy_8705 = { |
5564 | .type = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705, | 5802 | .type = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705, |
@@ -5586,7 +5824,8 @@ static struct bnx2x_phy phy_8705 = { | |||
5586 | .config_loopback = (config_loopback_t)NULL, | 5824 | .config_loopback = (config_loopback_t)NULL, |
5587 | .format_fw_ver = (format_fw_ver_t)bnx2x_null_format_ver, | 5825 | .format_fw_ver = (format_fw_ver_t)bnx2x_null_format_ver, |
5588 | .hw_reset = (hw_reset_t)NULL, | 5826 | .hw_reset = (hw_reset_t)NULL, |
5589 | .set_link_led = (set_link_led_t)NULL | 5827 | .set_link_led = (set_link_led_t)NULL, |
5828 | .phy_specific_func = (phy_specific_func_t)NULL | ||
5590 | }; | 5829 | }; |
5591 | static struct bnx2x_phy phy_8706 = { | 5830 | static struct bnx2x_phy phy_8706 = { |
5592 | .type = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8706, | 5831 | .type = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8706, |
@@ -5615,7 +5854,8 @@ static struct bnx2x_phy phy_8706 = { | |||
5615 | .config_loopback = (config_loopback_t)NULL, | 5854 | .config_loopback = (config_loopback_t)NULL, |
5616 | .format_fw_ver = (format_fw_ver_t)bnx2x_format_ver, | 5855 | .format_fw_ver = (format_fw_ver_t)bnx2x_format_ver, |
5617 | .hw_reset = (hw_reset_t)NULL, | 5856 | .hw_reset = (hw_reset_t)NULL, |
5618 | .set_link_led = (set_link_led_t)NULL | 5857 | .set_link_led = (set_link_led_t)NULL, |
5858 | .phy_specific_func = (phy_specific_func_t)NULL | ||
5619 | }; | 5859 | }; |
5620 | 5860 | ||
5621 | static struct bnx2x_phy phy_8726 = { | 5861 | static struct bnx2x_phy phy_8726 = { |
@@ -5647,7 +5887,8 @@ static struct bnx2x_phy phy_8726 = { | |||
5647 | .config_loopback = (config_loopback_t)bnx2x_8726_config_loopback, | 5887 | .config_loopback = (config_loopback_t)bnx2x_8726_config_loopback, |
5648 | .format_fw_ver = (format_fw_ver_t)bnx2x_format_ver, | 5888 | .format_fw_ver = (format_fw_ver_t)bnx2x_format_ver, |
5649 | .hw_reset = (hw_reset_t)NULL, | 5889 | .hw_reset = (hw_reset_t)NULL, |
5650 | .set_link_led = (set_link_led_t)NULL | 5890 | .set_link_led = (set_link_led_t)NULL, |
5891 | .phy_specific_func = (phy_specific_func_t)NULL | ||
5651 | }; | 5892 | }; |
5652 | 5893 | ||
5653 | static struct bnx2x_phy phy_8727 = { | 5894 | static struct bnx2x_phy phy_8727 = { |
@@ -5677,12 +5918,14 @@ static struct bnx2x_phy phy_8727 = { | |||
5677 | .config_loopback = (config_loopback_t)NULL, | 5918 | .config_loopback = (config_loopback_t)NULL, |
5678 | .format_fw_ver = (format_fw_ver_t)bnx2x_format_ver, | 5919 | .format_fw_ver = (format_fw_ver_t)bnx2x_format_ver, |
5679 | .hw_reset = (hw_reset_t)bnx2x_8727_hw_reset, | 5920 | .hw_reset = (hw_reset_t)bnx2x_8727_hw_reset, |
5680 | .set_link_led = (set_link_led_t)NULL | 5921 | .set_link_led = (set_link_led_t)NULL, |
5922 | .phy_specific_func = (phy_specific_func_t)bnx2x_8727_specific_func | ||
5681 | }; | 5923 | }; |
5682 | static struct bnx2x_phy phy_8481 = { | 5924 | static struct bnx2x_phy phy_8481 = { |
5683 | .type = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8481, | 5925 | .type = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8481, |
5684 | .addr = 0xff, | 5926 | .addr = 0xff, |
5685 | .flags = FLAGS_FAN_FAILURE_DET_REQ, | 5927 | .flags = FLAGS_FAN_FAILURE_DET_REQ | |
5928 | FLAGS_REARM_LATCH_SIGNAL, | ||
5686 | .def_md_devad = 0, | 5929 | .def_md_devad = 0, |
5687 | .reserved = 0, | 5930 | .reserved = 0, |
5688 | .rx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff}, | 5931 | .rx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff}, |
@@ -5711,13 +5954,15 @@ static struct bnx2x_phy phy_8481 = { | |||
5711 | .config_loopback = (config_loopback_t)NULL, | 5954 | .config_loopback = (config_loopback_t)NULL, |
5712 | .format_fw_ver = (format_fw_ver_t)bnx2x_848xx_format_ver, | 5955 | .format_fw_ver = (format_fw_ver_t)bnx2x_848xx_format_ver, |
5713 | .hw_reset = (hw_reset_t)bnx2x_8481_hw_reset, | 5956 | .hw_reset = (hw_reset_t)bnx2x_8481_hw_reset, |
5714 | .set_link_led = (set_link_led_t)NULL | 5957 | .set_link_led = (set_link_led_t)NULL, |
5958 | .phy_specific_func = (phy_specific_func_t)NULL | ||
5715 | }; | 5959 | }; |
5716 | 5960 | ||
5717 | static struct bnx2x_phy phy_84823 = { | 5961 | static struct bnx2x_phy phy_84823 = { |
5718 | .type = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84823, | 5962 | .type = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84823, |
5719 | .addr = 0xff, | 5963 | .addr = 0xff, |
5720 | .flags = FLAGS_FAN_FAILURE_DET_REQ, | 5964 | .flags = FLAGS_FAN_FAILURE_DET_REQ | |
5965 | FLAGS_REARM_LATCH_SIGNAL, | ||
5721 | .def_md_devad = 0, | 5966 | .def_md_devad = 0, |
5722 | .reserved = 0, | 5967 | .reserved = 0, |
5723 | .rx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff}, | 5968 | .rx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff}, |
@@ -5746,7 +5991,8 @@ static struct bnx2x_phy phy_84823 = { | |||
5746 | .config_loopback = (config_loopback_t)NULL, | 5991 | .config_loopback = (config_loopback_t)NULL, |
5747 | .format_fw_ver = (format_fw_ver_t)bnx2x_848xx_format_ver, | 5992 | .format_fw_ver = (format_fw_ver_t)bnx2x_848xx_format_ver, |
5748 | .hw_reset = (hw_reset_t)NULL, | 5993 | .hw_reset = (hw_reset_t)NULL, |
5749 | .set_link_led = (set_link_led_t)NULL | 5994 | .set_link_led = (set_link_led_t)NULL, |
5995 | .phy_specific_func = (phy_specific_func_t)NULL | ||
5750 | }; | 5996 | }; |
5751 | 5997 | ||
5752 | /*****************************************************************/ | 5998 | /*****************************************************************/ |
@@ -5767,14 +6013,23 @@ static void bnx2x_populate_preemphasis(struct bnx2x *bp, u32 shmem_base, | |||
5767 | * shmem. When num_phys is greater than 1, than this value | 6013 | * shmem. When num_phys is greater than 1, than this value |
5768 | * applies only to EXT_PHY1 | 6014 | * applies only to EXT_PHY1 |
5769 | */ | 6015 | */ |
6016 | if (phy_index == INT_PHY || phy_index == EXT_PHY1) { | ||
6017 | rx = REG_RD(bp, shmem_base + | ||
6018 | offsetof(struct shmem_region, | ||
6019 | dev_info.port_hw_config[port].xgxs_config_rx[i<<1])); | ||
6020 | |||
6021 | tx = REG_RD(bp, shmem_base + | ||
6022 | offsetof(struct shmem_region, | ||
6023 | dev_info.port_hw_config[port].xgxs_config_tx[i<<1])); | ||
6024 | } else { | ||
6025 | rx = REG_RD(bp, shmem_base + | ||
6026 | offsetof(struct shmem_region, | ||
6027 | dev_info.port_hw_config[port].xgxs_config2_rx[i<<1])); | ||
5770 | 6028 | ||
5771 | rx = REG_RD(bp, shmem_base + | 6029 | tx = REG_RD(bp, shmem_base + |
5772 | offsetof(struct shmem_region, | 6030 | offsetof(struct shmem_region, |
5773 | dev_info.port_hw_config[port].xgxs_config_rx[i<<1])); | 6031 | dev_info.port_hw_config[port].xgxs_config2_rx[i<<1])); |
5774 | 6032 | } | |
5775 | tx = REG_RD(bp, shmem_base + | ||
5776 | offsetof(struct shmem_region, | ||
5777 | dev_info.port_hw_config[port].xgxs_config_tx[i<<1])); | ||
5778 | 6033 | ||
5779 | phy->rx_preemphasis[i << 1] = ((rx>>16) & 0xffff); | 6034 | phy->rx_preemphasis[i << 1] = ((rx>>16) & 0xffff); |
5780 | phy->rx_preemphasis[(i << 1) + 1] = (rx & 0xffff); | 6035 | phy->rx_preemphasis[(i << 1) + 1] = (rx & 0xffff); |
@@ -5794,6 +6049,11 @@ static u32 bnx2x_get_ext_phy_config(struct bnx2x *bp, u32 shmem_base, | |||
5794 | offsetof(struct shmem_region, | 6049 | offsetof(struct shmem_region, |
5795 | dev_info.port_hw_config[port].external_phy_config)); | 6050 | dev_info.port_hw_config[port].external_phy_config)); |
5796 | break; | 6051 | break; |
6052 | case EXT_PHY2: | ||
6053 | ext_phy_config = REG_RD(bp, shmem_base + | ||
6054 | offsetof(struct shmem_region, | ||
6055 | dev_info.port_hw_config[port].external_phy_config2)); | ||
6056 | break; | ||
5797 | default: | 6057 | default: |
5798 | DP(NETIF_MSG_LINK, "Invalid phy_index %d\n", phy_index); | 6058 | DP(NETIF_MSG_LINK, "Invalid phy_index %d\n", phy_index); |
5799 | return -EINVAL; | 6059 | return -EINVAL; |
@@ -5844,6 +6104,7 @@ static u8 bnx2x_populate_int_phy(struct bnx2x *bp, u32 shmem_base, u8 port, | |||
5844 | static u8 bnx2x_populate_ext_phy(struct bnx2x *bp, | 6104 | static u8 bnx2x_populate_ext_phy(struct bnx2x *bp, |
5845 | u8 phy_index, | 6105 | u8 phy_index, |
5846 | u32 shmem_base, | 6106 | u32 shmem_base, |
6107 | u32 shmem2_base, | ||
5847 | u8 port, | 6108 | u8 port, |
5848 | struct bnx2x_phy *phy) | 6109 | struct bnx2x_phy *phy) |
5849 | { | 6110 | { |
@@ -5905,15 +6166,30 @@ static u8 bnx2x_populate_ext_phy(struct bnx2x *bp, | |||
5905 | */ | 6166 | */ |
5906 | config2 = REG_RD(bp, shmem_base + offsetof(struct shmem_region, | 6167 | config2 = REG_RD(bp, shmem_base + offsetof(struct shmem_region, |
5907 | dev_info.shared_hw_config.config2)); | 6168 | dev_info.shared_hw_config.config2)); |
5908 | 6169 | if (phy_index == EXT_PHY1) { | |
5909 | phy->ver_addr = shmem_base + offsetof(struct shmem_region, | 6170 | phy->ver_addr = shmem_base + offsetof(struct shmem_region, |
5910 | port_mb[port].ext_phy_fw_version); | 6171 | port_mb[port].ext_phy_fw_version); |
5911 | 6172 | ||
5912 | /* Check specific mdc mdio settings */ | 6173 | /* Check specific mdc mdio settings */ |
5913 | if (config2 & SHARED_HW_CFG_MDC_MDIO_ACCESS1_MASK) | 6174 | if (config2 & SHARED_HW_CFG_MDC_MDIO_ACCESS1_MASK) |
5914 | mdc_mdio_access = config2 & | 6175 | mdc_mdio_access = config2 & |
5915 | SHARED_HW_CFG_MDC_MDIO_ACCESS1_MASK; | 6176 | SHARED_HW_CFG_MDC_MDIO_ACCESS1_MASK; |
6177 | } else { | ||
6178 | u32 size = REG_RD(bp, shmem2_base); | ||
5916 | 6179 | ||
6180 | if (size > | ||
6181 | offsetof(struct shmem2_region, ext_phy_fw_version2)) { | ||
6182 | phy->ver_addr = shmem2_base + | ||
6183 | offsetof(struct shmem2_region, | ||
6184 | ext_phy_fw_version2[port]); | ||
6185 | } | ||
6186 | /* Check specific mdc mdio settings */ | ||
6187 | if (config2 & SHARED_HW_CFG_MDC_MDIO_ACCESS2_MASK) | ||
6188 | mdc_mdio_access = (config2 & | ||
6189 | SHARED_HW_CFG_MDC_MDIO_ACCESS2_MASK) >> | ||
6190 | (SHARED_HW_CFG_MDC_MDIO_ACCESS2_SHIFT - | ||
6191 | SHARED_HW_CFG_MDC_MDIO_ACCESS1_SHIFT); | ||
6192 | } | ||
5917 | phy->mdio_ctrl = bnx2x_get_emac_base(bp, mdc_mdio_access, port); | 6193 | phy->mdio_ctrl = bnx2x_get_emac_base(bp, mdc_mdio_access, port); |
5918 | 6194 | ||
5919 | /** | 6195 | /** |
@@ -5931,30 +6207,41 @@ static u8 bnx2x_populate_ext_phy(struct bnx2x *bp, | |||
5931 | } | 6207 | } |
5932 | 6208 | ||
5933 | static u8 bnx2x_populate_phy(struct bnx2x *bp, u8 phy_index, u32 shmem_base, | 6209 | static u8 bnx2x_populate_phy(struct bnx2x *bp, u8 phy_index, u32 shmem_base, |
5934 | u8 port, struct bnx2x_phy *phy) | 6210 | u32 shmem2_base, u8 port, struct bnx2x_phy *phy) |
5935 | { | 6211 | { |
5936 | u8 status = 0; | 6212 | u8 status = 0; |
5937 | phy->type = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_NOT_CONN; | 6213 | phy->type = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_NOT_CONN; |
5938 | if (phy_index == INT_PHY) | 6214 | if (phy_index == INT_PHY) |
5939 | return bnx2x_populate_int_phy(bp, shmem_base, port, phy); | 6215 | return bnx2x_populate_int_phy(bp, shmem_base, port, phy); |
5940 | status = bnx2x_populate_ext_phy(bp, phy_index, shmem_base, | 6216 | status = bnx2x_populate_ext_phy(bp, phy_index, shmem_base, shmem2_base, |
5941 | port, phy); | 6217 | port, phy); |
5942 | return status; | 6218 | return status; |
5943 | } | 6219 | } |
5944 | 6220 | ||
5945 | static void bnx2x_phy_def_cfg(struct link_params *params, | 6221 | static void bnx2x_phy_def_cfg(struct link_params *params, |
5946 | struct bnx2x_phy *phy, | 6222 | struct bnx2x_phy *phy, |
5947 | u8 actual_phy_idx) | 6223 | u8 phy_index) |
5948 | { | 6224 | { |
5949 | struct bnx2x *bp = params->bp; | 6225 | struct bnx2x *bp = params->bp; |
5950 | u32 link_config; | 6226 | u32 link_config; |
5951 | /* Populate the default phy configuration for MF mode */ | 6227 | /* Populate the default phy configuration for MF mode */ |
5952 | link_config = REG_RD(bp, params->shmem_base + | 6228 | if (phy_index == EXT_PHY2) { |
5953 | offsetof(struct shmem_region, dev_info. | 6229 | link_config = REG_RD(bp, params->shmem_base + |
5954 | port_feature_config[params->port].link_config)); | 6230 | offsetof(struct shmem_region, dev_info. |
5955 | phy->speed_cap_mask = REG_RD(bp, params->shmem_base + | 6231 | port_feature_config[params->port].link_config2)); |
6232 | phy->speed_cap_mask = REG_RD(bp, params->shmem_base + | ||
6233 | offsetof(struct shmem_region, dev_info. | ||
6234 | port_hw_config[params->port].speed_capability_mask2)); | ||
6235 | } else { | ||
6236 | link_config = REG_RD(bp, params->shmem_base + | ||
6237 | offsetof(struct shmem_region, dev_info. | ||
6238 | port_feature_config[params->port].link_config)); | ||
6239 | phy->speed_cap_mask = REG_RD(bp, params->shmem_base + | ||
5956 | offsetof(struct shmem_region, dev_info. | 6240 | offsetof(struct shmem_region, dev_info. |
5957 | port_hw_config[params->port].speed_capability_mask)); | 6241 | port_hw_config[params->port].speed_capability_mask)); |
6242 | } | ||
6243 | DP(NETIF_MSG_LINK, "Default config phy idx %x cfg 0x%x speed_cap_mask" | ||
6244 | " 0x%x\n", phy_index, link_config, phy->speed_cap_mask); | ||
5958 | 6245 | ||
5959 | phy->req_duplex = DUPLEX_FULL; | 6246 | phy->req_duplex = DUPLEX_FULL; |
5960 | switch (link_config & PORT_FEATURE_LINK_SPEED_MASK) { | 6247 | switch (link_config & PORT_FEATURE_LINK_SPEED_MASK) { |
@@ -6001,23 +6288,66 @@ static void bnx2x_phy_def_cfg(struct link_params *params, | |||
6001 | } | 6288 | } |
6002 | } | 6289 | } |
6003 | 6290 | ||
6291 | u32 bnx2x_phy_selection(struct link_params *params) | ||
6292 | { | ||
6293 | u32 phy_config_swapped, prio_cfg; | ||
6294 | u32 return_cfg = PORT_HW_CFG_PHY_SELECTION_HARDWARE_DEFAULT; | ||
6295 | |||
6296 | phy_config_swapped = params->multi_phy_config & | ||
6297 | PORT_HW_CFG_PHY_SWAPPED_ENABLED; | ||
6298 | |||
6299 | prio_cfg = params->multi_phy_config & | ||
6300 | PORT_HW_CFG_PHY_SELECTION_MASK; | ||
6301 | |||
6302 | if (phy_config_swapped) { | ||
6303 | switch (prio_cfg) { | ||
6304 | case PORT_HW_CFG_PHY_SELECTION_FIRST_PHY_PRIORITY: | ||
6305 | return_cfg = PORT_HW_CFG_PHY_SELECTION_SECOND_PHY_PRIORITY; | ||
6306 | break; | ||
6307 | case PORT_HW_CFG_PHY_SELECTION_SECOND_PHY_PRIORITY: | ||
6308 | return_cfg = PORT_HW_CFG_PHY_SELECTION_FIRST_PHY_PRIORITY; | ||
6309 | break; | ||
6310 | case PORT_HW_CFG_PHY_SELECTION_SECOND_PHY: | ||
6311 | return_cfg = PORT_HW_CFG_PHY_SELECTION_FIRST_PHY; | ||
6312 | break; | ||
6313 | case PORT_HW_CFG_PHY_SELECTION_FIRST_PHY: | ||
6314 | return_cfg = PORT_HW_CFG_PHY_SELECTION_SECOND_PHY; | ||
6315 | break; | ||
6316 | } | ||
6317 | } else | ||
6318 | return_cfg = prio_cfg; | ||
6319 | |||
6320 | return return_cfg; | ||
6321 | } | ||
6322 | |||
6323 | |||
6004 | u8 bnx2x_phy_probe(struct link_params *params) | 6324 | u8 bnx2x_phy_probe(struct link_params *params) |
6005 | { | 6325 | { |
6006 | u8 phy_index, actual_phy_idx, link_cfg_idx; | 6326 | u8 phy_index, actual_phy_idx, link_cfg_idx; |
6007 | 6327 | u32 phy_config_swapped; | |
6008 | struct bnx2x *bp = params->bp; | 6328 | struct bnx2x *bp = params->bp; |
6009 | struct bnx2x_phy *phy; | 6329 | struct bnx2x_phy *phy; |
6010 | params->num_phys = 0; | 6330 | params->num_phys = 0; |
6011 | DP(NETIF_MSG_LINK, "Begin phy probe\n"); | 6331 | DP(NETIF_MSG_LINK, "Begin phy probe\n"); |
6332 | phy_config_swapped = params->multi_phy_config & | ||
6333 | PORT_HW_CFG_PHY_SWAPPED_ENABLED; | ||
6012 | 6334 | ||
6013 | for (phy_index = INT_PHY; phy_index < MAX_PHYS; | 6335 | for (phy_index = INT_PHY; phy_index < MAX_PHYS; |
6014 | phy_index++) { | 6336 | phy_index++) { |
6015 | link_cfg_idx = LINK_CONFIG_IDX(phy_index); | 6337 | link_cfg_idx = LINK_CONFIG_IDX(phy_index); |
6016 | actual_phy_idx = phy_index; | 6338 | actual_phy_idx = phy_index; |
6017 | 6339 | if (phy_config_swapped) { | |
6340 | if (phy_index == EXT_PHY1) | ||
6341 | actual_phy_idx = EXT_PHY2; | ||
6342 | else if (phy_index == EXT_PHY2) | ||
6343 | actual_phy_idx = EXT_PHY1; | ||
6344 | } | ||
6345 | DP(NETIF_MSG_LINK, "phy_config_swapped %x, phy_index %x," | ||
6346 | " actual_phy_idx %x\n", phy_config_swapped, | ||
6347 | phy_index, actual_phy_idx); | ||
6018 | phy = ¶ms->phy[actual_phy_idx]; | 6348 | phy = ¶ms->phy[actual_phy_idx]; |
6019 | if (bnx2x_populate_phy(bp, phy_index, params->shmem_base, | 6349 | if (bnx2x_populate_phy(bp, phy_index, params->shmem_base, |
6020 | params->port, | 6350 | params->shmem2_base, params->port, |
6021 | phy) != 0) { | 6351 | phy) != 0) { |
6022 | params->num_phys = 0; | 6352 | params->num_phys = 0; |
6023 | DP(NETIF_MSG_LINK, "phy probe failed in phy index %d\n", | 6353 | DP(NETIF_MSG_LINK, "phy probe failed in phy index %d\n", |
@@ -6031,7 +6361,7 @@ u8 bnx2x_phy_probe(struct link_params *params) | |||
6031 | if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_NOT_CONN) | 6361 | if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_NOT_CONN) |
6032 | break; | 6362 | break; |
6033 | 6363 | ||
6034 | bnx2x_phy_def_cfg(params, phy, actual_phy_idx); | 6364 | bnx2x_phy_def_cfg(params, phy, phy_index); |
6035 | params->num_phys++; | 6365 | params->num_phys++; |
6036 | } | 6366 | } |
6037 | 6367 | ||
@@ -6049,23 +6379,30 @@ u32 bnx2x_supported_attr(struct link_params *params, u8 phy_idx) | |||
6049 | static void set_phy_vars(struct link_params *params) | 6379 | static void set_phy_vars(struct link_params *params) |
6050 | { | 6380 | { |
6051 | struct bnx2x *bp = params->bp; | 6381 | struct bnx2x *bp = params->bp; |
6052 | u8 actual_phy_idx, phy_index; | 6382 | u8 actual_phy_idx, phy_index, link_cfg_idx; |
6053 | 6383 | u8 phy_config_swapped = params->multi_phy_config & | |
6384 | PORT_HW_CFG_PHY_SWAPPED_ENABLED; | ||
6054 | for (phy_index = INT_PHY; phy_index < params->num_phys; | 6385 | for (phy_index = INT_PHY; phy_index < params->num_phys; |
6055 | phy_index++) { | 6386 | phy_index++) { |
6056 | 6387 | link_cfg_idx = LINK_CONFIG_IDX(phy_index); | |
6057 | actual_phy_idx = phy_index; | 6388 | actual_phy_idx = phy_index; |
6389 | if (phy_config_swapped) { | ||
6390 | if (phy_index == EXT_PHY1) | ||
6391 | actual_phy_idx = EXT_PHY2; | ||
6392 | else if (phy_index == EXT_PHY2) | ||
6393 | actual_phy_idx = EXT_PHY1; | ||
6394 | } | ||
6058 | params->phy[actual_phy_idx].req_flow_ctrl = | 6395 | params->phy[actual_phy_idx].req_flow_ctrl = |
6059 | params->req_flow_ctrl; | 6396 | params->req_flow_ctrl[link_cfg_idx]; |
6060 | 6397 | ||
6061 | params->phy[actual_phy_idx].req_line_speed = | 6398 | params->phy[actual_phy_idx].req_line_speed = |
6062 | params->req_line_speed; | 6399 | params->req_line_speed[link_cfg_idx]; |
6063 | 6400 | ||
6064 | params->phy[actual_phy_idx].speed_cap_mask = | 6401 | params->phy[actual_phy_idx].speed_cap_mask = |
6065 | params->speed_cap_mask; | 6402 | params->speed_cap_mask[link_cfg_idx]; |
6066 | 6403 | ||
6067 | params->phy[actual_phy_idx].req_duplex = | 6404 | params->phy[actual_phy_idx].req_duplex = |
6068 | params->req_duplex; | 6405 | params->req_duplex[link_cfg_idx]; |
6069 | 6406 | ||
6070 | DP(NETIF_MSG_LINK, "req_flow_ctrl %x, req_line_speed %x," | 6407 | DP(NETIF_MSG_LINK, "req_flow_ctrl %x, req_line_speed %x," |
6071 | " speed_cap_mask %x\n", | 6408 | " speed_cap_mask %x\n", |
@@ -6078,11 +6415,11 @@ static void set_phy_vars(struct link_params *params) | |||
6078 | u8 bnx2x_phy_init(struct link_params *params, struct link_vars *vars) | 6415 | u8 bnx2x_phy_init(struct link_params *params, struct link_vars *vars) |
6079 | { | 6416 | { |
6080 | struct bnx2x *bp = params->bp; | 6417 | struct bnx2x *bp = params->bp; |
6081 | u32 val; | ||
6082 | |||
6083 | DP(NETIF_MSG_LINK, "Phy Initialization started\n"); | 6418 | DP(NETIF_MSG_LINK, "Phy Initialization started\n"); |
6084 | DP(NETIF_MSG_LINK, "req_speed %d, req_flowctrl %d\n", | 6419 | DP(NETIF_MSG_LINK, "(1) req_speed %d, req_flowctrl %d\n", |
6085 | params->req_line_speed, params->req_flow_ctrl); | 6420 | params->req_line_speed[0], params->req_flow_ctrl[0]); |
6421 | DP(NETIF_MSG_LINK, "(2) req_speed %d, req_flowctrl %d\n", | ||
6422 | params->req_line_speed[1], params->req_flow_ctrl[1]); | ||
6086 | vars->link_status = 0; | 6423 | vars->link_status = 0; |
6087 | vars->phy_link_up = 0; | 6424 | vars->phy_link_up = 0; |
6088 | vars->link_up = 0; | 6425 | vars->link_up = 0; |
@@ -6196,21 +6533,23 @@ u8 bnx2x_phy_init(struct link_params *params, struct link_vars *vars) | |||
6196 | (params->loopback_mode == LOOPBACK_EXT_PHY)) { | 6533 | (params->loopback_mode == LOOPBACK_EXT_PHY)) { |
6197 | 6534 | ||
6198 | vars->link_up = 1; | 6535 | vars->link_up = 1; |
6199 | vars->line_speed = SPEED_10000; | ||
6200 | vars->duplex = DUPLEX_FULL; | ||
6201 | vars->flow_ctrl = BNX2X_FLOW_CTRL_NONE; | 6536 | vars->flow_ctrl = BNX2X_FLOW_CTRL_NONE; |
6202 | 6537 | vars->duplex = DUPLEX_FULL; | |
6203 | vars->phy_flags = PHY_XGXS_FLAG; | 6538 | if (params->req_line_speed[0] == SPEED_1000) { |
6204 | 6539 | vars->line_speed = SPEED_1000; | |
6205 | val = REG_RD(bp, | 6540 | vars->mac_type = MAC_TYPE_EMAC; |
6206 | NIG_REG_XGXS0_CTRL_PHY_ADDR+ | 6541 | } else { |
6207 | params->port*0x18); | 6542 | vars->line_speed = SPEED_10000; |
6543 | vars->mac_type = MAC_TYPE_BMAC; | ||
6544 | } | ||
6208 | 6545 | ||
6209 | bnx2x_xgxs_deassert(params); | 6546 | bnx2x_xgxs_deassert(params); |
6210 | bnx2x_link_initialize(params, vars); | 6547 | bnx2x_link_initialize(params, vars); |
6211 | 6548 | ||
6212 | vars->mac_type = MAC_TYPE_BMAC; | 6549 | if (params->req_line_speed[0] == SPEED_1000) { |
6213 | 6550 | bnx2x_emac_program(params, vars); | |
6551 | bnx2x_emac_enable(params, vars, 0); | ||
6552 | } else | ||
6214 | bnx2x_bmac_enable(params, vars, 0); | 6553 | bnx2x_bmac_enable(params, vars, 0); |
6215 | 6554 | ||
6216 | if (params->loopback_mode == LOOPBACK_XGXS) { | 6555 | if (params->loopback_mode == LOOPBACK_XGXS) { |
@@ -6311,7 +6650,7 @@ u8 bnx2x_link_reset(struct link_params *params, struct link_vars *vars, | |||
6311 | /****************************************************************************/ | 6650 | /****************************************************************************/ |
6312 | /* Common function */ | 6651 | /* Common function */ |
6313 | /****************************************************************************/ | 6652 | /****************************************************************************/ |
6314 | static u8 bnx2x_8073_common_init_phy(struct bnx2x *bp, u32 shmem_base) | 6653 | static u8 bnx2x_8073_common_init_phy(struct bnx2x *bp, u32 shmem_base, u32 shmem2_base, u8 phy_index) |
6315 | { | 6654 | { |
6316 | struct bnx2x_phy phy[PORT_MAX]; | 6655 | struct bnx2x_phy phy[PORT_MAX]; |
6317 | struct bnx2x_phy *phy_blk[PORT_MAX]; | 6656 | struct bnx2x_phy *phy_blk[PORT_MAX]; |
@@ -6321,7 +6660,7 @@ static u8 bnx2x_8073_common_init_phy(struct bnx2x *bp, u32 shmem_base) | |||
6321 | /* PART1 - Reset both phys */ | 6660 | /* PART1 - Reset both phys */ |
6322 | for (port = PORT_MAX - 1; port >= PORT_0; port--) { | 6661 | for (port = PORT_MAX - 1; port >= PORT_0; port--) { |
6323 | /* Extract the ext phy address for the port */ | 6662 | /* Extract the ext phy address for the port */ |
6324 | if (bnx2x_populate_phy(bp, EXT_PHY1, shmem_base, | 6663 | if (bnx2x_populate_phy(bp, phy_index, shmem_base, shmem2_base, |
6325 | port, &phy[port]) != | 6664 | port, &phy[port]) != |
6326 | 0) { | 6665 | 0) { |
6327 | DP(NETIF_MSG_LINK, "populate_phy failed\n"); | 6666 | DP(NETIF_MSG_LINK, "populate_phy failed\n"); |
@@ -6419,7 +6758,8 @@ static u8 bnx2x_8073_common_init_phy(struct bnx2x *bp, u32 shmem_base) | |||
6419 | return 0; | 6758 | return 0; |
6420 | } | 6759 | } |
6421 | 6760 | ||
6422 | static u8 bnx2x_8726_common_init_phy(struct bnx2x *bp, u32 shmem_base) | 6761 | static u8 bnx2x_8726_common_init_phy(struct bnx2x *bp, u32 shmem_base, |
6762 | u32 shmem2_base, u8 phy_index) | ||
6423 | { | 6763 | { |
6424 | u32 val; | 6764 | u32 val; |
6425 | s8 port; | 6765 | s8 port; |
@@ -6435,7 +6775,7 @@ static u8 bnx2x_8726_common_init_phy(struct bnx2x *bp, u32 shmem_base) | |||
6435 | msleep(5); | 6775 | msleep(5); |
6436 | for (port = 0; port < PORT_MAX; port++) { | 6776 | for (port = 0; port < PORT_MAX; port++) { |
6437 | /* Extract the ext phy address for the port */ | 6777 | /* Extract the ext phy address for the port */ |
6438 | if (bnx2x_populate_phy(bp, EXT_PHY1, shmem_base, | 6778 | if (bnx2x_populate_phy(bp, phy_index, shmem_base, shmem2_base, |
6439 | port, &phy) != | 6779 | port, &phy) != |
6440 | 0) { | 6780 | 0) { |
6441 | DP(NETIF_MSG_LINK, "populate phy failed\n"); | 6781 | DP(NETIF_MSG_LINK, "populate phy failed\n"); |
@@ -6455,10 +6795,10 @@ static u8 bnx2x_8726_common_init_phy(struct bnx2x *bp, u32 shmem_base) | |||
6455 | 6795 | ||
6456 | return 0; | 6796 | return 0; |
6457 | } | 6797 | } |
6458 | 6798 | static u8 bnx2x_8727_common_init_phy(struct bnx2x *bp, u32 shmem_base, | |
6459 | static u8 bnx2x_8727_common_init_phy(struct bnx2x *bp, u32 shmem_base) | 6799 | u32 shmem2_base, u8 phy_index) |
6460 | { | 6800 | { |
6461 | s8 port, first_port, i; | 6801 | s8 port; |
6462 | u32 swap_val, swap_override; | 6802 | u32 swap_val, swap_override; |
6463 | struct bnx2x_phy phy[PORT_MAX]; | 6803 | struct bnx2x_phy phy[PORT_MAX]; |
6464 | struct bnx2x_phy *phy_blk[PORT_MAX]; | 6804 | struct bnx2x_phy *phy_blk[PORT_MAX]; |
@@ -6466,18 +6806,19 @@ static u8 bnx2x_8727_common_init_phy(struct bnx2x *bp, u32 shmem_base) | |||
6466 | swap_val = REG_RD(bp, NIG_REG_PORT_SWAP); | 6806 | swap_val = REG_RD(bp, NIG_REG_PORT_SWAP); |
6467 | swap_override = REG_RD(bp, NIG_REG_STRAP_OVERRIDE); | 6807 | swap_override = REG_RD(bp, NIG_REG_STRAP_OVERRIDE); |
6468 | 6808 | ||
6469 | bnx2x_ext_phy_hw_reset(bp, 1 ^ (swap_val && swap_override)); | 6809 | port = 1; |
6470 | msleep(5); | ||
6471 | 6810 | ||
6472 | if (swap_val && swap_override) | 6811 | bnx2x_ext_phy_hw_reset(bp, port ^ (swap_val && swap_override)); |
6473 | first_port = PORT_0; | 6812 | |
6474 | else | 6813 | /* Calculate the port based on port swap */ |
6475 | first_port = PORT_1; | 6814 | port ^= (swap_val && swap_override); |
6815 | |||
6816 | msleep(5); | ||
6476 | 6817 | ||
6477 | /* PART1 - Reset both phys */ | 6818 | /* PART1 - Reset both phys */ |
6478 | for (i = 0, port = first_port; i < PORT_MAX; i++, port = !port) { | 6819 | for (port = PORT_MAX - 1; port >= PORT_0; port--) { |
6479 | /* Extract the ext phy address for the port */ | 6820 | /* Extract the ext phy address for the port */ |
6480 | if (bnx2x_populate_phy(bp, EXT_PHY1, shmem_base, | 6821 | if (bnx2x_populate_phy(bp, phy_index, shmem_base, shmem2_base, |
6481 | port, &phy[port]) != | 6822 | port, &phy[port]) != |
6482 | 0) { | 6823 | 0) { |
6483 | DP(NETIF_MSG_LINK, "populate phy failed\n"); | 6824 | DP(NETIF_MSG_LINK, "populate phy failed\n"); |
@@ -6528,35 +6869,32 @@ static u8 bnx2x_8727_common_init_phy(struct bnx2x *bp, u32 shmem_base) | |||
6528 | return 0; | 6869 | return 0; |
6529 | } | 6870 | } |
6530 | 6871 | ||
6531 | u8 bnx2x_common_init_phy(struct bnx2x *bp, u32 shmem_base) | 6872 | static u8 bnx2x_ext_phy_common_init(struct bnx2x *bp, u32 shmem_base, |
6873 | u32 shmem2_base, u8 phy_index, | ||
6874 | u32 ext_phy_type) | ||
6532 | { | 6875 | { |
6533 | u8 rc = 0; | 6876 | u8 rc = 0; |
6534 | u32 ext_phy_type; | ||
6535 | |||
6536 | DP(NETIF_MSG_LINK, "Begin common phy init\n"); | ||
6537 | |||
6538 | /* Read the ext_phy_type for arbitrary port(0) */ | ||
6539 | ext_phy_type = XGXS_EXT_PHY_TYPE( | ||
6540 | REG_RD(bp, shmem_base + | ||
6541 | offsetof(struct shmem_region, | ||
6542 | dev_info.port_hw_config[0].external_phy_config))); | ||
6543 | 6877 | ||
6544 | switch (ext_phy_type) { | 6878 | switch (ext_phy_type) { |
6545 | case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073: | 6879 | case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073: |
6546 | { | 6880 | rc = bnx2x_8073_common_init_phy(bp, shmem_base, |
6547 | rc = bnx2x_8073_common_init_phy(bp, shmem_base); | 6881 | shmem2_base, phy_index); |
6548 | break; | 6882 | break; |
6549 | } | ||
6550 | 6883 | ||
6551 | case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727: | 6884 | case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727: |
6552 | case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727_NOC: | 6885 | case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727_NOC: |
6553 | rc = bnx2x_8727_common_init_phy(bp, shmem_base); | 6886 | rc = bnx2x_8727_common_init_phy(bp, shmem_base, |
6887 | shmem2_base, phy_index); | ||
6554 | break; | 6888 | break; |
6555 | 6889 | ||
6556 | case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726: | 6890 | case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726: |
6557 | /* GPIO1 affects both ports, so there's need to pull | 6891 | /* GPIO1 affects both ports, so there's need to pull |
6558 | it for single port alone */ | 6892 | it for single port alone */ |
6559 | rc = bnx2x_8726_common_init_phy(bp, shmem_base); | 6893 | rc = bnx2x_8726_common_init_phy(bp, shmem_base, |
6894 | shmem2_base, phy_index); | ||
6895 | break; | ||
6896 | case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_FAILURE: | ||
6897 | rc = -EINVAL; | ||
6560 | break; | 6898 | break; |
6561 | default: | 6899 | default: |
6562 | DP(NETIF_MSG_LINK, | 6900 | DP(NETIF_MSG_LINK, |
@@ -6568,14 +6906,38 @@ u8 bnx2x_common_init_phy(struct bnx2x *bp, u32 shmem_base) | |||
6568 | return rc; | 6906 | return rc; |
6569 | } | 6907 | } |
6570 | 6908 | ||
6909 | u8 bnx2x_common_init_phy(struct bnx2x *bp, u32 shmem_base, | ||
6910 | u32 shmem2_base) | ||
6911 | { | ||
6912 | u8 rc = 0; | ||
6913 | u8 phy_index; | ||
6914 | u32 ext_phy_type, ext_phy_config; | ||
6915 | DP(NETIF_MSG_LINK, "Begin common phy init\n"); | ||
6916 | |||
6917 | if (CHIP_REV_IS_EMUL(bp)) | ||
6918 | return 0; | ||
6919 | |||
6920 | /* Read the ext_phy_type for arbitrary port(0) */ | ||
6921 | for (phy_index = EXT_PHY1; phy_index < MAX_PHYS; | ||
6922 | phy_index++) { | ||
6923 | ext_phy_config = bnx2x_get_ext_phy_config(bp, | ||
6924 | shmem_base, | ||
6925 | phy_index, 0); | ||
6926 | ext_phy_type = XGXS_EXT_PHY_TYPE(ext_phy_config); | ||
6927 | rc |= bnx2x_ext_phy_common_init(bp, shmem_base, | ||
6928 | shmem2_base, | ||
6929 | phy_index, ext_phy_type); | ||
6930 | } | ||
6931 | return rc; | ||
6932 | } | ||
6571 | 6933 | ||
6572 | u8 bnx2x_hw_lock_required(struct bnx2x *bp, u32 shmem_base) | 6934 | u8 bnx2x_hw_lock_required(struct bnx2x *bp, u32 shmem_base, u32 shmem2_base) |
6573 | { | 6935 | { |
6574 | u8 phy_index; | 6936 | u8 phy_index; |
6575 | struct bnx2x_phy phy; | 6937 | struct bnx2x_phy phy; |
6576 | for (phy_index = INT_PHY; phy_index < MAX_PHYS; | 6938 | for (phy_index = INT_PHY; phy_index < MAX_PHYS; |
6577 | phy_index++) { | 6939 | phy_index++) { |
6578 | if (bnx2x_populate_phy(bp, phy_index, shmem_base, | 6940 | if (bnx2x_populate_phy(bp, phy_index, shmem_base, shmem2_base, |
6579 | 0, &phy) != 0) { | 6941 | 0, &phy) != 0) { |
6580 | DP(NETIF_MSG_LINK, "populate phy failed\n"); | 6942 | DP(NETIF_MSG_LINK, "populate phy failed\n"); |
6581 | return 0; | 6943 | return 0; |
@@ -6589,13 +6951,14 @@ u8 bnx2x_hw_lock_required(struct bnx2x *bp, u32 shmem_base) | |||
6589 | 6951 | ||
6590 | u8 bnx2x_fan_failure_det_req(struct bnx2x *bp, | 6952 | u8 bnx2x_fan_failure_det_req(struct bnx2x *bp, |
6591 | u32 shmem_base, | 6953 | u32 shmem_base, |
6954 | u32 shmem2_base, | ||
6592 | u8 port) | 6955 | u8 port) |
6593 | { | 6956 | { |
6594 | u8 phy_index, fan_failure_det_req = 0; | 6957 | u8 phy_index, fan_failure_det_req = 0; |
6595 | struct bnx2x_phy phy; | 6958 | struct bnx2x_phy phy; |
6596 | for (phy_index = EXT_PHY1; phy_index < MAX_PHYS; | 6959 | for (phy_index = EXT_PHY1; phy_index < MAX_PHYS; |
6597 | phy_index++) { | 6960 | phy_index++) { |
6598 | if (bnx2x_populate_phy(bp, phy_index, shmem_base, | 6961 | if (bnx2x_populate_phy(bp, phy_index, shmem_base, shmem2_base, |
6599 | port, &phy) | 6962 | port, &phy) |
6600 | != 0) { | 6963 | != 0) { |
6601 | DP(NETIF_MSG_LINK, "populate phy failed\n"); | 6964 | DP(NETIF_MSG_LINK, "populate phy failed\n"); |
diff --git a/drivers/net/bnx2x/bnx2x_link.h b/drivers/net/bnx2x/bnx2x_link.h index 35f665f97be6..9115c125aeaf 100644 --- a/drivers/net/bnx2x/bnx2x_link.h +++ b/drivers/net/bnx2x/bnx2x_link.h | |||
@@ -59,13 +59,18 @@ | |||
59 | #define SINGLE_MEDIA_DIRECT(params) (params->num_phys == 1) | 59 | #define SINGLE_MEDIA_DIRECT(params) (params->num_phys == 1) |
60 | /* Single Media board contains single external phy */ | 60 | /* Single Media board contains single external phy */ |
61 | #define SINGLE_MEDIA(params) (params->num_phys == 2) | 61 | #define SINGLE_MEDIA(params) (params->num_phys == 2) |
62 | /* Dual Media board contains two external phy with different media */ | ||
63 | #define DUAL_MEDIA(params) (params->num_phys == 3) | ||
64 | #define FW_PARAM_MDIO_CTRL_OFFSET 16 | ||
65 | #define FW_PARAM_SET(phy_addr, phy_type, mdio_access) \ | ||
66 | (phy_addr | phy_type | mdio_access << FW_PARAM_MDIO_CTRL_OFFSET) | ||
62 | /***********************************************************/ | 67 | /***********************************************************/ |
63 | /* Structs */ | 68 | /* Structs */ |
64 | /***********************************************************/ | 69 | /***********************************************************/ |
65 | #define INT_PHY 0 | 70 | #define INT_PHY 0 |
66 | #define EXT_PHY1 1 | 71 | #define EXT_PHY1 1 |
67 | 72 | #define EXT_PHY2 2 | |
68 | #define MAX_PHYS 2 | 73 | #define MAX_PHYS 3 |
69 | 74 | ||
70 | /* Same configuration is shared between the XGXS and the first external phy */ | 75 | /* Same configuration is shared between the XGXS and the first external phy */ |
71 | #define LINK_CONFIG_SIZE (MAX_PHYS - 1) | 76 | #define LINK_CONFIG_SIZE (MAX_PHYS - 1) |
@@ -91,6 +96,8 @@ typedef u8 (*format_fw_ver_t)(u32 raw, u8 *str, u16 *len); | |||
91 | typedef void (*hw_reset_t)(struct bnx2x_phy *phy, struct link_params *params); | 96 | typedef void (*hw_reset_t)(struct bnx2x_phy *phy, struct link_params *params); |
92 | typedef void (*set_link_led_t)(struct bnx2x_phy *phy, | 97 | typedef void (*set_link_led_t)(struct bnx2x_phy *phy, |
93 | struct link_params *params, u8 mode); | 98 | struct link_params *params, u8 mode); |
99 | typedef void (*phy_specific_func_t)(struct bnx2x_phy *phy, | ||
100 | struct link_params *params, u32 action); | ||
94 | 101 | ||
95 | struct bnx2x_phy { | 102 | struct bnx2x_phy { |
96 | u32 type; | 103 | u32 type; |
@@ -106,7 +113,9 @@ struct bnx2x_phy { | |||
106 | /* Fan failure detection required */ | 113 | /* Fan failure detection required */ |
107 | #define FLAGS_FAN_FAILURE_DET_REQ (1<<2) | 114 | #define FLAGS_FAN_FAILURE_DET_REQ (1<<2) |
108 | /* Initialize first the XGXS and only then the phy itself */ | 115 | /* Initialize first the XGXS and only then the phy itself */ |
109 | #define FLAGS_INIT_XGXS_FIRST (1<<3) | 116 | #define FLAGS_INIT_XGXS_FIRST (1<<3) |
117 | #define FLAGS_REARM_LATCH_SIGNAL (1<<6) | ||
118 | #define FLAGS_SFP_NOT_APPROVED (1<<7) | ||
110 | 119 | ||
111 | u8 def_md_devad; | 120 | u8 def_md_devad; |
112 | u8 reserved; | 121 | u8 reserved; |
@@ -161,6 +170,11 @@ struct bnx2x_phy { | |||
161 | 170 | ||
162 | /* Set link led mode (on/off/oper)*/ | 171 | /* Set link led mode (on/off/oper)*/ |
163 | set_link_led_t set_link_led; | 172 | set_link_led_t set_link_led; |
173 | |||
174 | /* PHY Specific tasks */ | ||
175 | phy_specific_func_t phy_specific_func; | ||
176 | #define DISABLE_TX 1 | ||
177 | #define ENABLE_TX 2 | ||
164 | }; | 178 | }; |
165 | 179 | ||
166 | /* Inputs parameters to the CLC */ | 180 | /* Inputs parameters to the CLC */ |
@@ -177,18 +191,18 @@ struct link_params { | |||
177 | #define LOOPBACK_EXT_PHY 4 | 191 | #define LOOPBACK_EXT_PHY 4 |
178 | #define LOOPBACK_EXT 5 | 192 | #define LOOPBACK_EXT 5 |
179 | 193 | ||
180 | u16 req_duplex; | ||
181 | u16 req_flow_ctrl; | ||
182 | u16 req_fc_auto_adv; /* Should be set to TX / BOTH when | ||
183 | req_flow_ctrl is set to AUTO */ | ||
184 | u16 req_line_speed; /* Also determine AutoNeg */ | ||
185 | |||
186 | /* Device parameters */ | 194 | /* Device parameters */ |
187 | u8 mac_addr[6]; | 195 | u8 mac_addr[6]; |
188 | 196 | ||
197 | u16 req_duplex[LINK_CONFIG_SIZE]; | ||
198 | u16 req_flow_ctrl[LINK_CONFIG_SIZE]; | ||
199 | |||
200 | u16 req_line_speed[LINK_CONFIG_SIZE]; /* Also determine AutoNeg */ | ||
201 | |||
189 | /* shmem parameters */ | 202 | /* shmem parameters */ |
190 | u32 shmem_base; | 203 | u32 shmem_base; |
191 | u32 speed_cap_mask; | 204 | u32 shmem2_base; |
205 | u32 speed_cap_mask[LINK_CONFIG_SIZE]; | ||
192 | u32 switch_cfg; | 206 | u32 switch_cfg; |
193 | #define SWITCH_CFG_1G PORT_FEATURE_CON_SWITCH_1G_SWITCH | 207 | #define SWITCH_CFG_1G PORT_FEATURE_CON_SWITCH_1G_SWITCH |
194 | #define SWITCH_CFG_10G PORT_FEATURE_CON_SWITCH_10G_SWITCH | 208 | #define SWITCH_CFG_10G PORT_FEATURE_CON_SWITCH_10G_SWITCH |
@@ -202,6 +216,7 @@ struct link_params { | |||
202 | u32 feature_config_flags; | 216 | u32 feature_config_flags; |
203 | #define FEATURE_CONFIG_OVERRIDE_PREEMPHASIS_ENABLED (1<<0) | 217 | #define FEATURE_CONFIG_OVERRIDE_PREEMPHASIS_ENABLED (1<<0) |
204 | #define FEATURE_CONFIG_BC_SUPPORTS_OPT_MDL_VRFY (1<<2) | 218 | #define FEATURE_CONFIG_BC_SUPPORTS_OPT_MDL_VRFY (1<<2) |
219 | #define FEATURE_CONFIG_BC_SUPPORTS_DUAL_PHY_OPT_MDL_VRFY (1<<3) | ||
205 | /* Will be populated during common init */ | 220 | /* Will be populated during common init */ |
206 | struct bnx2x_phy phy[MAX_PHYS]; | 221 | struct bnx2x_phy phy[MAX_PHYS]; |
207 | 222 | ||
@@ -210,9 +225,12 @@ struct link_params { | |||
210 | 225 | ||
211 | u8 rsrv; | 226 | u8 rsrv; |
212 | u16 hw_led_mode; /* part of the hw_config read from the shmem */ | 227 | u16 hw_led_mode; /* part of the hw_config read from the shmem */ |
228 | u32 multi_phy_config; | ||
213 | 229 | ||
214 | /* Device pointer passed to all callback functions */ | 230 | /* Device pointer passed to all callback functions */ |
215 | struct bnx2x *bp; | 231 | struct bnx2x *bp; |
232 | u16 req_fc_auto_adv; /* Should be set to TX / BOTH when | ||
233 | req_flow_ctrl is set to AUTO */ | ||
216 | }; | 234 | }; |
217 | 235 | ||
218 | /* Output parameters */ | 236 | /* Output parameters */ |
@@ -233,12 +251,6 @@ struct link_vars { | |||
233 | u16 flow_ctrl; | 251 | u16 flow_ctrl; |
234 | u16 ieee_fc; | 252 | u16 ieee_fc; |
235 | 253 | ||
236 | u32 autoneg; | ||
237 | #define AUTO_NEG_DISABLED 0x0 | ||
238 | #define AUTO_NEG_ENABLED 0x1 | ||
239 | #define AUTO_NEG_COMPLETE 0x2 | ||
240 | #define AUTO_NEG_PARALLEL_DETECTION_USED 0x3 | ||
241 | |||
242 | /* The same definitions as the shmem parameter */ | 254 | /* The same definitions as the shmem parameter */ |
243 | u32 link_status; | 255 | u32 link_status; |
244 | }; | 256 | }; |
@@ -246,8 +258,6 @@ struct link_vars { | |||
246 | /***********************************************************/ | 258 | /***********************************************************/ |
247 | /* Functions */ | 259 | /* Functions */ |
248 | /***********************************************************/ | 260 | /***********************************************************/ |
249 | |||
250 | /* Initialize the phy */ | ||
251 | u8 bnx2x_phy_init(struct link_params *input, struct link_vars *output); | 261 | u8 bnx2x_phy_init(struct link_params *input, struct link_vars *output); |
252 | 262 | ||
253 | /* Reset the link. Should be called when driver or interface goes down | 263 | /* Reset the link. Should be called when driver or interface goes down |
@@ -298,10 +308,11 @@ void bnx2x_handle_module_detect_int(struct link_params *params); | |||
298 | 308 | ||
299 | /* Get the actual link status. In case it returns 0, link is up, | 309 | /* Get the actual link status. In case it returns 0, link is up, |
300 | otherwise link is down*/ | 310 | otherwise link is down*/ |
301 | u8 bnx2x_test_link(struct link_params *input, struct link_vars *vars); | 311 | u8 bnx2x_test_link(struct link_params *input, struct link_vars *vars, |
312 | u8 is_serdes); | ||
302 | 313 | ||
303 | /* One-time initialization for external phy after power up */ | 314 | /* One-time initialization for external phy after power up */ |
304 | u8 bnx2x_common_init_phy(struct bnx2x *bp, u32 shmem_base); | 315 | u8 bnx2x_common_init_phy(struct bnx2x *bp, u32 shmem_base, u32 shmem2_base); |
305 | 316 | ||
306 | /* Reset the external PHY using GPIO */ | 317 | /* Reset the external PHY using GPIO */ |
307 | void bnx2x_ext_phy_hw_reset(struct bnx2x *bp, u8 port); | 318 | void bnx2x_ext_phy_hw_reset(struct bnx2x *bp, u8 port); |
@@ -316,12 +327,19 @@ u8 bnx2x_read_sfp_module_eeprom(struct bnx2x_phy *phy, | |||
316 | void bnx2x_hw_reset_phy(struct link_params *params); | 327 | void bnx2x_hw_reset_phy(struct link_params *params); |
317 | 328 | ||
318 | /* Checks if HW lock is required for this phy/board type */ | 329 | /* Checks if HW lock is required for this phy/board type */ |
319 | u8 bnx2x_hw_lock_required(struct bnx2x *bp, u32 shmem_base); | 330 | u8 bnx2x_hw_lock_required(struct bnx2x *bp, u32 shmem_base, |
331 | u32 shmem2_base); | ||
332 | |||
320 | /* Returns the aggregative supported attributes of the phys on board */ | 333 | /* Returns the aggregative supported attributes of the phys on board */ |
321 | u32 bnx2x_supported_attr(struct link_params *params, u8 phy_idx); | 334 | u32 bnx2x_supported_attr(struct link_params *params, u8 phy_idx); |
335 | |||
336 | /* Check swap bit and adjust PHY order */ | ||
337 | u32 bnx2x_phy_selection(struct link_params *params); | ||
338 | |||
322 | /* Probe the phys on board, and populate them in "params" */ | 339 | /* Probe the phys on board, and populate them in "params" */ |
323 | u8 bnx2x_phy_probe(struct link_params *params); | 340 | u8 bnx2x_phy_probe(struct link_params *params); |
324 | /* Checks if fan failure detection is required on one of the phys on board */ | 341 | /* Checks if fan failure detection is required on one of the phys on board */ |
325 | u8 bnx2x_fan_failure_det_req(struct bnx2x *bp, u32 shmem_base, u8 port); | 342 | u8 bnx2x_fan_failure_det_req(struct bnx2x *bp, u32 shmem_base, |
343 | u32 shmem2_base, u8 port); | ||
326 | 344 | ||
327 | #endif /* BNX2X_LINK_H */ | 345 | #endif /* BNX2X_LINK_H */ |
diff --git a/drivers/net/bnx2x/bnx2x_main.c b/drivers/net/bnx2x/bnx2x_main.c index 30618c7ed4ed..f0a788467fb1 100644 --- a/drivers/net/bnx2x/bnx2x_main.c +++ b/drivers/net/bnx2x/bnx2x_main.c | |||
@@ -1227,26 +1227,66 @@ static int bnx2x_set_spio(struct bnx2x *bp, int spio_num, u32 mode) | |||
1227 | return 0; | 1227 | return 0; |
1228 | } | 1228 | } |
1229 | 1229 | ||
1230 | int bnx2x_get_link_cfg_idx(struct bnx2x *bp) | ||
1231 | { | ||
1232 | u32 sel_phy_idx = 0; | ||
1233 | if (bp->link_vars.link_up) { | ||
1234 | sel_phy_idx = EXT_PHY1; | ||
1235 | /* In case link is SERDES, check if the EXT_PHY2 is the one */ | ||
1236 | if ((bp->link_vars.link_status & LINK_STATUS_SERDES_LINK) && | ||
1237 | (bp->link_params.phy[EXT_PHY2].supported & SUPPORTED_FIBRE)) | ||
1238 | sel_phy_idx = EXT_PHY2; | ||
1239 | } else { | ||
1240 | |||
1241 | switch (bnx2x_phy_selection(&bp->link_params)) { | ||
1242 | case PORT_HW_CFG_PHY_SELECTION_HARDWARE_DEFAULT: | ||
1243 | case PORT_HW_CFG_PHY_SELECTION_FIRST_PHY: | ||
1244 | case PORT_HW_CFG_PHY_SELECTION_FIRST_PHY_PRIORITY: | ||
1245 | sel_phy_idx = EXT_PHY1; | ||
1246 | break; | ||
1247 | case PORT_HW_CFG_PHY_SELECTION_SECOND_PHY: | ||
1248 | case PORT_HW_CFG_PHY_SELECTION_SECOND_PHY_PRIORITY: | ||
1249 | sel_phy_idx = EXT_PHY2; | ||
1250 | break; | ||
1251 | } | ||
1252 | } | ||
1253 | /* | ||
1254 | * The selected actived PHY is always after swapping (in case PHY | ||
1255 | * swapping is enabled). So when swapping is enabled, we need to reverse | ||
1256 | * the configuration | ||
1257 | */ | ||
1258 | |||
1259 | if (bp->link_params.multi_phy_config & | ||
1260 | PORT_HW_CFG_PHY_SWAPPED_ENABLED) { | ||
1261 | if (sel_phy_idx == EXT_PHY1) | ||
1262 | sel_phy_idx = EXT_PHY2; | ||
1263 | else if (sel_phy_idx == EXT_PHY2) | ||
1264 | sel_phy_idx = EXT_PHY1; | ||
1265 | } | ||
1266 | return LINK_CONFIG_IDX(sel_phy_idx); | ||
1267 | } | ||
1268 | |||
1230 | void bnx2x_calc_fc_adv(struct bnx2x *bp) | 1269 | void bnx2x_calc_fc_adv(struct bnx2x *bp) |
1231 | { | 1270 | { |
1271 | u8 cfg_idx = bnx2x_get_link_cfg_idx(bp); | ||
1232 | switch (bp->link_vars.ieee_fc & | 1272 | switch (bp->link_vars.ieee_fc & |
1233 | MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_MASK) { | 1273 | MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_MASK) { |
1234 | case MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_NONE: | 1274 | case MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_NONE: |
1235 | bp->port.advertising &= ~(ADVERTISED_Asym_Pause | | 1275 | bp->port.advertising[cfg_idx] &= ~(ADVERTISED_Asym_Pause | |
1236 | ADVERTISED_Pause); | 1276 | ADVERTISED_Pause); |
1237 | break; | 1277 | break; |
1238 | 1278 | ||
1239 | case MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH: | 1279 | case MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH: |
1240 | bp->port.advertising |= (ADVERTISED_Asym_Pause | | 1280 | bp->port.advertising[cfg_idx] |= (ADVERTISED_Asym_Pause | |
1241 | ADVERTISED_Pause); | 1281 | ADVERTISED_Pause); |
1242 | break; | 1282 | break; |
1243 | 1283 | ||
1244 | case MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC: | 1284 | case MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC: |
1245 | bp->port.advertising |= ADVERTISED_Asym_Pause; | 1285 | bp->port.advertising[cfg_idx] |= ADVERTISED_Asym_Pause; |
1246 | break; | 1286 | break; |
1247 | 1287 | ||
1248 | default: | 1288 | default: |
1249 | bp->port.advertising &= ~(ADVERTISED_Asym_Pause | | 1289 | bp->port.advertising[cfg_idx] &= ~(ADVERTISED_Asym_Pause | |
1250 | ADVERTISED_Pause); | 1290 | ADVERTISED_Pause); |
1251 | break; | 1291 | break; |
1252 | } | 1292 | } |
@@ -1257,7 +1297,8 @@ u8 bnx2x_initial_phy_init(struct bnx2x *bp, int load_mode) | |||
1257 | { | 1297 | { |
1258 | if (!BP_NOMCP(bp)) { | 1298 | if (!BP_NOMCP(bp)) { |
1259 | u8 rc; | 1299 | u8 rc; |
1260 | 1300 | int cfx_idx = bnx2x_get_link_cfg_idx(bp); | |
1301 | u16 req_line_speed = bp->link_params.req_line_speed[cfx_idx]; | ||
1261 | /* Initialize link parameters structure variables */ | 1302 | /* Initialize link parameters structure variables */ |
1262 | /* It is recommended to turn off RX FC for jumbo frames | 1303 | /* It is recommended to turn off RX FC for jumbo frames |
1263 | for better performance */ | 1304 | for better performance */ |
@@ -1268,8 +1309,10 @@ u8 bnx2x_initial_phy_init(struct bnx2x *bp, int load_mode) | |||
1268 | 1309 | ||
1269 | bnx2x_acquire_phy_lock(bp); | 1310 | bnx2x_acquire_phy_lock(bp); |
1270 | 1311 | ||
1271 | if (load_mode == LOAD_DIAG) | 1312 | if (load_mode == LOAD_DIAG) { |
1272 | bp->link_params.loopback_mode = LOOPBACK_XGXS; | 1313 | bp->link_params.loopback_mode = LOOPBACK_XGXS; |
1314 | bp->link_params.req_line_speed[cfx_idx] = SPEED_10000; | ||
1315 | } | ||
1273 | 1316 | ||
1274 | rc = bnx2x_phy_init(&bp->link_params, &bp->link_vars); | 1317 | rc = bnx2x_phy_init(&bp->link_params, &bp->link_vars); |
1275 | 1318 | ||
@@ -1281,7 +1324,7 @@ u8 bnx2x_initial_phy_init(struct bnx2x *bp, int load_mode) | |||
1281 | bnx2x_stats_handle(bp, STATS_EVENT_LINK_UP); | 1324 | bnx2x_stats_handle(bp, STATS_EVENT_LINK_UP); |
1282 | bnx2x_link_report(bp); | 1325 | bnx2x_link_report(bp); |
1283 | } | 1326 | } |
1284 | 1327 | bp->link_params.req_line_speed[cfx_idx] = req_line_speed; | |
1285 | return rc; | 1328 | return rc; |
1286 | } | 1329 | } |
1287 | BNX2X_ERR("Bootcode is missing - can not initialize link\n"); | 1330 | BNX2X_ERR("Bootcode is missing - can not initialize link\n"); |
@@ -1311,13 +1354,14 @@ static void bnx2x__link_reset(struct bnx2x *bp) | |||
1311 | BNX2X_ERR("Bootcode is missing - can not reset link\n"); | 1354 | BNX2X_ERR("Bootcode is missing - can not reset link\n"); |
1312 | } | 1355 | } |
1313 | 1356 | ||
1314 | u8 bnx2x_link_test(struct bnx2x *bp) | 1357 | u8 bnx2x_link_test(struct bnx2x *bp, u8 is_serdes) |
1315 | { | 1358 | { |
1316 | u8 rc = 0; | 1359 | u8 rc = 0; |
1317 | 1360 | ||
1318 | if (!BP_NOMCP(bp)) { | 1361 | if (!BP_NOMCP(bp)) { |
1319 | bnx2x_acquire_phy_lock(bp); | 1362 | bnx2x_acquire_phy_lock(bp); |
1320 | rc = bnx2x_test_link(&bp->link_params, &bp->link_vars); | 1363 | rc = bnx2x_test_link(&bp->link_params, &bp->link_vars, |
1364 | is_serdes); | ||
1321 | bnx2x_release_phy_lock(bp); | 1365 | bnx2x_release_phy_lock(bp); |
1322 | } else | 1366 | } else |
1323 | BNX2X_ERR("Bootcode is missing - can not test link\n"); | 1367 | BNX2X_ERR("Bootcode is missing - can not test link\n"); |
@@ -1586,7 +1630,7 @@ static void bnx2x_pmf_update(struct bnx2x *bp) | |||
1586 | */ | 1630 | */ |
1587 | 1631 | ||
1588 | /* send the MCP a request, block until there is a reply */ | 1632 | /* send the MCP a request, block until there is a reply */ |
1589 | u32 bnx2x_fw_command(struct bnx2x *bp, u32 command) | 1633 | u32 bnx2x_fw_command(struct bnx2x *bp, u32 command, u32 param) |
1590 | { | 1634 | { |
1591 | int func = BP_FUNC(bp); | 1635 | int func = BP_FUNC(bp); |
1592 | u32 seq = ++bp->fw_seq; | 1636 | u32 seq = ++bp->fw_seq; |
@@ -1595,6 +1639,7 @@ u32 bnx2x_fw_command(struct bnx2x *bp, u32 command) | |||
1595 | u8 delay = CHIP_REV_IS_SLOW(bp) ? 100 : 10; | 1639 | u8 delay = CHIP_REV_IS_SLOW(bp) ? 100 : 10; |
1596 | 1640 | ||
1597 | mutex_lock(&bp->fw_mb_mutex); | 1641 | mutex_lock(&bp->fw_mb_mutex); |
1642 | SHMEM_WR(bp, func_mb[func].drv_mb_param, param); | ||
1598 | SHMEM_WR(bp, func_mb[func].drv_mb_header, (command | seq)); | 1643 | SHMEM_WR(bp, func_mb[func].drv_mb_header, (command | seq)); |
1599 | DP(BNX2X_MSG_MCP, "wrote command (%x) to FW MB\n", (command | seq)); | 1644 | DP(BNX2X_MSG_MCP, "wrote command (%x) to FW MB\n", (command | seq)); |
1600 | 1645 | ||
@@ -1716,9 +1761,9 @@ static void bnx2x_dcc_event(struct bnx2x *bp, u32 dcc_event) | |||
1716 | 1761 | ||
1717 | /* Report results to MCP */ | 1762 | /* Report results to MCP */ |
1718 | if (dcc_event) | 1763 | if (dcc_event) |
1719 | bnx2x_fw_command(bp, DRV_MSG_CODE_DCC_FAILURE); | 1764 | bnx2x_fw_command(bp, DRV_MSG_CODE_DCC_FAILURE, 0); |
1720 | else | 1765 | else |
1721 | bnx2x_fw_command(bp, DRV_MSG_CODE_DCC_OK); | 1766 | bnx2x_fw_command(bp, DRV_MSG_CODE_DCC_OK, 0); |
1722 | } | 1767 | } |
1723 | 1768 | ||
1724 | /* must be called under the spq lock */ | 1769 | /* must be called under the spq lock */ |
@@ -3848,6 +3893,7 @@ static void bnx2x_setup_fan_failure_detection(struct bnx2x *bp) | |||
3848 | bnx2x_fan_failure_det_req( | 3893 | bnx2x_fan_failure_det_req( |
3849 | bp, | 3894 | bp, |
3850 | bp->common.shmem_base, | 3895 | bp->common.shmem_base, |
3896 | bp->common.shmem2_base, | ||
3851 | port); | 3897 | port); |
3852 | } | 3898 | } |
3853 | 3899 | ||
@@ -4116,7 +4162,8 @@ static int bnx2x_init_common(struct bnx2x *bp) | |||
4116 | } | 4162 | } |
4117 | 4163 | ||
4118 | bp->port.need_hw_lock = bnx2x_hw_lock_required(bp, | 4164 | bp->port.need_hw_lock = bnx2x_hw_lock_required(bp, |
4119 | bp->common.shmem_base); | 4165 | bp->common.shmem_base, |
4166 | bp->common.shmem2_base); | ||
4120 | 4167 | ||
4121 | bnx2x_setup_fan_failure_detection(bp); | 4168 | bnx2x_setup_fan_failure_detection(bp); |
4122 | 4169 | ||
@@ -4129,7 +4176,8 @@ static int bnx2x_init_common(struct bnx2x *bp) | |||
4129 | 4176 | ||
4130 | if (!BP_NOMCP(bp)) { | 4177 | if (!BP_NOMCP(bp)) { |
4131 | bnx2x_acquire_phy_lock(bp); | 4178 | bnx2x_acquire_phy_lock(bp); |
4132 | bnx2x_common_init_phy(bp, bp->common.shmem_base); | 4179 | bnx2x_common_init_phy(bp, bp->common.shmem_base, |
4180 | bp->common.shmem2_base); | ||
4133 | bnx2x_release_phy_lock(bp); | 4181 | bnx2x_release_phy_lock(bp); |
4134 | } else | 4182 | } else |
4135 | BNX2X_ERR("Bootcode is missing - can not initialize link\n"); | 4183 | BNX2X_ERR("Bootcode is missing - can not initialize link\n"); |
@@ -4265,10 +4313,10 @@ static int bnx2x_init_port(struct bnx2x *bp) | |||
4265 | bnx2x_init_block(bp, MCP_BLOCK, init_stage); | 4313 | bnx2x_init_block(bp, MCP_BLOCK, init_stage); |
4266 | bnx2x_init_block(bp, DMAE_BLOCK, init_stage); | 4314 | bnx2x_init_block(bp, DMAE_BLOCK, init_stage); |
4267 | bp->port.need_hw_lock = bnx2x_hw_lock_required(bp, | 4315 | bp->port.need_hw_lock = bnx2x_hw_lock_required(bp, |
4268 | bp->common.shmem_base); | 4316 | bp->common.shmem_base, |
4269 | 4317 | bp->common.shmem2_base); | |
4270 | if (bnx2x_fan_failure_det_req(bp, bp->common.shmem_base, | 4318 | if (bnx2x_fan_failure_det_req(bp, bp->common.shmem_base, |
4271 | port)) { | 4319 | bp->common.shmem2_base, port)) { |
4272 | u32 reg_addr = (port ? MISC_REG_AEU_ENABLE1_FUNC_1_OUT_0 : | 4320 | u32 reg_addr = (port ? MISC_REG_AEU_ENABLE1_FUNC_1_OUT_0 : |
4273 | MISC_REG_AEU_ENABLE1_FUNC_0_OUT_0); | 4321 | MISC_REG_AEU_ENABLE1_FUNC_0_OUT_0); |
4274 | val = REG_RD(bp, reg_addr); | 4322 | val = REG_RD(bp, reg_addr); |
@@ -5226,7 +5274,7 @@ void bnx2x_chip_cleanup(struct bnx2x *bp, int unload_mode) | |||
5226 | 5274 | ||
5227 | unload_error: | 5275 | unload_error: |
5228 | if (!BP_NOMCP(bp)) | 5276 | if (!BP_NOMCP(bp)) |
5229 | reset_code = bnx2x_fw_command(bp, reset_code); | 5277 | reset_code = bnx2x_fw_command(bp, reset_code, 0); |
5230 | else { | 5278 | else { |
5231 | DP(NETIF_MSG_IFDOWN, "NO MCP - load counts %d, %d, %d\n", | 5279 | DP(NETIF_MSG_IFDOWN, "NO MCP - load counts %d, %d, %d\n", |
5232 | load_count[0], load_count[1], load_count[2]); | 5280 | load_count[0], load_count[1], load_count[2]); |
@@ -5251,7 +5299,7 @@ unload_error: | |||
5251 | 5299 | ||
5252 | /* Report UNLOAD_DONE to MCP */ | 5300 | /* Report UNLOAD_DONE to MCP */ |
5253 | if (!BP_NOMCP(bp)) | 5301 | if (!BP_NOMCP(bp)) |
5254 | bnx2x_fw_command(bp, DRV_MSG_CODE_UNLOAD_DONE); | 5302 | bnx2x_fw_command(bp, DRV_MSG_CODE_UNLOAD_DONE, 0); |
5255 | 5303 | ||
5256 | } | 5304 | } |
5257 | 5305 | ||
@@ -5816,13 +5864,14 @@ static void __devinit bnx2x_undi_unload(struct bnx2x *bp) | |||
5816 | bp->fw_seq = | 5864 | bp->fw_seq = |
5817 | (SHMEM_RD(bp, func_mb[bp->func].drv_mb_header) & | 5865 | (SHMEM_RD(bp, func_mb[bp->func].drv_mb_header) & |
5818 | DRV_MSG_SEQ_NUMBER_MASK); | 5866 | DRV_MSG_SEQ_NUMBER_MASK); |
5819 | reset_code = bnx2x_fw_command(bp, reset_code); | 5867 | reset_code = bnx2x_fw_command(bp, reset_code, 0); |
5820 | 5868 | ||
5821 | /* if UNDI is loaded on the other port */ | 5869 | /* if UNDI is loaded on the other port */ |
5822 | if (reset_code != FW_MSG_CODE_DRV_UNLOAD_COMMON) { | 5870 | if (reset_code != FW_MSG_CODE_DRV_UNLOAD_COMMON) { |
5823 | 5871 | ||
5824 | /* send "DONE" for previous unload */ | 5872 | /* send "DONE" for previous unload */ |
5825 | bnx2x_fw_command(bp, DRV_MSG_CODE_UNLOAD_DONE); | 5873 | bnx2x_fw_command(bp, |
5874 | DRV_MSG_CODE_UNLOAD_DONE, 0); | ||
5826 | 5875 | ||
5827 | /* unload UNDI on port 1 */ | 5876 | /* unload UNDI on port 1 */ |
5828 | bp->func = 1; | 5877 | bp->func = 1; |
@@ -5831,7 +5880,7 @@ static void __devinit bnx2x_undi_unload(struct bnx2x *bp) | |||
5831 | DRV_MSG_SEQ_NUMBER_MASK); | 5880 | DRV_MSG_SEQ_NUMBER_MASK); |
5832 | reset_code = DRV_MSG_CODE_UNLOAD_REQ_WOL_DIS; | 5881 | reset_code = DRV_MSG_CODE_UNLOAD_REQ_WOL_DIS; |
5833 | 5882 | ||
5834 | bnx2x_fw_command(bp, reset_code); | 5883 | bnx2x_fw_command(bp, reset_code, 0); |
5835 | } | 5884 | } |
5836 | 5885 | ||
5837 | /* now it's safe to release the lock */ | 5886 | /* now it's safe to release the lock */ |
@@ -5873,7 +5922,7 @@ static void __devinit bnx2x_undi_unload(struct bnx2x *bp) | |||
5873 | REG_WR(bp, NIG_REG_STRAP_OVERRIDE, swap_en); | 5922 | REG_WR(bp, NIG_REG_STRAP_OVERRIDE, swap_en); |
5874 | 5923 | ||
5875 | /* send unload done to the MCP */ | 5924 | /* send unload done to the MCP */ |
5876 | bnx2x_fw_command(bp, DRV_MSG_CODE_UNLOAD_DONE); | 5925 | bnx2x_fw_command(bp, DRV_MSG_CODE_UNLOAD_DONE, 0); |
5877 | 5926 | ||
5878 | /* restore our func and fw_seq */ | 5927 | /* restore our func and fw_seq */ |
5879 | bp->func = func; | 5928 | bp->func = func; |
@@ -5921,6 +5970,7 @@ static void __devinit bnx2x_get_common_hwinfo(struct bnx2x *bp) | |||
5921 | bp->common.shmem_base = REG_RD(bp, MISC_REG_SHARED_MEM_ADDR); | 5970 | bp->common.shmem_base = REG_RD(bp, MISC_REG_SHARED_MEM_ADDR); |
5922 | bp->common.shmem2_base = REG_RD(bp, MISC_REG_GENERIC_CR_0); | 5971 | bp->common.shmem2_base = REG_RD(bp, MISC_REG_GENERIC_CR_0); |
5923 | bp->link_params.shmem_base = bp->common.shmem_base; | 5972 | bp->link_params.shmem_base = bp->common.shmem_base; |
5973 | bp->link_params.shmem2_base = bp->common.shmem2_base; | ||
5924 | BNX2X_DEV_INFO("shmem offset 0x%x shmem2 offset 0x%x\n", | 5974 | BNX2X_DEV_INFO("shmem offset 0x%x shmem2 offset 0x%x\n", |
5925 | bp->common.shmem_base, bp->common.shmem2_base); | 5975 | bp->common.shmem_base, bp->common.shmem2_base); |
5926 | 5976 | ||
@@ -5963,8 +6013,11 @@ static void __devinit bnx2x_get_common_hwinfo(struct bnx2x *bp) | |||
5963 | "please upgrade BC\n", BNX2X_BC_VER, val); | 6013 | "please upgrade BC\n", BNX2X_BC_VER, val); |
5964 | } | 6014 | } |
5965 | bp->link_params.feature_config_flags |= | 6015 | bp->link_params.feature_config_flags |= |
5966 | (val >= REQ_BC_VER_4_VRFY_OPT_MDL) ? | 6016 | (val >= REQ_BC_VER_4_VRFY_FIRST_PHY_OPT_MDL) ? |
5967 | FEATURE_CONFIG_BC_SUPPORTS_OPT_MDL_VRFY : 0; | 6017 | FEATURE_CONFIG_BC_SUPPORTS_OPT_MDL_VRFY : 0; |
6018 | bp->link_params.feature_config_flags |= | ||
6019 | (val >= REQ_BC_VER_4_VRFY_SPECIFIC_PHY_OPT_MDL) ? | ||
6020 | FEATURE_CONFIG_BC_SUPPORTS_DUAL_PHY_OPT_MDL_VRFY : 0; | ||
5968 | 6021 | ||
5969 | if (BP_E1HVN(bp) == 0) { | 6022 | if (BP_E1HVN(bp) == 0) { |
5970 | pci_read_config_word(bp->pdev, bp->pm_cap + PCI_PM_PMC, &pmc); | 6023 | pci_read_config_word(bp->pdev, bp->pm_cap + PCI_PM_PMC, &pmc); |
@@ -5988,22 +6041,44 @@ static void __devinit bnx2x_get_common_hwinfo(struct bnx2x *bp) | |||
5988 | static void __devinit bnx2x_link_settings_supported(struct bnx2x *bp, | 6041 | static void __devinit bnx2x_link_settings_supported(struct bnx2x *bp, |
5989 | u32 switch_cfg) | 6042 | u32 switch_cfg) |
5990 | { | 6043 | { |
5991 | int port = BP_PORT(bp); | 6044 | int cfg_size = 0, idx, port = BP_PORT(bp); |
5992 | bp->port.supported = 0; | 6045 | |
6046 | /* Aggregation of supported attributes of all external phys */ | ||
6047 | bp->port.supported[0] = 0; | ||
6048 | bp->port.supported[1] = 0; | ||
5993 | switch (bp->link_params.num_phys) { | 6049 | switch (bp->link_params.num_phys) { |
5994 | case 1: | 6050 | case 1: |
5995 | bp->port.supported = bp->link_params.phy[INT_PHY].supported; | 6051 | bp->port.supported[0] = bp->link_params.phy[INT_PHY].supported; |
5996 | break; | 6052 | cfg_size = 1; |
6053 | break; | ||
5997 | case 2: | 6054 | case 2: |
5998 | bp->port.supported = bp->link_params.phy[EXT_PHY1].supported; | 6055 | bp->port.supported[0] = bp->link_params.phy[EXT_PHY1].supported; |
5999 | break; | 6056 | cfg_size = 1; |
6057 | break; | ||
6058 | case 3: | ||
6059 | if (bp->link_params.multi_phy_config & | ||
6060 | PORT_HW_CFG_PHY_SWAPPED_ENABLED) { | ||
6061 | bp->port.supported[1] = | ||
6062 | bp->link_params.phy[EXT_PHY1].supported; | ||
6063 | bp->port.supported[0] = | ||
6064 | bp->link_params.phy[EXT_PHY2].supported; | ||
6065 | } else { | ||
6066 | bp->port.supported[0] = | ||
6067 | bp->link_params.phy[EXT_PHY1].supported; | ||
6068 | bp->port.supported[1] = | ||
6069 | bp->link_params.phy[EXT_PHY2].supported; | ||
6070 | } | ||
6071 | cfg_size = 2; | ||
6072 | break; | ||
6000 | } | 6073 | } |
6001 | 6074 | ||
6002 | if (!(bp->port.supported)) { | 6075 | if (!(bp->port.supported[0] || bp->port.supported[1])) { |
6003 | BNX2X_ERR("NVRAM config error. BAD phy config." | 6076 | BNX2X_ERR("NVRAM config error. BAD phy config." |
6004 | "PHY1 config 0x%x\n", | 6077 | "PHY1 config 0x%x, PHY2 config 0x%x\n", |
6005 | SHMEM_RD(bp, | 6078 | SHMEM_RD(bp, |
6006 | dev_info.port_hw_config[port].external_phy_config)); | 6079 | dev_info.port_hw_config[port].external_phy_config), |
6080 | SHMEM_RD(bp, | ||
6081 | dev_info.port_hw_config[port].external_phy_config2)); | ||
6007 | return; | 6082 | return; |
6008 | } | 6083 | } |
6009 | 6084 | ||
@@ -6023,147 +6098,183 @@ static void __devinit bnx2x_link_settings_supported(struct bnx2x *bp, | |||
6023 | 6098 | ||
6024 | default: | 6099 | default: |
6025 | BNX2X_ERR("BAD switch_cfg link_config 0x%x\n", | 6100 | BNX2X_ERR("BAD switch_cfg link_config 0x%x\n", |
6026 | bp->port.link_config); | 6101 | bp->port.link_config[0]); |
6027 | return; | 6102 | return; |
6028 | } | 6103 | } |
6029 | /* mask what we support according to speed_cap_mask */ | 6104 | /* mask what we support according to speed_cap_mask per configuration */ |
6030 | if (!(bp->link_params.speed_cap_mask & | 6105 | for (idx = 0; idx < cfg_size; idx++) { |
6106 | if (!(bp->link_params.speed_cap_mask[idx] & | ||
6031 | PORT_HW_CFG_SPEED_CAPABILITY_D0_10M_HALF)) | 6107 | PORT_HW_CFG_SPEED_CAPABILITY_D0_10M_HALF)) |
6032 | bp->port.supported &= ~SUPPORTED_10baseT_Half; | 6108 | bp->port.supported[idx] &= ~SUPPORTED_10baseT_Half; |
6033 | 6109 | ||
6034 | if (!(bp->link_params.speed_cap_mask & | 6110 | if (!(bp->link_params.speed_cap_mask[idx] & |
6035 | PORT_HW_CFG_SPEED_CAPABILITY_D0_10M_FULL)) | 6111 | PORT_HW_CFG_SPEED_CAPABILITY_D0_10M_FULL)) |
6036 | bp->port.supported &= ~SUPPORTED_10baseT_Full; | 6112 | bp->port.supported[idx] &= ~SUPPORTED_10baseT_Full; |
6037 | 6113 | ||
6038 | if (!(bp->link_params.speed_cap_mask & | 6114 | if (!(bp->link_params.speed_cap_mask[idx] & |
6039 | PORT_HW_CFG_SPEED_CAPABILITY_D0_100M_HALF)) | 6115 | PORT_HW_CFG_SPEED_CAPABILITY_D0_100M_HALF)) |
6040 | bp->port.supported &= ~SUPPORTED_100baseT_Half; | 6116 | bp->port.supported[idx] &= ~SUPPORTED_100baseT_Half; |
6041 | 6117 | ||
6042 | if (!(bp->link_params.speed_cap_mask & | 6118 | if (!(bp->link_params.speed_cap_mask[idx] & |
6043 | PORT_HW_CFG_SPEED_CAPABILITY_D0_100M_FULL)) | 6119 | PORT_HW_CFG_SPEED_CAPABILITY_D0_100M_FULL)) |
6044 | bp->port.supported &= ~SUPPORTED_100baseT_Full; | 6120 | bp->port.supported[idx] &= ~SUPPORTED_100baseT_Full; |
6045 | 6121 | ||
6046 | if (!(bp->link_params.speed_cap_mask & | 6122 | if (!(bp->link_params.speed_cap_mask[idx] & |
6047 | PORT_HW_CFG_SPEED_CAPABILITY_D0_1G)) | 6123 | PORT_HW_CFG_SPEED_CAPABILITY_D0_1G)) |
6048 | bp->port.supported &= ~(SUPPORTED_1000baseT_Half | | 6124 | bp->port.supported[idx] &= ~(SUPPORTED_1000baseT_Half | |
6049 | SUPPORTED_1000baseT_Full); | 6125 | SUPPORTED_1000baseT_Full); |
6050 | 6126 | ||
6051 | if (!(bp->link_params.speed_cap_mask & | 6127 | if (!(bp->link_params.speed_cap_mask[idx] & |
6052 | PORT_HW_CFG_SPEED_CAPABILITY_D0_2_5G)) | 6128 | PORT_HW_CFG_SPEED_CAPABILITY_D0_2_5G)) |
6053 | bp->port.supported &= ~SUPPORTED_2500baseX_Full; | 6129 | bp->port.supported[idx] &= ~SUPPORTED_2500baseX_Full; |
6054 | 6130 | ||
6055 | if (!(bp->link_params.speed_cap_mask & | 6131 | if (!(bp->link_params.speed_cap_mask[idx] & |
6056 | PORT_HW_CFG_SPEED_CAPABILITY_D0_10G)) | 6132 | PORT_HW_CFG_SPEED_CAPABILITY_D0_10G)) |
6057 | bp->port.supported &= ~SUPPORTED_10000baseT_Full; | 6133 | bp->port.supported[idx] &= ~SUPPORTED_10000baseT_Full; |
6134 | |||
6135 | } | ||
6058 | 6136 | ||
6059 | BNX2X_DEV_INFO("supported 0x%x\n", bp->port.supported); | 6137 | BNX2X_DEV_INFO("supported 0x%x 0x%x\n", bp->port.supported[0], |
6138 | bp->port.supported[1]); | ||
6060 | } | 6139 | } |
6061 | 6140 | ||
6062 | static void __devinit bnx2x_link_settings_requested(struct bnx2x *bp) | 6141 | static void __devinit bnx2x_link_settings_requested(struct bnx2x *bp) |
6063 | { | 6142 | { |
6064 | bp->link_params.req_duplex = DUPLEX_FULL; | 6143 | u32 link_config, idx, cfg_size = 0; |
6065 | 6144 | bp->port.advertising[0] = 0; | |
6066 | switch (bp->port.link_config & PORT_FEATURE_LINK_SPEED_MASK) { | 6145 | bp->port.advertising[1] = 0; |
6146 | switch (bp->link_params.num_phys) { | ||
6147 | case 1: | ||
6148 | case 2: | ||
6149 | cfg_size = 1; | ||
6150 | break; | ||
6151 | case 3: | ||
6152 | cfg_size = 2; | ||
6153 | break; | ||
6154 | } | ||
6155 | for (idx = 0; idx < cfg_size; idx++) { | ||
6156 | bp->link_params.req_duplex[idx] = DUPLEX_FULL; | ||
6157 | link_config = bp->port.link_config[idx]; | ||
6158 | switch (link_config & PORT_FEATURE_LINK_SPEED_MASK) { | ||
6067 | case PORT_FEATURE_LINK_SPEED_AUTO: | 6159 | case PORT_FEATURE_LINK_SPEED_AUTO: |
6068 | if (bp->port.supported & SUPPORTED_Autoneg) { | 6160 | if (bp->port.supported[idx] & SUPPORTED_Autoneg) { |
6069 | bp->link_params.req_line_speed = SPEED_AUTO_NEG; | 6161 | bp->link_params.req_line_speed[idx] = |
6070 | bp->port.advertising = bp->port.supported; | 6162 | SPEED_AUTO_NEG; |
6163 | bp->port.advertising[idx] |= | ||
6164 | bp->port.supported[idx]; | ||
6071 | } else { | 6165 | } else { |
6072 | /* force 10G, no AN */ | 6166 | /* force 10G, no AN */ |
6073 | bp->link_params.req_line_speed = SPEED_10000; | 6167 | bp->link_params.req_line_speed[idx] = |
6074 | bp->port.advertising = (ADVERTISED_10000baseT_Full | | 6168 | SPEED_10000; |
6169 | bp->port.advertising[idx] |= | ||
6170 | (ADVERTISED_10000baseT_Full | | ||
6075 | ADVERTISED_FIBRE); | 6171 | ADVERTISED_FIBRE); |
6172 | continue; | ||
6076 | } | 6173 | } |
6077 | break; | 6174 | break; |
6078 | 6175 | ||
6079 | case PORT_FEATURE_LINK_SPEED_10M_FULL: | 6176 | case PORT_FEATURE_LINK_SPEED_10M_FULL: |
6080 | if (bp->port.supported & SUPPORTED_10baseT_Full) { | 6177 | if (bp->port.supported[idx] & SUPPORTED_10baseT_Full) { |
6081 | bp->link_params.req_line_speed = SPEED_10; | 6178 | bp->link_params.req_line_speed[idx] = |
6082 | bp->port.advertising = (ADVERTISED_10baseT_Full | | 6179 | SPEED_10; |
6180 | bp->port.advertising[idx] |= | ||
6181 | (ADVERTISED_10baseT_Full | | ||
6083 | ADVERTISED_TP); | 6182 | ADVERTISED_TP); |
6084 | } else { | 6183 | } else { |
6085 | BNX2X_ERROR("NVRAM config error. " | 6184 | BNX2X_ERROR("NVRAM config error. " |
6086 | "Invalid link_config 0x%x" | 6185 | "Invalid link_config 0x%x" |
6087 | " speed_cap_mask 0x%x\n", | 6186 | " speed_cap_mask 0x%x\n", |
6088 | bp->port.link_config, | 6187 | link_config, |
6089 | bp->link_params.speed_cap_mask); | 6188 | bp->link_params.speed_cap_mask[idx]); |
6090 | return; | 6189 | return; |
6091 | } | 6190 | } |
6092 | break; | 6191 | break; |
6093 | 6192 | ||
6094 | case PORT_FEATURE_LINK_SPEED_10M_HALF: | 6193 | case PORT_FEATURE_LINK_SPEED_10M_HALF: |
6095 | if (bp->port.supported & SUPPORTED_10baseT_Half) { | 6194 | if (bp->port.supported[idx] & SUPPORTED_10baseT_Half) { |
6096 | bp->link_params.req_line_speed = SPEED_10; | 6195 | bp->link_params.req_line_speed[idx] = |
6097 | bp->link_params.req_duplex = DUPLEX_HALF; | 6196 | SPEED_10; |
6098 | bp->port.advertising = (ADVERTISED_10baseT_Half | | 6197 | bp->link_params.req_duplex[idx] = |
6198 | DUPLEX_HALF; | ||
6199 | bp->port.advertising[idx] |= | ||
6200 | (ADVERTISED_10baseT_Half | | ||
6099 | ADVERTISED_TP); | 6201 | ADVERTISED_TP); |
6100 | } else { | 6202 | } else { |
6101 | BNX2X_ERROR("NVRAM config error. " | 6203 | BNX2X_ERROR("NVRAM config error. " |
6102 | "Invalid link_config 0x%x" | 6204 | "Invalid link_config 0x%x" |
6103 | " speed_cap_mask 0x%x\n", | 6205 | " speed_cap_mask 0x%x\n", |
6104 | bp->port.link_config, | 6206 | link_config, |
6105 | bp->link_params.speed_cap_mask); | 6207 | bp->link_params.speed_cap_mask[idx]); |
6106 | return; | 6208 | return; |
6107 | } | 6209 | } |
6108 | break; | 6210 | break; |
6109 | 6211 | ||
6110 | case PORT_FEATURE_LINK_SPEED_100M_FULL: | 6212 | case PORT_FEATURE_LINK_SPEED_100M_FULL: |
6111 | if (bp->port.supported & SUPPORTED_100baseT_Full) { | 6213 | if (bp->port.supported[idx] & SUPPORTED_100baseT_Full) { |
6112 | bp->link_params.req_line_speed = SPEED_100; | 6214 | bp->link_params.req_line_speed[idx] = |
6113 | bp->port.advertising = (ADVERTISED_100baseT_Full | | 6215 | SPEED_100; |
6216 | bp->port.advertising[idx] |= | ||
6217 | (ADVERTISED_100baseT_Full | | ||
6114 | ADVERTISED_TP); | 6218 | ADVERTISED_TP); |
6115 | } else { | 6219 | } else { |
6116 | BNX2X_ERROR("NVRAM config error. " | 6220 | BNX2X_ERROR("NVRAM config error. " |
6117 | "Invalid link_config 0x%x" | 6221 | "Invalid link_config 0x%x" |
6118 | " speed_cap_mask 0x%x\n", | 6222 | " speed_cap_mask 0x%x\n", |
6119 | bp->port.link_config, | 6223 | link_config, |
6120 | bp->link_params.speed_cap_mask); | 6224 | bp->link_params.speed_cap_mask[idx]); |
6121 | return; | 6225 | return; |
6122 | } | 6226 | } |
6123 | break; | 6227 | break; |
6124 | 6228 | ||
6125 | case PORT_FEATURE_LINK_SPEED_100M_HALF: | 6229 | case PORT_FEATURE_LINK_SPEED_100M_HALF: |
6126 | if (bp->port.supported & SUPPORTED_100baseT_Half) { | 6230 | if (bp->port.supported[idx] & SUPPORTED_100baseT_Half) { |
6127 | bp->link_params.req_line_speed = SPEED_100; | 6231 | bp->link_params.req_line_speed[idx] = SPEED_100; |
6128 | bp->link_params.req_duplex = DUPLEX_HALF; | 6232 | bp->link_params.req_duplex[idx] = DUPLEX_HALF; |
6129 | bp->port.advertising = (ADVERTISED_100baseT_Half | | 6233 | bp->port.advertising[idx] |= |
6234 | (ADVERTISED_100baseT_Half | | ||
6130 | ADVERTISED_TP); | 6235 | ADVERTISED_TP); |
6131 | } else { | 6236 | } else { |
6132 | BNX2X_ERROR("NVRAM config error. " | 6237 | BNX2X_ERROR("NVRAM config error. " |
6133 | "Invalid link_config 0x%x" | 6238 | "Invalid link_config 0x%x" |
6134 | " speed_cap_mask 0x%x\n", | 6239 | " speed_cap_mask 0x%x\n", |
6135 | bp->port.link_config, | 6240 | link_config, |
6136 | bp->link_params.speed_cap_mask); | 6241 | bp->link_params.speed_cap_mask[idx]); |
6137 | return; | 6242 | return; |
6138 | } | 6243 | } |
6139 | break; | 6244 | break; |
6140 | 6245 | ||
6141 | case PORT_FEATURE_LINK_SPEED_1G: | 6246 | case PORT_FEATURE_LINK_SPEED_1G: |
6142 | if (bp->port.supported & SUPPORTED_1000baseT_Full) { | 6247 | if (bp->port.supported[idx] & |
6143 | bp->link_params.req_line_speed = SPEED_1000; | 6248 | SUPPORTED_1000baseT_Full) { |
6144 | bp->port.advertising = (ADVERTISED_1000baseT_Full | | 6249 | bp->link_params.req_line_speed[idx] = |
6250 | SPEED_1000; | ||
6251 | bp->port.advertising[idx] |= | ||
6252 | (ADVERTISED_1000baseT_Full | | ||
6145 | ADVERTISED_TP); | 6253 | ADVERTISED_TP); |
6146 | } else { | 6254 | } else { |
6147 | BNX2X_ERROR("NVRAM config error. " | 6255 | BNX2X_ERROR("NVRAM config error. " |
6148 | "Invalid link_config 0x%x" | 6256 | "Invalid link_config 0x%x" |
6149 | " speed_cap_mask 0x%x\n", | 6257 | " speed_cap_mask 0x%x\n", |
6150 | bp->port.link_config, | 6258 | link_config, |
6151 | bp->link_params.speed_cap_mask); | 6259 | bp->link_params.speed_cap_mask[idx]); |
6152 | return; | 6260 | return; |
6153 | } | 6261 | } |
6154 | break; | 6262 | break; |
6155 | 6263 | ||
6156 | case PORT_FEATURE_LINK_SPEED_2_5G: | 6264 | case PORT_FEATURE_LINK_SPEED_2_5G: |
6157 | if (bp->port.supported & SUPPORTED_2500baseX_Full) { | 6265 | if (bp->port.supported[idx] & |
6158 | bp->link_params.req_line_speed = SPEED_2500; | 6266 | SUPPORTED_2500baseX_Full) { |
6159 | bp->port.advertising = (ADVERTISED_2500baseX_Full | | 6267 | bp->link_params.req_line_speed[idx] = |
6268 | SPEED_2500; | ||
6269 | bp->port.advertising[idx] |= | ||
6270 | (ADVERTISED_2500baseX_Full | | ||
6160 | ADVERTISED_TP); | 6271 | ADVERTISED_TP); |
6161 | } else { | 6272 | } else { |
6162 | BNX2X_ERROR("NVRAM config error. " | 6273 | BNX2X_ERROR("NVRAM config error. " |
6163 | "Invalid link_config 0x%x" | 6274 | "Invalid link_config 0x%x" |
6164 | " speed_cap_mask 0x%x\n", | 6275 | " speed_cap_mask 0x%x\n", |
6165 | bp->port.link_config, | 6276 | link_config, |
6166 | bp->link_params.speed_cap_mask); | 6277 | bp->link_params.speed_cap_mask[idx]); |
6167 | return; | 6278 | return; |
6168 | } | 6279 | } |
6169 | break; | 6280 | break; |
@@ -6171,16 +6282,19 @@ static void __devinit bnx2x_link_settings_requested(struct bnx2x *bp) | |||
6171 | case PORT_FEATURE_LINK_SPEED_10G_CX4: | 6282 | case PORT_FEATURE_LINK_SPEED_10G_CX4: |
6172 | case PORT_FEATURE_LINK_SPEED_10G_KX4: | 6283 | case PORT_FEATURE_LINK_SPEED_10G_KX4: |
6173 | case PORT_FEATURE_LINK_SPEED_10G_KR: | 6284 | case PORT_FEATURE_LINK_SPEED_10G_KR: |
6174 | if (bp->port.supported & SUPPORTED_10000baseT_Full) { | 6285 | if (bp->port.supported[idx] & |
6175 | bp->link_params.req_line_speed = SPEED_10000; | 6286 | SUPPORTED_10000baseT_Full) { |
6176 | bp->port.advertising = (ADVERTISED_10000baseT_Full | | 6287 | bp->link_params.req_line_speed[idx] = |
6288 | SPEED_10000; | ||
6289 | bp->port.advertising[idx] |= | ||
6290 | (ADVERTISED_10000baseT_Full | | ||
6177 | ADVERTISED_FIBRE); | 6291 | ADVERTISED_FIBRE); |
6178 | } else { | 6292 | } else { |
6179 | BNX2X_ERROR("NVRAM config error. " | 6293 | BNX2X_ERROR("NVRAM config error. " |
6180 | "Invalid link_config 0x%x" | 6294 | "Invalid link_config 0x%x" |
6181 | " speed_cap_mask 0x%x\n", | 6295 | " speed_cap_mask 0x%x\n", |
6182 | bp->port.link_config, | 6296 | link_config, |
6183 | bp->link_params.speed_cap_mask); | 6297 | bp->link_params.speed_cap_mask[idx]); |
6184 | return; | 6298 | return; |
6185 | } | 6299 | } |
6186 | break; | 6300 | break; |
@@ -6188,23 +6302,28 @@ static void __devinit bnx2x_link_settings_requested(struct bnx2x *bp) | |||
6188 | default: | 6302 | default: |
6189 | BNX2X_ERROR("NVRAM config error. " | 6303 | BNX2X_ERROR("NVRAM config error. " |
6190 | "BAD link speed link_config 0x%x\n", | 6304 | "BAD link speed link_config 0x%x\n", |
6191 | bp->port.link_config); | 6305 | link_config); |
6192 | bp->link_params.req_line_speed = SPEED_AUTO_NEG; | 6306 | bp->link_params.req_line_speed[idx] = SPEED_AUTO_NEG; |
6193 | bp->port.advertising = bp->port.supported; | 6307 | bp->port.advertising[idx] = bp->port.supported[idx]; |
6194 | break; | 6308 | break; |
6195 | } | 6309 | } |
6196 | 6310 | ||
6197 | bp->link_params.req_flow_ctrl = (bp->port.link_config & | 6311 | bp->link_params.req_flow_ctrl[idx] = (link_config & |
6198 | PORT_FEATURE_FLOW_CONTROL_MASK); | 6312 | PORT_FEATURE_FLOW_CONTROL_MASK); |
6199 | if ((bp->link_params.req_flow_ctrl == BNX2X_FLOW_CTRL_AUTO) && | 6313 | if ((bp->link_params.req_flow_ctrl[idx] == |
6200 | !(bp->port.supported & SUPPORTED_Autoneg)) | 6314 | BNX2X_FLOW_CTRL_AUTO) && |
6201 | bp->link_params.req_flow_ctrl = BNX2X_FLOW_CTRL_NONE; | 6315 | !(bp->port.supported[idx] & SUPPORTED_Autoneg)) { |
6316 | bp->link_params.req_flow_ctrl[idx] = | ||
6317 | BNX2X_FLOW_CTRL_NONE; | ||
6318 | } | ||
6202 | 6319 | ||
6203 | BNX2X_DEV_INFO("req_line_speed %d req_duplex %d req_flow_ctrl 0x%x" | 6320 | BNX2X_DEV_INFO("req_line_speed %d req_duplex %d req_flow_ctrl" |
6204 | " advertising 0x%x\n", | 6321 | " 0x%x advertising 0x%x\n", |
6205 | bp->link_params.req_line_speed, | 6322 | bp->link_params.req_line_speed[idx], |
6206 | bp->link_params.req_duplex, | 6323 | bp->link_params.req_duplex[idx], |
6207 | bp->link_params.req_flow_ctrl, bp->port.advertising); | 6324 | bp->link_params.req_flow_ctrl[idx], |
6325 | bp->port.advertising[idx]); | ||
6326 | } | ||
6208 | } | 6327 | } |
6209 | 6328 | ||
6210 | static void __devinit bnx2x_set_mac_buf(u8 *mac_buf, u32 mac_lo, u16 mac_hi) | 6329 | static void __devinit bnx2x_set_mac_buf(u8 *mac_buf, u32 mac_lo, u16 mac_hi) |
@@ -6228,14 +6347,20 @@ static void __devinit bnx2x_get_port_hwinfo(struct bnx2x *bp) | |||
6228 | bp->link_params.lane_config = | 6347 | bp->link_params.lane_config = |
6229 | SHMEM_RD(bp, dev_info.port_hw_config[port].lane_config); | 6348 | SHMEM_RD(bp, dev_info.port_hw_config[port].lane_config); |
6230 | 6349 | ||
6231 | bp->link_params.speed_cap_mask = | 6350 | bp->link_params.speed_cap_mask[0] = |
6232 | SHMEM_RD(bp, | 6351 | SHMEM_RD(bp, |
6233 | dev_info.port_hw_config[port].speed_capability_mask); | 6352 | dev_info.port_hw_config[port].speed_capability_mask); |
6234 | 6353 | bp->link_params.speed_cap_mask[1] = | |
6235 | bp->port.link_config = | 6354 | SHMEM_RD(bp, |
6355 | dev_info.port_hw_config[port].speed_capability_mask2); | ||
6356 | bp->port.link_config[0] = | ||
6236 | SHMEM_RD(bp, dev_info.port_feature_config[port].link_config); | 6357 | SHMEM_RD(bp, dev_info.port_feature_config[port].link_config); |
6237 | 6358 | ||
6359 | bp->port.link_config[1] = | ||
6360 | SHMEM_RD(bp, dev_info.port_feature_config[port].link_config2); | ||
6238 | 6361 | ||
6362 | bp->link_params.multi_phy_config = | ||
6363 | SHMEM_RD(bp, dev_info.port_hw_config[port].multi_phy_config); | ||
6239 | /* If the device is capable of WoL, set the default state according | 6364 | /* If the device is capable of WoL, set the default state according |
6240 | * to the HW | 6365 | * to the HW |
6241 | */ | 6366 | */ |
@@ -6244,11 +6369,12 @@ static void __devinit bnx2x_get_port_hwinfo(struct bnx2x *bp) | |||
6244 | (config & PORT_FEATURE_WOL_ENABLED)); | 6369 | (config & PORT_FEATURE_WOL_ENABLED)); |
6245 | 6370 | ||
6246 | BNX2X_DEV_INFO("lane_config 0x%08x" | 6371 | BNX2X_DEV_INFO("lane_config 0x%08x" |
6247 | " speed_cap_mask 0x%08x link_config 0x%08x\n", | 6372 | "speed_cap_mask0 0x%08x link_config0 0x%08x\n", |
6248 | bp->link_params.lane_config, | 6373 | bp->link_params.lane_config, |
6249 | bp->link_params.speed_cap_mask, bp->port.link_config); | 6374 | bp->link_params.speed_cap_mask[0], |
6375 | bp->port.link_config[0]); | ||
6250 | 6376 | ||
6251 | bp->link_params.switch_cfg |= (bp->port.link_config & | 6377 | bp->link_params.switch_cfg = (bp->port.link_config[0] & |
6252 | PORT_FEATURE_CONNECTED_SWITCH_MASK); | 6378 | PORT_FEATURE_CONNECTED_SWITCH_MASK); |
6253 | bnx2x_phy_probe(&bp->link_params); | 6379 | bnx2x_phy_probe(&bp->link_params); |
6254 | bnx2x_link_settings_supported(bp, bp->link_params.switch_cfg); | 6380 | bnx2x_link_settings_supported(bp, bp->link_params.switch_cfg); |
diff --git a/drivers/net/bnx2x/bnx2x_reg.h b/drivers/net/bnx2x/bnx2x_reg.h index 398cf55b8e10..f0a69563b66a 100644 --- a/drivers/net/bnx2x/bnx2x_reg.h +++ b/drivers/net/bnx2x/bnx2x_reg.h | |||
@@ -4964,6 +4964,8 @@ | |||
4964 | #define MDIO_SERDES_DIGITAL_A_1000X_CONTROL2_PRL_DT_EN 0x0001 | 4964 | #define MDIO_SERDES_DIGITAL_A_1000X_CONTROL2_PRL_DT_EN 0x0001 |
4965 | #define MDIO_SERDES_DIGITAL_A_1000X_CONTROL2_AN_FST_TMR 0x0040 | 4965 | #define MDIO_SERDES_DIGITAL_A_1000X_CONTROL2_AN_FST_TMR 0x0040 |
4966 | #define MDIO_SERDES_DIGITAL_A_1000X_STATUS1 0x14 | 4966 | #define MDIO_SERDES_DIGITAL_A_1000X_STATUS1 0x14 |
4967 | #define MDIO_SERDES_DIGITAL_A_1000X_STATUS1_SGMII 0x0001 | ||
4968 | #define MDIO_SERDES_DIGITAL_A_1000X_STATUS1_LINK 0x0002 | ||
4967 | #define MDIO_SERDES_DIGITAL_A_1000X_STATUS1_DUPLEX 0x0004 | 4969 | #define MDIO_SERDES_DIGITAL_A_1000X_STATUS1_DUPLEX 0x0004 |
4968 | #define MDIO_SERDES_DIGITAL_A_1000X_STATUS1_SPEED_MASK 0x0018 | 4970 | #define MDIO_SERDES_DIGITAL_A_1000X_STATUS1_SPEED_MASK 0x0018 |
4969 | #define MDIO_SERDES_DIGITAL_A_1000X_STATUS1_SPEED_SHIFT 3 | 4971 | #define MDIO_SERDES_DIGITAL_A_1000X_STATUS1_SPEED_SHIFT 3 |
@@ -5192,6 +5194,8 @@ Theotherbitsarereservedandshouldbezero*/ | |||
5192 | #define MDIO_XS_8706_REG_BANK_RX3 0x80ec | 5194 | #define MDIO_XS_8706_REG_BANK_RX3 0x80ec |
5193 | #define MDIO_XS_8706_REG_BANK_RXA 0x80fc | 5195 | #define MDIO_XS_8706_REG_BANK_RXA 0x80fc |
5194 | 5196 | ||
5197 | #define MDIO_XS_REG_8073_RX_CTRL_PCIE 0x80FA | ||
5198 | |||
5195 | #define MDIO_AN_DEVAD 0x7 | 5199 | #define MDIO_AN_DEVAD 0x7 |
5196 | /*ieee*/ | 5200 | /*ieee*/ |
5197 | #define MDIO_AN_REG_CTRL 0x0000 | 5201 | #define MDIO_AN_REG_CTRL 0x0000 |
@@ -5227,6 +5231,27 @@ Theotherbitsarereservedandshouldbezero*/ | |||
5227 | #define MDIO_AN_REG_8481_AUX_CTRL 0xfff8 | 5231 | #define MDIO_AN_REG_8481_AUX_CTRL 0xfff8 |
5228 | #define MDIO_AN_REG_8481_LEGACY_SHADOW 0xfffc | 5232 | #define MDIO_AN_REG_8481_LEGACY_SHADOW 0xfffc |
5229 | 5233 | ||
5234 | /* BCM84823 only */ | ||
5235 | #define MDIO_CTL_DEVAD 0x1e | ||
5236 | #define MDIO_CTL_REG_84823_MEDIA 0x401a | ||
5237 | #define MDIO_CTL_REG_84823_MEDIA_MAC_MASK 0x0018 | ||
5238 | /* These pins configure the BCM84823 interface to MAC after reset. */ | ||
5239 | #define MDIO_CTL_REG_84823_CTRL_MAC_XFI 0x0008 | ||
5240 | #define MDIO_CTL_REG_84823_MEDIA_MAC_XAUI_M 0x0010 | ||
5241 | /* These pins configure the BCM84823 interface to Line after reset. */ | ||
5242 | #define MDIO_CTL_REG_84823_MEDIA_LINE_MASK 0x0060 | ||
5243 | #define MDIO_CTL_REG_84823_MEDIA_LINE_XAUI_L 0x0020 | ||
5244 | #define MDIO_CTL_REG_84823_MEDIA_LINE_XFI 0x0040 | ||
5245 | /* When this pin is active high during reset, 10GBASE-T core is power | ||
5246 | * down, When it is active low the 10GBASE-T is power up | ||
5247 | */ | ||
5248 | #define MDIO_CTL_REG_84823_MEDIA_COPPER_CORE_DOWN 0x0080 | ||
5249 | #define MDIO_CTL_REG_84823_MEDIA_PRIORITY_MASK 0x0100 | ||
5250 | #define MDIO_CTL_REG_84823_MEDIA_PRIORITY_COPPER 0x0000 | ||
5251 | #define MDIO_CTL_REG_84823_MEDIA_PRIORITY_FIBER 0x0100 | ||
5252 | #define MDIO_CTL_REG_84823_MEDIA_FIBER_1G 0x1000 | ||
5253 | |||
5254 | |||
5230 | #define IGU_FUNC_BASE 0x0400 | 5255 | #define IGU_FUNC_BASE 0x0400 |
5231 | 5256 | ||
5232 | #define IGU_ADDR_MSIX 0x0000 | 5257 | #define IGU_ADDR_MSIX 0x0000 |