aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/bnx2x
diff options
context:
space:
mode:
authorYaniv Rosner <yaniv.rosner@broadcom.com>2010-09-07 07:41:20 -0400
committerDavid S. Miller <davem@davemloft.net>2010-09-07 16:15:42 -0400
commita22f078867ef362e35c54055878168e6613ff743 (patch)
tree2cf683f3057b7ed5dcaaaad16192f3a267dcf0f8 /drivers/net/bnx2x
parentde6eae1f42eae736548f293570fd867bd37c3bdd (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.h10
-rw-r--r--drivers/net/bnx2x/bnx2x_cmn.c14
-rw-r--r--drivers/net/bnx2x/bnx2x_cmn.h3
-rw-r--r--drivers/net/bnx2x/bnx2x_ethtool.c176
-rw-r--r--drivers/net/bnx2x/bnx2x_hsi.h111
-rw-r--r--drivers/net/bnx2x/bnx2x_link.c695
-rw-r--r--drivers/net/bnx2x/bnx2x_link.h62
-rw-r--r--drivers/net/bnx2x/bnx2x_main.c354
-rw-r--r--drivers/net/bnx2x/bnx2x_reg.h25
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 {
566struct bnx2x_port { 566struct 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,
931int bnx2x_get_gpio(struct bnx2x *bp, int gpio_num, u8 port); 931int bnx2x_get_gpio(struct bnx2x *bp, int gpio_num, u8 port);
932int bnx2x_set_gpio(struct bnx2x *bp, int gpio_num, u32 mode, u8 port); 932int bnx2x_set_gpio(struct bnx2x *bp, int gpio_num, u32 mode, u8 port);
933int bnx2x_set_gpio_int(struct bnx2x *bp, int gpio_num, u32 mode, u8 port); 933int bnx2x_set_gpio_int(struct bnx2x *bp, int gpio_num, u32 mode, u8 port);
934u32 bnx2x_fw_command(struct bnx2x *bp, u32 command); 934u32 bnx2x_fw_command(struct bnx2x *bp, u32 command, u32 param);
935void bnx2x_reg_wr_ind(struct bnx2x *bp, u32 addr, u32 val); 935void bnx2x_reg_wr_ind(struct bnx2x *bp, u32 addr, u32 val);
936void bnx2x_write_dmae_phys_len(struct bnx2x *bp, dma_addr_t phys_addr, 936void 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);
939int bnx2x_sp_post(struct bnx2x *bp, int command, int cid, 939int 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);
941void bnx2x_update_coalesce(struct bnx2x *bp); 941void bnx2x_update_coalesce(struct bnx2x *bp);
942 942int bnx2x_get_link_cfg_idx(struct bnx2x *bp);
943static inline u32 reg_poll(struct bnx2x *bp, u32 reg, u32 expected, int ms, 943static 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:
1455load_error3: 1455load_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 */
55u8 bnx2x_link_test(struct bnx2x *bp); 56u8 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 @@
29static int bnx2x_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) 29static 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)
85static int bnx2x_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) 87static 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
1253static void bnx2x_wait_for_link(struct bnx2x *bp, u8 link_up) 1317static 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
902void bnx2x_link_status_update(struct link_params *params, 903void 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
2167static void bnx2x_8481_rearm_latch_signal(struct bnx2x *bp, u8 port, 2160static 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
2203static void bnx2x_link_int_ack(struct link_params *params, 2195static 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
2291static u8 bnx2x_null_format_ver(u32 spirom_ver, u8 *str, u16 *len) 2285static 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
2553u8 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 */
2570u8 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, &params->phy[INT_PHY], 2578 CL45_RD_OVER_CL22(bp, &params->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 &params->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 &params->phy[phy_index], 2608 &params->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 &params->phy[phy_index], 2675 &params->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 &params->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
4220static 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
4095static u8 bnx2x_sfp_module_detection(struct bnx2x_phy *phy, 4241static 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
4975static u8 bnx2x_848xx_cmn_config_init(struct bnx2x_phy *phy, 5164static 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(&params->phy[INT_PHY], params, vars, 0);
5139 bnx2x_program_serdes(phy, params, vars); 5327 bnx2x_program_serdes(&params->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
5144static u8 bnx2x_848xx_read_status(struct bnx2x_phy *phy, 5377static 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
5432static struct bnx2x_phy phy_serdes = { 5666static 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
5467static struct bnx2x_phy phy_xgxs = { 5702static 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
5503static struct bnx2x_phy phy_7101 = { 5739static 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};
5532static struct bnx2x_phy phy_8073 = { 5769static 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};
5563static struct bnx2x_phy phy_8705 = { 5801static 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};
5591static struct bnx2x_phy phy_8706 = { 5830static 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
5621static struct bnx2x_phy phy_8726 = { 5861static 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
5653static struct bnx2x_phy phy_8727 = { 5894static 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};
5682static struct bnx2x_phy phy_8481 = { 5924static 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
5717static struct bnx2x_phy phy_84823 = { 5961static 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,
5844static u8 bnx2x_populate_ext_phy(struct bnx2x *bp, 6104static 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
5933static u8 bnx2x_populate_phy(struct bnx2x *bp, u8 phy_index, u32 shmem_base, 6209static 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
5945static void bnx2x_phy_def_cfg(struct link_params *params, 6221static 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
6291u32 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
6004u8 bnx2x_phy_probe(struct link_params *params) 6324u8 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 = &params->phy[actual_phy_idx]; 6348 phy = &params->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)
6049static void set_phy_vars(struct link_params *params) 6379static 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)
6078u8 bnx2x_phy_init(struct link_params *params, struct link_vars *vars) 6415u8 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/****************************************************************************/
6314static u8 bnx2x_8073_common_init_phy(struct bnx2x *bp, u32 shmem_base) 6653static 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
6422static u8 bnx2x_8726_common_init_phy(struct bnx2x *bp, u32 shmem_base) 6761static 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 6798static u8 bnx2x_8727_common_init_phy(struct bnx2x *bp, u32 shmem_base,
6459static 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
6531u8 bnx2x_common_init_phy(struct bnx2x *bp, u32 shmem_base) 6872static 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
6909u8 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
6572u8 bnx2x_hw_lock_required(struct bnx2x *bp, u32 shmem_base) 6934u8 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
6590u8 bnx2x_fan_failure_det_req(struct bnx2x *bp, 6952u8 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);
91typedef void (*hw_reset_t)(struct bnx2x_phy *phy, struct link_params *params); 96typedef void (*hw_reset_t)(struct bnx2x_phy *phy, struct link_params *params);
92typedef void (*set_link_led_t)(struct bnx2x_phy *phy, 97typedef void (*set_link_led_t)(struct bnx2x_phy *phy,
93 struct link_params *params, u8 mode); 98 struct link_params *params, u8 mode);
99typedef void (*phy_specific_func_t)(struct bnx2x_phy *phy,
100 struct link_params *params, u32 action);
94 101
95struct bnx2x_phy { 102struct 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 */
251u8 bnx2x_phy_init(struct link_params *input, struct link_vars *output); 261u8 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*/
301u8 bnx2x_test_link(struct link_params *input, struct link_vars *vars); 311u8 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 */
304u8 bnx2x_common_init_phy(struct bnx2x *bp, u32 shmem_base); 315u8 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 */
307void bnx2x_ext_phy_hw_reset(struct bnx2x *bp, u8 port); 318void bnx2x_ext_phy_hw_reset(struct bnx2x *bp, u8 port);
@@ -316,12 +327,19 @@ u8 bnx2x_read_sfp_module_eeprom(struct bnx2x_phy *phy,
316void bnx2x_hw_reset_phy(struct link_params *params); 327void 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 */
319u8 bnx2x_hw_lock_required(struct bnx2x *bp, u32 shmem_base); 330u8 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 */
321u32 bnx2x_supported_attr(struct link_params *params, u8 phy_idx); 334u32 bnx2x_supported_attr(struct link_params *params, u8 phy_idx);
335
336/* Check swap bit and adjust PHY order */
337u32 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" */
323u8 bnx2x_phy_probe(struct link_params *params); 340u8 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 */
325u8 bnx2x_fan_failure_det_req(struct bnx2x *bp, u32 shmem_base, u8 port); 342u8 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
1230int 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
1230void bnx2x_calc_fc_adv(struct bnx2x *bp) 1269void 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
1314u8 bnx2x_link_test(struct bnx2x *bp) 1357u8 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 */
1589u32 bnx2x_fw_command(struct bnx2x *bp, u32 command) 1633u32 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
5227unload_error: 5275unload_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)
5988static void __devinit bnx2x_link_settings_supported(struct bnx2x *bp, 6041static 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
6062static void __devinit bnx2x_link_settings_requested(struct bnx2x *bp) 6141static 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
6210static void __devinit bnx2x_set_mac_buf(u8 *mac_buf, u32 mac_lo, u16 mac_hi) 6329static 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