diff options
author | Eliezer Tamir <eliezert@broadcom.com> | 2008-02-28 14:51:50 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-02-28 14:51:50 -0500 |
commit | f14106478e372e64be54a3cdab1e2fa83a5c8a35 (patch) | |
tree | 5d66afdfdb0e9752e6ca13b28f6e61c4d8558e39 /drivers/net/bnx2x.c | |
parent | 250479504ff7d7e8c7d5cf85bedd40fb8d725429 (diff) |
[BNX2X]: Correct Link management
Properly protect PHY access between two devices on the same board with
a HW lock.
Use GPIO to clear all previous configurations before changing link
parameters.
Shut down the external PHY in case of fan failure.
Reducing the MDC/MDIO clock to 2.5MHz due to problems with some
devices.
Resolve the flow control response according to autoneg with external
PHY.
Unmasking all PHY interrupts in single write to prevent a race in the
interrupts order.
LASI indication fixes to work with peculiarities of PHYs.
Disable MAC RX to avoid a HW bug when closing the MAC under traffic.
Disable parallel detection on HiGig due to HW limitation.
Updating the shared memory structure to work with the current
bootcode.
Signed-off-by: Eliezer Tamir <eliezert@broadcom.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/bnx2x.c')
-rw-r--r-- | drivers/net/bnx2x.c | 1707 |
1 files changed, 1273 insertions, 434 deletions
diff --git a/drivers/net/bnx2x.c b/drivers/net/bnx2x.c index 77867161968b..5cd785064ba3 100644 --- a/drivers/net/bnx2x.c +++ b/drivers/net/bnx2x.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* bnx2x.c: Broadcom Everest network driver. | 1 | /* bnx2x.c: Broadcom Everest network driver. |
2 | * | 2 | * |
3 | * Copyright (c) 2007 Broadcom Corporation | 3 | * Copyright (c) 2007-2008 Broadcom Corporation |
4 | * | 4 | * |
5 | * This program is free software; you can redistribute it and/or modify | 5 | * This program is free software; you can redistribute it and/or modify |
6 | * it under the terms of the GNU General Public License as published by | 6 | * it under the terms of the GNU General Public License as published by |
@@ -65,7 +65,7 @@ | |||
65 | 65 | ||
66 | #define DRV_MODULE_VERSION "0.40.15" | 66 | #define DRV_MODULE_VERSION "0.40.15" |
67 | #define DRV_MODULE_RELDATE "$DateTime: 2007/11/15 07:28:37 $" | 67 | #define DRV_MODULE_RELDATE "$DateTime: 2007/11/15 07:28:37 $" |
68 | #define BNX2X_BC_VER 0x040009 | 68 | #define BNX2X_BC_VER 0x040200 |
69 | 69 | ||
70 | /* Time in jiffies before concluding the transmitter is hung. */ | 70 | /* Time in jiffies before concluding the transmitter is hung. */ |
71 | #define TX_TIMEOUT (5*HZ) | 71 | #define TX_TIMEOUT (5*HZ) |
@@ -78,7 +78,7 @@ MODULE_AUTHOR("Eliezer Tamir <eliezert@broadcom.com>"); | |||
78 | MODULE_DESCRIPTION("Broadcom NetXtreme II BCM57710 Driver"); | 78 | MODULE_DESCRIPTION("Broadcom NetXtreme II BCM57710 Driver"); |
79 | MODULE_LICENSE("GPL"); | 79 | MODULE_LICENSE("GPL"); |
80 | MODULE_VERSION(DRV_MODULE_VERSION); | 80 | MODULE_VERSION(DRV_MODULE_VERSION); |
81 | MODULE_INFO(cvs_version, "$Revision: #356 $"); | 81 | MODULE_INFO(cvs_version, "$Revision: #404 $"); |
82 | 82 | ||
83 | static int use_inta; | 83 | static int use_inta; |
84 | static int poll; | 84 | static int poll; |
@@ -1181,12 +1181,175 @@ static u32 bnx2x_bits_dis(struct bnx2x *bp, u32 reg, u32 bits) | |||
1181 | return val; | 1181 | return val; |
1182 | } | 1182 | } |
1183 | 1183 | ||
1184 | static int bnx2x_hw_lock(struct bnx2x *bp, u32 resource) | ||
1185 | { | ||
1186 | u32 cnt; | ||
1187 | u32 lock_status; | ||
1188 | u32 resource_bit = (1 << resource); | ||
1189 | u8 func = bp->port; | ||
1190 | |||
1191 | /* Validating that the resource is within range */ | ||
1192 | if (resource > HW_LOCK_MAX_RESOURCE_VALUE) { | ||
1193 | DP(NETIF_MSG_HW, | ||
1194 | "resource(0x%x) > HW_LOCK_MAX_RESOURCE_VALUE(0x%x)\n", | ||
1195 | resource, HW_LOCK_MAX_RESOURCE_VALUE); | ||
1196 | return -EINVAL; | ||
1197 | } | ||
1198 | |||
1199 | /* Validating that the resource is not already taken */ | ||
1200 | lock_status = REG_RD(bp, MISC_REG_DRIVER_CONTROL_1 + func*8); | ||
1201 | if (lock_status & resource_bit) { | ||
1202 | DP(NETIF_MSG_HW, "lock_status 0x%x resource_bit 0x%x\n", | ||
1203 | lock_status, resource_bit); | ||
1204 | return -EEXIST; | ||
1205 | } | ||
1206 | |||
1207 | /* Try for 1 second every 5ms */ | ||
1208 | for (cnt = 0; cnt < 200; cnt++) { | ||
1209 | /* Try to acquire the lock */ | ||
1210 | REG_WR(bp, MISC_REG_DRIVER_CONTROL_1 + func*8 + 4, | ||
1211 | resource_bit); | ||
1212 | lock_status = REG_RD(bp, MISC_REG_DRIVER_CONTROL_1 + func*8); | ||
1213 | if (lock_status & resource_bit) | ||
1214 | return 0; | ||
1215 | |||
1216 | msleep(5); | ||
1217 | } | ||
1218 | DP(NETIF_MSG_HW, "Timeout\n"); | ||
1219 | return -EAGAIN; | ||
1220 | } | ||
1221 | |||
1222 | static int bnx2x_hw_unlock(struct bnx2x *bp, u32 resource) | ||
1223 | { | ||
1224 | u32 lock_status; | ||
1225 | u32 resource_bit = (1 << resource); | ||
1226 | u8 func = bp->port; | ||
1227 | |||
1228 | /* Validating that the resource is within range */ | ||
1229 | if (resource > HW_LOCK_MAX_RESOURCE_VALUE) { | ||
1230 | DP(NETIF_MSG_HW, | ||
1231 | "resource(0x%x) > HW_LOCK_MAX_RESOURCE_VALUE(0x%x)\n", | ||
1232 | resource, HW_LOCK_MAX_RESOURCE_VALUE); | ||
1233 | return -EINVAL; | ||
1234 | } | ||
1235 | |||
1236 | /* Validating that the resource is currently taken */ | ||
1237 | lock_status = REG_RD(bp, MISC_REG_DRIVER_CONTROL_1 + func*8); | ||
1238 | if (!(lock_status & resource_bit)) { | ||
1239 | DP(NETIF_MSG_HW, "lock_status 0x%x resource_bit 0x%x\n", | ||
1240 | lock_status, resource_bit); | ||
1241 | return -EFAULT; | ||
1242 | } | ||
1243 | |||
1244 | REG_WR(bp, MISC_REG_DRIVER_CONTROL_1 + func*8, resource_bit); | ||
1245 | return 0; | ||
1246 | } | ||
1247 | |||
1248 | static int bnx2x_set_gpio(struct bnx2x *bp, int gpio_num, u32 mode) | ||
1249 | { | ||
1250 | /* The GPIO should be swapped if swap register is set and active */ | ||
1251 | int gpio_port = (REG_RD(bp, NIG_REG_PORT_SWAP) && | ||
1252 | REG_RD(bp, NIG_REG_STRAP_OVERRIDE)) ^ bp->port; | ||
1253 | int gpio_shift = gpio_num + | ||
1254 | (gpio_port ? MISC_REGISTERS_GPIO_PORT_SHIFT : 0); | ||
1255 | u32 gpio_mask = (1 << gpio_shift); | ||
1256 | u32 gpio_reg; | ||
1257 | |||
1258 | if (gpio_num > MISC_REGISTERS_GPIO_3) { | ||
1259 | BNX2X_ERR("Invalid GPIO %d\n", gpio_num); | ||
1260 | return -EINVAL; | ||
1261 | } | ||
1262 | |||
1263 | bnx2x_hw_lock(bp, HW_LOCK_RESOURCE_GPIO); | ||
1264 | /* read GPIO and mask except the float bits */ | ||
1265 | gpio_reg = (REG_RD(bp, MISC_REG_GPIO) & MISC_REGISTERS_GPIO_FLOAT); | ||
1266 | |||
1267 | switch (mode) { | ||
1268 | case MISC_REGISTERS_GPIO_OUTPUT_LOW: | ||
1269 | DP(NETIF_MSG_LINK, "Set GPIO %d (shift %d) -> output low\n", | ||
1270 | gpio_num, gpio_shift); | ||
1271 | /* clear FLOAT and set CLR */ | ||
1272 | gpio_reg &= ~(gpio_mask << MISC_REGISTERS_GPIO_FLOAT_POS); | ||
1273 | gpio_reg |= (gpio_mask << MISC_REGISTERS_GPIO_CLR_POS); | ||
1274 | break; | ||
1275 | |||
1276 | case MISC_REGISTERS_GPIO_OUTPUT_HIGH: | ||
1277 | DP(NETIF_MSG_LINK, "Set GPIO %d (shift %d) -> output high\n", | ||
1278 | gpio_num, gpio_shift); | ||
1279 | /* clear FLOAT and set SET */ | ||
1280 | gpio_reg &= ~(gpio_mask << MISC_REGISTERS_GPIO_FLOAT_POS); | ||
1281 | gpio_reg |= (gpio_mask << MISC_REGISTERS_GPIO_SET_POS); | ||
1282 | break; | ||
1283 | |||
1284 | case MISC_REGISTERS_GPIO_INPUT_HI_Z : | ||
1285 | DP(NETIF_MSG_LINK, "Set GPIO %d (shift %d) -> input\n", | ||
1286 | gpio_num, gpio_shift); | ||
1287 | /* set FLOAT */ | ||
1288 | gpio_reg |= (gpio_mask << MISC_REGISTERS_GPIO_FLOAT_POS); | ||
1289 | break; | ||
1290 | |||
1291 | default: | ||
1292 | break; | ||
1293 | } | ||
1294 | |||
1295 | REG_WR(bp, MISC_REG_GPIO, gpio_reg); | ||
1296 | bnx2x_hw_unlock(bp, HW_LOCK_RESOURCE_GPIO); | ||
1297 | |||
1298 | return 0; | ||
1299 | } | ||
1300 | |||
1301 | static int bnx2x_set_spio(struct bnx2x *bp, int spio_num, u32 mode) | ||
1302 | { | ||
1303 | u32 spio_mask = (1 << spio_num); | ||
1304 | u32 spio_reg; | ||
1305 | |||
1306 | if ((spio_num < MISC_REGISTERS_SPIO_4) || | ||
1307 | (spio_num > MISC_REGISTERS_SPIO_7)) { | ||
1308 | BNX2X_ERR("Invalid SPIO %d\n", spio_num); | ||
1309 | return -EINVAL; | ||
1310 | } | ||
1311 | |||
1312 | bnx2x_hw_lock(bp, HW_LOCK_RESOURCE_SPIO); | ||
1313 | /* read SPIO and mask except the float bits */ | ||
1314 | spio_reg = (REG_RD(bp, MISC_REG_SPIO) & MISC_REGISTERS_SPIO_FLOAT); | ||
1315 | |||
1316 | switch (mode) { | ||
1317 | case MISC_REGISTERS_SPIO_OUTPUT_LOW : | ||
1318 | DP(NETIF_MSG_LINK, "Set SPIO %d -> output low\n", spio_num); | ||
1319 | /* clear FLOAT and set CLR */ | ||
1320 | spio_reg &= ~(spio_mask << MISC_REGISTERS_SPIO_FLOAT_POS); | ||
1321 | spio_reg |= (spio_mask << MISC_REGISTERS_SPIO_CLR_POS); | ||
1322 | break; | ||
1323 | |||
1324 | case MISC_REGISTERS_SPIO_OUTPUT_HIGH : | ||
1325 | DP(NETIF_MSG_LINK, "Set SPIO %d -> output high\n", spio_num); | ||
1326 | /* clear FLOAT and set SET */ | ||
1327 | spio_reg &= ~(spio_mask << MISC_REGISTERS_SPIO_FLOAT_POS); | ||
1328 | spio_reg |= (spio_mask << MISC_REGISTERS_SPIO_SET_POS); | ||
1329 | break; | ||
1330 | |||
1331 | case MISC_REGISTERS_SPIO_INPUT_HI_Z: | ||
1332 | DP(NETIF_MSG_LINK, "Set SPIO %d -> input\n", spio_num); | ||
1333 | /* set FLOAT */ | ||
1334 | spio_reg |= (spio_mask << MISC_REGISTERS_SPIO_FLOAT_POS); | ||
1335 | break; | ||
1336 | |||
1337 | default: | ||
1338 | break; | ||
1339 | } | ||
1340 | |||
1341 | REG_WR(bp, MISC_REG_SPIO, spio_reg); | ||
1342 | bnx2x_hw_unlock(bp, HW_LOCK_RESOURCE_SPIO); | ||
1343 | |||
1344 | return 0; | ||
1345 | } | ||
1346 | |||
1184 | static int bnx2x_mdio22_write(struct bnx2x *bp, u32 reg, u32 val) | 1347 | static int bnx2x_mdio22_write(struct bnx2x *bp, u32 reg, u32 val) |
1185 | { | 1348 | { |
1186 | int rc; | ||
1187 | u32 tmp, i; | ||
1188 | int port = bp->port; | 1349 | int port = bp->port; |
1189 | u32 emac_base = port ? GRCBASE_EMAC1 : GRCBASE_EMAC0; | 1350 | u32 emac_base = port ? GRCBASE_EMAC1 : GRCBASE_EMAC0; |
1351 | u32 tmp; | ||
1352 | int i, rc; | ||
1190 | 1353 | ||
1191 | /* DP(NETIF_MSG_HW, "phy_addr 0x%x reg 0x%x val 0x%08x\n", | 1354 | /* DP(NETIF_MSG_HW, "phy_addr 0x%x reg 0x%x val 0x%08x\n", |
1192 | bp->phy_addr, reg, val); */ | 1355 | bp->phy_addr, reg, val); */ |
@@ -1238,8 +1401,8 @@ static int bnx2x_mdio22_read(struct bnx2x *bp, u32 reg, u32 *ret_val) | |||
1238 | { | 1401 | { |
1239 | int port = bp->port; | 1402 | int port = bp->port; |
1240 | u32 emac_base = port ? GRCBASE_EMAC1 : GRCBASE_EMAC0; | 1403 | u32 emac_base = port ? GRCBASE_EMAC1 : GRCBASE_EMAC0; |
1241 | u32 val, i; | 1404 | u32 val; |
1242 | int rc; | 1405 | int i, rc; |
1243 | 1406 | ||
1244 | if (bp->phy_flags & PHY_INT_MODE_AUTO_POLLING_FLAG) { | 1407 | if (bp->phy_flags & PHY_INT_MODE_AUTO_POLLING_FLAG) { |
1245 | 1408 | ||
@@ -1288,58 +1451,54 @@ static int bnx2x_mdio22_read(struct bnx2x *bp, u32 reg, u32 *ret_val) | |||
1288 | return rc; | 1451 | return rc; |
1289 | } | 1452 | } |
1290 | 1453 | ||
1291 | static int bnx2x_mdio45_write(struct bnx2x *bp, u32 reg, u32 addr, u32 val) | 1454 | static int bnx2x_mdio45_ctrl_write(struct bnx2x *bp, u32 mdio_ctrl, |
1455 | u32 phy_addr, u32 reg, u32 addr, u32 val) | ||
1292 | { | 1456 | { |
1293 | int rc = 0; | 1457 | u32 tmp; |
1294 | u32 tmp, i; | 1458 | int i, rc = 0; |
1295 | int port = bp->port; | ||
1296 | u32 emac_base = port ? GRCBASE_EMAC1 : GRCBASE_EMAC0; | ||
1297 | |||
1298 | if (bp->phy_flags & PHY_INT_MODE_AUTO_POLLING_FLAG) { | ||
1299 | |||
1300 | tmp = REG_RD(bp, emac_base + EMAC_REG_EMAC_MDIO_MODE); | ||
1301 | tmp &= ~EMAC_MDIO_MODE_AUTO_POLL; | ||
1302 | EMAC_WR(EMAC_REG_EMAC_MDIO_MODE, tmp); | ||
1303 | REG_RD(bp, emac_base + EMAC_REG_EMAC_MDIO_MODE); | ||
1304 | udelay(40); | ||
1305 | } | ||
1306 | 1459 | ||
1307 | /* set clause 45 mode */ | 1460 | /* set clause 45 mode, slow down the MDIO clock to 2.5MHz |
1308 | tmp = REG_RD(bp, emac_base + EMAC_REG_EMAC_MDIO_MODE); | 1461 | * (a value of 49==0x31) and make sure that the AUTO poll is off |
1309 | tmp |= EMAC_MDIO_MODE_CLAUSE_45; | 1462 | */ |
1310 | EMAC_WR(EMAC_REG_EMAC_MDIO_MODE, tmp); | 1463 | tmp = REG_RD(bp, mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE); |
1464 | tmp &= ~(EMAC_MDIO_MODE_AUTO_POLL | EMAC_MDIO_MODE_CLOCK_CNT); | ||
1465 | tmp |= (EMAC_MDIO_MODE_CLAUSE_45 | | ||
1466 | (49 << EMAC_MDIO_MODE_CLOCK_CNT_BITSHIFT)); | ||
1467 | REG_WR(bp, mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE, tmp); | ||
1468 | REG_RD(bp, mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE); | ||
1469 | udelay(40); | ||
1311 | 1470 | ||
1312 | /* address */ | 1471 | /* address */ |
1313 | tmp = ((bp->phy_addr << 21) | (reg << 16) | addr | | 1472 | tmp = ((phy_addr << 21) | (reg << 16) | addr | |
1314 | EMAC_MDIO_COMM_COMMAND_ADDRESS | | 1473 | EMAC_MDIO_COMM_COMMAND_ADDRESS | |
1315 | EMAC_MDIO_COMM_START_BUSY); | 1474 | EMAC_MDIO_COMM_START_BUSY); |
1316 | EMAC_WR(EMAC_REG_EMAC_MDIO_COMM, tmp); | 1475 | REG_WR(bp, mdio_ctrl + EMAC_REG_EMAC_MDIO_COMM, tmp); |
1317 | 1476 | ||
1318 | for (i = 0; i < 50; i++) { | 1477 | for (i = 0; i < 50; i++) { |
1319 | udelay(10); | 1478 | udelay(10); |
1320 | 1479 | ||
1321 | tmp = REG_RD(bp, emac_base + EMAC_REG_EMAC_MDIO_COMM); | 1480 | tmp = REG_RD(bp, mdio_ctrl + EMAC_REG_EMAC_MDIO_COMM); |
1322 | if (!(tmp & EMAC_MDIO_COMM_START_BUSY)) { | 1481 | if (!(tmp & EMAC_MDIO_COMM_START_BUSY)) { |
1323 | udelay(5); | 1482 | udelay(5); |
1324 | break; | 1483 | break; |
1325 | } | 1484 | } |
1326 | } | 1485 | } |
1327 | |||
1328 | if (tmp & EMAC_MDIO_COMM_START_BUSY) { | 1486 | if (tmp & EMAC_MDIO_COMM_START_BUSY) { |
1329 | BNX2X_ERR("write phy register failed\n"); | 1487 | BNX2X_ERR("write phy register failed\n"); |
1330 | 1488 | ||
1331 | rc = -EBUSY; | 1489 | rc = -EBUSY; |
1490 | |||
1332 | } else { | 1491 | } else { |
1333 | /* data */ | 1492 | /* data */ |
1334 | tmp = ((bp->phy_addr << 21) | (reg << 16) | val | | 1493 | tmp = ((phy_addr << 21) | (reg << 16) | val | |
1335 | EMAC_MDIO_COMM_COMMAND_WRITE_45 | | 1494 | EMAC_MDIO_COMM_COMMAND_WRITE_45 | |
1336 | EMAC_MDIO_COMM_START_BUSY); | 1495 | EMAC_MDIO_COMM_START_BUSY); |
1337 | EMAC_WR(EMAC_REG_EMAC_MDIO_COMM, tmp); | 1496 | REG_WR(bp, mdio_ctrl + EMAC_REG_EMAC_MDIO_COMM, tmp); |
1338 | 1497 | ||
1339 | for (i = 0; i < 50; i++) { | 1498 | for (i = 0; i < 50; i++) { |
1340 | udelay(10); | 1499 | udelay(10); |
1341 | 1500 | ||
1342 | tmp = REG_RD(bp, emac_base + EMAC_REG_EMAC_MDIO_COMM); | 1501 | tmp = REG_RD(bp, mdio_ctrl + EMAC_REG_EMAC_MDIO_COMM); |
1343 | if (!(tmp & EMAC_MDIO_COMM_START_BUSY)) { | 1502 | if (!(tmp & EMAC_MDIO_COMM_START_BUSY)) { |
1344 | udelay(5); | 1503 | udelay(5); |
1345 | break; | 1504 | break; |
@@ -1353,75 +1512,78 @@ static int bnx2x_mdio45_write(struct bnx2x *bp, u32 reg, u32 addr, u32 val) | |||
1353 | } | 1512 | } |
1354 | } | 1513 | } |
1355 | 1514 | ||
1356 | /* unset clause 45 mode */ | 1515 | /* unset clause 45 mode, set the MDIO clock to a faster value |
1357 | tmp = REG_RD(bp, emac_base + EMAC_REG_EMAC_MDIO_MODE); | 1516 | * (0x13 => 6.25Mhz) and restore the AUTO poll if needed |
1358 | tmp &= ~EMAC_MDIO_MODE_CLAUSE_45; | 1517 | */ |
1359 | EMAC_WR(EMAC_REG_EMAC_MDIO_MODE, tmp); | 1518 | tmp = REG_RD(bp, mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE); |
1360 | 1519 | tmp &= ~(EMAC_MDIO_MODE_CLAUSE_45 | EMAC_MDIO_MODE_CLOCK_CNT); | |
1361 | if (bp->phy_flags & PHY_INT_MODE_AUTO_POLLING_FLAG) { | 1520 | tmp |= (0x13 << EMAC_MDIO_MODE_CLOCK_CNT_BITSHIFT); |
1362 | 1521 | if (bp->phy_flags & PHY_INT_MODE_AUTO_POLLING_FLAG) | |
1363 | tmp = REG_RD(bp, emac_base + EMAC_REG_EMAC_MDIO_MODE); | ||
1364 | tmp |= EMAC_MDIO_MODE_AUTO_POLL; | 1522 | tmp |= EMAC_MDIO_MODE_AUTO_POLL; |
1365 | EMAC_WR(EMAC_REG_EMAC_MDIO_MODE, tmp); | 1523 | REG_WR(bp, mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE, tmp); |
1366 | } | ||
1367 | 1524 | ||
1368 | return rc; | 1525 | return rc; |
1369 | } | 1526 | } |
1370 | 1527 | ||
1371 | static int bnx2x_mdio45_read(struct bnx2x *bp, u32 reg, u32 addr, | 1528 | static int bnx2x_mdio45_write(struct bnx2x *bp, u32 phy_addr, u32 reg, |
1372 | u32 *ret_val) | 1529 | u32 addr, u32 val) |
1373 | { | 1530 | { |
1374 | int port = bp->port; | 1531 | u32 emac_base = bp->port ? GRCBASE_EMAC1 : GRCBASE_EMAC0; |
1375 | u32 emac_base = port ? GRCBASE_EMAC1 : GRCBASE_EMAC0; | ||
1376 | u32 val, i; | ||
1377 | int rc = 0; | ||
1378 | 1532 | ||
1379 | if (bp->phy_flags & PHY_INT_MODE_AUTO_POLLING_FLAG) { | 1533 | return bnx2x_mdio45_ctrl_write(bp, emac_base, phy_addr, |
1534 | reg, addr, val); | ||
1535 | } | ||
1380 | 1536 | ||
1381 | val = REG_RD(bp, emac_base + EMAC_REG_EMAC_MDIO_MODE); | 1537 | static int bnx2x_mdio45_ctrl_read(struct bnx2x *bp, u32 mdio_ctrl, |
1382 | val &= ~EMAC_MDIO_MODE_AUTO_POLL; | 1538 | u32 phy_addr, u32 reg, u32 addr, |
1383 | EMAC_WR(EMAC_REG_EMAC_MDIO_MODE, val); | 1539 | u32 *ret_val) |
1384 | REG_RD(bp, emac_base + EMAC_REG_EMAC_MDIO_MODE); | 1540 | { |
1385 | udelay(40); | 1541 | u32 val; |
1386 | } | 1542 | int i, rc = 0; |
1387 | 1543 | ||
1388 | /* set clause 45 mode */ | 1544 | /* set clause 45 mode, slow down the MDIO clock to 2.5MHz |
1389 | val = REG_RD(bp, emac_base + EMAC_REG_EMAC_MDIO_MODE); | 1545 | * (a value of 49==0x31) and make sure that the AUTO poll is off |
1390 | val |= EMAC_MDIO_MODE_CLAUSE_45; | 1546 | */ |
1391 | EMAC_WR(EMAC_REG_EMAC_MDIO_MODE, val); | 1547 | val = REG_RD(bp, mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE); |
1548 | val &= ~(EMAC_MDIO_MODE_AUTO_POLL | EMAC_MDIO_MODE_CLOCK_CNT); | ||
1549 | val |= (EMAC_MDIO_MODE_CLAUSE_45 | | ||
1550 | (49 << EMAC_MDIO_MODE_CLOCK_CNT_BITSHIFT)); | ||
1551 | REG_WR(bp, mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE, val); | ||
1552 | REG_RD(bp, mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE); | ||
1553 | udelay(40); | ||
1392 | 1554 | ||
1393 | /* address */ | 1555 | /* address */ |
1394 | val = ((bp->phy_addr << 21) | (reg << 16) | addr | | 1556 | val = ((phy_addr << 21) | (reg << 16) | addr | |
1395 | EMAC_MDIO_COMM_COMMAND_ADDRESS | | 1557 | EMAC_MDIO_COMM_COMMAND_ADDRESS | |
1396 | EMAC_MDIO_COMM_START_BUSY); | 1558 | EMAC_MDIO_COMM_START_BUSY); |
1397 | EMAC_WR(EMAC_REG_EMAC_MDIO_COMM, val); | 1559 | REG_WR(bp, mdio_ctrl + EMAC_REG_EMAC_MDIO_COMM, val); |
1398 | 1560 | ||
1399 | for (i = 0; i < 50; i++) { | 1561 | for (i = 0; i < 50; i++) { |
1400 | udelay(10); | 1562 | udelay(10); |
1401 | 1563 | ||
1402 | val = REG_RD(bp, emac_base + EMAC_REG_EMAC_MDIO_COMM); | 1564 | val = REG_RD(bp, mdio_ctrl + EMAC_REG_EMAC_MDIO_COMM); |
1403 | if (!(val & EMAC_MDIO_COMM_START_BUSY)) { | 1565 | if (!(val & EMAC_MDIO_COMM_START_BUSY)) { |
1404 | udelay(5); | 1566 | udelay(5); |
1405 | break; | 1567 | break; |
1406 | } | 1568 | } |
1407 | } | 1569 | } |
1408 | |||
1409 | if (val & EMAC_MDIO_COMM_START_BUSY) { | 1570 | if (val & EMAC_MDIO_COMM_START_BUSY) { |
1410 | BNX2X_ERR("read phy register failed\n"); | 1571 | BNX2X_ERR("read phy register failed\n"); |
1411 | 1572 | ||
1412 | *ret_val = 0; | 1573 | *ret_val = 0; |
1413 | rc = -EBUSY; | 1574 | rc = -EBUSY; |
1575 | |||
1414 | } else { | 1576 | } else { |
1415 | /* data */ | 1577 | /* data */ |
1416 | val = ((bp->phy_addr << 21) | (reg << 16) | | 1578 | val = ((phy_addr << 21) | (reg << 16) | |
1417 | EMAC_MDIO_COMM_COMMAND_READ_45 | | 1579 | EMAC_MDIO_COMM_COMMAND_READ_45 | |
1418 | EMAC_MDIO_COMM_START_BUSY); | 1580 | EMAC_MDIO_COMM_START_BUSY); |
1419 | EMAC_WR(EMAC_REG_EMAC_MDIO_COMM, val); | 1581 | REG_WR(bp, mdio_ctrl + EMAC_REG_EMAC_MDIO_COMM, val); |
1420 | 1582 | ||
1421 | for (i = 0; i < 50; i++) { | 1583 | for (i = 0; i < 50; i++) { |
1422 | udelay(10); | 1584 | udelay(10); |
1423 | 1585 | ||
1424 | val = REG_RD(bp, emac_base + EMAC_REG_EMAC_MDIO_COMM); | 1586 | val = REG_RD(bp, mdio_ctrl + EMAC_REG_EMAC_MDIO_COMM); |
1425 | if (!(val & EMAC_MDIO_COMM_START_BUSY)) { | 1587 | if (!(val & EMAC_MDIO_COMM_START_BUSY)) { |
1426 | val &= EMAC_MDIO_COMM_DATA; | 1588 | val &= EMAC_MDIO_COMM_DATA; |
1427 | break; | 1589 | break; |
@@ -1438,31 +1600,39 @@ static int bnx2x_mdio45_read(struct bnx2x *bp, u32 reg, u32 addr, | |||
1438 | *ret_val = val; | 1600 | *ret_val = val; |
1439 | } | 1601 | } |
1440 | 1602 | ||
1441 | /* unset clause 45 mode */ | 1603 | /* unset clause 45 mode, set the MDIO clock to a faster value |
1442 | val = REG_RD(bp, emac_base + EMAC_REG_EMAC_MDIO_MODE); | 1604 | * (0x13 => 6.25Mhz) and restore the AUTO poll if needed |
1443 | val &= ~EMAC_MDIO_MODE_CLAUSE_45; | 1605 | */ |
1444 | EMAC_WR(EMAC_REG_EMAC_MDIO_MODE, val); | 1606 | val = REG_RD(bp, mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE); |
1445 | 1607 | val &= ~(EMAC_MDIO_MODE_CLAUSE_45 | EMAC_MDIO_MODE_CLOCK_CNT); | |
1446 | if (bp->phy_flags & PHY_INT_MODE_AUTO_POLLING_FLAG) { | 1608 | val |= (0x13 << EMAC_MDIO_MODE_CLOCK_CNT_BITSHIFT); |
1447 | 1609 | if (bp->phy_flags & PHY_INT_MODE_AUTO_POLLING_FLAG) | |
1448 | val = REG_RD(bp, emac_base + EMAC_REG_EMAC_MDIO_MODE); | ||
1449 | val |= EMAC_MDIO_MODE_AUTO_POLL; | 1610 | val |= EMAC_MDIO_MODE_AUTO_POLL; |
1450 | EMAC_WR(EMAC_REG_EMAC_MDIO_MODE, val); | 1611 | REG_WR(bp, mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE, val); |
1451 | } | ||
1452 | 1612 | ||
1453 | return rc; | 1613 | return rc; |
1454 | } | 1614 | } |
1455 | 1615 | ||
1456 | static int bnx2x_mdio45_vwrite(struct bnx2x *bp, u32 reg, u32 addr, u32 val) | 1616 | static int bnx2x_mdio45_read(struct bnx2x *bp, u32 phy_addr, u32 reg, |
1617 | u32 addr, u32 *ret_val) | ||
1618 | { | ||
1619 | u32 emac_base = bp->port ? GRCBASE_EMAC1 : GRCBASE_EMAC0; | ||
1620 | |||
1621 | return bnx2x_mdio45_ctrl_read(bp, emac_base, phy_addr, | ||
1622 | reg, addr, ret_val); | ||
1623 | } | ||
1624 | |||
1625 | static int bnx2x_mdio45_vwrite(struct bnx2x *bp, u32 phy_addr, u32 reg, | ||
1626 | u32 addr, u32 val) | ||
1457 | { | 1627 | { |
1458 | int i; | 1628 | int i; |
1459 | u32 rd_val; | 1629 | u32 rd_val; |
1460 | 1630 | ||
1461 | might_sleep(); | 1631 | might_sleep(); |
1462 | for (i = 0; i < 10; i++) { | 1632 | for (i = 0; i < 10; i++) { |
1463 | bnx2x_mdio45_write(bp, reg, addr, val); | 1633 | bnx2x_mdio45_write(bp, phy_addr, reg, addr, val); |
1464 | msleep(5); | 1634 | msleep(5); |
1465 | bnx2x_mdio45_read(bp, reg, addr, &rd_val); | 1635 | bnx2x_mdio45_read(bp, phy_addr, reg, addr, &rd_val); |
1466 | /* if the read value is not the same as the value we wrote, | 1636 | /* if the read value is not the same as the value we wrote, |
1467 | we should write it again */ | 1637 | we should write it again */ |
1468 | if (rd_val == val) | 1638 | if (rd_val == val) |
@@ -1476,10 +1646,73 @@ static int bnx2x_mdio45_vwrite(struct bnx2x *bp, u32 reg, u32 addr, u32 val) | |||
1476 | * link management | 1646 | * link management |
1477 | */ | 1647 | */ |
1478 | 1648 | ||
1649 | static void bnx2x_pause_resolve(struct bnx2x *bp, u32 pause_result) | ||
1650 | { | ||
1651 | switch (pause_result) { /* ASYM P ASYM P */ | ||
1652 | case 0xb: /* 1 0 1 1 */ | ||
1653 | bp->flow_ctrl = FLOW_CTRL_TX; | ||
1654 | break; | ||
1655 | |||
1656 | case 0xe: /* 1 1 1 0 */ | ||
1657 | bp->flow_ctrl = FLOW_CTRL_RX; | ||
1658 | break; | ||
1659 | |||
1660 | case 0x5: /* 0 1 0 1 */ | ||
1661 | case 0x7: /* 0 1 1 1 */ | ||
1662 | case 0xd: /* 1 1 0 1 */ | ||
1663 | case 0xf: /* 1 1 1 1 */ | ||
1664 | bp->flow_ctrl = FLOW_CTRL_BOTH; | ||
1665 | break; | ||
1666 | |||
1667 | default: | ||
1668 | break; | ||
1669 | } | ||
1670 | } | ||
1671 | |||
1672 | static u8 bnx2x_ext_phy_resove_fc(struct bnx2x *bp) | ||
1673 | { | ||
1674 | u32 ext_phy_addr; | ||
1675 | u32 ld_pause; /* local */ | ||
1676 | u32 lp_pause; /* link partner */ | ||
1677 | u32 an_complete; /* AN complete */ | ||
1678 | u32 pause_result; | ||
1679 | u8 ret = 0; | ||
1680 | |||
1681 | ext_phy_addr = ((bp->ext_phy_config & | ||
1682 | PORT_HW_CFG_XGXS_EXT_PHY_ADDR_MASK) >> | ||
1683 | PORT_HW_CFG_XGXS_EXT_PHY_ADDR_SHIFT); | ||
1684 | |||
1685 | /* read twice */ | ||
1686 | bnx2x_mdio45_read(bp, ext_phy_addr, | ||
1687 | EXT_PHY_KR_AUTO_NEG_DEVAD, | ||
1688 | EXT_PHY_KR_STATUS, &an_complete); | ||
1689 | bnx2x_mdio45_read(bp, ext_phy_addr, | ||
1690 | EXT_PHY_KR_AUTO_NEG_DEVAD, | ||
1691 | EXT_PHY_KR_STATUS, &an_complete); | ||
1692 | |||
1693 | if (an_complete & EXT_PHY_KR_AUTO_NEG_COMPLETE) { | ||
1694 | ret = 1; | ||
1695 | bnx2x_mdio45_read(bp, ext_phy_addr, | ||
1696 | EXT_PHY_KR_AUTO_NEG_DEVAD, | ||
1697 | EXT_PHY_KR_AUTO_NEG_ADVERT, &ld_pause); | ||
1698 | bnx2x_mdio45_read(bp, ext_phy_addr, | ||
1699 | EXT_PHY_KR_AUTO_NEG_DEVAD, | ||
1700 | EXT_PHY_KR_LP_AUTO_NEG, &lp_pause); | ||
1701 | pause_result = (ld_pause & | ||
1702 | EXT_PHY_KR_AUTO_NEG_ADVERT_PAUSE_MASK) >> 8; | ||
1703 | pause_result |= (lp_pause & | ||
1704 | EXT_PHY_KR_AUTO_NEG_ADVERT_PAUSE_MASK) >> 10; | ||
1705 | DP(NETIF_MSG_LINK, "Ext PHY pause result 0x%x \n", | ||
1706 | pause_result); | ||
1707 | bnx2x_pause_resolve(bp, pause_result); | ||
1708 | } | ||
1709 | return ret; | ||
1710 | } | ||
1711 | |||
1479 | static void bnx2x_flow_ctrl_resolve(struct bnx2x *bp, u32 gp_status) | 1712 | static void bnx2x_flow_ctrl_resolve(struct bnx2x *bp, u32 gp_status) |
1480 | { | 1713 | { |
1481 | u32 ld_pause; /* local driver */ | 1714 | u32 ld_pause; /* local driver */ |
1482 | u32 lp_pause; /* link partner */ | 1715 | u32 lp_pause; /* link partner */ |
1483 | u32 pause_result; | 1716 | u32 pause_result; |
1484 | 1717 | ||
1485 | bp->flow_ctrl = 0; | 1718 | bp->flow_ctrl = 0; |
@@ -1501,45 +1734,57 @@ static void bnx2x_flow_ctrl_resolve(struct bnx2x *bp, u32 gp_status) | |||
1501 | pause_result |= (lp_pause & | 1734 | pause_result |= (lp_pause & |
1502 | MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_MASK)>>7; | 1735 | MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_MASK)>>7; |
1503 | DP(NETIF_MSG_LINK, "pause_result 0x%x\n", pause_result); | 1736 | DP(NETIF_MSG_LINK, "pause_result 0x%x\n", pause_result); |
1737 | bnx2x_pause_resolve(bp, pause_result); | ||
1738 | } else if (!(bp->req_autoneg & AUTONEG_FLOW_CTRL) || | ||
1739 | !(bnx2x_ext_phy_resove_fc(bp))) { | ||
1740 | /* forced speed */ | ||
1741 | if (bp->req_autoneg & AUTONEG_FLOW_CTRL) { | ||
1742 | switch (bp->req_flow_ctrl) { | ||
1743 | case FLOW_CTRL_AUTO: | ||
1744 | if (bp->dev->mtu <= 4500) | ||
1745 | bp->flow_ctrl = FLOW_CTRL_BOTH; | ||
1746 | else | ||
1747 | bp->flow_ctrl = FLOW_CTRL_TX; | ||
1748 | break; | ||
1504 | 1749 | ||
1505 | switch (pause_result) { /* ASYM P ASYM P */ | 1750 | case FLOW_CTRL_TX: |
1506 | case 0xb: /* 1 0 1 1 */ | 1751 | bp->flow_ctrl = FLOW_CTRL_TX; |
1507 | bp->flow_ctrl = FLOW_CTRL_TX; | 1752 | break; |
1508 | break; | ||
1509 | |||
1510 | case 0xe: /* 1 1 1 0 */ | ||
1511 | bp->flow_ctrl = FLOW_CTRL_RX; | ||
1512 | break; | ||
1513 | 1753 | ||
1514 | case 0x5: /* 0 1 0 1 */ | 1754 | case FLOW_CTRL_RX: |
1515 | case 0x7: /* 0 1 1 1 */ | 1755 | if (bp->dev->mtu <= 4500) |
1516 | case 0xd: /* 1 1 0 1 */ | 1756 | bp->flow_ctrl = FLOW_CTRL_RX; |
1517 | case 0xf: /* 1 1 1 1 */ | 1757 | break; |
1518 | bp->flow_ctrl = FLOW_CTRL_BOTH; | ||
1519 | break; | ||
1520 | 1758 | ||
1521 | default: | 1759 | case FLOW_CTRL_BOTH: |
1522 | break; | 1760 | if (bp->dev->mtu <= 4500) |
1523 | } | 1761 | bp->flow_ctrl = FLOW_CTRL_BOTH; |
1762 | else | ||
1763 | bp->flow_ctrl = FLOW_CTRL_TX; | ||
1764 | break; | ||
1524 | 1765 | ||
1525 | } else { /* forced mode */ | 1766 | case FLOW_CTRL_NONE: |
1526 | switch (bp->req_flow_ctrl) { | 1767 | default: |
1527 | case FLOW_CTRL_AUTO: | 1768 | break; |
1528 | if (bp->dev->mtu <= 4500) | 1769 | } |
1529 | bp->flow_ctrl = FLOW_CTRL_BOTH; | 1770 | } else { /* forced mode */ |
1530 | else | 1771 | switch (bp->req_flow_ctrl) { |
1531 | bp->flow_ctrl = FLOW_CTRL_TX; | 1772 | case FLOW_CTRL_AUTO: |
1532 | break; | 1773 | DP(NETIF_MSG_LINK, "req_flow_ctrl 0x%x while" |
1774 | " req_autoneg 0x%x\n", | ||
1775 | bp->req_flow_ctrl, bp->req_autoneg); | ||
1776 | break; | ||
1533 | 1777 | ||
1534 | case FLOW_CTRL_TX: | 1778 | case FLOW_CTRL_TX: |
1535 | case FLOW_CTRL_RX: | 1779 | case FLOW_CTRL_RX: |
1536 | case FLOW_CTRL_BOTH: | 1780 | case FLOW_CTRL_BOTH: |
1537 | bp->flow_ctrl = bp->req_flow_ctrl; | 1781 | bp->flow_ctrl = bp->req_flow_ctrl; |
1538 | break; | 1782 | break; |
1539 | 1783 | ||
1540 | case FLOW_CTRL_NONE: | 1784 | case FLOW_CTRL_NONE: |
1541 | default: | 1785 | default: |
1542 | break; | 1786 | break; |
1787 | } | ||
1543 | } | 1788 | } |
1544 | } | 1789 | } |
1545 | DP(NETIF_MSG_LINK, "flow_ctrl 0x%x\n", bp->flow_ctrl); | 1790 | DP(NETIF_MSG_LINK, "flow_ctrl 0x%x\n", bp->flow_ctrl); |
@@ -1550,9 +1795,9 @@ static void bnx2x_link_settings_status(struct bnx2x *bp, u32 gp_status) | |||
1550 | bp->link_status = 0; | 1795 | bp->link_status = 0; |
1551 | 1796 | ||
1552 | if (gp_status & MDIO_GP_STATUS_TOP_AN_STATUS1_LINK_STATUS) { | 1797 | if (gp_status & MDIO_GP_STATUS_TOP_AN_STATUS1_LINK_STATUS) { |
1553 | DP(NETIF_MSG_LINK, "link up\n"); | 1798 | DP(NETIF_MSG_LINK, "phy link up\n"); |
1554 | 1799 | ||
1555 | bp->link_up = 1; | 1800 | bp->phy_link_up = 1; |
1556 | bp->link_status |= LINK_STATUS_LINK_UP; | 1801 | bp->link_status |= LINK_STATUS_LINK_UP; |
1557 | 1802 | ||
1558 | if (gp_status & MDIO_GP_STATUS_TOP_AN_STATUS1_DUPLEX_STATUS) | 1803 | if (gp_status & MDIO_GP_STATUS_TOP_AN_STATUS1_DUPLEX_STATUS) |
@@ -1661,20 +1906,20 @@ static void bnx2x_link_settings_status(struct bnx2x *bp, u32 gp_status) | |||
1661 | bp->link_status |= LINK_STATUS_RX_FLOW_CONTROL_ENABLED; | 1906 | bp->link_status |= LINK_STATUS_RX_FLOW_CONTROL_ENABLED; |
1662 | 1907 | ||
1663 | } else { /* link_down */ | 1908 | } else { /* link_down */ |
1664 | DP(NETIF_MSG_LINK, "link down\n"); | 1909 | DP(NETIF_MSG_LINK, "phy link down\n"); |
1665 | 1910 | ||
1666 | bp->link_up = 0; | 1911 | bp->phy_link_up = 0; |
1667 | 1912 | ||
1668 | bp->line_speed = 0; | 1913 | bp->line_speed = 0; |
1669 | bp->duplex = DUPLEX_FULL; | 1914 | bp->duplex = DUPLEX_FULL; |
1670 | bp->flow_ctrl = 0; | 1915 | bp->flow_ctrl = 0; |
1671 | } | 1916 | } |
1672 | 1917 | ||
1673 | DP(NETIF_MSG_LINK, "gp_status 0x%x link_up %d\n" | 1918 | DP(NETIF_MSG_LINK, "gp_status 0x%x phy_link_up %d\n" |
1674 | DP_LEVEL " line_speed %d duplex %d flow_ctrl 0x%x" | 1919 | DP_LEVEL " line_speed %d duplex %d flow_ctrl 0x%x" |
1675 | " link_status 0x%x\n", | 1920 | " link_status 0x%x\n", |
1676 | gp_status, bp->link_up, bp->line_speed, bp->duplex, bp->flow_ctrl, | 1921 | gp_status, bp->phy_link_up, bp->line_speed, bp->duplex, |
1677 | bp->link_status); | 1922 | bp->flow_ctrl, bp->link_status); |
1678 | } | 1923 | } |
1679 | 1924 | ||
1680 | static void bnx2x_link_int_ack(struct bnx2x *bp, int is_10g) | 1925 | static void bnx2x_link_int_ack(struct bnx2x *bp, int is_10g) |
@@ -1684,38 +1929,38 @@ static void bnx2x_link_int_ack(struct bnx2x *bp, int is_10g) | |||
1684 | /* first reset all status | 1929 | /* first reset all status |
1685 | * we assume only one line will be change at a time */ | 1930 | * we assume only one line will be change at a time */ |
1686 | bnx2x_bits_dis(bp, NIG_REG_STATUS_INTERRUPT_PORT0 + port*4, | 1931 | bnx2x_bits_dis(bp, NIG_REG_STATUS_INTERRUPT_PORT0 + port*4, |
1687 | (NIG_XGXS0_LINK_STATUS | | 1932 | (NIG_STATUS_XGXS0_LINK10G | |
1688 | NIG_SERDES0_LINK_STATUS | | 1933 | NIG_STATUS_XGXS0_LINK_STATUS | |
1689 | NIG_STATUS_INTERRUPT_XGXS0_LINK10G)); | 1934 | NIG_STATUS_SERDES0_LINK_STATUS)); |
1690 | if (bp->link_up) { | 1935 | if (bp->phy_link_up) { |
1691 | if (is_10g) { | 1936 | if (is_10g) { |
1692 | /* Disable the 10G link interrupt | 1937 | /* Disable the 10G link interrupt |
1693 | * by writing 1 to the status register | 1938 | * by writing 1 to the status register |
1694 | */ | 1939 | */ |
1695 | DP(NETIF_MSG_LINK, "10G XGXS link up\n"); | 1940 | DP(NETIF_MSG_LINK, "10G XGXS phy link up\n"); |
1696 | bnx2x_bits_en(bp, | 1941 | bnx2x_bits_en(bp, |
1697 | NIG_REG_STATUS_INTERRUPT_PORT0 + port*4, | 1942 | NIG_REG_STATUS_INTERRUPT_PORT0 + port*4, |
1698 | NIG_STATUS_INTERRUPT_XGXS0_LINK10G); | 1943 | NIG_STATUS_XGXS0_LINK10G); |
1699 | 1944 | ||
1700 | } else if (bp->phy_flags & PHY_XGXS_FLAG) { | 1945 | } else if (bp->phy_flags & PHY_XGXS_FLAG) { |
1701 | /* Disable the link interrupt | 1946 | /* Disable the link interrupt |
1702 | * by writing 1 to the relevant lane | 1947 | * by writing 1 to the relevant lane |
1703 | * in the status register | 1948 | * in the status register |
1704 | */ | 1949 | */ |
1705 | DP(NETIF_MSG_LINK, "1G XGXS link up\n"); | 1950 | DP(NETIF_MSG_LINK, "1G XGXS phy link up\n"); |
1706 | bnx2x_bits_en(bp, | 1951 | bnx2x_bits_en(bp, |
1707 | NIG_REG_STATUS_INTERRUPT_PORT0 + port*4, | 1952 | NIG_REG_STATUS_INTERRUPT_PORT0 + port*4, |
1708 | ((1 << bp->ser_lane) << | 1953 | ((1 << bp->ser_lane) << |
1709 | NIG_XGXS0_LINK_STATUS_SIZE)); | 1954 | NIG_STATUS_XGXS0_LINK_STATUS_SIZE)); |
1710 | 1955 | ||
1711 | } else { /* SerDes */ | 1956 | } else { /* SerDes */ |
1712 | DP(NETIF_MSG_LINK, "SerDes link up\n"); | 1957 | DP(NETIF_MSG_LINK, "SerDes phy link up\n"); |
1713 | /* Disable the link interrupt | 1958 | /* Disable the link interrupt |
1714 | * by writing 1 to the status register | 1959 | * by writing 1 to the status register |
1715 | */ | 1960 | */ |
1716 | bnx2x_bits_en(bp, | 1961 | bnx2x_bits_en(bp, |
1717 | NIG_REG_STATUS_INTERRUPT_PORT0 + port*4, | 1962 | NIG_REG_STATUS_INTERRUPT_PORT0 + port*4, |
1718 | NIG_SERDES0_LINK_STATUS); | 1963 | NIG_STATUS_SERDES0_LINK_STATUS); |
1719 | } | 1964 | } |
1720 | 1965 | ||
1721 | } else { /* link_down */ | 1966 | } else { /* link_down */ |
@@ -1726,91 +1971,182 @@ static int bnx2x_ext_phy_is_link_up(struct bnx2x *bp) | |||
1726 | { | 1971 | { |
1727 | u32 ext_phy_type; | 1972 | u32 ext_phy_type; |
1728 | u32 ext_phy_addr; | 1973 | u32 ext_phy_addr; |
1729 | u32 local_phy; | 1974 | u32 val1 = 0, val2; |
1730 | u32 val = 0; | ||
1731 | u32 rx_sd, pcs_status; | 1975 | u32 rx_sd, pcs_status; |
1732 | 1976 | ||
1733 | if (bp->phy_flags & PHY_XGXS_FLAG) { | 1977 | if (bp->phy_flags & PHY_XGXS_FLAG) { |
1734 | local_phy = bp->phy_addr; | ||
1735 | ext_phy_addr = ((bp->ext_phy_config & | 1978 | ext_phy_addr = ((bp->ext_phy_config & |
1736 | PORT_HW_CFG_XGXS_EXT_PHY_ADDR_MASK) >> | 1979 | PORT_HW_CFG_XGXS_EXT_PHY_ADDR_MASK) >> |
1737 | PORT_HW_CFG_XGXS_EXT_PHY_ADDR_SHIFT); | 1980 | PORT_HW_CFG_XGXS_EXT_PHY_ADDR_SHIFT); |
1738 | bp->phy_addr = (u8)ext_phy_addr; | ||
1739 | 1981 | ||
1740 | ext_phy_type = XGXS_EXT_PHY_TYPE(bp); | 1982 | ext_phy_type = XGXS_EXT_PHY_TYPE(bp); |
1741 | switch (ext_phy_type) { | 1983 | switch (ext_phy_type) { |
1742 | case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT: | 1984 | case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT: |
1743 | DP(NETIF_MSG_LINK, "XGXS Direct\n"); | 1985 | DP(NETIF_MSG_LINK, "XGXS Direct\n"); |
1744 | val = 1; | 1986 | val1 = 1; |
1745 | break; | 1987 | break; |
1746 | 1988 | ||
1747 | case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705: | 1989 | case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705: |
1748 | DP(NETIF_MSG_LINK, "XGXS 8705\n"); | 1990 | DP(NETIF_MSG_LINK, "XGXS 8705\n"); |
1749 | bnx2x_mdio45_read(bp, EXT_PHY_OPT_WIS_DEVAD, | 1991 | bnx2x_mdio45_read(bp, ext_phy_addr, |
1750 | EXT_PHY_OPT_LASI_STATUS, &val); | 1992 | EXT_PHY_OPT_WIS_DEVAD, |
1751 | DP(NETIF_MSG_LINK, "8705 LASI status is %d\n", val); | 1993 | EXT_PHY_OPT_LASI_STATUS, &val1); |
1752 | 1994 | DP(NETIF_MSG_LINK, "8705 LASI status 0x%x\n", val1); | |
1753 | bnx2x_mdio45_read(bp, EXT_PHY_OPT_WIS_DEVAD, | 1995 | |
1754 | EXT_PHY_OPT_LASI_STATUS, &val); | 1996 | bnx2x_mdio45_read(bp, ext_phy_addr, |
1755 | DP(NETIF_MSG_LINK, "8705 LASI status is %d\n", val); | 1997 | EXT_PHY_OPT_WIS_DEVAD, |
1756 | 1998 | EXT_PHY_OPT_LASI_STATUS, &val1); | |
1757 | bnx2x_mdio45_read(bp, EXT_PHY_OPT_PMA_PMD_DEVAD, | 1999 | DP(NETIF_MSG_LINK, "8705 LASI status 0x%x\n", val1); |
2000 | |||
2001 | bnx2x_mdio45_read(bp, ext_phy_addr, | ||
2002 | EXT_PHY_OPT_PMA_PMD_DEVAD, | ||
1758 | EXT_PHY_OPT_PMD_RX_SD, &rx_sd); | 2003 | EXT_PHY_OPT_PMD_RX_SD, &rx_sd); |
1759 | val = (rx_sd & 0x1); | 2004 | DP(NETIF_MSG_LINK, "8705 rx_sd 0x%x\n", rx_sd); |
2005 | val1 = (rx_sd & 0x1); | ||
1760 | break; | 2006 | break; |
1761 | 2007 | ||
1762 | case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8706: | 2008 | case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8706: |
1763 | DP(NETIF_MSG_LINK, "XGXS 8706\n"); | 2009 | DP(NETIF_MSG_LINK, "XGXS 8706\n"); |
1764 | bnx2x_mdio45_read(bp, EXT_PHY_OPT_PMA_PMD_DEVAD, | 2010 | bnx2x_mdio45_read(bp, ext_phy_addr, |
1765 | EXT_PHY_OPT_LASI_STATUS, &val); | 2011 | EXT_PHY_OPT_PMA_PMD_DEVAD, |
1766 | DP(NETIF_MSG_LINK, "8706 LASI status is %d\n", val); | 2012 | EXT_PHY_OPT_LASI_STATUS, &val1); |
1767 | 2013 | DP(NETIF_MSG_LINK, "8706 LASI status 0x%x\n", val1); | |
1768 | bnx2x_mdio45_read(bp, EXT_PHY_OPT_PMA_PMD_DEVAD, | 2014 | |
1769 | EXT_PHY_OPT_LASI_STATUS, &val); | 2015 | bnx2x_mdio45_read(bp, ext_phy_addr, |
1770 | DP(NETIF_MSG_LINK, "8706 LASI status is %d\n", val); | 2016 | EXT_PHY_OPT_PMA_PMD_DEVAD, |
1771 | 2017 | EXT_PHY_OPT_LASI_STATUS, &val1); | |
1772 | bnx2x_mdio45_read(bp, EXT_PHY_OPT_PMA_PMD_DEVAD, | 2018 | DP(NETIF_MSG_LINK, "8706 LASI status 0x%x\n", val1); |
2019 | |||
2020 | bnx2x_mdio45_read(bp, ext_phy_addr, | ||
2021 | EXT_PHY_OPT_PMA_PMD_DEVAD, | ||
1773 | EXT_PHY_OPT_PMD_RX_SD, &rx_sd); | 2022 | EXT_PHY_OPT_PMD_RX_SD, &rx_sd); |
1774 | bnx2x_mdio45_read(bp, EXT_PHY_OPT_PCS_DEVAD, | 2023 | bnx2x_mdio45_read(bp, ext_phy_addr, |
1775 | EXT_PHY_OPT_PCS_STATUS, &pcs_status); | 2024 | EXT_PHY_OPT_PCS_DEVAD, |
2025 | EXT_PHY_OPT_PCS_STATUS, &pcs_status); | ||
2026 | bnx2x_mdio45_read(bp, ext_phy_addr, | ||
2027 | EXT_PHY_AUTO_NEG_DEVAD, | ||
2028 | EXT_PHY_OPT_AN_LINK_STATUS, &val2); | ||
2029 | |||
1776 | DP(NETIF_MSG_LINK, "8706 rx_sd 0x%x" | 2030 | DP(NETIF_MSG_LINK, "8706 rx_sd 0x%x" |
1777 | " pcs_status 0x%x\n", rx_sd, pcs_status); | 2031 | " pcs_status 0x%x 1Gbps link_status 0x%x 0x%x\n", |
1778 | /* link is up if both bit 0 of pmd_rx and | 2032 | rx_sd, pcs_status, val2, (val2 & (1<<1))); |
1779 | * bit 0 of pcs_status are set | 2033 | /* link is up if both bit 0 of pmd_rx_sd and |
2034 | * bit 0 of pcs_status are set, or if the autoneg bit | ||
2035 | 1 is set | ||
2036 | */ | ||
2037 | val1 = ((rx_sd & pcs_status & 0x1) || (val2 & (1<<1))); | ||
2038 | break; | ||
2039 | |||
2040 | case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072: | ||
2041 | bnx2x_hw_lock(bp, HW_LOCK_RESOURCE_8072_MDIO); | ||
2042 | |||
2043 | /* clear the interrupt LASI status register */ | ||
2044 | bnx2x_mdio45_ctrl_read(bp, GRCBASE_EMAC0, | ||
2045 | ext_phy_addr, | ||
2046 | EXT_PHY_KR_PCS_DEVAD, | ||
2047 | EXT_PHY_KR_LASI_STATUS, &val2); | ||
2048 | bnx2x_mdio45_ctrl_read(bp, GRCBASE_EMAC0, | ||
2049 | ext_phy_addr, | ||
2050 | EXT_PHY_KR_PCS_DEVAD, | ||
2051 | EXT_PHY_KR_LASI_STATUS, &val1); | ||
2052 | DP(NETIF_MSG_LINK, "KR LASI status 0x%x->0x%x\n", | ||
2053 | val2, val1); | ||
2054 | /* Check the LASI */ | ||
2055 | bnx2x_mdio45_ctrl_read(bp, GRCBASE_EMAC0, | ||
2056 | ext_phy_addr, | ||
2057 | EXT_PHY_KR_PMA_PMD_DEVAD, | ||
2058 | 0x9003, &val2); | ||
2059 | bnx2x_mdio45_ctrl_read(bp, GRCBASE_EMAC0, | ||
2060 | ext_phy_addr, | ||
2061 | EXT_PHY_KR_PMA_PMD_DEVAD, | ||
2062 | 0x9003, &val1); | ||
2063 | DP(NETIF_MSG_LINK, "KR 0x9003 0x%x->0x%x\n", | ||
2064 | val2, val1); | ||
2065 | /* Check the link status */ | ||
2066 | bnx2x_mdio45_ctrl_read(bp, GRCBASE_EMAC0, | ||
2067 | ext_phy_addr, | ||
2068 | EXT_PHY_KR_PCS_DEVAD, | ||
2069 | EXT_PHY_KR_PCS_STATUS, &val2); | ||
2070 | DP(NETIF_MSG_LINK, "KR PCS status 0x%x\n", val2); | ||
2071 | /* Check the link status on 1.1.2 */ | ||
2072 | bnx2x_mdio45_ctrl_read(bp, GRCBASE_EMAC0, | ||
2073 | ext_phy_addr, | ||
2074 | EXT_PHY_OPT_PMA_PMD_DEVAD, | ||
2075 | EXT_PHY_KR_STATUS, &val2); | ||
2076 | bnx2x_mdio45_ctrl_read(bp, GRCBASE_EMAC0, | ||
2077 | ext_phy_addr, | ||
2078 | EXT_PHY_OPT_PMA_PMD_DEVAD, | ||
2079 | EXT_PHY_KR_STATUS, &val1); | ||
2080 | DP(NETIF_MSG_LINK, | ||
2081 | "KR PMA status 0x%x->0x%x\n", val2, val1); | ||
2082 | val1 = ((val1 & 4) == 4); | ||
2083 | /* If 1G was requested assume the link is up */ | ||
2084 | if (!(bp->req_autoneg & AUTONEG_SPEED) && | ||
2085 | (bp->req_line_speed == SPEED_1000)) | ||
2086 | val1 = 1; | ||
2087 | bnx2x_hw_unlock(bp, HW_LOCK_RESOURCE_8072_MDIO); | ||
2088 | break; | ||
2089 | |||
2090 | case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101: | ||
2091 | bnx2x_mdio45_read(bp, ext_phy_addr, | ||
2092 | EXT_PHY_OPT_PMA_PMD_DEVAD, | ||
2093 | EXT_PHY_OPT_LASI_STATUS, &val2); | ||
2094 | bnx2x_mdio45_read(bp, ext_phy_addr, | ||
2095 | EXT_PHY_OPT_PMA_PMD_DEVAD, | ||
2096 | EXT_PHY_OPT_LASI_STATUS, &val1); | ||
2097 | DP(NETIF_MSG_LINK, | ||
2098 | "10G-base-T LASI status 0x%x->0x%x\n", val2, val1); | ||
2099 | bnx2x_mdio45_read(bp, ext_phy_addr, | ||
2100 | EXT_PHY_OPT_PMA_PMD_DEVAD, | ||
2101 | EXT_PHY_KR_STATUS, &val2); | ||
2102 | bnx2x_mdio45_read(bp, ext_phy_addr, | ||
2103 | EXT_PHY_OPT_PMA_PMD_DEVAD, | ||
2104 | EXT_PHY_KR_STATUS, &val1); | ||
2105 | DP(NETIF_MSG_LINK, | ||
2106 | "10G-base-T PMA status 0x%x->0x%x\n", val2, val1); | ||
2107 | val1 = ((val1 & 4) == 4); | ||
2108 | /* if link is up | ||
2109 | * print the AN outcome of the SFX7101 PHY | ||
1780 | */ | 2110 | */ |
1781 | val = (rx_sd & pcs_status); | 2111 | if (val1) { |
2112 | bnx2x_mdio45_read(bp, ext_phy_addr, | ||
2113 | EXT_PHY_KR_AUTO_NEG_DEVAD, | ||
2114 | 0x21, &val2); | ||
2115 | DP(NETIF_MSG_LINK, | ||
2116 | "SFX7101 AN status 0x%x->%s\n", val2, | ||
2117 | (val2 & (1<<14)) ? "Master" : "Slave"); | ||
2118 | } | ||
1782 | break; | 2119 | break; |
1783 | 2120 | ||
1784 | default: | 2121 | default: |
1785 | DP(NETIF_MSG_LINK, "BAD XGXS ext_phy_config 0x%x\n", | 2122 | DP(NETIF_MSG_LINK, "BAD XGXS ext_phy_config 0x%x\n", |
1786 | bp->ext_phy_config); | 2123 | bp->ext_phy_config); |
1787 | val = 0; | 2124 | val1 = 0; |
1788 | break; | 2125 | break; |
1789 | } | 2126 | } |
1790 | bp->phy_addr = local_phy; | ||
1791 | 2127 | ||
1792 | } else { /* SerDes */ | 2128 | } else { /* SerDes */ |
1793 | ext_phy_type = SERDES_EXT_PHY_TYPE(bp); | 2129 | ext_phy_type = SERDES_EXT_PHY_TYPE(bp); |
1794 | switch (ext_phy_type) { | 2130 | switch (ext_phy_type) { |
1795 | case PORT_HW_CFG_SERDES_EXT_PHY_TYPE_DIRECT: | 2131 | case PORT_HW_CFG_SERDES_EXT_PHY_TYPE_DIRECT: |
1796 | DP(NETIF_MSG_LINK, "SerDes Direct\n"); | 2132 | DP(NETIF_MSG_LINK, "SerDes Direct\n"); |
1797 | val = 1; | 2133 | val1 = 1; |
1798 | break; | 2134 | break; |
1799 | 2135 | ||
1800 | case PORT_HW_CFG_SERDES_EXT_PHY_TYPE_BCM5482: | 2136 | case PORT_HW_CFG_SERDES_EXT_PHY_TYPE_BCM5482: |
1801 | DP(NETIF_MSG_LINK, "SerDes 5482\n"); | 2137 | DP(NETIF_MSG_LINK, "SerDes 5482\n"); |
1802 | val = 1; | 2138 | val1 = 1; |
1803 | break; | 2139 | break; |
1804 | 2140 | ||
1805 | default: | 2141 | default: |
1806 | DP(NETIF_MSG_LINK, "BAD SerDes ext_phy_config 0x%x\n", | 2142 | DP(NETIF_MSG_LINK, "BAD SerDes ext_phy_config 0x%x\n", |
1807 | bp->ext_phy_config); | 2143 | bp->ext_phy_config); |
1808 | val = 0; | 2144 | val1 = 0; |
1809 | break; | 2145 | break; |
1810 | } | 2146 | } |
1811 | } | 2147 | } |
1812 | 2148 | ||
1813 | return val; | 2149 | return val1; |
1814 | } | 2150 | } |
1815 | 2151 | ||
1816 | static void bnx2x_bmac_enable(struct bnx2x *bp, int is_lb) | 2152 | static void bnx2x_bmac_enable(struct bnx2x *bp, int is_lb) |
@@ -1935,6 +2271,35 @@ static void bnx2x_bmac_enable(struct bnx2x *bp, int is_lb) | |||
1935 | bp->stats_state = STATS_STATE_ENABLE; | 2271 | bp->stats_state = STATS_STATE_ENABLE; |
1936 | } | 2272 | } |
1937 | 2273 | ||
2274 | static void bnx2x_bmac_rx_disable(struct bnx2x *bp) | ||
2275 | { | ||
2276 | int port = bp->port; | ||
2277 | u32 bmac_addr = port ? NIG_REG_INGRESS_BMAC1_MEM : | ||
2278 | NIG_REG_INGRESS_BMAC0_MEM; | ||
2279 | u32 wb_write[2]; | ||
2280 | |||
2281 | /* Only if the bmac is out of reset */ | ||
2282 | if (REG_RD(bp, MISC_REG_RESET_REG_2) & | ||
2283 | (MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << port)) { | ||
2284 | /* Clear Rx Enable bit in BMAC_CONTROL register */ | ||
2285 | #ifdef BNX2X_DMAE_RD | ||
2286 | bnx2x_read_dmae(bp, bmac_addr + | ||
2287 | BIGMAC_REGISTER_BMAC_CONTROL, 2); | ||
2288 | wb_write[0] = *bnx2x_sp(bp, wb_data[0]); | ||
2289 | wb_write[1] = *bnx2x_sp(bp, wb_data[1]); | ||
2290 | #else | ||
2291 | wb_write[0] = REG_RD(bp, | ||
2292 | bmac_addr + BIGMAC_REGISTER_BMAC_CONTROL); | ||
2293 | wb_write[1] = REG_RD(bp, | ||
2294 | bmac_addr + BIGMAC_REGISTER_BMAC_CONTROL + 4); | ||
2295 | #endif | ||
2296 | wb_write[0] &= ~BMAC_CONTROL_RX_ENABLE; | ||
2297 | REG_WR_DMAE(bp, bmac_addr + BIGMAC_REGISTER_BMAC_CONTROL, | ||
2298 | wb_write, 2); | ||
2299 | msleep(1); | ||
2300 | } | ||
2301 | } | ||
2302 | |||
1938 | static void bnx2x_emac_enable(struct bnx2x *bp) | 2303 | static void bnx2x_emac_enable(struct bnx2x *bp) |
1939 | { | 2304 | { |
1940 | int port = bp->port; | 2305 | int port = bp->port; |
@@ -2233,7 +2598,7 @@ static void bnx2x_pbf_update(struct bnx2x *bp) | |||
2233 | static void bnx2x_update_mng(struct bnx2x *bp) | 2598 | static void bnx2x_update_mng(struct bnx2x *bp) |
2234 | { | 2599 | { |
2235 | if (!nomcp) | 2600 | if (!nomcp) |
2236 | SHMEM_WR(bp, drv_fw_mb[bp->port].link_status, | 2601 | SHMEM_WR(bp, port_mb[bp->port].link_status, |
2237 | bp->link_status); | 2602 | bp->link_status); |
2238 | } | 2603 | } |
2239 | 2604 | ||
@@ -2295,19 +2660,19 @@ static void bnx2x_link_down(struct bnx2x *bp) | |||
2295 | DP(BNX2X_MSG_STATS, "stats_state - STOP\n"); | 2660 | DP(BNX2X_MSG_STATS, "stats_state - STOP\n"); |
2296 | } | 2661 | } |
2297 | 2662 | ||
2298 | /* indicate link down */ | 2663 | /* indicate no mac active */ |
2299 | bp->phy_flags &= ~(PHY_BMAC_FLAG | PHY_EMAC_FLAG); | 2664 | bp->phy_flags &= ~(PHY_BMAC_FLAG | PHY_EMAC_FLAG); |
2300 | 2665 | ||
2301 | /* reset BigMac */ | 2666 | /* update shared memory */ |
2302 | REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_CLEAR, | 2667 | bnx2x_update_mng(bp); |
2303 | (MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << port)); | ||
2304 | 2668 | ||
2305 | /* ignore drain flag interrupt */ | ||
2306 | /* activate nig drain */ | 2669 | /* activate nig drain */ |
2307 | NIG_WR(NIG_REG_EGRESS_DRAIN0_MODE + port*4, 1); | 2670 | NIG_WR(NIG_REG_EGRESS_DRAIN0_MODE + port*4, 1); |
2308 | 2671 | ||
2309 | /* update shared memory */ | 2672 | /* reset BigMac */ |
2310 | bnx2x_update_mng(bp); | 2673 | bnx2x_bmac_rx_disable(bp); |
2674 | REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_CLEAR, | ||
2675 | (MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << port)); | ||
2311 | 2676 | ||
2312 | /* indicate link down */ | 2677 | /* indicate link down */ |
2313 | bnx2x_link_report(bp); | 2678 | bnx2x_link_report(bp); |
@@ -2318,14 +2683,15 @@ static void bnx2x_init_mac_stats(struct bnx2x *bp); | |||
2318 | /* This function is called upon link interrupt */ | 2683 | /* This function is called upon link interrupt */ |
2319 | static void bnx2x_link_update(struct bnx2x *bp) | 2684 | static void bnx2x_link_update(struct bnx2x *bp) |
2320 | { | 2685 | { |
2321 | u32 gp_status; | ||
2322 | int port = bp->port; | 2686 | int port = bp->port; |
2323 | int i; | 2687 | int i; |
2688 | u32 gp_status; | ||
2324 | int link_10g; | 2689 | int link_10g; |
2325 | 2690 | ||
2326 | DP(NETIF_MSG_LINK, "port %x, is xgxs %x, stat_mask 0x%x," | 2691 | DP(NETIF_MSG_LINK, "port %x, %s, int_status 0x%x," |
2327 | " int_mask 0x%x, saved_mask 0x%x, MI_INT %x, SERDES_LINK %x," | 2692 | " int_mask 0x%x, saved_mask 0x%x, MI_INT %x, SERDES_LINK %x," |
2328 | " 10G %x, XGXS_LINK %x\n", port, (bp->phy_flags & PHY_XGXS_FLAG), | 2693 | " 10G %x, XGXS_LINK %x\n", port, |
2694 | (bp->phy_flags & PHY_XGXS_FLAG)? "XGXS":"SerDes", | ||
2329 | REG_RD(bp, NIG_REG_STATUS_INTERRUPT_PORT0 + port*4), | 2695 | REG_RD(bp, NIG_REG_STATUS_INTERRUPT_PORT0 + port*4), |
2330 | REG_RD(bp, NIG_REG_MASK_INTERRUPT_PORT0 + port*4), bp->nig_mask, | 2696 | REG_RD(bp, NIG_REG_MASK_INTERRUPT_PORT0 + port*4), bp->nig_mask, |
2331 | REG_RD(bp, NIG_REG_EMAC0_STATUS_MISC_MI_INT + port*0x18), | 2697 | REG_RD(bp, NIG_REG_EMAC0_STATUS_MISC_MI_INT + port*0x18), |
@@ -2337,7 +2703,7 @@ static void bnx2x_link_update(struct bnx2x *bp) | |||
2337 | might_sleep(); | 2703 | might_sleep(); |
2338 | MDIO_SET_REG_BANK(bp, MDIO_REG_BANK_GP_STATUS); | 2704 | MDIO_SET_REG_BANK(bp, MDIO_REG_BANK_GP_STATUS); |
2339 | /* avoid fast toggling */ | 2705 | /* avoid fast toggling */ |
2340 | for (i = 0 ; i < 10 ; i++) { | 2706 | for (i = 0; i < 10; i++) { |
2341 | msleep(10); | 2707 | msleep(10); |
2342 | bnx2x_mdio22_read(bp, MDIO_GP_STATUS_TOP_AN_STATUS1, | 2708 | bnx2x_mdio22_read(bp, MDIO_GP_STATUS_TOP_AN_STATUS1, |
2343 | &gp_status); | 2709 | &gp_status); |
@@ -2352,7 +2718,8 @@ static void bnx2x_link_update(struct bnx2x *bp) | |||
2352 | bnx2x_link_int_ack(bp, link_10g); | 2718 | bnx2x_link_int_ack(bp, link_10g); |
2353 | 2719 | ||
2354 | /* link is up only if both local phy and external phy are up */ | 2720 | /* link is up only if both local phy and external phy are up */ |
2355 | if (bp->link_up && bnx2x_ext_phy_is_link_up(bp)) { | 2721 | bp->link_up = (bp->phy_link_up && bnx2x_ext_phy_is_link_up(bp)); |
2722 | if (bp->link_up) { | ||
2356 | if (link_10g) { | 2723 | if (link_10g) { |
2357 | bnx2x_bmac_enable(bp, 0); | 2724 | bnx2x_bmac_enable(bp, 0); |
2358 | bnx2x_leds_set(bp, SPEED_10000); | 2725 | bnx2x_leds_set(bp, SPEED_10000); |
@@ -2428,7 +2795,9 @@ static void bnx2x_reset_unicore(struct bnx2x *bp) | |||
2428 | } | 2795 | } |
2429 | } | 2796 | } |
2430 | 2797 | ||
2431 | BNX2X_ERR("BUG! unicore is still in reset!\n"); | 2798 | BNX2X_ERR("BUG! %s (0x%x) is still in reset!\n", |
2799 | (bp->phy_flags & PHY_XGXS_FLAG)? "XGXS":"SerDes", | ||
2800 | bp->phy_addr); | ||
2432 | } | 2801 | } |
2433 | 2802 | ||
2434 | static void bnx2x_set_swap_lanes(struct bnx2x *bp) | 2803 | static void bnx2x_set_swap_lanes(struct bnx2x *bp) |
@@ -2476,12 +2845,12 @@ static void bnx2x_set_parallel_detection(struct bnx2x *bp) | |||
2476 | MDIO_SET_REG_BANK(bp, MDIO_REG_BANK_10G_PARALLEL_DETECT); | 2845 | MDIO_SET_REG_BANK(bp, MDIO_REG_BANK_10G_PARALLEL_DETECT); |
2477 | 2846 | ||
2478 | bnx2x_mdio22_write(bp, | 2847 | bnx2x_mdio22_write(bp, |
2479 | MDIO_10G_PARALLEL_DETECT_PAR_DET_10G_LINK, | 2848 | MDIO_10G_PARALLEL_DETECT_PAR_DET_10G_LINK, |
2480 | MDIO_10G_PARALLEL_DETECT_PAR_DET_10G_LINK_CNT); | 2849 | MDIO_10G_PARALLEL_DETECT_PAR_DET_10G_LINK_CNT); |
2481 | 2850 | ||
2482 | bnx2x_mdio22_read(bp, | 2851 | bnx2x_mdio22_read(bp, |
2483 | MDIO_10G_PARALLEL_DETECT_PAR_DET_10G_CONTROL, | 2852 | MDIO_10G_PARALLEL_DETECT_PAR_DET_10G_CONTROL, |
2484 | &control2); | 2853 | &control2); |
2485 | 2854 | ||
2486 | if (bp->autoneg & AUTONEG_PARALLEL) { | 2855 | if (bp->autoneg & AUTONEG_PARALLEL) { |
2487 | control2 |= | 2856 | control2 |= |
@@ -2491,8 +2860,14 @@ static void bnx2x_set_parallel_detection(struct bnx2x *bp) | |||
2491 | ~MDIO_10G_PARALLEL_DETECT_PAR_DET_10G_CONTROL_PARDET10G_EN; | 2860 | ~MDIO_10G_PARALLEL_DETECT_PAR_DET_10G_CONTROL_PARDET10G_EN; |
2492 | } | 2861 | } |
2493 | bnx2x_mdio22_write(bp, | 2862 | bnx2x_mdio22_write(bp, |
2494 | MDIO_10G_PARALLEL_DETECT_PAR_DET_10G_CONTROL, | 2863 | MDIO_10G_PARALLEL_DETECT_PAR_DET_10G_CONTROL, |
2495 | control2); | 2864 | control2); |
2865 | |||
2866 | /* Disable parallel detection of HiG */ | ||
2867 | MDIO_SET_REG_BANK(bp, MDIO_REG_BANK_XGXS_BLOCK2); | ||
2868 | bnx2x_mdio22_write(bp, MDIO_XGXS_BLOCK2_UNICORE_MODE_10G, | ||
2869 | MDIO_XGXS_BLOCK2_UNICORE_MODE_10G_CX4_XGXS | | ||
2870 | MDIO_XGXS_BLOCK2_UNICORE_MODE_10G_HIGIG_XGXS); | ||
2496 | } | 2871 | } |
2497 | } | 2872 | } |
2498 | 2873 | ||
@@ -2626,7 +3001,7 @@ static void bnx2x_set_brcm_cl37_advertisment(struct bnx2x *bp) | |||
2626 | MDIO_SET_REG_BANK(bp, MDIO_REG_BANK_OVER_1G); | 3001 | MDIO_SET_REG_BANK(bp, MDIO_REG_BANK_OVER_1G); |
2627 | 3002 | ||
2628 | /* set extended capabilities */ | 3003 | /* set extended capabilities */ |
2629 | if (bp->advertising & ADVERTISED_2500baseT_Full) | 3004 | if (bp->advertising & ADVERTISED_2500baseX_Full) |
2630 | val |= MDIO_OVER_1G_UP1_2_5G; | 3005 | val |= MDIO_OVER_1G_UP1_2_5G; |
2631 | if (bp->advertising & ADVERTISED_10000baseT_Full) | 3006 | if (bp->advertising & ADVERTISED_10000baseT_Full) |
2632 | val |= MDIO_OVER_1G_UP1_10G; | 3007 | val |= MDIO_OVER_1G_UP1_10G; |
@@ -2642,20 +3017,91 @@ static void bnx2x_set_ieee_aneg_advertisment(struct bnx2x *bp) | |||
2642 | /* for AN, we are always publishing full duplex */ | 3017 | /* for AN, we are always publishing full duplex */ |
2643 | an_adv = MDIO_COMBO_IEEE0_AUTO_NEG_ADV_FULL_DUPLEX; | 3018 | an_adv = MDIO_COMBO_IEEE0_AUTO_NEG_ADV_FULL_DUPLEX; |
2644 | 3019 | ||
2645 | /* set pause */ | 3020 | /* resolve pause mode and advertisement |
2646 | switch (bp->pause_mode) { | 3021 | * Please refer to Table 28B-3 of the 802.3ab-1999 spec */ |
2647 | case PAUSE_SYMMETRIC: | 3022 | if (bp->req_autoneg & AUTONEG_FLOW_CTRL) { |
2648 | an_adv |= MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_SYMMETRIC; | 3023 | switch (bp->req_flow_ctrl) { |
2649 | break; | 3024 | case FLOW_CTRL_AUTO: |
2650 | case PAUSE_ASYMMETRIC: | 3025 | if (bp->dev->mtu <= 4500) { |
2651 | an_adv |= MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC; | 3026 | an_adv |= |
2652 | break; | 3027 | MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH; |
2653 | case PAUSE_BOTH: | 3028 | bp->advertising |= (ADVERTISED_Pause | |
2654 | an_adv |= MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH; | 3029 | ADVERTISED_Asym_Pause); |
2655 | break; | 3030 | } else { |
2656 | case PAUSE_NONE: | 3031 | an_adv |= |
2657 | an_adv |= MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_NONE; | 3032 | MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC; |
2658 | break; | 3033 | bp->advertising |= ADVERTISED_Asym_Pause; |
3034 | } | ||
3035 | break; | ||
3036 | |||
3037 | case FLOW_CTRL_TX: | ||
3038 | an_adv |= | ||
3039 | MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC; | ||
3040 | bp->advertising |= ADVERTISED_Asym_Pause; | ||
3041 | break; | ||
3042 | |||
3043 | case FLOW_CTRL_RX: | ||
3044 | if (bp->dev->mtu <= 4500) { | ||
3045 | an_adv |= | ||
3046 | MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH; | ||
3047 | bp->advertising |= (ADVERTISED_Pause | | ||
3048 | ADVERTISED_Asym_Pause); | ||
3049 | } else { | ||
3050 | an_adv |= | ||
3051 | MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_NONE; | ||
3052 | bp->advertising &= ~(ADVERTISED_Pause | | ||
3053 | ADVERTISED_Asym_Pause); | ||
3054 | } | ||
3055 | break; | ||
3056 | |||
3057 | case FLOW_CTRL_BOTH: | ||
3058 | if (bp->dev->mtu <= 4500) { | ||
3059 | an_adv |= | ||
3060 | MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH; | ||
3061 | bp->advertising |= (ADVERTISED_Pause | | ||
3062 | ADVERTISED_Asym_Pause); | ||
3063 | } else { | ||
3064 | an_adv |= | ||
3065 | MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC; | ||
3066 | bp->advertising |= ADVERTISED_Asym_Pause; | ||
3067 | } | ||
3068 | break; | ||
3069 | |||
3070 | case FLOW_CTRL_NONE: | ||
3071 | default: | ||
3072 | an_adv |= MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_NONE; | ||
3073 | bp->advertising &= ~(ADVERTISED_Pause | | ||
3074 | ADVERTISED_Asym_Pause); | ||
3075 | break; | ||
3076 | } | ||
3077 | } else { /* forced mode */ | ||
3078 | switch (bp->req_flow_ctrl) { | ||
3079 | case FLOW_CTRL_AUTO: | ||
3080 | DP(NETIF_MSG_LINK, "req_flow_ctrl 0x%x while" | ||
3081 | " req_autoneg 0x%x\n", | ||
3082 | bp->req_flow_ctrl, bp->req_autoneg); | ||
3083 | break; | ||
3084 | |||
3085 | case FLOW_CTRL_TX: | ||
3086 | an_adv |= | ||
3087 | MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC; | ||
3088 | bp->advertising |= ADVERTISED_Asym_Pause; | ||
3089 | break; | ||
3090 | |||
3091 | case FLOW_CTRL_RX: | ||
3092 | case FLOW_CTRL_BOTH: | ||
3093 | an_adv |= MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH; | ||
3094 | bp->advertising |= (ADVERTISED_Pause | | ||
3095 | ADVERTISED_Asym_Pause); | ||
3096 | break; | ||
3097 | |||
3098 | case FLOW_CTRL_NONE: | ||
3099 | default: | ||
3100 | an_adv |= MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_NONE; | ||
3101 | bp->advertising &= ~(ADVERTISED_Pause | | ||
3102 | ADVERTISED_Asym_Pause); | ||
3103 | break; | ||
3104 | } | ||
2659 | } | 3105 | } |
2660 | 3106 | ||
2661 | MDIO_SET_REG_BANK(bp, MDIO_REG_BANK_COMBO_IEEE0); | 3107 | MDIO_SET_REG_BANK(bp, MDIO_REG_BANK_COMBO_IEEE0); |
@@ -2753,47 +3199,162 @@ static void bnx2x_initialize_sgmii_process(struct bnx2x *bp) | |||
2753 | static void bnx2x_link_int_enable(struct bnx2x *bp) | 3199 | static void bnx2x_link_int_enable(struct bnx2x *bp) |
2754 | { | 3200 | { |
2755 | int port = bp->port; | 3201 | int port = bp->port; |
3202 | u32 ext_phy_type; | ||
3203 | u32 mask; | ||
2756 | 3204 | ||
2757 | /* setting the status to report on link up | 3205 | /* setting the status to report on link up |
2758 | for either XGXS or SerDes */ | 3206 | for either XGXS or SerDes */ |
2759 | bnx2x_bits_dis(bp, NIG_REG_STATUS_INTERRUPT_PORT0 + port*4, | 3207 | bnx2x_bits_dis(bp, NIG_REG_STATUS_INTERRUPT_PORT0 + port*4, |
2760 | (NIG_XGXS0_LINK_STATUS | | 3208 | (NIG_STATUS_XGXS0_LINK10G | |
2761 | NIG_STATUS_INTERRUPT_XGXS0_LINK10G | | 3209 | NIG_STATUS_XGXS0_LINK_STATUS | |
2762 | NIG_SERDES0_LINK_STATUS)); | 3210 | NIG_STATUS_SERDES0_LINK_STATUS)); |
2763 | 3211 | ||
2764 | if (bp->phy_flags & PHY_XGXS_FLAG) { | 3212 | if (bp->phy_flags & PHY_XGXS_FLAG) { |
2765 | /* TBD - | 3213 | mask = (NIG_MASK_XGXS0_LINK10G | |
2766 | * in force mode (not AN) we can enable just the relevant | 3214 | NIG_MASK_XGXS0_LINK_STATUS); |
2767 | * interrupt | 3215 | DP(NETIF_MSG_LINK, "enabled XGXS interrupt\n"); |
2768 | * Even in AN we might enable only one according to the AN | 3216 | ext_phy_type = XGXS_EXT_PHY_TYPE(bp); |
2769 | * speed mask | 3217 | if ((ext_phy_type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT) && |
2770 | */ | 3218 | (ext_phy_type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_FAILURE) && |
2771 | bnx2x_bits_en(bp, NIG_REG_MASK_INTERRUPT_PORT0 + port*4, | 3219 | (ext_phy_type != |
2772 | (NIG_MASK_XGXS0_LINK_STATUS | | 3220 | PORT_HW_CFG_XGXS_EXT_PHY_TYPE_NOT_CONN)) { |
2773 | NIG_MASK_XGXS0_LINK10G)); | 3221 | mask |= NIG_MASK_MI_INT; |
2774 | DP(NETIF_MSG_LINK, "enable XGXS interrupt\n"); | 3222 | DP(NETIF_MSG_LINK, "enabled external phy int\n"); |
3223 | } | ||
2775 | 3224 | ||
2776 | } else { /* SerDes */ | 3225 | } else { /* SerDes */ |
2777 | bnx2x_bits_en(bp, NIG_REG_MASK_INTERRUPT_PORT0 + port*4, | 3226 | mask = NIG_MASK_SERDES0_LINK_STATUS; |
2778 | NIG_MASK_SERDES0_LINK_STATUS); | 3227 | DP(NETIF_MSG_LINK, "enabled SerDes interrupt\n"); |
2779 | DP(NETIF_MSG_LINK, "enable SerDes interrupt\n"); | 3228 | ext_phy_type = SERDES_EXT_PHY_TYPE(bp); |
3229 | if ((ext_phy_type != | ||
3230 | PORT_HW_CFG_SERDES_EXT_PHY_TYPE_DIRECT) && | ||
3231 | (ext_phy_type != | ||
3232 | PORT_HW_CFG_SERDES_EXT_PHY_TYPE_NOT_CONN)) { | ||
3233 | mask |= NIG_MASK_MI_INT; | ||
3234 | DP(NETIF_MSG_LINK, "enabled external phy int\n"); | ||
3235 | } | ||
2780 | } | 3236 | } |
3237 | bnx2x_bits_en(bp, | ||
3238 | NIG_REG_MASK_INTERRUPT_PORT0 + port*4, | ||
3239 | mask); | ||
3240 | DP(NETIF_MSG_LINK, "port %x, %s, int_status 0x%x," | ||
3241 | " int_mask 0x%x, MI_INT %x, SERDES_LINK %x," | ||
3242 | " 10G %x, XGXS_LINK %x\n", port, | ||
3243 | (bp->phy_flags & PHY_XGXS_FLAG)? "XGXS":"SerDes", | ||
3244 | REG_RD(bp, NIG_REG_STATUS_INTERRUPT_PORT0 + port*4), | ||
3245 | REG_RD(bp, NIG_REG_MASK_INTERRUPT_PORT0 + port*4), | ||
3246 | REG_RD(bp, NIG_REG_EMAC0_STATUS_MISC_MI_INT + port*0x18), | ||
3247 | REG_RD(bp, NIG_REG_SERDES0_STATUS_LINK_STATUS + port*0x3c), | ||
3248 | REG_RD(bp, NIG_REG_XGXS0_STATUS_LINK10G + port*0x68), | ||
3249 | REG_RD(bp, NIG_REG_XGXS0_STATUS_LINK_STATUS + port*0x68) | ||
3250 | ); | ||
3251 | } | ||
3252 | |||
3253 | static void bnx2x_bcm8072_external_rom_boot(struct bnx2x *bp) | ||
3254 | { | ||
3255 | u32 ext_phy_addr = ((bp->ext_phy_config & | ||
3256 | PORT_HW_CFG_XGXS_EXT_PHY_ADDR_MASK) >> | ||
3257 | PORT_HW_CFG_XGXS_EXT_PHY_ADDR_SHIFT); | ||
3258 | u32 fw_ver1, fw_ver2; | ||
3259 | |||
3260 | /* Need to wait 200ms after reset */ | ||
3261 | msleep(200); | ||
3262 | /* Boot port from external ROM | ||
3263 | * Set ser_boot_ctl bit in the MISC_CTRL1 register | ||
3264 | */ | ||
3265 | bnx2x_mdio45_ctrl_write(bp, GRCBASE_EMAC0, ext_phy_addr, | ||
3266 | EXT_PHY_KR_PMA_PMD_DEVAD, | ||
3267 | EXT_PHY_KR_MISC_CTRL1, 0x0001); | ||
3268 | |||
3269 | /* Reset internal microprocessor */ | ||
3270 | bnx2x_mdio45_ctrl_write(bp, GRCBASE_EMAC0, ext_phy_addr, | ||
3271 | EXT_PHY_KR_PMA_PMD_DEVAD, EXT_PHY_KR_GEN_CTRL, | ||
3272 | EXT_PHY_KR_ROM_RESET_INTERNAL_MP); | ||
3273 | /* set micro reset = 0 */ | ||
3274 | bnx2x_mdio45_ctrl_write(bp, GRCBASE_EMAC0, ext_phy_addr, | ||
3275 | EXT_PHY_KR_PMA_PMD_DEVAD, EXT_PHY_KR_GEN_CTRL, | ||
3276 | EXT_PHY_KR_ROM_MICRO_RESET); | ||
3277 | /* Reset internal microprocessor */ | ||
3278 | bnx2x_mdio45_ctrl_write(bp, GRCBASE_EMAC0, ext_phy_addr, | ||
3279 | EXT_PHY_KR_PMA_PMD_DEVAD, EXT_PHY_KR_GEN_CTRL, | ||
3280 | EXT_PHY_KR_ROM_RESET_INTERNAL_MP); | ||
3281 | /* wait for 100ms for code download via SPI port */ | ||
3282 | msleep(100); | ||
3283 | |||
3284 | /* Clear ser_boot_ctl bit */ | ||
3285 | bnx2x_mdio45_ctrl_write(bp, GRCBASE_EMAC0, ext_phy_addr, | ||
3286 | EXT_PHY_KR_PMA_PMD_DEVAD, | ||
3287 | EXT_PHY_KR_MISC_CTRL1, 0x0000); | ||
3288 | /* Wait 100ms */ | ||
3289 | msleep(100); | ||
3290 | |||
3291 | /* Print the PHY FW version */ | ||
3292 | bnx2x_mdio45_ctrl_read(bp, GRCBASE_EMAC0, ext_phy_addr, | ||
3293 | EXT_PHY_KR_PMA_PMD_DEVAD, | ||
3294 | 0xca19, &fw_ver1); | ||
3295 | bnx2x_mdio45_ctrl_read(bp, GRCBASE_EMAC0, ext_phy_addr, | ||
3296 | EXT_PHY_KR_PMA_PMD_DEVAD, | ||
3297 | 0xca1a, &fw_ver2); | ||
3298 | DP(NETIF_MSG_LINK, | ||
3299 | "8072 FW version 0x%x:0x%x\n", fw_ver1, fw_ver2); | ||
3300 | } | ||
3301 | |||
3302 | static void bnx2x_bcm8072_force_10G(struct bnx2x *bp) | ||
3303 | { | ||
3304 | u32 ext_phy_addr = ((bp->ext_phy_config & | ||
3305 | PORT_HW_CFG_XGXS_EXT_PHY_ADDR_MASK) >> | ||
3306 | PORT_HW_CFG_XGXS_EXT_PHY_ADDR_SHIFT); | ||
3307 | |||
3308 | /* Force KR or KX */ | ||
3309 | bnx2x_mdio45_ctrl_write(bp, GRCBASE_EMAC0, ext_phy_addr, | ||
3310 | EXT_PHY_KR_PMA_PMD_DEVAD, EXT_PHY_KR_CTRL, | ||
3311 | 0x2040); | ||
3312 | bnx2x_mdio45_ctrl_write(bp, GRCBASE_EMAC0, ext_phy_addr, | ||
3313 | EXT_PHY_KR_PMA_PMD_DEVAD, EXT_PHY_KR_CTRL2, | ||
3314 | 0x000b); | ||
3315 | bnx2x_mdio45_ctrl_write(bp, GRCBASE_EMAC0, ext_phy_addr, | ||
3316 | EXT_PHY_KR_PMA_PMD_DEVAD, EXT_PHY_KR_PMD_CTRL, | ||
3317 | 0x0000); | ||
3318 | bnx2x_mdio45_ctrl_write(bp, GRCBASE_EMAC0, ext_phy_addr, | ||
3319 | EXT_PHY_KR_AUTO_NEG_DEVAD, EXT_PHY_KR_CTRL, | ||
3320 | 0x0000); | ||
2781 | } | 3321 | } |
2782 | 3322 | ||
2783 | static void bnx2x_ext_phy_init(struct bnx2x *bp) | 3323 | static void bnx2x_ext_phy_init(struct bnx2x *bp) |
2784 | { | 3324 | { |
2785 | int port = bp->port; | ||
2786 | u32 ext_phy_type; | 3325 | u32 ext_phy_type; |
2787 | u32 ext_phy_addr; | 3326 | u32 ext_phy_addr; |
2788 | u32 local_phy; | 3327 | u32 cnt; |
3328 | u32 ctrl; | ||
3329 | u32 val = 0; | ||
2789 | 3330 | ||
2790 | if (bp->phy_flags & PHY_XGXS_FLAG) { | 3331 | if (bp->phy_flags & PHY_XGXS_FLAG) { |
2791 | local_phy = bp->phy_addr; | ||
2792 | ext_phy_addr = ((bp->ext_phy_config & | 3332 | ext_phy_addr = ((bp->ext_phy_config & |
2793 | PORT_HW_CFG_XGXS_EXT_PHY_ADDR_MASK) >> | 3333 | PORT_HW_CFG_XGXS_EXT_PHY_ADDR_MASK) >> |
2794 | PORT_HW_CFG_XGXS_EXT_PHY_ADDR_SHIFT); | 3334 | PORT_HW_CFG_XGXS_EXT_PHY_ADDR_SHIFT); |
2795 | 3335 | ||
2796 | ext_phy_type = XGXS_EXT_PHY_TYPE(bp); | 3336 | ext_phy_type = XGXS_EXT_PHY_TYPE(bp); |
3337 | /* Make sure that the soft reset is off (expect for the 8072: | ||
3338 | * due to the lock, it will be done inside the specific | ||
3339 | * handling) | ||
3340 | */ | ||
3341 | if ((ext_phy_type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT) && | ||
3342 | (ext_phy_type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_FAILURE) && | ||
3343 | (ext_phy_type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_NOT_CONN) && | ||
3344 | (ext_phy_type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072)) { | ||
3345 | /* Wait for soft reset to get cleared upto 1 sec */ | ||
3346 | for (cnt = 0; cnt < 1000; cnt++) { | ||
3347 | bnx2x_mdio45_read(bp, ext_phy_addr, | ||
3348 | EXT_PHY_OPT_PMA_PMD_DEVAD, | ||
3349 | EXT_PHY_OPT_CNTL, &ctrl); | ||
3350 | if (!(ctrl & (1<<15))) | ||
3351 | break; | ||
3352 | msleep(1); | ||
3353 | } | ||
3354 | DP(NETIF_MSG_LINK, | ||
3355 | "control reg 0x%x (after %d ms)\n", ctrl, cnt); | ||
3356 | } | ||
3357 | |||
2797 | switch (ext_phy_type) { | 3358 | switch (ext_phy_type) { |
2798 | case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT: | 3359 | case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT: |
2799 | DP(NETIF_MSG_LINK, "XGXS Direct\n"); | 3360 | DP(NETIF_MSG_LINK, "XGXS Direct\n"); |
@@ -2801,49 +3362,235 @@ static void bnx2x_ext_phy_init(struct bnx2x *bp) | |||
2801 | 3362 | ||
2802 | case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705: | 3363 | case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705: |
2803 | DP(NETIF_MSG_LINK, "XGXS 8705\n"); | 3364 | DP(NETIF_MSG_LINK, "XGXS 8705\n"); |
2804 | bnx2x_bits_en(bp, | ||
2805 | NIG_REG_MASK_INTERRUPT_PORT0 + port*4, | ||
2806 | NIG_MASK_MI_INT); | ||
2807 | DP(NETIF_MSG_LINK, "enabled external phy int\n"); | ||
2808 | 3365 | ||
2809 | bp->phy_addr = ext_phy_type; | 3366 | bnx2x_mdio45_vwrite(bp, ext_phy_addr, |
2810 | bnx2x_mdio45_vwrite(bp, EXT_PHY_OPT_PMA_PMD_DEVAD, | 3367 | EXT_PHY_OPT_PMA_PMD_DEVAD, |
2811 | EXT_PHY_OPT_PMD_MISC_CNTL, | 3368 | EXT_PHY_OPT_PMD_MISC_CNTL, |
2812 | 0x8288); | 3369 | 0x8288); |
2813 | bnx2x_mdio45_vwrite(bp, EXT_PHY_OPT_PMA_PMD_DEVAD, | 3370 | bnx2x_mdio45_vwrite(bp, ext_phy_addr, |
3371 | EXT_PHY_OPT_PMA_PMD_DEVAD, | ||
2814 | EXT_PHY_OPT_PHY_IDENTIFIER, | 3372 | EXT_PHY_OPT_PHY_IDENTIFIER, |
2815 | 0x7fbf); | 3373 | 0x7fbf); |
2816 | bnx2x_mdio45_vwrite(bp, EXT_PHY_OPT_PMA_PMD_DEVAD, | 3374 | bnx2x_mdio45_vwrite(bp, ext_phy_addr, |
3375 | EXT_PHY_OPT_PMA_PMD_DEVAD, | ||
2817 | EXT_PHY_OPT_CMU_PLL_BYPASS, | 3376 | EXT_PHY_OPT_CMU_PLL_BYPASS, |
2818 | 0x0100); | 3377 | 0x0100); |
2819 | bnx2x_mdio45_vwrite(bp, EXT_PHY_OPT_WIS_DEVAD, | 3378 | bnx2x_mdio45_vwrite(bp, ext_phy_addr, |
3379 | EXT_PHY_OPT_WIS_DEVAD, | ||
2820 | EXT_PHY_OPT_LASI_CNTL, 0x1); | 3380 | EXT_PHY_OPT_LASI_CNTL, 0x1); |
2821 | break; | 3381 | break; |
2822 | 3382 | ||
2823 | case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8706: | 3383 | case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8706: |
2824 | DP(NETIF_MSG_LINK, "XGXS 8706\n"); | 3384 | DP(NETIF_MSG_LINK, "XGXS 8706\n"); |
2825 | bnx2x_bits_en(bp, | ||
2826 | NIG_REG_MASK_INTERRUPT_PORT0 + port*4, | ||
2827 | NIG_MASK_MI_INT); | ||
2828 | DP(NETIF_MSG_LINK, "enabled external phy int\n"); | ||
2829 | 3385 | ||
2830 | bp->phy_addr = ext_phy_type; | 3386 | if (!(bp->req_autoneg & AUTONEG_SPEED)) { |
2831 | bnx2x_mdio45_vwrite(bp, EXT_PHY_OPT_PMA_PMD_DEVAD, | 3387 | /* Force speed */ |
2832 | EXT_PHY_OPT_PMD_DIGITAL_CNT, | 3388 | if (bp->req_line_speed == SPEED_10000) { |
2833 | 0x400); | 3389 | DP(NETIF_MSG_LINK, |
2834 | bnx2x_mdio45_vwrite(bp, EXT_PHY_OPT_PMA_PMD_DEVAD, | 3390 | "XGXS 8706 force 10Gbps\n"); |
3391 | bnx2x_mdio45_vwrite(bp, ext_phy_addr, | ||
3392 | EXT_PHY_OPT_PMA_PMD_DEVAD, | ||
3393 | EXT_PHY_OPT_PMD_DIGITAL_CNT, | ||
3394 | 0x400); | ||
3395 | } else { | ||
3396 | /* Force 1Gbps */ | ||
3397 | DP(NETIF_MSG_LINK, | ||
3398 | "XGXS 8706 force 1Gbps\n"); | ||
3399 | |||
3400 | bnx2x_mdio45_vwrite(bp, ext_phy_addr, | ||
3401 | EXT_PHY_OPT_PMA_PMD_DEVAD, | ||
3402 | EXT_PHY_OPT_CNTL, | ||
3403 | 0x0040); | ||
3404 | |||
3405 | bnx2x_mdio45_vwrite(bp, ext_phy_addr, | ||
3406 | EXT_PHY_OPT_PMA_PMD_DEVAD, | ||
3407 | EXT_PHY_OPT_CNTL2, | ||
3408 | 0x000D); | ||
3409 | } | ||
3410 | |||
3411 | /* Enable LASI */ | ||
3412 | bnx2x_mdio45_vwrite(bp, ext_phy_addr, | ||
3413 | EXT_PHY_OPT_PMA_PMD_DEVAD, | ||
3414 | EXT_PHY_OPT_LASI_CNTL, | ||
3415 | 0x1); | ||
3416 | } else { | ||
3417 | /* AUTONEG */ | ||
3418 | /* Allow CL37 through CL73 */ | ||
3419 | DP(NETIF_MSG_LINK, "XGXS 8706 AutoNeg\n"); | ||
3420 | bnx2x_mdio45_vwrite(bp, ext_phy_addr, | ||
3421 | EXT_PHY_AUTO_NEG_DEVAD, | ||
3422 | EXT_PHY_OPT_AN_CL37_CL73, | ||
3423 | 0x040c); | ||
3424 | |||
3425 | /* Enable Full-Duplex advertisment on CL37 */ | ||
3426 | bnx2x_mdio45_vwrite(bp, ext_phy_addr, | ||
3427 | EXT_PHY_AUTO_NEG_DEVAD, | ||
3428 | EXT_PHY_OPT_AN_CL37_FD, | ||
3429 | 0x0020); | ||
3430 | /* Enable CL37 AN */ | ||
3431 | bnx2x_mdio45_vwrite(bp, ext_phy_addr, | ||
3432 | EXT_PHY_AUTO_NEG_DEVAD, | ||
3433 | EXT_PHY_OPT_AN_CL37_AN, | ||
3434 | 0x1000); | ||
3435 | /* Advertise 10G/1G support */ | ||
3436 | if (bp->advertising & | ||
3437 | ADVERTISED_1000baseT_Full) | ||
3438 | val = (1<<5); | ||
3439 | if (bp->advertising & | ||
3440 | ADVERTISED_10000baseT_Full) | ||
3441 | val |= (1<<7); | ||
3442 | |||
3443 | bnx2x_mdio45_vwrite(bp, ext_phy_addr, | ||
3444 | EXT_PHY_AUTO_NEG_DEVAD, | ||
3445 | EXT_PHY_OPT_AN_ADV, val); | ||
3446 | /* Enable LASI */ | ||
3447 | bnx2x_mdio45_vwrite(bp, ext_phy_addr, | ||
3448 | EXT_PHY_OPT_PMA_PMD_DEVAD, | ||
3449 | EXT_PHY_OPT_LASI_CNTL, | ||
3450 | 0x1); | ||
3451 | |||
3452 | /* Enable clause 73 AN */ | ||
3453 | bnx2x_mdio45_write(bp, ext_phy_addr, | ||
3454 | EXT_PHY_AUTO_NEG_DEVAD, | ||
3455 | EXT_PHY_OPT_CNTL, | ||
3456 | 0x1200); | ||
3457 | } | ||
3458 | break; | ||
3459 | |||
3460 | case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072: | ||
3461 | bnx2x_hw_lock(bp, HW_LOCK_RESOURCE_8072_MDIO); | ||
3462 | /* Wait for soft reset to get cleared upto 1 sec */ | ||
3463 | for (cnt = 0; cnt < 1000; cnt++) { | ||
3464 | bnx2x_mdio45_ctrl_read(bp, GRCBASE_EMAC0, | ||
3465 | ext_phy_addr, | ||
3466 | EXT_PHY_OPT_PMA_PMD_DEVAD, | ||
3467 | EXT_PHY_OPT_CNTL, &ctrl); | ||
3468 | if (!(ctrl & (1<<15))) | ||
3469 | break; | ||
3470 | msleep(1); | ||
3471 | } | ||
3472 | DP(NETIF_MSG_LINK, | ||
3473 | "8072 control reg 0x%x (after %d ms)\n", | ||
3474 | ctrl, cnt); | ||
3475 | |||
3476 | bnx2x_bcm8072_external_rom_boot(bp); | ||
3477 | DP(NETIF_MSG_LINK, "Finshed loading 8072 KR ROM\n"); | ||
3478 | |||
3479 | /* enable LASI */ | ||
3480 | bnx2x_mdio45_ctrl_write(bp, GRCBASE_EMAC0, | ||
3481 | ext_phy_addr, | ||
3482 | EXT_PHY_KR_PMA_PMD_DEVAD, | ||
3483 | 0x9000, 0x0400); | ||
3484 | bnx2x_mdio45_ctrl_write(bp, GRCBASE_EMAC0, | ||
3485 | ext_phy_addr, | ||
3486 | EXT_PHY_KR_PMA_PMD_DEVAD, | ||
3487 | EXT_PHY_KR_LASI_CNTL, 0x0004); | ||
3488 | |||
3489 | /* If this is forced speed, set to KR or KX | ||
3490 | * (all other are not supported) | ||
3491 | */ | ||
3492 | if (!(bp->req_autoneg & AUTONEG_SPEED)) { | ||
3493 | if (bp->req_line_speed == SPEED_10000) { | ||
3494 | bnx2x_bcm8072_force_10G(bp); | ||
3495 | DP(NETIF_MSG_LINK, | ||
3496 | "Forced speed 10G on 8072\n"); | ||
3497 | /* unlock */ | ||
3498 | bnx2x_hw_unlock(bp, | ||
3499 | HW_LOCK_RESOURCE_8072_MDIO); | ||
3500 | break; | ||
3501 | } else | ||
3502 | val = (1<<5); | ||
3503 | } else { | ||
3504 | |||
3505 | /* Advertise 10G/1G support */ | ||
3506 | if (bp->advertising & | ||
3507 | ADVERTISED_1000baseT_Full) | ||
3508 | val = (1<<5); | ||
3509 | if (bp->advertising & | ||
3510 | ADVERTISED_10000baseT_Full) | ||
3511 | val |= (1<<7); | ||
3512 | } | ||
3513 | bnx2x_mdio45_ctrl_write(bp, GRCBASE_EMAC0, | ||
3514 | ext_phy_addr, | ||
3515 | EXT_PHY_KR_AUTO_NEG_DEVAD, | ||
3516 | 0x11, val); | ||
3517 | /* Add support for CL37 ( passive mode ) I */ | ||
3518 | bnx2x_mdio45_ctrl_write(bp, GRCBASE_EMAC0, | ||
3519 | ext_phy_addr, | ||
3520 | EXT_PHY_KR_AUTO_NEG_DEVAD, | ||
3521 | 0x8370, 0x040c); | ||
3522 | /* Add support for CL37 ( passive mode ) II */ | ||
3523 | bnx2x_mdio45_ctrl_write(bp, GRCBASE_EMAC0, | ||
3524 | ext_phy_addr, | ||
3525 | EXT_PHY_KR_AUTO_NEG_DEVAD, | ||
3526 | 0xffe4, 0x20); | ||
3527 | /* Add support for CL37 ( passive mode ) III */ | ||
3528 | bnx2x_mdio45_ctrl_write(bp, GRCBASE_EMAC0, | ||
3529 | ext_phy_addr, | ||
3530 | EXT_PHY_KR_AUTO_NEG_DEVAD, | ||
3531 | 0xffe0, 0x1000); | ||
3532 | /* Restart autoneg */ | ||
3533 | msleep(500); | ||
3534 | bnx2x_mdio45_ctrl_write(bp, GRCBASE_EMAC0, | ||
3535 | ext_phy_addr, | ||
3536 | EXT_PHY_KR_AUTO_NEG_DEVAD, | ||
3537 | EXT_PHY_KR_CTRL, 0x1200); | ||
3538 | DP(NETIF_MSG_LINK, "8072 Autoneg Restart: " | ||
3539 | "1G %ssupported 10G %ssupported\n", | ||
3540 | (val & (1<<5)) ? "" : "not ", | ||
3541 | (val & (1<<7)) ? "" : "not "); | ||
3542 | |||
3543 | /* unlock */ | ||
3544 | bnx2x_hw_unlock(bp, HW_LOCK_RESOURCE_8072_MDIO); | ||
3545 | break; | ||
3546 | |||
3547 | case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101: | ||
3548 | DP(NETIF_MSG_LINK, | ||
3549 | "Setting the SFX7101 LASI indication\n"); | ||
3550 | bnx2x_mdio45_vwrite(bp, ext_phy_addr, | ||
3551 | EXT_PHY_OPT_PMA_PMD_DEVAD, | ||
2835 | EXT_PHY_OPT_LASI_CNTL, 0x1); | 3552 | EXT_PHY_OPT_LASI_CNTL, 0x1); |
3553 | DP(NETIF_MSG_LINK, | ||
3554 | "Setting the SFX7101 LED to blink on traffic\n"); | ||
3555 | bnx2x_mdio45_vwrite(bp, ext_phy_addr, | ||
3556 | EXT_PHY_OPT_PMA_PMD_DEVAD, | ||
3557 | 0xC007, (1<<3)); | ||
3558 | |||
3559 | /* read modify write pause advertizing */ | ||
3560 | bnx2x_mdio45_read(bp, ext_phy_addr, | ||
3561 | EXT_PHY_KR_AUTO_NEG_DEVAD, | ||
3562 | EXT_PHY_KR_AUTO_NEG_ADVERT, &val); | ||
3563 | val &= ~EXT_PHY_KR_AUTO_NEG_ADVERT_PAUSE_BOTH; | ||
3564 | /* Please refer to Table 28B-3 of 802.3ab-1999 spec. */ | ||
3565 | if (bp->advertising & ADVERTISED_Pause) | ||
3566 | val |= EXT_PHY_KR_AUTO_NEG_ADVERT_PAUSE; | ||
3567 | |||
3568 | if (bp->advertising & ADVERTISED_Asym_Pause) { | ||
3569 | val |= | ||
3570 | EXT_PHY_KR_AUTO_NEG_ADVERT_PAUSE_ASYMMETRIC; | ||
3571 | } | ||
3572 | DP(NETIF_MSG_LINK, "SFX7101 AN advertize 0x%x\n", val); | ||
3573 | bnx2x_mdio45_vwrite(bp, ext_phy_addr, | ||
3574 | EXT_PHY_KR_AUTO_NEG_DEVAD, | ||
3575 | EXT_PHY_KR_AUTO_NEG_ADVERT, val); | ||
3576 | /* Restart autoneg */ | ||
3577 | bnx2x_mdio45_read(bp, ext_phy_addr, | ||
3578 | EXT_PHY_KR_AUTO_NEG_DEVAD, | ||
3579 | EXT_PHY_KR_CTRL, &val); | ||
3580 | val |= 0x200; | ||
3581 | bnx2x_mdio45_write(bp, ext_phy_addr, | ||
3582 | EXT_PHY_KR_AUTO_NEG_DEVAD, | ||
3583 | EXT_PHY_KR_CTRL, val); | ||
2836 | break; | 3584 | break; |
2837 | 3585 | ||
2838 | default: | 3586 | default: |
2839 | DP(NETIF_MSG_LINK, "BAD XGXS ext_phy_config 0x%x\n", | 3587 | BNX2X_ERR("BAD XGXS ext_phy_config 0x%x\n", |
2840 | bp->ext_phy_config); | 3588 | bp->ext_phy_config); |
2841 | break; | 3589 | break; |
2842 | } | 3590 | } |
2843 | bp->phy_addr = local_phy; | ||
2844 | 3591 | ||
2845 | } else { /* SerDes */ | 3592 | } else { /* SerDes */ |
2846 | /* ext_phy_addr = ((bp->ext_phy_config & | 3593 | /* ext_phy_addr = ((bp->ext_phy_config & |
2847 | PORT_HW_CFG_SERDES_EXT_PHY_ADDR_MASK) >> | 3594 | PORT_HW_CFG_SERDES_EXT_PHY_ADDR_MASK) >> |
2848 | PORT_HW_CFG_SERDES_EXT_PHY_ADDR_SHIFT); | 3595 | PORT_HW_CFG_SERDES_EXT_PHY_ADDR_SHIFT); |
2849 | */ | 3596 | */ |
@@ -2855,10 +3602,6 @@ static void bnx2x_ext_phy_init(struct bnx2x *bp) | |||
2855 | 3602 | ||
2856 | case PORT_HW_CFG_SERDES_EXT_PHY_TYPE_BCM5482: | 3603 | case PORT_HW_CFG_SERDES_EXT_PHY_TYPE_BCM5482: |
2857 | DP(NETIF_MSG_LINK, "SerDes 5482\n"); | 3604 | DP(NETIF_MSG_LINK, "SerDes 5482\n"); |
2858 | bnx2x_bits_en(bp, | ||
2859 | NIG_REG_MASK_INTERRUPT_PORT0 + port*4, | ||
2860 | NIG_MASK_MI_INT); | ||
2861 | DP(NETIF_MSG_LINK, "enabled external phy int\n"); | ||
2862 | break; | 3605 | break; |
2863 | 3606 | ||
2864 | default: | 3607 | default: |
@@ -2872,8 +3615,22 @@ static void bnx2x_ext_phy_init(struct bnx2x *bp) | |||
2872 | static void bnx2x_ext_phy_reset(struct bnx2x *bp) | 3615 | static void bnx2x_ext_phy_reset(struct bnx2x *bp) |
2873 | { | 3616 | { |
2874 | u32 ext_phy_type; | 3617 | u32 ext_phy_type; |
2875 | u32 ext_phy_addr; | 3618 | u32 ext_phy_addr = ((bp->ext_phy_config & |
2876 | u32 local_phy; | 3619 | PORT_HW_CFG_XGXS_EXT_PHY_ADDR_MASK) >> |
3620 | PORT_HW_CFG_XGXS_EXT_PHY_ADDR_SHIFT); | ||
3621 | u32 board = (bp->board & SHARED_HW_CFG_BOARD_TYPE_MASK); | ||
3622 | |||
3623 | /* The PHY reset is controled by GPIO 1 | ||
3624 | * Give it 1ms of reset pulse | ||
3625 | */ | ||
3626 | if ((board != SHARED_HW_CFG_BOARD_TYPE_BCM957710T1002G) && | ||
3627 | (board != SHARED_HW_CFG_BOARD_TYPE_BCM957710T1003G)) { | ||
3628 | bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_1, | ||
3629 | MISC_REGISTERS_GPIO_OUTPUT_LOW); | ||
3630 | msleep(1); | ||
3631 | bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_1, | ||
3632 | MISC_REGISTERS_GPIO_OUTPUT_HIGH); | ||
3633 | } | ||
2877 | 3634 | ||
2878 | if (bp->phy_flags & PHY_XGXS_FLAG) { | 3635 | if (bp->phy_flags & PHY_XGXS_FLAG) { |
2879 | ext_phy_type = XGXS_EXT_PHY_TYPE(bp); | 3636 | ext_phy_type = XGXS_EXT_PHY_TYPE(bp); |
@@ -2884,15 +3641,24 @@ static void bnx2x_ext_phy_reset(struct bnx2x *bp) | |||
2884 | 3641 | ||
2885 | case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705: | 3642 | case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705: |
2886 | case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8706: | 3643 | case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8706: |
2887 | DP(NETIF_MSG_LINK, "XGXS 8705/6\n"); | 3644 | DP(NETIF_MSG_LINK, "XGXS 8705/8706\n"); |
2888 | local_phy = bp->phy_addr; | 3645 | bnx2x_mdio45_write(bp, ext_phy_addr, |
2889 | ext_phy_addr = ((bp->ext_phy_config & | 3646 | EXT_PHY_OPT_PMA_PMD_DEVAD, |
2890 | PORT_HW_CFG_XGXS_EXT_PHY_ADDR_MASK) >> | ||
2891 | PORT_HW_CFG_XGXS_EXT_PHY_ADDR_SHIFT); | ||
2892 | bp->phy_addr = (u8)ext_phy_addr; | ||
2893 | bnx2x_mdio45_write(bp, EXT_PHY_OPT_PMA_PMD_DEVAD, | ||
2894 | EXT_PHY_OPT_CNTL, 0xa040); | 3647 | EXT_PHY_OPT_CNTL, 0xa040); |
2895 | bp->phy_addr = local_phy; | 3648 | break; |
3649 | |||
3650 | case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072: | ||
3651 | DP(NETIF_MSG_LINK, "XGXS 8072\n"); | ||
3652 | bnx2x_hw_lock(bp, HW_LOCK_RESOURCE_8072_MDIO); | ||
3653 | bnx2x_mdio45_ctrl_write(bp, GRCBASE_EMAC0, | ||
3654 | ext_phy_addr, | ||
3655 | EXT_PHY_KR_PMA_PMD_DEVAD, | ||
3656 | 0, 1<<15); | ||
3657 | bnx2x_hw_unlock(bp, HW_LOCK_RESOURCE_8072_MDIO); | ||
3658 | break; | ||
3659 | |||
3660 | case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101: | ||
3661 | DP(NETIF_MSG_LINK, "XGXS SFX7101\n"); | ||
2896 | break; | 3662 | break; |
2897 | 3663 | ||
2898 | default: | 3664 | default: |
@@ -2931,6 +3697,7 @@ static void bnx2x_link_initialize(struct bnx2x *bp) | |||
2931 | NIG_MASK_SERDES0_LINK_STATUS | | 3697 | NIG_MASK_SERDES0_LINK_STATUS | |
2932 | NIG_MASK_MI_INT)); | 3698 | NIG_MASK_MI_INT)); |
2933 | 3699 | ||
3700 | /* Activate the external PHY */ | ||
2934 | bnx2x_ext_phy_reset(bp); | 3701 | bnx2x_ext_phy_reset(bp); |
2935 | 3702 | ||
2936 | bnx2x_set_aer_mmd(bp); | 3703 | bnx2x_set_aer_mmd(bp); |
@@ -3011,11 +3778,11 @@ static void bnx2x_link_initialize(struct bnx2x *bp) | |||
3011 | bnx2x_initialize_sgmii_process(bp); | 3778 | bnx2x_initialize_sgmii_process(bp); |
3012 | } | 3779 | } |
3013 | 3780 | ||
3014 | /* enable the interrupt */ | ||
3015 | bnx2x_link_int_enable(bp); | ||
3016 | |||
3017 | /* init ext phy and enable link state int */ | 3781 | /* init ext phy and enable link state int */ |
3018 | bnx2x_ext_phy_init(bp); | 3782 | bnx2x_ext_phy_init(bp); |
3783 | |||
3784 | /* enable the interrupt */ | ||
3785 | bnx2x_link_int_enable(bp); | ||
3019 | } | 3786 | } |
3020 | 3787 | ||
3021 | static void bnx2x_phy_deassert(struct bnx2x *bp) | 3788 | static void bnx2x_phy_deassert(struct bnx2x *bp) |
@@ -3074,6 +3841,11 @@ static int bnx2x_phy_init(struct bnx2x *bp) | |||
3074 | static void bnx2x_link_reset(struct bnx2x *bp) | 3841 | static void bnx2x_link_reset(struct bnx2x *bp) |
3075 | { | 3842 | { |
3076 | int port = bp->port; | 3843 | int port = bp->port; |
3844 | u32 board = (bp->board & SHARED_HW_CFG_BOARD_TYPE_MASK); | ||
3845 | |||
3846 | /* update shared memory */ | ||
3847 | bp->link_status = 0; | ||
3848 | bnx2x_update_mng(bp); | ||
3077 | 3849 | ||
3078 | /* disable attentions */ | 3850 | /* disable attentions */ |
3079 | bnx2x_bits_dis(bp, NIG_REG_MASK_INTERRUPT_PORT0 + port*4, | 3851 | bnx2x_bits_dis(bp, NIG_REG_MASK_INTERRUPT_PORT0 + port*4, |
@@ -3082,21 +3854,45 @@ static void bnx2x_link_reset(struct bnx2x *bp) | |||
3082 | NIG_MASK_SERDES0_LINK_STATUS | | 3854 | NIG_MASK_SERDES0_LINK_STATUS | |
3083 | NIG_MASK_MI_INT)); | 3855 | NIG_MASK_MI_INT)); |
3084 | 3856 | ||
3085 | bnx2x_ext_phy_reset(bp); | 3857 | /* activate nig drain */ |
3858 | NIG_WR(NIG_REG_EGRESS_DRAIN0_MODE + port*4, 1); | ||
3859 | |||
3860 | /* disable nig egress interface */ | ||
3861 | NIG_WR(NIG_REG_BMAC0_OUT_EN + port*4, 0); | ||
3862 | NIG_WR(NIG_REG_EGRESS_EMAC0_OUT_EN + port*4, 0); | ||
3863 | |||
3864 | /* Stop BigMac rx */ | ||
3865 | bnx2x_bmac_rx_disable(bp); | ||
3866 | |||
3867 | /* disable emac */ | ||
3868 | NIG_WR(NIG_REG_NIG_EMAC0_EN + port*4, 0); | ||
3869 | |||
3870 | msleep(10); | ||
3871 | |||
3872 | /* The PHY reset is controled by GPIO 1 | ||
3873 | * Hold it as output low | ||
3874 | */ | ||
3875 | if ((board != SHARED_HW_CFG_BOARD_TYPE_BCM957710T1002G) && | ||
3876 | (board != SHARED_HW_CFG_BOARD_TYPE_BCM957710T1003G)) { | ||
3877 | bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_1, | ||
3878 | MISC_REGISTERS_GPIO_OUTPUT_LOW); | ||
3879 | DP(NETIF_MSG_LINK, "reset external PHY\n"); | ||
3880 | } | ||
3086 | 3881 | ||
3087 | /* reset the SerDes/XGXS */ | 3882 | /* reset the SerDes/XGXS */ |
3088 | REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_3_CLEAR, | 3883 | REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_3_CLEAR, |
3089 | (0x1ff << (port*16))); | 3884 | (0x1ff << (port*16))); |
3090 | 3885 | ||
3091 | /* reset EMAC / BMAC and disable NIG interfaces */ | 3886 | /* reset BigMac */ |
3092 | NIG_WR(NIG_REG_BMAC0_IN_EN + port*4, 0); | 3887 | REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_CLEAR, |
3093 | NIG_WR(NIG_REG_BMAC0_OUT_EN + port*4, 0); | 3888 | (MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << port)); |
3094 | 3889 | ||
3095 | NIG_WR(NIG_REG_NIG_EMAC0_EN + port*4, 0); | 3890 | /* disable nig ingress interface */ |
3891 | NIG_WR(NIG_REG_BMAC0_IN_EN + port*4, 0); | ||
3096 | NIG_WR(NIG_REG_EMAC0_IN_EN + port*4, 0); | 3892 | NIG_WR(NIG_REG_EMAC0_IN_EN + port*4, 0); |
3097 | NIG_WR(NIG_REG_EGRESS_EMAC0_OUT_EN + port*4, 0); | ||
3098 | 3893 | ||
3099 | NIG_WR(NIG_REG_EGRESS_DRAIN0_MODE + port*4, 1); | 3894 | /* set link down */ |
3895 | bp->link_up = 0; | ||
3100 | } | 3896 | } |
3101 | 3897 | ||
3102 | #ifdef BNX2X_XGXS_LB | 3898 | #ifdef BNX2X_XGXS_LB |
@@ -3177,6 +3973,7 @@ static int bnx2x_sp_post(struct bnx2x *bp, int command, int cid, | |||
3177 | bnx2x_panic(); | 3973 | bnx2x_panic(); |
3178 | return -EBUSY; | 3974 | return -EBUSY; |
3179 | } | 3975 | } |
3976 | |||
3180 | /* CID needs port number to be encoded int it */ | 3977 | /* CID needs port number to be encoded int it */ |
3181 | bp->spq_prod_bd->hdr.conn_and_cmd_data = | 3978 | bp->spq_prod_bd->hdr.conn_and_cmd_data = |
3182 | cpu_to_le32(((command << SPE_HDR_CMD_ID_SHIFT) | | 3979 | cpu_to_le32(((command << SPE_HDR_CMD_ID_SHIFT) | |
@@ -4335,7 +5132,7 @@ static void bnx2x_timer(unsigned long data) | |||
4335 | return; | 5132 | return; |
4336 | 5133 | ||
4337 | if (atomic_read(&bp->intr_sem) != 0) | 5134 | if (atomic_read(&bp->intr_sem) != 0) |
4338 | goto bnx2x_restart_timer; | 5135 | goto timer_restart; |
4339 | 5136 | ||
4340 | if (poll) { | 5137 | if (poll) { |
4341 | struct bnx2x_fastpath *fp = &bp->fp[0]; | 5138 | struct bnx2x_fastpath *fp = &bp->fp[0]; |
@@ -4345,7 +5142,7 @@ static void bnx2x_timer(unsigned long data) | |||
4345 | rc = bnx2x_rx_int(fp, 1000); | 5142 | rc = bnx2x_rx_int(fp, 1000); |
4346 | } | 5143 | } |
4347 | 5144 | ||
4348 | if (!nomcp && (bp->bc_ver >= 0x040003)) { | 5145 | if (!nomcp) { |
4349 | int port = bp->port; | 5146 | int port = bp->port; |
4350 | u32 drv_pulse; | 5147 | u32 drv_pulse; |
4351 | u32 mcp_pulse; | 5148 | u32 mcp_pulse; |
@@ -4354,9 +5151,9 @@ static void bnx2x_timer(unsigned long data) | |||
4354 | bp->fw_drv_pulse_wr_seq &= DRV_PULSE_SEQ_MASK; | 5151 | bp->fw_drv_pulse_wr_seq &= DRV_PULSE_SEQ_MASK; |
4355 | /* TBD - add SYSTEM_TIME */ | 5152 | /* TBD - add SYSTEM_TIME */ |
4356 | drv_pulse = bp->fw_drv_pulse_wr_seq; | 5153 | drv_pulse = bp->fw_drv_pulse_wr_seq; |
4357 | SHMEM_WR(bp, drv_fw_mb[port].drv_pulse_mb, drv_pulse); | 5154 | SHMEM_WR(bp, func_mb[port].drv_pulse_mb, drv_pulse); |
4358 | 5155 | ||
4359 | mcp_pulse = (SHMEM_RD(bp, drv_fw_mb[port].mcp_pulse_mb) & | 5156 | mcp_pulse = (SHMEM_RD(bp, func_mb[port].mcp_pulse_mb) & |
4360 | MCP_PULSE_SEQ_MASK); | 5157 | MCP_PULSE_SEQ_MASK); |
4361 | /* The delta between driver pulse and mcp response | 5158 | /* The delta between driver pulse and mcp response |
4362 | * should be 1 (before mcp response) or 0 (after mcp response) | 5159 | * should be 1 (before mcp response) or 0 (after mcp response) |
@@ -4370,11 +5167,11 @@ static void bnx2x_timer(unsigned long data) | |||
4370 | } | 5167 | } |
4371 | 5168 | ||
4372 | if (bp->stats_state == STATS_STATE_DISABLE) | 5169 | if (bp->stats_state == STATS_STATE_DISABLE) |
4373 | goto bnx2x_restart_timer; | 5170 | goto timer_restart; |
4374 | 5171 | ||
4375 | bnx2x_update_stats(bp); | 5172 | bnx2x_update_stats(bp); |
4376 | 5173 | ||
4377 | bnx2x_restart_timer: | 5174 | timer_restart: |
4378 | mod_timer(&bp->timer, jiffies + bp->current_interval); | 5175 | mod_timer(&bp->timer, jiffies + bp->current_interval); |
4379 | } | 5176 | } |
4380 | 5177 | ||
@@ -5266,8 +6063,10 @@ static int bnx2x_function_init(struct bnx2x *bp, int mode) | |||
5266 | if (mode & 0x1) { /* init common */ | 6063 | if (mode & 0x1) { /* init common */ |
5267 | DP(BNX2X_MSG_MCP, "starting common init func %d mode %x\n", | 6064 | DP(BNX2X_MSG_MCP, "starting common init func %d mode %x\n", |
5268 | func, mode); | 6065 | func, mode); |
5269 | REG_WR(bp, MISC_REG_RESET_REG_1, 0xffffffff); | 6066 | REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_1_SET, |
5270 | REG_WR(bp, MISC_REG_RESET_REG_2, 0xfffc); | 6067 | 0xffffffff); |
6068 | REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_1_SET, | ||
6069 | 0xfffc); | ||
5271 | bnx2x_init_block(bp, MISC_COMMON_START, MISC_COMMON_END); | 6070 | bnx2x_init_block(bp, MISC_COMMON_START, MISC_COMMON_END); |
5272 | 6071 | ||
5273 | REG_WR(bp, MISC_REG_LCPLL_CTRL_REG_2, 0x100); | 6072 | REG_WR(bp, MISC_REG_LCPLL_CTRL_REG_2, 0x100); |
@@ -5487,6 +6286,28 @@ static int bnx2x_function_init(struct bnx2x *bp, int mode) | |||
5487 | enable_blocks_attention(bp); | 6286 | enable_blocks_attention(bp); |
5488 | /* enable_blocks_parity(bp); */ | 6287 | /* enable_blocks_parity(bp); */ |
5489 | 6288 | ||
6289 | switch (bp->board & SHARED_HW_CFG_BOARD_TYPE_MASK) { | ||
6290 | case SHARED_HW_CFG_BOARD_TYPE_BCM957710A1022G: | ||
6291 | /* Fan failure is indicated by SPIO 5 */ | ||
6292 | bnx2x_set_spio(bp, MISC_REGISTERS_SPIO_5, | ||
6293 | MISC_REGISTERS_SPIO_INPUT_HI_Z); | ||
6294 | |||
6295 | /* set to active low mode */ | ||
6296 | val = REG_RD(bp, MISC_REG_SPIO_INT); | ||
6297 | val |= ((1 << MISC_REGISTERS_SPIO_5) << | ||
6298 | MISC_REGISTERS_SPIO_INT_OLD_SET_POS); | ||
6299 | REG_WR(bp, MISC_REG_SPIO_INT, val); | ||
6300 | |||
6301 | /* enable interrupt to signal the IGU */ | ||
6302 | val = REG_RD(bp, MISC_REG_SPIO_EVENT_EN); | ||
6303 | val |= (1 << MISC_REGISTERS_SPIO_5); | ||
6304 | REG_WR(bp, MISC_REG_SPIO_EVENT_EN, val); | ||
6305 | break; | ||
6306 | |||
6307 | default: | ||
6308 | break; | ||
6309 | } | ||
6310 | |||
5490 | } /* end of common init */ | 6311 | } /* end of common init */ |
5491 | 6312 | ||
5492 | /* per port init */ | 6313 | /* per port init */ |
@@ -5646,6 +6467,18 @@ static int bnx2x_function_init(struct bnx2x *bp, int mode) | |||
5646 | /* Port MCP comes here */ | 6467 | /* Port MCP comes here */ |
5647 | /* Port DMAE comes here */ | 6468 | /* Port DMAE comes here */ |
5648 | 6469 | ||
6470 | switch (bp->board & SHARED_HW_CFG_BOARD_TYPE_MASK) { | ||
6471 | case SHARED_HW_CFG_BOARD_TYPE_BCM957710A1022G: | ||
6472 | /* add SPIO 5 to group 0 */ | ||
6473 | val = REG_RD(bp, MISC_REG_AEU_ENABLE1_FUNC_0_OUT_0); | ||
6474 | val |= AEU_INPUTS_ATTN_BITS_SPIO5; | ||
6475 | REG_WR(bp, MISC_REG_AEU_ENABLE1_FUNC_0_OUT_0, val); | ||
6476 | break; | ||
6477 | |||
6478 | default: | ||
6479 | break; | ||
6480 | } | ||
6481 | |||
5649 | bnx2x_link_reset(bp); | 6482 | bnx2x_link_reset(bp); |
5650 | 6483 | ||
5651 | /* Reset PCIE errors for debug */ | 6484 | /* Reset PCIE errors for debug */ |
@@ -5670,9 +6503,9 @@ static int bnx2x_function_init(struct bnx2x *bp, int mode) | |||
5670 | port = bp->port; | 6503 | port = bp->port; |
5671 | 6504 | ||
5672 | bp->fw_drv_pulse_wr_seq = | 6505 | bp->fw_drv_pulse_wr_seq = |
5673 | (SHMEM_RD(bp, drv_fw_mb[port].drv_pulse_mb) & | 6506 | (SHMEM_RD(bp, func_mb[port].drv_pulse_mb) & |
5674 | DRV_PULSE_SEQ_MASK); | 6507 | DRV_PULSE_SEQ_MASK); |
5675 | bp->fw_mb = SHMEM_RD(bp, drv_fw_mb[port].fw_mb_param); | 6508 | bp->fw_mb = SHMEM_RD(bp, func_mb[port].fw_mb_param); |
5676 | DP(BNX2X_MSG_MCP, "drv_pulse 0x%x fw_mb 0x%x\n", | 6509 | DP(BNX2X_MSG_MCP, "drv_pulse 0x%x fw_mb 0x%x\n", |
5677 | bp->fw_drv_pulse_wr_seq, bp->fw_mb); | 6510 | bp->fw_drv_pulse_wr_seq, bp->fw_mb); |
5678 | } else { | 6511 | } else { |
@@ -5685,12 +6518,12 @@ static int bnx2x_function_init(struct bnx2x *bp, int mode) | |||
5685 | /* send the MCP a request, block until there is a reply */ | 6518 | /* send the MCP a request, block until there is a reply */ |
5686 | static u32 bnx2x_fw_command(struct bnx2x *bp, u32 command) | 6519 | static u32 bnx2x_fw_command(struct bnx2x *bp, u32 command) |
5687 | { | 6520 | { |
5688 | u32 rc = 0; | ||
5689 | u32 seq = ++bp->fw_seq; | ||
5690 | int port = bp->port; | 6521 | int port = bp->port; |
6522 | u32 seq = ++bp->fw_seq; | ||
6523 | u32 rc = 0; | ||
5691 | 6524 | ||
5692 | SHMEM_WR(bp, drv_fw_mb[port].drv_mb_header, command|seq); | 6525 | SHMEM_WR(bp, func_mb[port].drv_mb_header, (command | seq)); |
5693 | DP(BNX2X_MSG_MCP, "wrote command (%x) to FW MB\n", command|seq); | 6526 | DP(BNX2X_MSG_MCP, "wrote command (%x) to FW MB\n", (command | seq)); |
5694 | 6527 | ||
5695 | /* let the FW do it's magic ... */ | 6528 | /* let the FW do it's magic ... */ |
5696 | msleep(100); /* TBD */ | 6529 | msleep(100); /* TBD */ |
@@ -5698,19 +6531,20 @@ static u32 bnx2x_fw_command(struct bnx2x *bp, u32 command) | |||
5698 | if (CHIP_REV_IS_SLOW(bp)) | 6531 | if (CHIP_REV_IS_SLOW(bp)) |
5699 | msleep(900); | 6532 | msleep(900); |
5700 | 6533 | ||
5701 | rc = SHMEM_RD(bp, drv_fw_mb[port].fw_mb_header); | 6534 | rc = SHMEM_RD(bp, func_mb[port].fw_mb_header); |
5702 | |||
5703 | DP(BNX2X_MSG_MCP, "read (%x) seq is (%x) from FW MB\n", rc, seq); | 6535 | DP(BNX2X_MSG_MCP, "read (%x) seq is (%x) from FW MB\n", rc, seq); |
5704 | 6536 | ||
5705 | /* is this a reply to our command? */ | 6537 | /* is this a reply to our command? */ |
5706 | if (seq == (rc & FW_MSG_SEQ_NUMBER_MASK)) { | 6538 | if (seq == (rc & FW_MSG_SEQ_NUMBER_MASK)) { |
5707 | rc &= FW_MSG_CODE_MASK; | 6539 | rc &= FW_MSG_CODE_MASK; |
6540 | |||
5708 | } else { | 6541 | } else { |
5709 | /* FW BUG! */ | 6542 | /* FW BUG! */ |
5710 | BNX2X_ERR("FW failed to respond!\n"); | 6543 | BNX2X_ERR("FW failed to respond!\n"); |
5711 | bnx2x_fw_dump(bp); | 6544 | bnx2x_fw_dump(bp); |
5712 | rc = 0; | 6545 | rc = 0; |
5713 | } | 6546 | } |
6547 | |||
5714 | return rc; | 6548 | return rc; |
5715 | } | 6549 | } |
5716 | 6550 | ||
@@ -6559,7 +7393,7 @@ static void bnx2x_link_settings_supported(struct bnx2x *bp, u32 switch_cfg) | |||
6559 | SUPPORTED_100baseT_Half | | 7393 | SUPPORTED_100baseT_Half | |
6560 | SUPPORTED_100baseT_Full | | 7394 | SUPPORTED_100baseT_Full | |
6561 | SUPPORTED_1000baseT_Full | | 7395 | SUPPORTED_1000baseT_Full | |
6562 | SUPPORTED_2500baseT_Full | | 7396 | SUPPORTED_2500baseX_Full | |
6563 | SUPPORTED_TP | SUPPORTED_FIBRE | | 7397 | SUPPORTED_TP | SUPPORTED_FIBRE | |
6564 | SUPPORTED_Autoneg | | 7398 | SUPPORTED_Autoneg | |
6565 | SUPPORTED_Pause | | 7399 | SUPPORTED_Pause | |
@@ -6572,10 +7406,10 @@ static void bnx2x_link_settings_supported(struct bnx2x *bp, u32 switch_cfg) | |||
6572 | 7406 | ||
6573 | bp->phy_flags |= PHY_SGMII_FLAG; | 7407 | bp->phy_flags |= PHY_SGMII_FLAG; |
6574 | 7408 | ||
6575 | bp->supported |= (/* SUPPORTED_10baseT_Half | | 7409 | bp->supported |= (SUPPORTED_10baseT_Half | |
6576 | SUPPORTED_10baseT_Full | | 7410 | SUPPORTED_10baseT_Full | |
6577 | SUPPORTED_100baseT_Half | | 7411 | SUPPORTED_100baseT_Half | |
6578 | SUPPORTED_100baseT_Full |*/ | 7412 | SUPPORTED_100baseT_Full | |
6579 | SUPPORTED_1000baseT_Full | | 7413 | SUPPORTED_1000baseT_Full | |
6580 | SUPPORTED_TP | SUPPORTED_FIBRE | | 7414 | SUPPORTED_TP | SUPPORTED_FIBRE | |
6581 | SUPPORTED_Autoneg | | 7415 | SUPPORTED_Autoneg | |
@@ -6611,7 +7445,7 @@ static void bnx2x_link_settings_supported(struct bnx2x *bp, u32 switch_cfg) | |||
6611 | SUPPORTED_100baseT_Half | | 7445 | SUPPORTED_100baseT_Half | |
6612 | SUPPORTED_100baseT_Full | | 7446 | SUPPORTED_100baseT_Full | |
6613 | SUPPORTED_1000baseT_Full | | 7447 | SUPPORTED_1000baseT_Full | |
6614 | SUPPORTED_2500baseT_Full | | 7448 | SUPPORTED_2500baseX_Full | |
6615 | SUPPORTED_10000baseT_Full | | 7449 | SUPPORTED_10000baseT_Full | |
6616 | SUPPORTED_TP | SUPPORTED_FIBRE | | 7450 | SUPPORTED_TP | SUPPORTED_FIBRE | |
6617 | SUPPORTED_Autoneg | | 7451 | SUPPORTED_Autoneg | |
@@ -6620,12 +7454,46 @@ static void bnx2x_link_settings_supported(struct bnx2x *bp, u32 switch_cfg) | |||
6620 | break; | 7454 | break; |
6621 | 7455 | ||
6622 | case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705: | 7456 | case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705: |
7457 | BNX2X_DEV_INFO("ext_phy_type 0x%x (8705)\n", | ||
7458 | ext_phy_type); | ||
7459 | |||
7460 | bp->supported |= (SUPPORTED_10000baseT_Full | | ||
7461 | SUPPORTED_FIBRE | | ||
7462 | SUPPORTED_Pause | | ||
7463 | SUPPORTED_Asym_Pause); | ||
7464 | break; | ||
7465 | |||
6623 | case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8706: | 7466 | case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8706: |
6624 | BNX2X_DEV_INFO("ext_phy_type 0x%x (8705/6)\n", | 7467 | BNX2X_DEV_INFO("ext_phy_type 0x%x (8706)\n", |
7468 | ext_phy_type); | ||
7469 | |||
7470 | bp->supported |= (SUPPORTED_10000baseT_Full | | ||
7471 | SUPPORTED_1000baseT_Full | | ||
7472 | SUPPORTED_Autoneg | | ||
7473 | SUPPORTED_FIBRE | | ||
7474 | SUPPORTED_Pause | | ||
7475 | SUPPORTED_Asym_Pause); | ||
7476 | break; | ||
7477 | |||
7478 | case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072: | ||
7479 | BNX2X_DEV_INFO("ext_phy_type 0x%x (8072)\n", | ||
6625 | ext_phy_type); | 7480 | ext_phy_type); |
6626 | 7481 | ||
6627 | bp->supported |= (SUPPORTED_10000baseT_Full | | 7482 | bp->supported |= (SUPPORTED_10000baseT_Full | |
7483 | SUPPORTED_1000baseT_Full | | ||
6628 | SUPPORTED_FIBRE | | 7484 | SUPPORTED_FIBRE | |
7485 | SUPPORTED_Autoneg | | ||
7486 | SUPPORTED_Pause | | ||
7487 | SUPPORTED_Asym_Pause); | ||
7488 | break; | ||
7489 | |||
7490 | case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101: | ||
7491 | BNX2X_DEV_INFO("ext_phy_type 0x%x (SFX7101)\n", | ||
7492 | ext_phy_type); | ||
7493 | |||
7494 | bp->supported |= (SUPPORTED_10000baseT_Full | | ||
7495 | SUPPORTED_TP | | ||
7496 | SUPPORTED_Autoneg | | ||
6629 | SUPPORTED_Pause | | 7497 | SUPPORTED_Pause | |
6630 | SUPPORTED_Asym_Pause); | 7498 | SUPPORTED_Asym_Pause); |
6631 | break; | 7499 | break; |
@@ -6682,7 +7550,7 @@ static void bnx2x_link_settings_supported(struct bnx2x *bp, u32 switch_cfg) | |||
6682 | SUPPORTED_1000baseT_Full); | 7550 | SUPPORTED_1000baseT_Full); |
6683 | 7551 | ||
6684 | if (!(bp->speed_cap_mask & PORT_HW_CFG_SPEED_CAPABILITY_D0_2_5G)) | 7552 | if (!(bp->speed_cap_mask & PORT_HW_CFG_SPEED_CAPABILITY_D0_2_5G)) |
6685 | bp->supported &= ~SUPPORTED_2500baseT_Full; | 7553 | bp->supported &= ~SUPPORTED_2500baseX_Full; |
6686 | 7554 | ||
6687 | if (!(bp->speed_cap_mask & PORT_HW_CFG_SPEED_CAPABILITY_D0_10G)) | 7555 | if (!(bp->speed_cap_mask & PORT_HW_CFG_SPEED_CAPABILITY_D0_10G)) |
6688 | bp->supported &= ~SUPPORTED_10000baseT_Full; | 7556 | bp->supported &= ~SUPPORTED_10000baseT_Full; |
@@ -6702,13 +7570,8 @@ static void bnx2x_link_settings_requested(struct bnx2x *bp) | |||
6702 | bp->req_line_speed = 0; | 7570 | bp->req_line_speed = 0; |
6703 | bp->advertising = bp->supported; | 7571 | bp->advertising = bp->supported; |
6704 | } else { | 7572 | } else { |
6705 | u32 ext_phy_type; | 7573 | if (XGXS_EXT_PHY_TYPE(bp) == |
6706 | 7574 | PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705) { | |
6707 | ext_phy_type = XGXS_EXT_PHY_TYPE(bp); | ||
6708 | if ((ext_phy_type == | ||
6709 | PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705) || | ||
6710 | (ext_phy_type == | ||
6711 | PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8706)) { | ||
6712 | /* force 10G, no AN */ | 7575 | /* force 10G, no AN */ |
6713 | bp->req_line_speed = SPEED_10000; | 7576 | bp->req_line_speed = SPEED_10000; |
6714 | bp->advertising = | 7577 | bp->advertising = |
@@ -6725,8 +7588,7 @@ static void bnx2x_link_settings_requested(struct bnx2x *bp) | |||
6725 | break; | 7588 | break; |
6726 | 7589 | ||
6727 | case PORT_FEATURE_LINK_SPEED_10M_FULL: | 7590 | case PORT_FEATURE_LINK_SPEED_10M_FULL: |
6728 | if (bp->speed_cap_mask & | 7591 | if (bp->supported & SUPPORTED_10baseT_Full) { |
6729 | PORT_HW_CFG_SPEED_CAPABILITY_D0_10M_FULL) { | ||
6730 | bp->req_line_speed = SPEED_10; | 7592 | bp->req_line_speed = SPEED_10; |
6731 | bp->advertising = (ADVERTISED_10baseT_Full | | 7593 | bp->advertising = (ADVERTISED_10baseT_Full | |
6732 | ADVERTISED_TP); | 7594 | ADVERTISED_TP); |
@@ -6740,8 +7602,7 @@ static void bnx2x_link_settings_requested(struct bnx2x *bp) | |||
6740 | break; | 7602 | break; |
6741 | 7603 | ||
6742 | case PORT_FEATURE_LINK_SPEED_10M_HALF: | 7604 | case PORT_FEATURE_LINK_SPEED_10M_HALF: |
6743 | if (bp->speed_cap_mask & | 7605 | if (bp->supported & SUPPORTED_10baseT_Half) { |
6744 | PORT_HW_CFG_SPEED_CAPABILITY_D0_10M_HALF) { | ||
6745 | bp->req_line_speed = SPEED_10; | 7606 | bp->req_line_speed = SPEED_10; |
6746 | bp->req_duplex = DUPLEX_HALF; | 7607 | bp->req_duplex = DUPLEX_HALF; |
6747 | bp->advertising = (ADVERTISED_10baseT_Half | | 7608 | bp->advertising = (ADVERTISED_10baseT_Half | |
@@ -6756,8 +7617,7 @@ static void bnx2x_link_settings_requested(struct bnx2x *bp) | |||
6756 | break; | 7617 | break; |
6757 | 7618 | ||
6758 | case PORT_FEATURE_LINK_SPEED_100M_FULL: | 7619 | case PORT_FEATURE_LINK_SPEED_100M_FULL: |
6759 | if (bp->speed_cap_mask & | 7620 | if (bp->supported & SUPPORTED_100baseT_Full) { |
6760 | PORT_HW_CFG_SPEED_CAPABILITY_D0_100M_FULL) { | ||
6761 | bp->req_line_speed = SPEED_100; | 7621 | bp->req_line_speed = SPEED_100; |
6762 | bp->advertising = (ADVERTISED_100baseT_Full | | 7622 | bp->advertising = (ADVERTISED_100baseT_Full | |
6763 | ADVERTISED_TP); | 7623 | ADVERTISED_TP); |
@@ -6771,8 +7631,7 @@ static void bnx2x_link_settings_requested(struct bnx2x *bp) | |||
6771 | break; | 7631 | break; |
6772 | 7632 | ||
6773 | case PORT_FEATURE_LINK_SPEED_100M_HALF: | 7633 | case PORT_FEATURE_LINK_SPEED_100M_HALF: |
6774 | if (bp->speed_cap_mask & | 7634 | if (bp->supported & SUPPORTED_100baseT_Half) { |
6775 | PORT_HW_CFG_SPEED_CAPABILITY_D0_100M_HALF) { | ||
6776 | bp->req_line_speed = SPEED_100; | 7635 | bp->req_line_speed = SPEED_100; |
6777 | bp->req_duplex = DUPLEX_HALF; | 7636 | bp->req_duplex = DUPLEX_HALF; |
6778 | bp->advertising = (ADVERTISED_100baseT_Half | | 7637 | bp->advertising = (ADVERTISED_100baseT_Half | |
@@ -6787,8 +7646,7 @@ static void bnx2x_link_settings_requested(struct bnx2x *bp) | |||
6787 | break; | 7646 | break; |
6788 | 7647 | ||
6789 | case PORT_FEATURE_LINK_SPEED_1G: | 7648 | case PORT_FEATURE_LINK_SPEED_1G: |
6790 | if (bp->speed_cap_mask & | 7649 | if (bp->supported & SUPPORTED_1000baseT_Full) { |
6791 | PORT_HW_CFG_SPEED_CAPABILITY_D0_1G) { | ||
6792 | bp->req_line_speed = SPEED_1000; | 7650 | bp->req_line_speed = SPEED_1000; |
6793 | bp->advertising = (ADVERTISED_1000baseT_Full | | 7651 | bp->advertising = (ADVERTISED_1000baseT_Full | |
6794 | ADVERTISED_TP); | 7652 | ADVERTISED_TP); |
@@ -6802,10 +7660,9 @@ static void bnx2x_link_settings_requested(struct bnx2x *bp) | |||
6802 | break; | 7660 | break; |
6803 | 7661 | ||
6804 | case PORT_FEATURE_LINK_SPEED_2_5G: | 7662 | case PORT_FEATURE_LINK_SPEED_2_5G: |
6805 | if (bp->speed_cap_mask & | 7663 | if (bp->supported & SUPPORTED_2500baseX_Full) { |
6806 | PORT_HW_CFG_SPEED_CAPABILITY_D0_2_5G) { | ||
6807 | bp->req_line_speed = SPEED_2500; | 7664 | bp->req_line_speed = SPEED_2500; |
6808 | bp->advertising = (ADVERTISED_2500baseT_Full | | 7665 | bp->advertising = (ADVERTISED_2500baseX_Full | |
6809 | ADVERTISED_TP); | 7666 | ADVERTISED_TP); |
6810 | } else { | 7667 | } else { |
6811 | BNX2X_ERR("NVRAM config error. " | 7668 | BNX2X_ERR("NVRAM config error. " |
@@ -6819,15 +7676,7 @@ static void bnx2x_link_settings_requested(struct bnx2x *bp) | |||
6819 | case PORT_FEATURE_LINK_SPEED_10G_CX4: | 7676 | case PORT_FEATURE_LINK_SPEED_10G_CX4: |
6820 | case PORT_FEATURE_LINK_SPEED_10G_KX4: | 7677 | case PORT_FEATURE_LINK_SPEED_10G_KX4: |
6821 | case PORT_FEATURE_LINK_SPEED_10G_KR: | 7678 | case PORT_FEATURE_LINK_SPEED_10G_KR: |
6822 | if (!(bp->phy_flags & PHY_XGXS_FLAG)) { | 7679 | if (bp->supported & SUPPORTED_10000baseT_Full) { |
6823 | BNX2X_ERR("NVRAM config error. " | ||
6824 | "Invalid link_config 0x%x" | ||
6825 | " phy_flags 0x%x\n", | ||
6826 | bp->link_config, bp->phy_flags); | ||
6827 | return; | ||
6828 | } | ||
6829 | if (bp->speed_cap_mask & | ||
6830 | PORT_HW_CFG_SPEED_CAPABILITY_D0_10G) { | ||
6831 | bp->req_line_speed = SPEED_10000; | 7680 | bp->req_line_speed = SPEED_10000; |
6832 | bp->advertising = (ADVERTISED_10000baseT_Full | | 7681 | bp->advertising = (ADVERTISED_10000baseT_Full | |
6833 | ADVERTISED_FIBRE); | 7682 | ADVERTISED_FIBRE); |
@@ -6854,43 +7703,13 @@ static void bnx2x_link_settings_requested(struct bnx2x *bp) | |||
6854 | 7703 | ||
6855 | bp->req_flow_ctrl = (bp->link_config & | 7704 | bp->req_flow_ctrl = (bp->link_config & |
6856 | PORT_FEATURE_FLOW_CONTROL_MASK); | 7705 | PORT_FEATURE_FLOW_CONTROL_MASK); |
6857 | /* Please refer to Table 28B-3 of the 802.3ab-1999 spec */ | 7706 | if ((bp->req_flow_ctrl == FLOW_CTRL_AUTO) && |
6858 | switch (bp->req_flow_ctrl) { | 7707 | (bp->supported & SUPPORTED_Autoneg)) |
6859 | case FLOW_CTRL_AUTO: | ||
6860 | bp->req_autoneg |= AUTONEG_FLOW_CTRL; | 7708 | bp->req_autoneg |= AUTONEG_FLOW_CTRL; |
6861 | if (bp->dev->mtu <= 4500) { | ||
6862 | bp->pause_mode = PAUSE_BOTH; | ||
6863 | bp->advertising |= (ADVERTISED_Pause | | ||
6864 | ADVERTISED_Asym_Pause); | ||
6865 | } else { | ||
6866 | bp->pause_mode = PAUSE_ASYMMETRIC; | ||
6867 | bp->advertising |= ADVERTISED_Asym_Pause; | ||
6868 | } | ||
6869 | break; | ||
6870 | |||
6871 | case FLOW_CTRL_TX: | ||
6872 | bp->pause_mode = PAUSE_ASYMMETRIC; | ||
6873 | bp->advertising |= ADVERTISED_Asym_Pause; | ||
6874 | break; | ||
6875 | |||
6876 | case FLOW_CTRL_RX: | ||
6877 | case FLOW_CTRL_BOTH: | ||
6878 | bp->pause_mode = PAUSE_BOTH; | ||
6879 | bp->advertising |= (ADVERTISED_Pause | | ||
6880 | ADVERTISED_Asym_Pause); | ||
6881 | break; | ||
6882 | 7709 | ||
6883 | case FLOW_CTRL_NONE: | 7710 | BNX2X_DEV_INFO("req_autoneg 0x%x req_flow_ctrl 0x%x" |
6884 | default: | 7711 | " advertising 0x%x\n", |
6885 | bp->pause_mode = PAUSE_NONE; | 7712 | bp->req_autoneg, bp->req_flow_ctrl, bp->advertising); |
6886 | bp->advertising &= ~(ADVERTISED_Pause | | ||
6887 | ADVERTISED_Asym_Pause); | ||
6888 | break; | ||
6889 | } | ||
6890 | BNX2X_DEV_INFO("req_autoneg 0x%x req_flow_ctrl 0x%x\n" | ||
6891 | KERN_INFO " pause_mode %d advertising 0x%x\n", | ||
6892 | bp->req_autoneg, bp->req_flow_ctrl, | ||
6893 | bp->pause_mode, bp->advertising); | ||
6894 | } | 7713 | } |
6895 | 7714 | ||
6896 | static void bnx2x_get_hwinfo(struct bnx2x *bp) | 7715 | static void bnx2x_get_hwinfo(struct bnx2x *bp) |
@@ -6923,16 +7742,16 @@ static void bnx2x_get_hwinfo(struct bnx2x *bp) | |||
6923 | 7742 | ||
6924 | val = SHMEM_RD(bp, validity_map[port]); | 7743 | val = SHMEM_RD(bp, validity_map[port]); |
6925 | if ((val & (SHR_MEM_VALIDITY_DEV_INFO | SHR_MEM_VALIDITY_MB)) | 7744 | if ((val & (SHR_MEM_VALIDITY_DEV_INFO | SHR_MEM_VALIDITY_MB)) |
6926 | != (SHR_MEM_VALIDITY_DEV_INFO | SHR_MEM_VALIDITY_MB)) | 7745 | != (SHR_MEM_VALIDITY_DEV_INFO | SHR_MEM_VALIDITY_MB)) |
6927 | BNX2X_ERR("MCP validity signature bad\n"); | 7746 | BNX2X_ERR("BAD MCP validity signature\n"); |
6928 | 7747 | ||
6929 | bp->fw_seq = (SHMEM_RD(bp, drv_fw_mb[port].drv_mb_header) & | 7748 | bp->fw_seq = (SHMEM_RD(bp, func_mb[port].drv_mb_header) & |
6930 | DRV_MSG_SEQ_NUMBER_MASK); | 7749 | DRV_MSG_SEQ_NUMBER_MASK); |
6931 | 7750 | ||
6932 | bp->hw_config = SHMEM_RD(bp, dev_info.shared_hw_config.config); | 7751 | bp->hw_config = SHMEM_RD(bp, dev_info.shared_hw_config.config); |
6933 | 7752 | bp->board = SHMEM_RD(bp, dev_info.shared_hw_config.board); | |
6934 | bp->serdes_config = | 7753 | bp->serdes_config = |
6935 | SHMEM_RD(bp, dev_info.port_hw_config[bp->port].serdes_config); | 7754 | SHMEM_RD(bp, dev_info.port_hw_config[port].serdes_config); |
6936 | bp->lane_config = | 7755 | bp->lane_config = |
6937 | SHMEM_RD(bp, dev_info.port_hw_config[port].lane_config); | 7756 | SHMEM_RD(bp, dev_info.port_hw_config[port].lane_config); |
6938 | bp->ext_phy_config = | 7757 | bp->ext_phy_config = |
@@ -6945,13 +7764,13 @@ static void bnx2x_get_hwinfo(struct bnx2x *bp) | |||
6945 | bp->link_config = | 7764 | bp->link_config = |
6946 | SHMEM_RD(bp, dev_info.port_feature_config[port].link_config); | 7765 | SHMEM_RD(bp, dev_info.port_feature_config[port].link_config); |
6947 | 7766 | ||
6948 | BNX2X_DEV_INFO("hw_config (%08x) serdes_config (%08x)\n" | 7767 | BNX2X_DEV_INFO("hw_config (%08x) board (%08x) serdes_config (%08x)\n" |
6949 | KERN_INFO " lane_config (%08x) ext_phy_config (%08x)\n" | 7768 | KERN_INFO " lane_config (%08x) ext_phy_config (%08x)\n" |
6950 | KERN_INFO " speed_cap_mask (%08x) link_config (%08x)" | 7769 | KERN_INFO " speed_cap_mask (%08x) link_config (%08x)" |
6951 | " fw_seq (%08x)\n", | 7770 | " fw_seq (%08x)\n", |
6952 | bp->hw_config, bp->serdes_config, bp->lane_config, | 7771 | bp->hw_config, bp->board, bp->serdes_config, |
6953 | bp->ext_phy_config, bp->speed_cap_mask, | 7772 | bp->lane_config, bp->ext_phy_config, |
6954 | bp->link_config, bp->fw_seq); | 7773 | bp->speed_cap_mask, bp->link_config, bp->fw_seq); |
6955 | 7774 | ||
6956 | switch_cfg = (bp->link_config & PORT_FEATURE_CONNECTED_SWITCH_MASK); | 7775 | switch_cfg = (bp->link_config & PORT_FEATURE_CONNECTED_SWITCH_MASK); |
6957 | bnx2x_link_settings_supported(bp, switch_cfg); | 7776 | bnx2x_link_settings_supported(bp, switch_cfg); |
@@ -7005,14 +7824,8 @@ static void bnx2x_get_hwinfo(struct bnx2x *bp) | |||
7005 | return; | 7824 | return; |
7006 | 7825 | ||
7007 | set_mac: /* only supposed to happen on emulation/FPGA */ | 7826 | set_mac: /* only supposed to happen on emulation/FPGA */ |
7008 | BNX2X_ERR("warning constant MAC workaround active\n"); | 7827 | BNX2X_ERR("warning rendom MAC workaround active\n"); |
7009 | bp->dev->dev_addr[0] = 0; | 7828 | random_ether_addr(bp->dev->dev_addr); |
7010 | bp->dev->dev_addr[1] = 0x50; | ||
7011 | bp->dev->dev_addr[2] = 0xc2; | ||
7012 | bp->dev->dev_addr[3] = 0x2c; | ||
7013 | bp->dev->dev_addr[4] = 0x71; | ||
7014 | bp->dev->dev_addr[5] = port ? 0x0d : 0x0e; | ||
7015 | |||
7016 | memcpy(bp->dev->perm_addr, bp->dev->dev_addr, 6); | 7829 | memcpy(bp->dev->perm_addr, bp->dev->dev_addr, 6); |
7017 | 7830 | ||
7018 | } | 7831 | } |
@@ -7039,19 +7852,34 @@ static int bnx2x_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) | |||
7039 | } | 7852 | } |
7040 | 7853 | ||
7041 | if (bp->phy_flags & PHY_XGXS_FLAG) { | 7854 | if (bp->phy_flags & PHY_XGXS_FLAG) { |
7042 | cmd->port = PORT_FIBRE; | 7855 | u32 ext_phy_type = XGXS_EXT_PHY_TYPE(bp); |
7043 | } else { | 7856 | |
7857 | switch (ext_phy_type) { | ||
7858 | case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT: | ||
7859 | case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705: | ||
7860 | case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8706: | ||
7861 | case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072: | ||
7862 | cmd->port = PORT_FIBRE; | ||
7863 | break; | ||
7864 | |||
7865 | case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101: | ||
7866 | cmd->port = PORT_TP; | ||
7867 | break; | ||
7868 | |||
7869 | default: | ||
7870 | DP(NETIF_MSG_LINK, "BAD XGXS ext_phy_config 0x%x\n", | ||
7871 | bp->ext_phy_config); | ||
7872 | } | ||
7873 | } else | ||
7044 | cmd->port = PORT_TP; | 7874 | cmd->port = PORT_TP; |
7045 | } | ||
7046 | 7875 | ||
7047 | cmd->phy_address = bp->phy_addr; | 7876 | cmd->phy_address = bp->phy_addr; |
7048 | cmd->transceiver = XCVR_INTERNAL; | 7877 | cmd->transceiver = XCVR_INTERNAL; |
7049 | 7878 | ||
7050 | if (bp->req_autoneg & AUTONEG_SPEED) { | 7879 | if (bp->req_autoneg & AUTONEG_SPEED) |
7051 | cmd->autoneg = AUTONEG_ENABLE; | 7880 | cmd->autoneg = AUTONEG_ENABLE; |
7052 | } else { | 7881 | else |
7053 | cmd->autoneg = AUTONEG_DISABLE; | 7882 | cmd->autoneg = AUTONEG_DISABLE; |
7054 | } | ||
7055 | 7883 | ||
7056 | cmd->maxtxpkt = 0; | 7884 | cmd->maxtxpkt = 0; |
7057 | cmd->maxrxpkt = 0; | 7885 | cmd->maxrxpkt = 0; |
@@ -7082,8 +7910,10 @@ static int bnx2x_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) | |||
7082 | 7910 | ||
7083 | switch (cmd->port) { | 7911 | switch (cmd->port) { |
7084 | case PORT_TP: | 7912 | case PORT_TP: |
7085 | if (!(bp->supported & SUPPORTED_TP)) | 7913 | if (!(bp->supported & SUPPORTED_TP)) { |
7914 | DP(NETIF_MSG_LINK, "TP not supported\n"); | ||
7086 | return -EINVAL; | 7915 | return -EINVAL; |
7916 | } | ||
7087 | 7917 | ||
7088 | if (bp->phy_flags & PHY_XGXS_FLAG) { | 7918 | if (bp->phy_flags & PHY_XGXS_FLAG) { |
7089 | bnx2x_link_reset(bp); | 7919 | bnx2x_link_reset(bp); |
@@ -7093,8 +7923,10 @@ static int bnx2x_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) | |||
7093 | break; | 7923 | break; |
7094 | 7924 | ||
7095 | case PORT_FIBRE: | 7925 | case PORT_FIBRE: |
7096 | if (!(bp->supported & SUPPORTED_FIBRE)) | 7926 | if (!(bp->supported & SUPPORTED_FIBRE)) { |
7927 | DP(NETIF_MSG_LINK, "FIBRE not supported\n"); | ||
7097 | return -EINVAL; | 7928 | return -EINVAL; |
7929 | } | ||
7098 | 7930 | ||
7099 | if (!(bp->phy_flags & PHY_XGXS_FLAG)) { | 7931 | if (!(bp->phy_flags & PHY_XGXS_FLAG)) { |
7100 | bnx2x_link_reset(bp); | 7932 | bnx2x_link_reset(bp); |
@@ -7104,12 +7936,15 @@ static int bnx2x_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) | |||
7104 | break; | 7936 | break; |
7105 | 7937 | ||
7106 | default: | 7938 | default: |
7939 | DP(NETIF_MSG_LINK, "Unknown port type\n"); | ||
7107 | return -EINVAL; | 7940 | return -EINVAL; |
7108 | } | 7941 | } |
7109 | 7942 | ||
7110 | if (cmd->autoneg == AUTONEG_ENABLE) { | 7943 | if (cmd->autoneg == AUTONEG_ENABLE) { |
7111 | if (!(bp->supported & SUPPORTED_Autoneg)) | 7944 | if (!(bp->supported & SUPPORTED_Autoneg)) { |
7945 | DP(NETIF_MSG_LINK, "Aotoneg not supported\n"); | ||
7112 | return -EINVAL; | 7946 | return -EINVAL; |
7947 | } | ||
7113 | 7948 | ||
7114 | /* advertise the requested speed and duplex if supported */ | 7949 | /* advertise the requested speed and duplex if supported */ |
7115 | cmd->advertising &= bp->supported; | 7950 | cmd->advertising &= bp->supported; |
@@ -7124,14 +7959,22 @@ static int bnx2x_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) | |||
7124 | switch (cmd->speed) { | 7959 | switch (cmd->speed) { |
7125 | case SPEED_10: | 7960 | case SPEED_10: |
7126 | if (cmd->duplex == DUPLEX_FULL) { | 7961 | if (cmd->duplex == DUPLEX_FULL) { |
7127 | if (!(bp->supported & SUPPORTED_10baseT_Full)) | 7962 | if (!(bp->supported & |
7963 | SUPPORTED_10baseT_Full)) { | ||
7964 | DP(NETIF_MSG_LINK, | ||
7965 | "10M full not supported\n"); | ||
7128 | return -EINVAL; | 7966 | return -EINVAL; |
7967 | } | ||
7129 | 7968 | ||
7130 | advertising = (ADVERTISED_10baseT_Full | | 7969 | advertising = (ADVERTISED_10baseT_Full | |
7131 | ADVERTISED_TP); | 7970 | ADVERTISED_TP); |
7132 | } else { | 7971 | } else { |
7133 | if (!(bp->supported & SUPPORTED_10baseT_Half)) | 7972 | if (!(bp->supported & |
7973 | SUPPORTED_10baseT_Half)) { | ||
7974 | DP(NETIF_MSG_LINK, | ||
7975 | "10M half not supported\n"); | ||
7134 | return -EINVAL; | 7976 | return -EINVAL; |
7977 | } | ||
7135 | 7978 | ||
7136 | advertising = (ADVERTISED_10baseT_Half | | 7979 | advertising = (ADVERTISED_10baseT_Half | |
7137 | ADVERTISED_TP); | 7980 | ADVERTISED_TP); |
@@ -7141,15 +7984,21 @@ static int bnx2x_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) | |||
7141 | case SPEED_100: | 7984 | case SPEED_100: |
7142 | if (cmd->duplex == DUPLEX_FULL) { | 7985 | if (cmd->duplex == DUPLEX_FULL) { |
7143 | if (!(bp->supported & | 7986 | if (!(bp->supported & |
7144 | SUPPORTED_100baseT_Full)) | 7987 | SUPPORTED_100baseT_Full)) { |
7988 | DP(NETIF_MSG_LINK, | ||
7989 | "100M full not supported\n"); | ||
7145 | return -EINVAL; | 7990 | return -EINVAL; |
7991 | } | ||
7146 | 7992 | ||
7147 | advertising = (ADVERTISED_100baseT_Full | | 7993 | advertising = (ADVERTISED_100baseT_Full | |
7148 | ADVERTISED_TP); | 7994 | ADVERTISED_TP); |
7149 | } else { | 7995 | } else { |
7150 | if (!(bp->supported & | 7996 | if (!(bp->supported & |
7151 | SUPPORTED_100baseT_Half)) | 7997 | SUPPORTED_100baseT_Half)) { |
7998 | DP(NETIF_MSG_LINK, | ||
7999 | "100M half not supported\n"); | ||
7152 | return -EINVAL; | 8000 | return -EINVAL; |
8001 | } | ||
7153 | 8002 | ||
7154 | advertising = (ADVERTISED_100baseT_Half | | 8003 | advertising = (ADVERTISED_100baseT_Half | |
7155 | ADVERTISED_TP); | 8004 | ADVERTISED_TP); |
@@ -7157,39 +8006,54 @@ static int bnx2x_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) | |||
7157 | break; | 8006 | break; |
7158 | 8007 | ||
7159 | case SPEED_1000: | 8008 | case SPEED_1000: |
7160 | if (cmd->duplex != DUPLEX_FULL) | 8009 | if (cmd->duplex != DUPLEX_FULL) { |
8010 | DP(NETIF_MSG_LINK, "1G half not supported\n"); | ||
7161 | return -EINVAL; | 8011 | return -EINVAL; |
8012 | } | ||
7162 | 8013 | ||
7163 | if (!(bp->supported & SUPPORTED_1000baseT_Full)) | 8014 | if (!(bp->supported & SUPPORTED_1000baseT_Full)) { |
8015 | DP(NETIF_MSG_LINK, "1G full not supported\n"); | ||
7164 | return -EINVAL; | 8016 | return -EINVAL; |
8017 | } | ||
7165 | 8018 | ||
7166 | advertising = (ADVERTISED_1000baseT_Full | | 8019 | advertising = (ADVERTISED_1000baseT_Full | |
7167 | ADVERTISED_TP); | 8020 | ADVERTISED_TP); |
7168 | break; | 8021 | break; |
7169 | 8022 | ||
7170 | case SPEED_2500: | 8023 | case SPEED_2500: |
7171 | if (cmd->duplex != DUPLEX_FULL) | 8024 | if (cmd->duplex != DUPLEX_FULL) { |
8025 | DP(NETIF_MSG_LINK, | ||
8026 | "2.5G half not supported\n"); | ||
7172 | return -EINVAL; | 8027 | return -EINVAL; |
8028 | } | ||
7173 | 8029 | ||
7174 | if (!(bp->supported & SUPPORTED_2500baseT_Full)) | 8030 | if (!(bp->supported & SUPPORTED_2500baseX_Full)) { |
8031 | DP(NETIF_MSG_LINK, | ||
8032 | "2.5G full not supported\n"); | ||
7175 | return -EINVAL; | 8033 | return -EINVAL; |
8034 | } | ||
7176 | 8035 | ||
7177 | advertising = (ADVERTISED_2500baseT_Full | | 8036 | advertising = (ADVERTISED_2500baseX_Full | |
7178 | ADVERTISED_TP); | 8037 | ADVERTISED_TP); |
7179 | break; | 8038 | break; |
7180 | 8039 | ||
7181 | case SPEED_10000: | 8040 | case SPEED_10000: |
7182 | if (cmd->duplex != DUPLEX_FULL) | 8041 | if (cmd->duplex != DUPLEX_FULL) { |
8042 | DP(NETIF_MSG_LINK, "10G half not supported\n"); | ||
7183 | return -EINVAL; | 8043 | return -EINVAL; |
8044 | } | ||
7184 | 8045 | ||
7185 | if (!(bp->supported & SUPPORTED_10000baseT_Full)) | 8046 | if (!(bp->supported & SUPPORTED_10000baseT_Full)) { |
8047 | DP(NETIF_MSG_LINK, "10G full not supported\n"); | ||
7186 | return -EINVAL; | 8048 | return -EINVAL; |
8049 | } | ||
7187 | 8050 | ||
7188 | advertising = (ADVERTISED_10000baseT_Full | | 8051 | advertising = (ADVERTISED_10000baseT_Full | |
7189 | ADVERTISED_FIBRE); | 8052 | ADVERTISED_FIBRE); |
7190 | break; | 8053 | break; |
7191 | 8054 | ||
7192 | default: | 8055 | default: |
8056 | DP(NETIF_MSG_LINK, "Unsupported speed\n"); | ||
7193 | return -EINVAL; | 8057 | return -EINVAL; |
7194 | } | 8058 | } |
7195 | 8059 | ||
@@ -7389,8 +8253,7 @@ static void bnx2x_disable_nvram_access(struct bnx2x *bp) | |||
7389 | static int bnx2x_nvram_read_dword(struct bnx2x *bp, u32 offset, u32 *ret_val, | 8253 | static int bnx2x_nvram_read_dword(struct bnx2x *bp, u32 offset, u32 *ret_val, |
7390 | u32 cmd_flags) | 8254 | u32 cmd_flags) |
7391 | { | 8255 | { |
7392 | int rc; | 8256 | int count, i, rc; |
7393 | int count, i; | ||
7394 | u32 val; | 8257 | u32 val; |
7395 | 8258 | ||
7396 | /* build the command word */ | 8259 | /* build the command word */ |
@@ -7510,8 +8373,7 @@ static int bnx2x_get_eeprom(struct net_device *dev, | |||
7510 | static int bnx2x_nvram_write_dword(struct bnx2x *bp, u32 offset, u32 val, | 8373 | static int bnx2x_nvram_write_dword(struct bnx2x *bp, u32 offset, u32 val, |
7511 | u32 cmd_flags) | 8374 | u32 cmd_flags) |
7512 | { | 8375 | { |
7513 | int rc; | 8376 | int count, i, rc; |
7514 | int count, i; | ||
7515 | 8377 | ||
7516 | /* build the command word */ | 8378 | /* build the command word */ |
7517 | cmd_flags |= MCPR_NVM_COMMAND_DOIT | MCPR_NVM_COMMAND_WR; | 8379 | cmd_flags |= MCPR_NVM_COMMAND_DOIT | MCPR_NVM_COMMAND_WR; |
@@ -7548,7 +8410,7 @@ static int bnx2x_nvram_write_dword(struct bnx2x *bp, u32 offset, u32 val, | |||
7548 | return rc; | 8410 | return rc; |
7549 | } | 8411 | } |
7550 | 8412 | ||
7551 | #define BYTE_OFFSET(offset) (8 * (offset & 0x03)) | 8413 | #define BYTE_OFFSET(offset) (8 * (offset & 0x03)) |
7552 | 8414 | ||
7553 | static int bnx2x_nvram_write1(struct bnx2x *bp, u32 offset, u8 *data_buf, | 8415 | static int bnx2x_nvram_write1(struct bnx2x *bp, u32 offset, u8 *data_buf, |
7554 | int buf_size) | 8416 | int buf_size) |
@@ -7779,52 +8641,29 @@ static int bnx2x_set_pauseparam(struct net_device *dev, | |||
7779 | DP_LEVEL " autoneg %d rx_pause %d tx_pause %d\n", | 8641 | DP_LEVEL " autoneg %d rx_pause %d tx_pause %d\n", |
7780 | epause->cmd, epause->autoneg, epause->rx_pause, epause->tx_pause); | 8642 | epause->cmd, epause->autoneg, epause->rx_pause, epause->tx_pause); |
7781 | 8643 | ||
7782 | bp->req_flow_ctrl = FLOW_CTRL_AUTO; | ||
7783 | if (epause->autoneg) { | 8644 | if (epause->autoneg) { |
7784 | bp->req_autoneg |= AUTONEG_FLOW_CTRL; | 8645 | if (!(bp->supported & SUPPORTED_Autoneg)) { |
7785 | if (bp->dev->mtu <= 4500) { | 8646 | DP(NETIF_MSG_LINK, "Aotoneg not supported\n"); |
7786 | bp->pause_mode = PAUSE_BOTH; | 8647 | return -EINVAL; |
7787 | bp->advertising |= (ADVERTISED_Pause | | ||
7788 | ADVERTISED_Asym_Pause); | ||
7789 | } else { | ||
7790 | bp->pause_mode = PAUSE_ASYMMETRIC; | ||
7791 | bp->advertising |= ADVERTISED_Asym_Pause; | ||
7792 | } | 8648 | } |
7793 | 8649 | ||
7794 | } else { | 8650 | bp->req_autoneg |= AUTONEG_FLOW_CTRL; |
8651 | } else | ||
7795 | bp->req_autoneg &= ~AUTONEG_FLOW_CTRL; | 8652 | bp->req_autoneg &= ~AUTONEG_FLOW_CTRL; |
7796 | 8653 | ||
7797 | if (epause->rx_pause) | 8654 | bp->req_flow_ctrl = FLOW_CTRL_AUTO; |
7798 | bp->req_flow_ctrl |= FLOW_CTRL_RX; | ||
7799 | if (epause->tx_pause) | ||
7800 | bp->req_flow_ctrl |= FLOW_CTRL_TX; | ||
7801 | |||
7802 | switch (bp->req_flow_ctrl) { | ||
7803 | case FLOW_CTRL_AUTO: | ||
7804 | bp->req_flow_ctrl = FLOW_CTRL_NONE; | ||
7805 | bp->pause_mode = PAUSE_NONE; | ||
7806 | bp->advertising &= ~(ADVERTISED_Pause | | ||
7807 | ADVERTISED_Asym_Pause); | ||
7808 | break; | ||
7809 | 8655 | ||
7810 | case FLOW_CTRL_TX: | 8656 | if (epause->rx_pause) |
7811 | bp->pause_mode = PAUSE_ASYMMETRIC; | 8657 | bp->req_flow_ctrl |= FLOW_CTRL_RX; |
7812 | bp->advertising |= ADVERTISED_Asym_Pause; | 8658 | if (epause->tx_pause) |
7813 | break; | 8659 | bp->req_flow_ctrl |= FLOW_CTRL_TX; |
7814 | 8660 | ||
7815 | case FLOW_CTRL_RX: | 8661 | if (!(bp->req_autoneg & AUTONEG_FLOW_CTRL) && |
7816 | case FLOW_CTRL_BOTH: | 8662 | (bp->req_flow_ctrl == FLOW_CTRL_AUTO)) |
7817 | bp->pause_mode = PAUSE_BOTH; | 8663 | bp->req_flow_ctrl = FLOW_CTRL_NONE; |
7818 | bp->advertising |= (ADVERTISED_Pause | | ||
7819 | ADVERTISED_Asym_Pause); | ||
7820 | break; | ||
7821 | } | ||
7822 | } | ||
7823 | 8664 | ||
7824 | DP(NETIF_MSG_LINK, "req_autoneg 0x%x req_flow_ctrl 0x%x\n" | 8665 | DP(NETIF_MSG_LINK, "req_autoneg 0x%x req_flow_ctrl 0x%x\n", |
7825 | DP_LEVEL " pause_mode %d advertising 0x%x\n", | 8666 | bp->req_autoneg, bp->req_flow_ctrl); |
7826 | bp->req_autoneg, bp->req_flow_ctrl, bp->pause_mode, | ||
7827 | bp->advertising); | ||
7828 | 8667 | ||
7829 | bnx2x_stop_stats(bp); | 8668 | bnx2x_stop_stats(bp); |
7830 | bnx2x_link_initialize(bp); | 8669 | bnx2x_link_initialize(bp); |