diff options
Diffstat (limited to 'drivers/net/bnx2.c')
-rw-r--r-- | drivers/net/bnx2.c | 503 |
1 files changed, 430 insertions, 73 deletions
diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c index 23958f73c421..02e994b1b028 100644 --- a/drivers/net/bnx2.c +++ b/drivers/net/bnx2.c | |||
@@ -40,7 +40,6 @@ | |||
40 | #define BCM_VLAN 1 | 40 | #define BCM_VLAN 1 |
41 | #endif | 41 | #endif |
42 | #include <net/ip.h> | 42 | #include <net/ip.h> |
43 | #include <net/tcp.h> | ||
44 | #include <net/checksum.h> | 43 | #include <net/checksum.h> |
45 | #include <linux/workqueue.h> | 44 | #include <linux/workqueue.h> |
46 | #include <linux/crc32.h> | 45 | #include <linux/crc32.h> |
@@ -54,8 +53,8 @@ | |||
54 | 53 | ||
55 | #define DRV_MODULE_NAME "bnx2" | 54 | #define DRV_MODULE_NAME "bnx2" |
56 | #define PFX DRV_MODULE_NAME ": " | 55 | #define PFX DRV_MODULE_NAME ": " |
57 | #define DRV_MODULE_VERSION "1.5.11" | 56 | #define DRV_MODULE_VERSION "1.6.2" |
58 | #define DRV_MODULE_RELDATE "June 4, 2007" | 57 | #define DRV_MODULE_RELDATE "July 6, 2007" |
59 | 58 | ||
60 | #define RUN_AT(x) (jiffies + (x)) | 59 | #define RUN_AT(x) (jiffies + (x)) |
61 | 60 | ||
@@ -550,6 +549,9 @@ bnx2_report_fw_link(struct bnx2 *bp) | |||
550 | { | 549 | { |
551 | u32 fw_link_status = 0; | 550 | u32 fw_link_status = 0; |
552 | 551 | ||
552 | if (bp->phy_flags & REMOTE_PHY_CAP_FLAG) | ||
553 | return; | ||
554 | |||
553 | if (bp->link_up) { | 555 | if (bp->link_up) { |
554 | u32 bmsr; | 556 | u32 bmsr; |
555 | 557 | ||
@@ -601,12 +603,21 @@ bnx2_report_fw_link(struct bnx2 *bp) | |||
601 | REG_WR_IND(bp, bp->shmem_base + BNX2_LINK_STATUS, fw_link_status); | 603 | REG_WR_IND(bp, bp->shmem_base + BNX2_LINK_STATUS, fw_link_status); |
602 | } | 604 | } |
603 | 605 | ||
606 | static char * | ||
607 | bnx2_xceiver_str(struct bnx2 *bp) | ||
608 | { | ||
609 | return ((bp->phy_port == PORT_FIBRE) ? "SerDes" : | ||
610 | ((bp->phy_flags & PHY_SERDES_FLAG) ? "Remote Copper" : | ||
611 | "Copper")); | ||
612 | } | ||
613 | |||
604 | static void | 614 | static void |
605 | bnx2_report_link(struct bnx2 *bp) | 615 | bnx2_report_link(struct bnx2 *bp) |
606 | { | 616 | { |
607 | if (bp->link_up) { | 617 | if (bp->link_up) { |
608 | netif_carrier_on(bp->dev); | 618 | netif_carrier_on(bp->dev); |
609 | printk(KERN_INFO PFX "%s NIC Link is Up, ", bp->dev->name); | 619 | printk(KERN_INFO PFX "%s NIC %s Link is Up, ", bp->dev->name, |
620 | bnx2_xceiver_str(bp)); | ||
610 | 621 | ||
611 | printk("%d Mbps ", bp->line_speed); | 622 | printk("%d Mbps ", bp->line_speed); |
612 | 623 | ||
@@ -630,7 +641,8 @@ bnx2_report_link(struct bnx2 *bp) | |||
630 | } | 641 | } |
631 | else { | 642 | else { |
632 | netif_carrier_off(bp->dev); | 643 | netif_carrier_off(bp->dev); |
633 | printk(KERN_ERR PFX "%s NIC Link is Down\n", bp->dev->name); | 644 | printk(KERN_ERR PFX "%s NIC %s Link is Down\n", bp->dev->name, |
645 | bnx2_xceiver_str(bp)); | ||
634 | } | 646 | } |
635 | 647 | ||
636 | bnx2_report_fw_link(bp); | 648 | bnx2_report_fw_link(bp); |
@@ -1100,6 +1112,9 @@ bnx2_set_link(struct bnx2 *bp) | |||
1100 | return 0; | 1112 | return 0; |
1101 | } | 1113 | } |
1102 | 1114 | ||
1115 | if (bp->phy_flags & REMOTE_PHY_CAP_FLAG) | ||
1116 | return 0; | ||
1117 | |||
1103 | link_up = bp->link_up; | 1118 | link_up = bp->link_up; |
1104 | 1119 | ||
1105 | bnx2_enable_bmsr1(bp); | 1120 | bnx2_enable_bmsr1(bp); |
@@ -1210,12 +1225,74 @@ bnx2_phy_get_pause_adv(struct bnx2 *bp) | |||
1210 | return adv; | 1225 | return adv; |
1211 | } | 1226 | } |
1212 | 1227 | ||
1228 | static int bnx2_fw_sync(struct bnx2 *, u32, int); | ||
1229 | |||
1213 | static int | 1230 | static int |
1214 | bnx2_setup_serdes_phy(struct bnx2 *bp) | 1231 | bnx2_setup_remote_phy(struct bnx2 *bp, u8 port) |
1232 | { | ||
1233 | u32 speed_arg = 0, pause_adv; | ||
1234 | |||
1235 | pause_adv = bnx2_phy_get_pause_adv(bp); | ||
1236 | |||
1237 | if (bp->autoneg & AUTONEG_SPEED) { | ||
1238 | speed_arg |= BNX2_NETLINK_SET_LINK_ENABLE_AUTONEG; | ||
1239 | if (bp->advertising & ADVERTISED_10baseT_Half) | ||
1240 | speed_arg |= BNX2_NETLINK_SET_LINK_SPEED_10HALF; | ||
1241 | if (bp->advertising & ADVERTISED_10baseT_Full) | ||
1242 | speed_arg |= BNX2_NETLINK_SET_LINK_SPEED_10FULL; | ||
1243 | if (bp->advertising & ADVERTISED_100baseT_Half) | ||
1244 | speed_arg |= BNX2_NETLINK_SET_LINK_SPEED_100HALF; | ||
1245 | if (bp->advertising & ADVERTISED_100baseT_Full) | ||
1246 | speed_arg |= BNX2_NETLINK_SET_LINK_SPEED_100FULL; | ||
1247 | if (bp->advertising & ADVERTISED_1000baseT_Full) | ||
1248 | speed_arg |= BNX2_NETLINK_SET_LINK_SPEED_1GFULL; | ||
1249 | if (bp->advertising & ADVERTISED_2500baseX_Full) | ||
1250 | speed_arg |= BNX2_NETLINK_SET_LINK_SPEED_2G5FULL; | ||
1251 | } else { | ||
1252 | if (bp->req_line_speed == SPEED_2500) | ||
1253 | speed_arg = BNX2_NETLINK_SET_LINK_SPEED_2G5FULL; | ||
1254 | else if (bp->req_line_speed == SPEED_1000) | ||
1255 | speed_arg = BNX2_NETLINK_SET_LINK_SPEED_1GFULL; | ||
1256 | else if (bp->req_line_speed == SPEED_100) { | ||
1257 | if (bp->req_duplex == DUPLEX_FULL) | ||
1258 | speed_arg = BNX2_NETLINK_SET_LINK_SPEED_100FULL; | ||
1259 | else | ||
1260 | speed_arg = BNX2_NETLINK_SET_LINK_SPEED_100HALF; | ||
1261 | } else if (bp->req_line_speed == SPEED_10) { | ||
1262 | if (bp->req_duplex == DUPLEX_FULL) | ||
1263 | speed_arg = BNX2_NETLINK_SET_LINK_SPEED_10FULL; | ||
1264 | else | ||
1265 | speed_arg = BNX2_NETLINK_SET_LINK_SPEED_10HALF; | ||
1266 | } | ||
1267 | } | ||
1268 | |||
1269 | if (pause_adv & (ADVERTISE_1000XPAUSE | ADVERTISE_PAUSE_CAP)) | ||
1270 | speed_arg |= BNX2_NETLINK_SET_LINK_FC_SYM_PAUSE; | ||
1271 | if (pause_adv & (ADVERTISE_1000XPSE_ASYM | ADVERTISE_1000XPSE_ASYM)) | ||
1272 | speed_arg |= BNX2_NETLINK_SET_LINK_FC_ASYM_PAUSE; | ||
1273 | |||
1274 | if (port == PORT_TP) | ||
1275 | speed_arg |= BNX2_NETLINK_SET_LINK_PHY_APP_REMOTE | | ||
1276 | BNX2_NETLINK_SET_LINK_ETH_AT_WIRESPEED; | ||
1277 | |||
1278 | REG_WR_IND(bp, bp->shmem_base + BNX2_DRV_MB_ARG0, speed_arg); | ||
1279 | |||
1280 | spin_unlock_bh(&bp->phy_lock); | ||
1281 | bnx2_fw_sync(bp, BNX2_DRV_MSG_CODE_CMD_SET_LINK, 0); | ||
1282 | spin_lock_bh(&bp->phy_lock); | ||
1283 | |||
1284 | return 0; | ||
1285 | } | ||
1286 | |||
1287 | static int | ||
1288 | bnx2_setup_serdes_phy(struct bnx2 *bp, u8 port) | ||
1215 | { | 1289 | { |
1216 | u32 adv, bmcr; | 1290 | u32 adv, bmcr; |
1217 | u32 new_adv = 0; | 1291 | u32 new_adv = 0; |
1218 | 1292 | ||
1293 | if (bp->phy_flags & REMOTE_PHY_CAP_FLAG) | ||
1294 | return (bnx2_setup_remote_phy(bp, port)); | ||
1295 | |||
1219 | if (!(bp->autoneg & AUTONEG_SPEED)) { | 1296 | if (!(bp->autoneg & AUTONEG_SPEED)) { |
1220 | u32 new_bmcr; | 1297 | u32 new_bmcr; |
1221 | int force_link_down = 0; | 1298 | int force_link_down = 0; |
@@ -1323,7 +1400,9 @@ bnx2_setup_serdes_phy(struct bnx2 *bp) | |||
1323 | } | 1400 | } |
1324 | 1401 | ||
1325 | #define ETHTOOL_ALL_FIBRE_SPEED \ | 1402 | #define ETHTOOL_ALL_FIBRE_SPEED \ |
1326 | (ADVERTISED_1000baseT_Full) | 1403 | (bp->phy_flags & PHY_2_5G_CAPABLE_FLAG) ? \ |
1404 | (ADVERTISED_2500baseX_Full | ADVERTISED_1000baseT_Full) :\ | ||
1405 | (ADVERTISED_1000baseT_Full) | ||
1327 | 1406 | ||
1328 | #define ETHTOOL_ALL_COPPER_SPEED \ | 1407 | #define ETHTOOL_ALL_COPPER_SPEED \ |
1329 | (ADVERTISED_10baseT_Half | ADVERTISED_10baseT_Full | \ | 1408 | (ADVERTISED_10baseT_Half | ADVERTISED_10baseT_Full | \ |
@@ -1335,6 +1414,188 @@ bnx2_setup_serdes_phy(struct bnx2 *bp) | |||
1335 | 1414 | ||
1336 | #define PHY_ALL_1000_SPEED (ADVERTISE_1000HALF | ADVERTISE_1000FULL) | 1415 | #define PHY_ALL_1000_SPEED (ADVERTISE_1000HALF | ADVERTISE_1000FULL) |
1337 | 1416 | ||
1417 | static void | ||
1418 | bnx2_set_default_remote_link(struct bnx2 *bp) | ||
1419 | { | ||
1420 | u32 link; | ||
1421 | |||
1422 | if (bp->phy_port == PORT_TP) | ||
1423 | link = REG_RD_IND(bp, bp->shmem_base + BNX2_RPHY_COPPER_LINK); | ||
1424 | else | ||
1425 | link = REG_RD_IND(bp, bp->shmem_base + BNX2_RPHY_SERDES_LINK); | ||
1426 | |||
1427 | if (link & BNX2_NETLINK_SET_LINK_ENABLE_AUTONEG) { | ||
1428 | bp->req_line_speed = 0; | ||
1429 | bp->autoneg |= AUTONEG_SPEED; | ||
1430 | bp->advertising = ADVERTISED_Autoneg; | ||
1431 | if (link & BNX2_NETLINK_SET_LINK_SPEED_10HALF) | ||
1432 | bp->advertising |= ADVERTISED_10baseT_Half; | ||
1433 | if (link & BNX2_NETLINK_SET_LINK_SPEED_10FULL) | ||
1434 | bp->advertising |= ADVERTISED_10baseT_Full; | ||
1435 | if (link & BNX2_NETLINK_SET_LINK_SPEED_100HALF) | ||
1436 | bp->advertising |= ADVERTISED_100baseT_Half; | ||
1437 | if (link & BNX2_NETLINK_SET_LINK_SPEED_100FULL) | ||
1438 | bp->advertising |= ADVERTISED_100baseT_Full; | ||
1439 | if (link & BNX2_NETLINK_SET_LINK_SPEED_1GFULL) | ||
1440 | bp->advertising |= ADVERTISED_1000baseT_Full; | ||
1441 | if (link & BNX2_NETLINK_SET_LINK_SPEED_2G5FULL) | ||
1442 | bp->advertising |= ADVERTISED_2500baseX_Full; | ||
1443 | } else { | ||
1444 | bp->autoneg = 0; | ||
1445 | bp->advertising = 0; | ||
1446 | bp->req_duplex = DUPLEX_FULL; | ||
1447 | if (link & BNX2_NETLINK_SET_LINK_SPEED_10) { | ||
1448 | bp->req_line_speed = SPEED_10; | ||
1449 | if (link & BNX2_NETLINK_SET_LINK_SPEED_10HALF) | ||
1450 | bp->req_duplex = DUPLEX_HALF; | ||
1451 | } | ||
1452 | if (link & BNX2_NETLINK_SET_LINK_SPEED_100) { | ||
1453 | bp->req_line_speed = SPEED_100; | ||
1454 | if (link & BNX2_NETLINK_SET_LINK_SPEED_100HALF) | ||
1455 | bp->req_duplex = DUPLEX_HALF; | ||
1456 | } | ||
1457 | if (link & BNX2_NETLINK_SET_LINK_SPEED_1GFULL) | ||
1458 | bp->req_line_speed = SPEED_1000; | ||
1459 | if (link & BNX2_NETLINK_SET_LINK_SPEED_2G5FULL) | ||
1460 | bp->req_line_speed = SPEED_2500; | ||
1461 | } | ||
1462 | } | ||
1463 | |||
1464 | static void | ||
1465 | bnx2_set_default_link(struct bnx2 *bp) | ||
1466 | { | ||
1467 | if (bp->phy_flags & REMOTE_PHY_CAP_FLAG) | ||
1468 | return bnx2_set_default_remote_link(bp); | ||
1469 | |||
1470 | bp->autoneg = AUTONEG_SPEED | AUTONEG_FLOW_CTRL; | ||
1471 | bp->req_line_speed = 0; | ||
1472 | if (bp->phy_flags & PHY_SERDES_FLAG) { | ||
1473 | u32 reg; | ||
1474 | |||
1475 | bp->advertising = ETHTOOL_ALL_FIBRE_SPEED | ADVERTISED_Autoneg; | ||
1476 | |||
1477 | reg = REG_RD_IND(bp, bp->shmem_base + BNX2_PORT_HW_CFG_CONFIG); | ||
1478 | reg &= BNX2_PORT_HW_CFG_CFG_DFLT_LINK_MASK; | ||
1479 | if (reg == BNX2_PORT_HW_CFG_CFG_DFLT_LINK_1G) { | ||
1480 | bp->autoneg = 0; | ||
1481 | bp->req_line_speed = bp->line_speed = SPEED_1000; | ||
1482 | bp->req_duplex = DUPLEX_FULL; | ||
1483 | } | ||
1484 | } else | ||
1485 | bp->advertising = ETHTOOL_ALL_COPPER_SPEED | ADVERTISED_Autoneg; | ||
1486 | } | ||
1487 | |||
1488 | static void | ||
1489 | bnx2_send_heart_beat(struct bnx2 *bp) | ||
1490 | { | ||
1491 | u32 msg; | ||
1492 | u32 addr; | ||
1493 | |||
1494 | spin_lock(&bp->indirect_lock); | ||
1495 | msg = (u32) (++bp->fw_drv_pulse_wr_seq & BNX2_DRV_PULSE_SEQ_MASK); | ||
1496 | addr = bp->shmem_base + BNX2_DRV_PULSE_MB; | ||
1497 | REG_WR(bp, BNX2_PCICFG_REG_WINDOW_ADDRESS, addr); | ||
1498 | REG_WR(bp, BNX2_PCICFG_REG_WINDOW, msg); | ||
1499 | spin_unlock(&bp->indirect_lock); | ||
1500 | } | ||
1501 | |||
1502 | static void | ||
1503 | bnx2_remote_phy_event(struct bnx2 *bp) | ||
1504 | { | ||
1505 | u32 msg; | ||
1506 | u8 link_up = bp->link_up; | ||
1507 | u8 old_port; | ||
1508 | |||
1509 | msg = REG_RD_IND(bp, bp->shmem_base + BNX2_LINK_STATUS); | ||
1510 | |||
1511 | if (msg & BNX2_LINK_STATUS_HEART_BEAT_EXPIRED) | ||
1512 | bnx2_send_heart_beat(bp); | ||
1513 | |||
1514 | msg &= ~BNX2_LINK_STATUS_HEART_BEAT_EXPIRED; | ||
1515 | |||
1516 | if ((msg & BNX2_LINK_STATUS_LINK_UP) == BNX2_LINK_STATUS_LINK_DOWN) | ||
1517 | bp->link_up = 0; | ||
1518 | else { | ||
1519 | u32 speed; | ||
1520 | |||
1521 | bp->link_up = 1; | ||
1522 | speed = msg & BNX2_LINK_STATUS_SPEED_MASK; | ||
1523 | bp->duplex = DUPLEX_FULL; | ||
1524 | switch (speed) { | ||
1525 | case BNX2_LINK_STATUS_10HALF: | ||
1526 | bp->duplex = DUPLEX_HALF; | ||
1527 | case BNX2_LINK_STATUS_10FULL: | ||
1528 | bp->line_speed = SPEED_10; | ||
1529 | break; | ||
1530 | case BNX2_LINK_STATUS_100HALF: | ||
1531 | bp->duplex = DUPLEX_HALF; | ||
1532 | case BNX2_LINK_STATUS_100BASE_T4: | ||
1533 | case BNX2_LINK_STATUS_100FULL: | ||
1534 | bp->line_speed = SPEED_100; | ||
1535 | break; | ||
1536 | case BNX2_LINK_STATUS_1000HALF: | ||
1537 | bp->duplex = DUPLEX_HALF; | ||
1538 | case BNX2_LINK_STATUS_1000FULL: | ||
1539 | bp->line_speed = SPEED_1000; | ||
1540 | break; | ||
1541 | case BNX2_LINK_STATUS_2500HALF: | ||
1542 | bp->duplex = DUPLEX_HALF; | ||
1543 | case BNX2_LINK_STATUS_2500FULL: | ||
1544 | bp->line_speed = SPEED_2500; | ||
1545 | break; | ||
1546 | default: | ||
1547 | bp->line_speed = 0; | ||
1548 | break; | ||
1549 | } | ||
1550 | |||
1551 | spin_lock(&bp->phy_lock); | ||
1552 | bp->flow_ctrl = 0; | ||
1553 | if ((bp->autoneg & (AUTONEG_SPEED | AUTONEG_FLOW_CTRL)) != | ||
1554 | (AUTONEG_SPEED | AUTONEG_FLOW_CTRL)) { | ||
1555 | if (bp->duplex == DUPLEX_FULL) | ||
1556 | bp->flow_ctrl = bp->req_flow_ctrl; | ||
1557 | } else { | ||
1558 | if (msg & BNX2_LINK_STATUS_TX_FC_ENABLED) | ||
1559 | bp->flow_ctrl |= FLOW_CTRL_TX; | ||
1560 | if (msg & BNX2_LINK_STATUS_RX_FC_ENABLED) | ||
1561 | bp->flow_ctrl |= FLOW_CTRL_RX; | ||
1562 | } | ||
1563 | |||
1564 | old_port = bp->phy_port; | ||
1565 | if (msg & BNX2_LINK_STATUS_SERDES_LINK) | ||
1566 | bp->phy_port = PORT_FIBRE; | ||
1567 | else | ||
1568 | bp->phy_port = PORT_TP; | ||
1569 | |||
1570 | if (old_port != bp->phy_port) | ||
1571 | bnx2_set_default_link(bp); | ||
1572 | |||
1573 | spin_unlock(&bp->phy_lock); | ||
1574 | } | ||
1575 | if (bp->link_up != link_up) | ||
1576 | bnx2_report_link(bp); | ||
1577 | |||
1578 | bnx2_set_mac_link(bp); | ||
1579 | } | ||
1580 | |||
1581 | static int | ||
1582 | bnx2_set_remote_link(struct bnx2 *bp) | ||
1583 | { | ||
1584 | u32 evt_code; | ||
1585 | |||
1586 | evt_code = REG_RD_IND(bp, bp->shmem_base + BNX2_FW_EVT_CODE_MB); | ||
1587 | switch (evt_code) { | ||
1588 | case BNX2_FW_EVT_CODE_LINK_EVENT: | ||
1589 | bnx2_remote_phy_event(bp); | ||
1590 | break; | ||
1591 | case BNX2_FW_EVT_CODE_SW_TIMER_EXPIRATION_EVENT: | ||
1592 | default: | ||
1593 | bnx2_send_heart_beat(bp); | ||
1594 | break; | ||
1595 | } | ||
1596 | return 0; | ||
1597 | } | ||
1598 | |||
1338 | static int | 1599 | static int |
1339 | bnx2_setup_copper_phy(struct bnx2 *bp) | 1600 | bnx2_setup_copper_phy(struct bnx2 *bp) |
1340 | { | 1601 | { |
@@ -1433,13 +1694,13 @@ bnx2_setup_copper_phy(struct bnx2 *bp) | |||
1433 | } | 1694 | } |
1434 | 1695 | ||
1435 | static int | 1696 | static int |
1436 | bnx2_setup_phy(struct bnx2 *bp) | 1697 | bnx2_setup_phy(struct bnx2 *bp, u8 port) |
1437 | { | 1698 | { |
1438 | if (bp->loopback == MAC_LOOPBACK) | 1699 | if (bp->loopback == MAC_LOOPBACK) |
1439 | return 0; | 1700 | return 0; |
1440 | 1701 | ||
1441 | if (bp->phy_flags & PHY_SERDES_FLAG) { | 1702 | if (bp->phy_flags & PHY_SERDES_FLAG) { |
1442 | return (bnx2_setup_serdes_phy(bp)); | 1703 | return (bnx2_setup_serdes_phy(bp, port)); |
1443 | } | 1704 | } |
1444 | else { | 1705 | else { |
1445 | return (bnx2_setup_copper_phy(bp)); | 1706 | return (bnx2_setup_copper_phy(bp)); |
@@ -1659,6 +1920,9 @@ bnx2_init_phy(struct bnx2 *bp) | |||
1659 | 1920 | ||
1660 | REG_WR(bp, BNX2_EMAC_ATTENTION_ENA, BNX2_EMAC_ATTENTION_ENA_LINK); | 1921 | REG_WR(bp, BNX2_EMAC_ATTENTION_ENA, BNX2_EMAC_ATTENTION_ENA_LINK); |
1661 | 1922 | ||
1923 | if (bp->phy_flags & REMOTE_PHY_CAP_FLAG) | ||
1924 | goto setup_phy; | ||
1925 | |||
1662 | bnx2_read_phy(bp, MII_PHYSID1, &val); | 1926 | bnx2_read_phy(bp, MII_PHYSID1, &val); |
1663 | bp->phy_id = val << 16; | 1927 | bp->phy_id = val << 16; |
1664 | bnx2_read_phy(bp, MII_PHYSID2, &val); | 1928 | bnx2_read_phy(bp, MII_PHYSID2, &val); |
@@ -1676,7 +1940,9 @@ bnx2_init_phy(struct bnx2 *bp) | |||
1676 | rc = bnx2_init_copper_phy(bp); | 1940 | rc = bnx2_init_copper_phy(bp); |
1677 | } | 1941 | } |
1678 | 1942 | ||
1679 | bnx2_setup_phy(bp); | 1943 | setup_phy: |
1944 | if (!rc) | ||
1945 | rc = bnx2_setup_phy(bp, bp->phy_port); | ||
1680 | 1946 | ||
1681 | return rc; | 1947 | return rc; |
1682 | } | 1948 | } |
@@ -1984,6 +2250,9 @@ bnx2_phy_int(struct bnx2 *bp) | |||
1984 | bnx2_set_link(bp); | 2250 | bnx2_set_link(bp); |
1985 | spin_unlock(&bp->phy_lock); | 2251 | spin_unlock(&bp->phy_lock); |
1986 | } | 2252 | } |
2253 | if (bnx2_phy_event_is_set(bp, STATUS_ATTN_BITS_TIMER_ABORT)) | ||
2254 | bnx2_set_remote_link(bp); | ||
2255 | |||
1987 | } | 2256 | } |
1988 | 2257 | ||
1989 | static void | 2258 | static void |
@@ -2297,6 +2566,7 @@ bnx2_interrupt(int irq, void *dev_instance) | |||
2297 | { | 2566 | { |
2298 | struct net_device *dev = dev_instance; | 2567 | struct net_device *dev = dev_instance; |
2299 | struct bnx2 *bp = netdev_priv(dev); | 2568 | struct bnx2 *bp = netdev_priv(dev); |
2569 | struct status_block *sblk = bp->status_blk; | ||
2300 | 2570 | ||
2301 | /* When using INTx, it is possible for the interrupt to arrive | 2571 | /* When using INTx, it is possible for the interrupt to arrive |
2302 | * at the CPU before the status block posted prior to the | 2572 | * at the CPU before the status block posted prior to the |
@@ -2304,7 +2574,7 @@ bnx2_interrupt(int irq, void *dev_instance) | |||
2304 | * When using MSI, the MSI message will always complete after | 2574 | * When using MSI, the MSI message will always complete after |
2305 | * the status block write. | 2575 | * the status block write. |
2306 | */ | 2576 | */ |
2307 | if ((bp->status_blk->status_idx == bp->last_status_idx) && | 2577 | if ((sblk->status_idx == bp->last_status_idx) && |
2308 | (REG_RD(bp, BNX2_PCICFG_MISC_STATUS) & | 2578 | (REG_RD(bp, BNX2_PCICFG_MISC_STATUS) & |
2309 | BNX2_PCICFG_MISC_STATUS_INTA_VALUE)) | 2579 | BNX2_PCICFG_MISC_STATUS_INTA_VALUE)) |
2310 | return IRQ_NONE; | 2580 | return IRQ_NONE; |
@@ -2313,16 +2583,25 @@ bnx2_interrupt(int irq, void *dev_instance) | |||
2313 | BNX2_PCICFG_INT_ACK_CMD_USE_INT_HC_PARAM | | 2583 | BNX2_PCICFG_INT_ACK_CMD_USE_INT_HC_PARAM | |
2314 | BNX2_PCICFG_INT_ACK_CMD_MASK_INT); | 2584 | BNX2_PCICFG_INT_ACK_CMD_MASK_INT); |
2315 | 2585 | ||
2586 | /* Read back to deassert IRQ immediately to avoid too many | ||
2587 | * spurious interrupts. | ||
2588 | */ | ||
2589 | REG_RD(bp, BNX2_PCICFG_INT_ACK_CMD); | ||
2590 | |||
2316 | /* Return here if interrupt is shared and is disabled. */ | 2591 | /* Return here if interrupt is shared and is disabled. */ |
2317 | if (unlikely(atomic_read(&bp->intr_sem) != 0)) | 2592 | if (unlikely(atomic_read(&bp->intr_sem) != 0)) |
2318 | return IRQ_HANDLED; | 2593 | return IRQ_HANDLED; |
2319 | 2594 | ||
2320 | netif_rx_schedule(dev); | 2595 | if (netif_rx_schedule_prep(dev)) { |
2596 | bp->last_status_idx = sblk->status_idx; | ||
2597 | __netif_rx_schedule(dev); | ||
2598 | } | ||
2321 | 2599 | ||
2322 | return IRQ_HANDLED; | 2600 | return IRQ_HANDLED; |
2323 | } | 2601 | } |
2324 | 2602 | ||
2325 | #define STATUS_ATTN_EVENTS STATUS_ATTN_BITS_LINK_STATE | 2603 | #define STATUS_ATTN_EVENTS (STATUS_ATTN_BITS_LINK_STATE | \ |
2604 | STATUS_ATTN_BITS_TIMER_ABORT) | ||
2326 | 2605 | ||
2327 | static inline int | 2606 | static inline int |
2328 | bnx2_has_work(struct bnx2 *bp) | 2607 | bnx2_has_work(struct bnx2 *bp) |
@@ -3562,6 +3841,36 @@ nvram_write_end: | |||
3562 | return rc; | 3841 | return rc; |
3563 | } | 3842 | } |
3564 | 3843 | ||
3844 | static void | ||
3845 | bnx2_init_remote_phy(struct bnx2 *bp) | ||
3846 | { | ||
3847 | u32 val; | ||
3848 | |||
3849 | bp->phy_flags &= ~REMOTE_PHY_CAP_FLAG; | ||
3850 | if (!(bp->phy_flags & PHY_SERDES_FLAG)) | ||
3851 | return; | ||
3852 | |||
3853 | val = REG_RD_IND(bp, bp->shmem_base + BNX2_FW_CAP_MB); | ||
3854 | if ((val & BNX2_FW_CAP_SIGNATURE_MASK) != BNX2_FW_CAP_SIGNATURE) | ||
3855 | return; | ||
3856 | |||
3857 | if (val & BNX2_FW_CAP_REMOTE_PHY_CAPABLE) { | ||
3858 | if (netif_running(bp->dev)) { | ||
3859 | val = BNX2_DRV_ACK_CAP_SIGNATURE | | ||
3860 | BNX2_FW_CAP_REMOTE_PHY_CAPABLE; | ||
3861 | REG_WR_IND(bp, bp->shmem_base + BNX2_DRV_ACK_CAP_MB, | ||
3862 | val); | ||
3863 | } | ||
3864 | bp->phy_flags |= REMOTE_PHY_CAP_FLAG; | ||
3865 | |||
3866 | val = REG_RD_IND(bp, bp->shmem_base + BNX2_LINK_STATUS); | ||
3867 | if (val & BNX2_LINK_STATUS_SERDES_LINK) | ||
3868 | bp->phy_port = PORT_FIBRE; | ||
3869 | else | ||
3870 | bp->phy_port = PORT_TP; | ||
3871 | } | ||
3872 | } | ||
3873 | |||
3565 | static int | 3874 | static int |
3566 | bnx2_reset_chip(struct bnx2 *bp, u32 reset_code) | 3875 | bnx2_reset_chip(struct bnx2 *bp, u32 reset_code) |
3567 | { | 3876 | { |
@@ -3642,6 +3951,12 @@ bnx2_reset_chip(struct bnx2 *bp, u32 reset_code) | |||
3642 | if (rc) | 3951 | if (rc) |
3643 | return rc; | 3952 | return rc; |
3644 | 3953 | ||
3954 | spin_lock_bh(&bp->phy_lock); | ||
3955 | bnx2_init_remote_phy(bp); | ||
3956 | if (bp->phy_flags & REMOTE_PHY_CAP_FLAG) | ||
3957 | bnx2_set_default_remote_link(bp); | ||
3958 | spin_unlock_bh(&bp->phy_lock); | ||
3959 | |||
3645 | if (CHIP_ID(bp) == CHIP_ID_5706_A0) { | 3960 | if (CHIP_ID(bp) == CHIP_ID_5706_A0) { |
3646 | /* Adjust the voltage regular to two steps lower. The default | 3961 | /* Adjust the voltage regular to two steps lower. The default |
3647 | * of this register is 0x0000000e. */ | 3962 | * of this register is 0x0000000e. */ |
@@ -3826,7 +4141,7 @@ bnx2_init_chip(struct bnx2 *bp) | |||
3826 | rc = bnx2_fw_sync(bp, BNX2_DRV_MSG_DATA_WAIT2 | BNX2_DRV_MSG_CODE_RESET, | 4141 | rc = bnx2_fw_sync(bp, BNX2_DRV_MSG_DATA_WAIT2 | BNX2_DRV_MSG_CODE_RESET, |
3827 | 0); | 4142 | 0); |
3828 | 4143 | ||
3829 | REG_WR(bp, BNX2_MISC_ENABLE_SET_BITS, 0x5ffffff); | 4144 | REG_WR(bp, BNX2_MISC_ENABLE_SET_BITS, BNX2_MISC_ENABLE_DEFAULT); |
3830 | REG_RD(bp, BNX2_MISC_ENABLE_SET_BITS); | 4145 | REG_RD(bp, BNX2_MISC_ENABLE_SET_BITS); |
3831 | 4146 | ||
3832 | udelay(20); | 4147 | udelay(20); |
@@ -4069,8 +4384,8 @@ bnx2_init_nic(struct bnx2 *bp) | |||
4069 | 4384 | ||
4070 | spin_lock_bh(&bp->phy_lock); | 4385 | spin_lock_bh(&bp->phy_lock); |
4071 | bnx2_init_phy(bp); | 4386 | bnx2_init_phy(bp); |
4072 | spin_unlock_bh(&bp->phy_lock); | ||
4073 | bnx2_set_link(bp); | 4387 | bnx2_set_link(bp); |
4388 | spin_unlock_bh(&bp->phy_lock); | ||
4074 | return 0; | 4389 | return 0; |
4075 | } | 4390 | } |
4076 | 4391 | ||
@@ -4600,6 +4915,9 @@ bnx2_5706_serdes_timer(struct bnx2 *bp) | |||
4600 | static void | 4915 | static void |
4601 | bnx2_5708_serdes_timer(struct bnx2 *bp) | 4916 | bnx2_5708_serdes_timer(struct bnx2 *bp) |
4602 | { | 4917 | { |
4918 | if (bp->phy_flags & REMOTE_PHY_CAP_FLAG) | ||
4919 | return; | ||
4920 | |||
4603 | if ((bp->phy_flags & PHY_2_5G_CAPABLE_FLAG) == 0) { | 4921 | if ((bp->phy_flags & PHY_2_5G_CAPABLE_FLAG) == 0) { |
4604 | bp->serdes_an_pending = 0; | 4922 | bp->serdes_an_pending = 0; |
4605 | return; | 4923 | return; |
@@ -4631,7 +4949,6 @@ static void | |||
4631 | bnx2_timer(unsigned long data) | 4949 | bnx2_timer(unsigned long data) |
4632 | { | 4950 | { |
4633 | struct bnx2 *bp = (struct bnx2 *) data; | 4951 | struct bnx2 *bp = (struct bnx2 *) data; |
4634 | u32 msg; | ||
4635 | 4952 | ||
4636 | if (!netif_running(bp->dev)) | 4953 | if (!netif_running(bp->dev)) |
4637 | return; | 4954 | return; |
@@ -4639,8 +4956,7 @@ bnx2_timer(unsigned long data) | |||
4639 | if (atomic_read(&bp->intr_sem) != 0) | 4956 | if (atomic_read(&bp->intr_sem) != 0) |
4640 | goto bnx2_restart_timer; | 4957 | goto bnx2_restart_timer; |
4641 | 4958 | ||
4642 | msg = (u32) ++bp->fw_drv_pulse_wr_seq; | 4959 | bnx2_send_heart_beat(bp); |
4643 | REG_WR_IND(bp, bp->shmem_base + BNX2_DRV_PULSE_MB, msg); | ||
4644 | 4960 | ||
4645 | bp->stats_blk->stat_FwRxDrop = REG_RD_IND(bp, BNX2_FW_RX_DROP_COUNT); | 4961 | bp->stats_blk->stat_FwRxDrop = REG_RD_IND(bp, BNX2_FW_RX_DROP_COUNT); |
4646 | 4962 | ||
@@ -5083,17 +5399,25 @@ static int | |||
5083 | bnx2_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) | 5399 | bnx2_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) |
5084 | { | 5400 | { |
5085 | struct bnx2 *bp = netdev_priv(dev); | 5401 | struct bnx2 *bp = netdev_priv(dev); |
5402 | int support_serdes = 0, support_copper = 0; | ||
5086 | 5403 | ||
5087 | cmd->supported = SUPPORTED_Autoneg; | 5404 | cmd->supported = SUPPORTED_Autoneg; |
5088 | if (bp->phy_flags & PHY_SERDES_FLAG) { | 5405 | if (bp->phy_flags & REMOTE_PHY_CAP_FLAG) { |
5406 | support_serdes = 1; | ||
5407 | support_copper = 1; | ||
5408 | } else if (bp->phy_port == PORT_FIBRE) | ||
5409 | support_serdes = 1; | ||
5410 | else | ||
5411 | support_copper = 1; | ||
5412 | |||
5413 | if (support_serdes) { | ||
5089 | cmd->supported |= SUPPORTED_1000baseT_Full | | 5414 | cmd->supported |= SUPPORTED_1000baseT_Full | |
5090 | SUPPORTED_FIBRE; | 5415 | SUPPORTED_FIBRE; |
5091 | if (bp->phy_flags & PHY_2_5G_CAPABLE_FLAG) | 5416 | if (bp->phy_flags & PHY_2_5G_CAPABLE_FLAG) |
5092 | cmd->supported |= SUPPORTED_2500baseX_Full; | 5417 | cmd->supported |= SUPPORTED_2500baseX_Full; |
5093 | 5418 | ||
5094 | cmd->port = PORT_FIBRE; | ||
5095 | } | 5419 | } |
5096 | else { | 5420 | if (support_copper) { |
5097 | cmd->supported |= SUPPORTED_10baseT_Half | | 5421 | cmd->supported |= SUPPORTED_10baseT_Half | |
5098 | SUPPORTED_10baseT_Full | | 5422 | SUPPORTED_10baseT_Full | |
5099 | SUPPORTED_100baseT_Half | | 5423 | SUPPORTED_100baseT_Half | |
@@ -5101,9 +5425,10 @@ bnx2_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) | |||
5101 | SUPPORTED_1000baseT_Full | | 5425 | SUPPORTED_1000baseT_Full | |
5102 | SUPPORTED_TP; | 5426 | SUPPORTED_TP; |
5103 | 5427 | ||
5104 | cmd->port = PORT_TP; | ||
5105 | } | 5428 | } |
5106 | 5429 | ||
5430 | spin_lock_bh(&bp->phy_lock); | ||
5431 | cmd->port = bp->phy_port; | ||
5107 | cmd->advertising = bp->advertising; | 5432 | cmd->advertising = bp->advertising; |
5108 | 5433 | ||
5109 | if (bp->autoneg & AUTONEG_SPEED) { | 5434 | if (bp->autoneg & AUTONEG_SPEED) { |
@@ -5121,6 +5446,7 @@ bnx2_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) | |||
5121 | cmd->speed = -1; | 5446 | cmd->speed = -1; |
5122 | cmd->duplex = -1; | 5447 | cmd->duplex = -1; |
5123 | } | 5448 | } |
5449 | spin_unlock_bh(&bp->phy_lock); | ||
5124 | 5450 | ||
5125 | cmd->transceiver = XCVR_INTERNAL; | 5451 | cmd->transceiver = XCVR_INTERNAL; |
5126 | cmd->phy_address = bp->phy_addr; | 5452 | cmd->phy_address = bp->phy_addr; |
@@ -5136,6 +5462,15 @@ bnx2_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) | |||
5136 | u8 req_duplex = bp->req_duplex; | 5462 | u8 req_duplex = bp->req_duplex; |
5137 | u16 req_line_speed = bp->req_line_speed; | 5463 | u16 req_line_speed = bp->req_line_speed; |
5138 | u32 advertising = bp->advertising; | 5464 | u32 advertising = bp->advertising; |
5465 | int err = -EINVAL; | ||
5466 | |||
5467 | spin_lock_bh(&bp->phy_lock); | ||
5468 | |||
5469 | if (cmd->port != PORT_TP && cmd->port != PORT_FIBRE) | ||
5470 | goto err_out_unlock; | ||
5471 | |||
5472 | if (cmd->port != bp->phy_port && !(bp->phy_flags & REMOTE_PHY_CAP_FLAG)) | ||
5473 | goto err_out_unlock; | ||
5139 | 5474 | ||
5140 | if (cmd->autoneg == AUTONEG_ENABLE) { | 5475 | if (cmd->autoneg == AUTONEG_ENABLE) { |
5141 | autoneg |= AUTONEG_SPEED; | 5476 | autoneg |= AUTONEG_SPEED; |
@@ -5148,44 +5483,41 @@ bnx2_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) | |||
5148 | (cmd->advertising == ADVERTISED_100baseT_Half) || | 5483 | (cmd->advertising == ADVERTISED_100baseT_Half) || |
5149 | (cmd->advertising == ADVERTISED_100baseT_Full)) { | 5484 | (cmd->advertising == ADVERTISED_100baseT_Full)) { |
5150 | 5485 | ||
5151 | if (bp->phy_flags & PHY_SERDES_FLAG) | 5486 | if (cmd->port == PORT_FIBRE) |
5152 | return -EINVAL; | 5487 | goto err_out_unlock; |
5153 | 5488 | ||
5154 | advertising = cmd->advertising; | 5489 | advertising = cmd->advertising; |
5155 | 5490 | ||
5156 | } else if (cmd->advertising == ADVERTISED_2500baseX_Full) { | 5491 | } else if (cmd->advertising == ADVERTISED_2500baseX_Full) { |
5157 | if (!(bp->phy_flags & PHY_2_5G_CAPABLE_FLAG)) | 5492 | if (!(bp->phy_flags & PHY_2_5G_CAPABLE_FLAG) || |
5158 | return -EINVAL; | 5493 | (cmd->port == PORT_TP)) |
5159 | } else if (cmd->advertising == ADVERTISED_1000baseT_Full) { | 5494 | goto err_out_unlock; |
5495 | } else if (cmd->advertising == ADVERTISED_1000baseT_Full) | ||
5160 | advertising = cmd->advertising; | 5496 | advertising = cmd->advertising; |
5161 | } | 5497 | else if (cmd->advertising == ADVERTISED_1000baseT_Half) |
5162 | else if (cmd->advertising == ADVERTISED_1000baseT_Half) { | 5498 | goto err_out_unlock; |
5163 | return -EINVAL; | ||
5164 | } | ||
5165 | else { | 5499 | else { |
5166 | if (bp->phy_flags & PHY_SERDES_FLAG) { | 5500 | if (cmd->port == PORT_FIBRE) |
5167 | advertising = ETHTOOL_ALL_FIBRE_SPEED; | 5501 | advertising = ETHTOOL_ALL_FIBRE_SPEED; |
5168 | } | 5502 | else |
5169 | else { | ||
5170 | advertising = ETHTOOL_ALL_COPPER_SPEED; | 5503 | advertising = ETHTOOL_ALL_COPPER_SPEED; |
5171 | } | ||
5172 | } | 5504 | } |
5173 | advertising |= ADVERTISED_Autoneg; | 5505 | advertising |= ADVERTISED_Autoneg; |
5174 | } | 5506 | } |
5175 | else { | 5507 | else { |
5176 | if (bp->phy_flags & PHY_SERDES_FLAG) { | 5508 | if (cmd->port == PORT_FIBRE) { |
5177 | if ((cmd->speed != SPEED_1000 && | 5509 | if ((cmd->speed != SPEED_1000 && |
5178 | cmd->speed != SPEED_2500) || | 5510 | cmd->speed != SPEED_2500) || |
5179 | (cmd->duplex != DUPLEX_FULL)) | 5511 | (cmd->duplex != DUPLEX_FULL)) |
5180 | return -EINVAL; | 5512 | goto err_out_unlock; |
5181 | 5513 | ||
5182 | if (cmd->speed == SPEED_2500 && | 5514 | if (cmd->speed == SPEED_2500 && |
5183 | !(bp->phy_flags & PHY_2_5G_CAPABLE_FLAG)) | 5515 | !(bp->phy_flags & PHY_2_5G_CAPABLE_FLAG)) |
5184 | return -EINVAL; | 5516 | goto err_out_unlock; |
5185 | } | ||
5186 | else if (cmd->speed == SPEED_1000) { | ||
5187 | return -EINVAL; | ||
5188 | } | 5517 | } |
5518 | else if (cmd->speed == SPEED_1000 || cmd->speed == SPEED_2500) | ||
5519 | goto err_out_unlock; | ||
5520 | |||
5189 | autoneg &= ~AUTONEG_SPEED; | 5521 | autoneg &= ~AUTONEG_SPEED; |
5190 | req_line_speed = cmd->speed; | 5522 | req_line_speed = cmd->speed; |
5191 | req_duplex = cmd->duplex; | 5523 | req_duplex = cmd->duplex; |
@@ -5197,13 +5529,12 @@ bnx2_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) | |||
5197 | bp->req_line_speed = req_line_speed; | 5529 | bp->req_line_speed = req_line_speed; |
5198 | bp->req_duplex = req_duplex; | 5530 | bp->req_duplex = req_duplex; |
5199 | 5531 | ||
5200 | spin_lock_bh(&bp->phy_lock); | 5532 | err = bnx2_setup_phy(bp, cmd->port); |
5201 | |||
5202 | bnx2_setup_phy(bp); | ||
5203 | 5533 | ||
5534 | err_out_unlock: | ||
5204 | spin_unlock_bh(&bp->phy_lock); | 5535 | spin_unlock_bh(&bp->phy_lock); |
5205 | 5536 | ||
5206 | return 0; | 5537 | return err; |
5207 | } | 5538 | } |
5208 | 5539 | ||
5209 | static void | 5540 | static void |
@@ -5214,11 +5545,7 @@ bnx2_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) | |||
5214 | strcpy(info->driver, DRV_MODULE_NAME); | 5545 | strcpy(info->driver, DRV_MODULE_NAME); |
5215 | strcpy(info->version, DRV_MODULE_VERSION); | 5546 | strcpy(info->version, DRV_MODULE_VERSION); |
5216 | strcpy(info->bus_info, pci_name(bp->pdev)); | 5547 | strcpy(info->bus_info, pci_name(bp->pdev)); |
5217 | info->fw_version[0] = ((bp->fw_ver & 0xff000000) >> 24) + '0'; | 5548 | strcpy(info->fw_version, bp->fw_version); |
5218 | info->fw_version[2] = ((bp->fw_ver & 0xff0000) >> 16) + '0'; | ||
5219 | info->fw_version[4] = ((bp->fw_ver & 0xff00) >> 8) + '0'; | ||
5220 | info->fw_version[1] = info->fw_version[3] = '.'; | ||
5221 | info->fw_version[5] = 0; | ||
5222 | } | 5549 | } |
5223 | 5550 | ||
5224 | #define BNX2_REGDUMP_LEN (32 * 1024) | 5551 | #define BNX2_REGDUMP_LEN (32 * 1024) |
@@ -5330,6 +5657,14 @@ bnx2_nway_reset(struct net_device *dev) | |||
5330 | 5657 | ||
5331 | spin_lock_bh(&bp->phy_lock); | 5658 | spin_lock_bh(&bp->phy_lock); |
5332 | 5659 | ||
5660 | if (bp->phy_flags & REMOTE_PHY_CAP_FLAG) { | ||
5661 | int rc; | ||
5662 | |||
5663 | rc = bnx2_setup_remote_phy(bp, bp->phy_port); | ||
5664 | spin_unlock_bh(&bp->phy_lock); | ||
5665 | return rc; | ||
5666 | } | ||
5667 | |||
5333 | /* Force a link down visible on the other side */ | 5668 | /* Force a link down visible on the other side */ |
5334 | if (bp->phy_flags & PHY_SERDES_FLAG) { | 5669 | if (bp->phy_flags & PHY_SERDES_FLAG) { |
5335 | bnx2_write_phy(bp, bp->mii_bmcr, BMCR_LOOPBACK); | 5670 | bnx2_write_phy(bp, bp->mii_bmcr, BMCR_LOOPBACK); |
@@ -5543,7 +5878,7 @@ bnx2_set_pauseparam(struct net_device *dev, struct ethtool_pauseparam *epause) | |||
5543 | 5878 | ||
5544 | spin_lock_bh(&bp->phy_lock); | 5879 | spin_lock_bh(&bp->phy_lock); |
5545 | 5880 | ||
5546 | bnx2_setup_phy(bp); | 5881 | bnx2_setup_phy(bp, bp->phy_port); |
5547 | 5882 | ||
5548 | spin_unlock_bh(&bp->phy_lock); | 5883 | spin_unlock_bh(&bp->phy_lock); |
5549 | 5884 | ||
@@ -5939,6 +6274,9 @@ bnx2_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) | |||
5939 | case SIOCGMIIREG: { | 6274 | case SIOCGMIIREG: { |
5940 | u32 mii_regval; | 6275 | u32 mii_regval; |
5941 | 6276 | ||
6277 | if (bp->phy_flags & REMOTE_PHY_CAP_FLAG) | ||
6278 | return -EOPNOTSUPP; | ||
6279 | |||
5942 | if (!netif_running(dev)) | 6280 | if (!netif_running(dev)) |
5943 | return -EAGAIN; | 6281 | return -EAGAIN; |
5944 | 6282 | ||
@@ -5955,6 +6293,9 @@ bnx2_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) | |||
5955 | if (!capable(CAP_NET_ADMIN)) | 6293 | if (!capable(CAP_NET_ADMIN)) |
5956 | return -EPERM; | 6294 | return -EPERM; |
5957 | 6295 | ||
6296 | if (bp->phy_flags & REMOTE_PHY_CAP_FLAG) | ||
6297 | return -EOPNOTSUPP; | ||
6298 | |||
5958 | if (!netif_running(dev)) | 6299 | if (!netif_running(dev)) |
5959 | return -EAGAIN; | 6300 | return -EAGAIN; |
5960 | 6301 | ||
@@ -6116,7 +6457,7 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev) | |||
6116 | { | 6457 | { |
6117 | struct bnx2 *bp; | 6458 | struct bnx2 *bp; |
6118 | unsigned long mem_len; | 6459 | unsigned long mem_len; |
6119 | int rc; | 6460 | int rc, i, j; |
6120 | u32 reg; | 6461 | u32 reg; |
6121 | u64 dma_mask, persist_dma_mask; | 6462 | u64 dma_mask, persist_dma_mask; |
6122 | 6463 | ||
@@ -6273,7 +6614,35 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev) | |||
6273 | goto err_out_unmap; | 6614 | goto err_out_unmap; |
6274 | } | 6615 | } |
6275 | 6616 | ||
6276 | bp->fw_ver = REG_RD_IND(bp, bp->shmem_base + BNX2_DEV_INFO_BC_REV); | 6617 | reg = REG_RD_IND(bp, bp->shmem_base + BNX2_DEV_INFO_BC_REV); |
6618 | for (i = 0, j = 0; i < 3; i++) { | ||
6619 | u8 num, k, skip0; | ||
6620 | |||
6621 | num = (u8) (reg >> (24 - (i * 8))); | ||
6622 | for (k = 100, skip0 = 1; k >= 1; num %= k, k /= 10) { | ||
6623 | if (num >= k || !skip0 || k == 1) { | ||
6624 | bp->fw_version[j++] = (num / k) + '0'; | ||
6625 | skip0 = 0; | ||
6626 | } | ||
6627 | } | ||
6628 | if (i != 2) | ||
6629 | bp->fw_version[j++] = '.'; | ||
6630 | } | ||
6631 | reg = REG_RD_IND(bp, bp->shmem_base + BNX2_BC_STATE_CONDITION); | ||
6632 | reg &= BNX2_CONDITION_MFW_RUN_MASK; | ||
6633 | if (reg != BNX2_CONDITION_MFW_RUN_UNKNOWN && | ||
6634 | reg != BNX2_CONDITION_MFW_RUN_NONE) { | ||
6635 | int i; | ||
6636 | u32 addr = REG_RD_IND(bp, bp->shmem_base + BNX2_MFW_VER_PTR); | ||
6637 | |||
6638 | bp->fw_version[j++] = ' '; | ||
6639 | for (i = 0; i < 3; i++) { | ||
6640 | reg = REG_RD_IND(bp, addr + i * 4); | ||
6641 | reg = swab32(reg); | ||
6642 | memcpy(&bp->fw_version[j], ®, 4); | ||
6643 | j += 4; | ||
6644 | } | ||
6645 | } | ||
6277 | 6646 | ||
6278 | reg = REG_RD_IND(bp, bp->shmem_base + BNX2_PORT_HW_CFG_MAC_UPPER); | 6647 | reg = REG_RD_IND(bp, bp->shmem_base + BNX2_PORT_HW_CFG_MAC_UPPER); |
6279 | bp->mac_addr[0] = (u8) (reg >> 8); | 6648 | bp->mac_addr[0] = (u8) (reg >> 8); |
@@ -6315,7 +6684,9 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev) | |||
6315 | else if (CHIP_BOND_ID(bp) & CHIP_BOND_ID_SERDES_BIT) | 6684 | else if (CHIP_BOND_ID(bp) & CHIP_BOND_ID_SERDES_BIT) |
6316 | bp->phy_flags |= PHY_SERDES_FLAG; | 6685 | bp->phy_flags |= PHY_SERDES_FLAG; |
6317 | 6686 | ||
6687 | bp->phy_port = PORT_TP; | ||
6318 | if (bp->phy_flags & PHY_SERDES_FLAG) { | 6688 | if (bp->phy_flags & PHY_SERDES_FLAG) { |
6689 | bp->phy_port = PORT_FIBRE; | ||
6319 | bp->flags |= NO_WOL_FLAG; | 6690 | bp->flags |= NO_WOL_FLAG; |
6320 | if (CHIP_NUM(bp) != CHIP_NUM_5706) { | 6691 | if (CHIP_NUM(bp) != CHIP_NUM_5706) { |
6321 | bp->phy_addr = 2; | 6692 | bp->phy_addr = 2; |
@@ -6324,6 +6695,8 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev) | |||
6324 | if (reg & BNX2_SHARED_HW_CFG_PHY_2_5G) | 6695 | if (reg & BNX2_SHARED_HW_CFG_PHY_2_5G) |
6325 | bp->phy_flags |= PHY_2_5G_CAPABLE_FLAG; | 6696 | bp->phy_flags |= PHY_2_5G_CAPABLE_FLAG; |
6326 | } | 6697 | } |
6698 | bnx2_init_remote_phy(bp); | ||
6699 | |||
6327 | } else if (CHIP_NUM(bp) == CHIP_NUM_5706 || | 6700 | } else if (CHIP_NUM(bp) == CHIP_NUM_5706 || |
6328 | CHIP_NUM(bp) == CHIP_NUM_5708) | 6701 | CHIP_NUM(bp) == CHIP_NUM_5708) |
6329 | bp->phy_flags |= PHY_CRC_FIX_FLAG; | 6702 | bp->phy_flags |= PHY_CRC_FIX_FLAG; |
@@ -6373,23 +6746,7 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev) | |||
6373 | } | 6746 | } |
6374 | } | 6747 | } |
6375 | 6748 | ||
6376 | bp->autoneg = AUTONEG_SPEED | AUTONEG_FLOW_CTRL; | 6749 | bnx2_set_default_link(bp); |
6377 | bp->req_line_speed = 0; | ||
6378 | if (bp->phy_flags & PHY_SERDES_FLAG) { | ||
6379 | bp->advertising = ETHTOOL_ALL_FIBRE_SPEED | ADVERTISED_Autoneg; | ||
6380 | |||
6381 | reg = REG_RD_IND(bp, bp->shmem_base + BNX2_PORT_HW_CFG_CONFIG); | ||
6382 | reg &= BNX2_PORT_HW_CFG_CFG_DFLT_LINK_MASK; | ||
6383 | if (reg == BNX2_PORT_HW_CFG_CFG_DFLT_LINK_1G) { | ||
6384 | bp->autoneg = 0; | ||
6385 | bp->req_line_speed = bp->line_speed = SPEED_1000; | ||
6386 | bp->req_duplex = DUPLEX_FULL; | ||
6387 | } | ||
6388 | } | ||
6389 | else { | ||
6390 | bp->advertising = ETHTOOL_ALL_COPPER_SPEED | ADVERTISED_Autoneg; | ||
6391 | } | ||
6392 | |||
6393 | bp->req_flow_ctrl = FLOW_CTRL_RX | FLOW_CTRL_TX; | 6750 | bp->req_flow_ctrl = FLOW_CTRL_RX | FLOW_CTRL_TX; |
6394 | 6751 | ||
6395 | init_timer(&bp->timer); | 6752 | init_timer(&bp->timer); |
@@ -6489,10 +6846,10 @@ bnx2_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
6489 | memcpy(dev->perm_addr, bp->mac_addr, 6); | 6846 | memcpy(dev->perm_addr, bp->mac_addr, 6); |
6490 | bp->name = board_info[ent->driver_data].name; | 6847 | bp->name = board_info[ent->driver_data].name; |
6491 | 6848 | ||
6849 | dev->features |= NETIF_F_IP_CSUM | NETIF_F_SG; | ||
6492 | if (CHIP_NUM(bp) == CHIP_NUM_5709) | 6850 | if (CHIP_NUM(bp) == CHIP_NUM_5709) |
6493 | dev->features |= NETIF_F_HW_CSUM | NETIF_F_SG; | 6851 | dev->features |= NETIF_F_IPV6_CSUM; |
6494 | else | 6852 | |
6495 | dev->features |= NETIF_F_IP_CSUM | NETIF_F_SG; | ||
6496 | #ifdef BCM_VLAN | 6853 | #ifdef BCM_VLAN |
6497 | dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX; | 6854 | dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX; |
6498 | #endif | 6855 | #endif |