diff options
Diffstat (limited to 'drivers/net/b44.c')
-rw-r--r-- | drivers/net/b44.c | 308 |
1 files changed, 254 insertions, 54 deletions
diff --git a/drivers/net/b44.c b/drivers/net/b44.c index d8233e0b7899..bea0fc0ede2f 100644 --- a/drivers/net/b44.c +++ b/drivers/net/b44.c | |||
@@ -29,8 +29,8 @@ | |||
29 | 29 | ||
30 | #define DRV_MODULE_NAME "b44" | 30 | #define DRV_MODULE_NAME "b44" |
31 | #define PFX DRV_MODULE_NAME ": " | 31 | #define PFX DRV_MODULE_NAME ": " |
32 | #define DRV_MODULE_VERSION "1.00" | 32 | #define DRV_MODULE_VERSION "1.01" |
33 | #define DRV_MODULE_RELDATE "Apr 7, 2006" | 33 | #define DRV_MODULE_RELDATE "Jun 16, 2006" |
34 | 34 | ||
35 | #define B44_DEF_MSG_ENABLE \ | 35 | #define B44_DEF_MSG_ENABLE \ |
36 | (NETIF_MSG_DRV | \ | 36 | (NETIF_MSG_DRV | \ |
@@ -75,6 +75,15 @@ | |||
75 | /* minimum number of free TX descriptors required to wake up TX process */ | 75 | /* minimum number of free TX descriptors required to wake up TX process */ |
76 | #define B44_TX_WAKEUP_THRESH (B44_TX_RING_SIZE / 4) | 76 | #define B44_TX_WAKEUP_THRESH (B44_TX_RING_SIZE / 4) |
77 | 77 | ||
78 | /* b44 internal pattern match filter info */ | ||
79 | #define B44_PATTERN_BASE 0x400 | ||
80 | #define B44_PATTERN_SIZE 0x80 | ||
81 | #define B44_PMASK_BASE 0x600 | ||
82 | #define B44_PMASK_SIZE 0x10 | ||
83 | #define B44_MAX_PATTERNS 16 | ||
84 | #define B44_ETHIPV6UDP_HLEN 62 | ||
85 | #define B44_ETHIPV4UDP_HLEN 42 | ||
86 | |||
78 | static char version[] __devinitdata = | 87 | static char version[] __devinitdata = |
79 | DRV_MODULE_NAME ".c:v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n"; | 88 | DRV_MODULE_NAME ".c:v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n"; |
80 | 89 | ||
@@ -101,7 +110,7 @@ MODULE_DEVICE_TABLE(pci, b44_pci_tbl); | |||
101 | 110 | ||
102 | static void b44_halt(struct b44 *); | 111 | static void b44_halt(struct b44 *); |
103 | static void b44_init_rings(struct b44 *); | 112 | static void b44_init_rings(struct b44 *); |
104 | static void b44_init_hw(struct b44 *); | 113 | static void b44_init_hw(struct b44 *, int); |
105 | 114 | ||
106 | static int dma_desc_align_mask; | 115 | static int dma_desc_align_mask; |
107 | static int dma_desc_sync_size; | 116 | static int dma_desc_sync_size; |
@@ -873,7 +882,7 @@ static int b44_poll(struct net_device *netdev, int *budget) | |||
873 | spin_lock_irq(&bp->lock); | 882 | spin_lock_irq(&bp->lock); |
874 | b44_halt(bp); | 883 | b44_halt(bp); |
875 | b44_init_rings(bp); | 884 | b44_init_rings(bp); |
876 | b44_init_hw(bp); | 885 | b44_init_hw(bp, 1); |
877 | netif_wake_queue(bp->dev); | 886 | netif_wake_queue(bp->dev); |
878 | spin_unlock_irq(&bp->lock); | 887 | spin_unlock_irq(&bp->lock); |
879 | done = 1; | 888 | done = 1; |
@@ -942,7 +951,7 @@ static void b44_tx_timeout(struct net_device *dev) | |||
942 | 951 | ||
943 | b44_halt(bp); | 952 | b44_halt(bp); |
944 | b44_init_rings(bp); | 953 | b44_init_rings(bp); |
945 | b44_init_hw(bp); | 954 | b44_init_hw(bp, 1); |
946 | 955 | ||
947 | spin_unlock_irq(&bp->lock); | 956 | spin_unlock_irq(&bp->lock); |
948 | 957 | ||
@@ -1059,7 +1068,7 @@ static int b44_change_mtu(struct net_device *dev, int new_mtu) | |||
1059 | b44_halt(bp); | 1068 | b44_halt(bp); |
1060 | dev->mtu = new_mtu; | 1069 | dev->mtu = new_mtu; |
1061 | b44_init_rings(bp); | 1070 | b44_init_rings(bp); |
1062 | b44_init_hw(bp); | 1071 | b44_init_hw(bp, 1); |
1063 | spin_unlock_irq(&bp->lock); | 1072 | spin_unlock_irq(&bp->lock); |
1064 | 1073 | ||
1065 | b44_enable_ints(bp); | 1074 | b44_enable_ints(bp); |
@@ -1356,13 +1365,15 @@ static int b44_set_mac_addr(struct net_device *dev, void *p) | |||
1356 | * packet processing. Invoked with bp->lock held. | 1365 | * packet processing. Invoked with bp->lock held. |
1357 | */ | 1366 | */ |
1358 | static void __b44_set_rx_mode(struct net_device *); | 1367 | static void __b44_set_rx_mode(struct net_device *); |
1359 | static void b44_init_hw(struct b44 *bp) | 1368 | static void b44_init_hw(struct b44 *bp, int full_reset) |
1360 | { | 1369 | { |
1361 | u32 val; | 1370 | u32 val; |
1362 | 1371 | ||
1363 | b44_chip_reset(bp); | 1372 | b44_chip_reset(bp); |
1364 | b44_phy_reset(bp); | 1373 | if (full_reset) { |
1365 | b44_setup_phy(bp); | 1374 | b44_phy_reset(bp); |
1375 | b44_setup_phy(bp); | ||
1376 | } | ||
1366 | 1377 | ||
1367 | /* Enable CRC32, set proper LED modes and power on PHY */ | 1378 | /* Enable CRC32, set proper LED modes and power on PHY */ |
1368 | bw32(bp, B44_MAC_CTRL, MAC_CTRL_CRC32_ENAB | MAC_CTRL_PHY_LEDCTRL); | 1379 | bw32(bp, B44_MAC_CTRL, MAC_CTRL_CRC32_ENAB | MAC_CTRL_PHY_LEDCTRL); |
@@ -1376,16 +1387,21 @@ static void b44_init_hw(struct b44 *bp) | |||
1376 | bw32(bp, B44_TXMAXLEN, bp->dev->mtu + ETH_HLEN + 8 + RX_HEADER_LEN); | 1387 | bw32(bp, B44_TXMAXLEN, bp->dev->mtu + ETH_HLEN + 8 + RX_HEADER_LEN); |
1377 | 1388 | ||
1378 | bw32(bp, B44_TX_WMARK, 56); /* XXX magic */ | 1389 | bw32(bp, B44_TX_WMARK, 56); /* XXX magic */ |
1379 | bw32(bp, B44_DMATX_CTRL, DMATX_CTRL_ENABLE); | 1390 | if (full_reset) { |
1380 | bw32(bp, B44_DMATX_ADDR, bp->tx_ring_dma + bp->dma_offset); | 1391 | bw32(bp, B44_DMATX_CTRL, DMATX_CTRL_ENABLE); |
1381 | bw32(bp, B44_DMARX_CTRL, (DMARX_CTRL_ENABLE | | 1392 | bw32(bp, B44_DMATX_ADDR, bp->tx_ring_dma + bp->dma_offset); |
1382 | (bp->rx_offset << DMARX_CTRL_ROSHIFT))); | 1393 | bw32(bp, B44_DMARX_CTRL, (DMARX_CTRL_ENABLE | |
1383 | bw32(bp, B44_DMARX_ADDR, bp->rx_ring_dma + bp->dma_offset); | 1394 | (bp->rx_offset << DMARX_CTRL_ROSHIFT))); |
1395 | bw32(bp, B44_DMARX_ADDR, bp->rx_ring_dma + bp->dma_offset); | ||
1384 | 1396 | ||
1385 | bw32(bp, B44_DMARX_PTR, bp->rx_pending); | 1397 | bw32(bp, B44_DMARX_PTR, bp->rx_pending); |
1386 | bp->rx_prod = bp->rx_pending; | 1398 | bp->rx_prod = bp->rx_pending; |
1387 | 1399 | ||
1388 | bw32(bp, B44_MIB_CTRL, MIB_CTRL_CLR_ON_READ); | 1400 | bw32(bp, B44_MIB_CTRL, MIB_CTRL_CLR_ON_READ); |
1401 | } else { | ||
1402 | bw32(bp, B44_DMARX_CTRL, (DMARX_CTRL_ENABLE | | ||
1403 | (bp->rx_offset << DMARX_CTRL_ROSHIFT))); | ||
1404 | } | ||
1389 | 1405 | ||
1390 | val = br32(bp, B44_ENET_CTRL); | 1406 | val = br32(bp, B44_ENET_CTRL); |
1391 | bw32(bp, B44_ENET_CTRL, (val | ENET_CTRL_ENABLE)); | 1407 | bw32(bp, B44_ENET_CTRL, (val | ENET_CTRL_ENABLE)); |
@@ -1401,11 +1417,11 @@ static int b44_open(struct net_device *dev) | |||
1401 | goto out; | 1417 | goto out; |
1402 | 1418 | ||
1403 | b44_init_rings(bp); | 1419 | b44_init_rings(bp); |
1404 | b44_init_hw(bp); | 1420 | b44_init_hw(bp, 1); |
1405 | 1421 | ||
1406 | b44_check_phy(bp); | 1422 | b44_check_phy(bp); |
1407 | 1423 | ||
1408 | err = request_irq(dev->irq, b44_interrupt, SA_SHIRQ, dev->name, dev); | 1424 | err = request_irq(dev->irq, b44_interrupt, IRQF_SHARED, dev->name, dev); |
1409 | if (unlikely(err < 0)) { | 1425 | if (unlikely(err < 0)) { |
1410 | b44_chip_reset(bp); | 1426 | b44_chip_reset(bp); |
1411 | b44_free_rings(bp); | 1427 | b44_free_rings(bp); |
@@ -1450,6 +1466,140 @@ static void b44_poll_controller(struct net_device *dev) | |||
1450 | } | 1466 | } |
1451 | #endif | 1467 | #endif |
1452 | 1468 | ||
1469 | static void bwfilter_table(struct b44 *bp, u8 *pp, u32 bytes, u32 table_offset) | ||
1470 | { | ||
1471 | u32 i; | ||
1472 | u32 *pattern = (u32 *) pp; | ||
1473 | |||
1474 | for (i = 0; i < bytes; i += sizeof(u32)) { | ||
1475 | bw32(bp, B44_FILT_ADDR, table_offset + i); | ||
1476 | bw32(bp, B44_FILT_DATA, pattern[i / sizeof(u32)]); | ||
1477 | } | ||
1478 | } | ||
1479 | |||
1480 | static int b44_magic_pattern(u8 *macaddr, u8 *ppattern, u8 *pmask, int offset) | ||
1481 | { | ||
1482 | int magicsync = 6; | ||
1483 | int k, j, len = offset; | ||
1484 | int ethaddr_bytes = ETH_ALEN; | ||
1485 | |||
1486 | memset(ppattern + offset, 0xff, magicsync); | ||
1487 | for (j = 0; j < magicsync; j++) | ||
1488 | set_bit(len++, (unsigned long *) pmask); | ||
1489 | |||
1490 | for (j = 0; j < B44_MAX_PATTERNS; j++) { | ||
1491 | if ((B44_PATTERN_SIZE - len) >= ETH_ALEN) | ||
1492 | ethaddr_bytes = ETH_ALEN; | ||
1493 | else | ||
1494 | ethaddr_bytes = B44_PATTERN_SIZE - len; | ||
1495 | if (ethaddr_bytes <=0) | ||
1496 | break; | ||
1497 | for (k = 0; k< ethaddr_bytes; k++) { | ||
1498 | ppattern[offset + magicsync + | ||
1499 | (j * ETH_ALEN) + k] = macaddr[k]; | ||
1500 | len++; | ||
1501 | set_bit(len, (unsigned long *) pmask); | ||
1502 | } | ||
1503 | } | ||
1504 | return len - 1; | ||
1505 | } | ||
1506 | |||
1507 | /* Setup magic packet patterns in the b44 WOL | ||
1508 | * pattern matching filter. | ||
1509 | */ | ||
1510 | static void b44_setup_pseudo_magicp(struct b44 *bp) | ||
1511 | { | ||
1512 | |||
1513 | u32 val; | ||
1514 | int plen0, plen1, plen2; | ||
1515 | u8 *pwol_pattern; | ||
1516 | u8 pwol_mask[B44_PMASK_SIZE]; | ||
1517 | |||
1518 | pwol_pattern = kmalloc(B44_PATTERN_SIZE, GFP_KERNEL); | ||
1519 | if (!pwol_pattern) { | ||
1520 | printk(KERN_ERR PFX "Memory not available for WOL\n"); | ||
1521 | return; | ||
1522 | } | ||
1523 | |||
1524 | /* Ipv4 magic packet pattern - pattern 0.*/ | ||
1525 | memset(pwol_pattern, 0, B44_PATTERN_SIZE); | ||
1526 | memset(pwol_mask, 0, B44_PMASK_SIZE); | ||
1527 | plen0 = b44_magic_pattern(bp->dev->dev_addr, pwol_pattern, pwol_mask, | ||
1528 | B44_ETHIPV4UDP_HLEN); | ||
1529 | |||
1530 | bwfilter_table(bp, pwol_pattern, B44_PATTERN_SIZE, B44_PATTERN_BASE); | ||
1531 | bwfilter_table(bp, pwol_mask, B44_PMASK_SIZE, B44_PMASK_BASE); | ||
1532 | |||
1533 | /* Raw ethernet II magic packet pattern - pattern 1 */ | ||
1534 | memset(pwol_pattern, 0, B44_PATTERN_SIZE); | ||
1535 | memset(pwol_mask, 0, B44_PMASK_SIZE); | ||
1536 | plen1 = b44_magic_pattern(bp->dev->dev_addr, pwol_pattern, pwol_mask, | ||
1537 | ETH_HLEN); | ||
1538 | |||
1539 | bwfilter_table(bp, pwol_pattern, B44_PATTERN_SIZE, | ||
1540 | B44_PATTERN_BASE + B44_PATTERN_SIZE); | ||
1541 | bwfilter_table(bp, pwol_mask, B44_PMASK_SIZE, | ||
1542 | B44_PMASK_BASE + B44_PMASK_SIZE); | ||
1543 | |||
1544 | /* Ipv6 magic packet pattern - pattern 2 */ | ||
1545 | memset(pwol_pattern, 0, B44_PATTERN_SIZE); | ||
1546 | memset(pwol_mask, 0, B44_PMASK_SIZE); | ||
1547 | plen2 = b44_magic_pattern(bp->dev->dev_addr, pwol_pattern, pwol_mask, | ||
1548 | B44_ETHIPV6UDP_HLEN); | ||
1549 | |||
1550 | bwfilter_table(bp, pwol_pattern, B44_PATTERN_SIZE, | ||
1551 | B44_PATTERN_BASE + B44_PATTERN_SIZE + B44_PATTERN_SIZE); | ||
1552 | bwfilter_table(bp, pwol_mask, B44_PMASK_SIZE, | ||
1553 | B44_PMASK_BASE + B44_PMASK_SIZE + B44_PMASK_SIZE); | ||
1554 | |||
1555 | kfree(pwol_pattern); | ||
1556 | |||
1557 | /* set these pattern's lengths: one less than each real length */ | ||
1558 | val = plen0 | (plen1 << 8) | (plen2 << 16) | WKUP_LEN_ENABLE_THREE; | ||
1559 | bw32(bp, B44_WKUP_LEN, val); | ||
1560 | |||
1561 | /* enable wakeup pattern matching */ | ||
1562 | val = br32(bp, B44_DEVCTRL); | ||
1563 | bw32(bp, B44_DEVCTRL, val | DEVCTRL_PFE); | ||
1564 | |||
1565 | } | ||
1566 | |||
1567 | static void b44_setup_wol(struct b44 *bp) | ||
1568 | { | ||
1569 | u32 val; | ||
1570 | u16 pmval; | ||
1571 | |||
1572 | bw32(bp, B44_RXCONFIG, RXCONFIG_ALLMULTI); | ||
1573 | |||
1574 | if (bp->flags & B44_FLAG_B0_ANDLATER) { | ||
1575 | |||
1576 | bw32(bp, B44_WKUP_LEN, WKUP_LEN_DISABLE); | ||
1577 | |||
1578 | val = bp->dev->dev_addr[2] << 24 | | ||
1579 | bp->dev->dev_addr[3] << 16 | | ||
1580 | bp->dev->dev_addr[4] << 8 | | ||
1581 | bp->dev->dev_addr[5]; | ||
1582 | bw32(bp, B44_ADDR_LO, val); | ||
1583 | |||
1584 | val = bp->dev->dev_addr[0] << 8 | | ||
1585 | bp->dev->dev_addr[1]; | ||
1586 | bw32(bp, B44_ADDR_HI, val); | ||
1587 | |||
1588 | val = br32(bp, B44_DEVCTRL); | ||
1589 | bw32(bp, B44_DEVCTRL, val | DEVCTRL_MPM | DEVCTRL_PFE); | ||
1590 | |||
1591 | } else { | ||
1592 | b44_setup_pseudo_magicp(bp); | ||
1593 | } | ||
1594 | |||
1595 | val = br32(bp, B44_SBTMSLOW); | ||
1596 | bw32(bp, B44_SBTMSLOW, val | SBTMSLOW_PE); | ||
1597 | |||
1598 | pci_read_config_word(bp->pdev, SSB_PMCSR, &pmval); | ||
1599 | pci_write_config_word(bp->pdev, SSB_PMCSR, pmval | SSB_PE); | ||
1600 | |||
1601 | } | ||
1602 | |||
1453 | static int b44_close(struct net_device *dev) | 1603 | static int b44_close(struct net_device *dev) |
1454 | { | 1604 | { |
1455 | struct b44 *bp = netdev_priv(dev); | 1605 | struct b44 *bp = netdev_priv(dev); |
@@ -1475,6 +1625,11 @@ static int b44_close(struct net_device *dev) | |||
1475 | 1625 | ||
1476 | netif_poll_enable(dev); | 1626 | netif_poll_enable(dev); |
1477 | 1627 | ||
1628 | if (bp->flags & B44_FLAG_WOL_ENABLE) { | ||
1629 | b44_init_hw(bp, 0); | ||
1630 | b44_setup_wol(bp); | ||
1631 | } | ||
1632 | |||
1478 | b44_free_consistent(bp); | 1633 | b44_free_consistent(bp); |
1479 | 1634 | ||
1480 | return 0; | 1635 | return 0; |
@@ -1620,8 +1775,6 @@ static int b44_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) | |||
1620 | { | 1775 | { |
1621 | struct b44 *bp = netdev_priv(dev); | 1776 | struct b44 *bp = netdev_priv(dev); |
1622 | 1777 | ||
1623 | if (!netif_running(dev)) | ||
1624 | return -EAGAIN; | ||
1625 | cmd->supported = (SUPPORTED_Autoneg); | 1778 | cmd->supported = (SUPPORTED_Autoneg); |
1626 | cmd->supported |= (SUPPORTED_100baseT_Half | | 1779 | cmd->supported |= (SUPPORTED_100baseT_Half | |
1627 | SUPPORTED_100baseT_Full | | 1780 | SUPPORTED_100baseT_Full | |
@@ -1649,6 +1802,12 @@ static int b44_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) | |||
1649 | XCVR_INTERNAL : XCVR_EXTERNAL; | 1802 | XCVR_INTERNAL : XCVR_EXTERNAL; |
1650 | cmd->autoneg = (bp->flags & B44_FLAG_FORCE_LINK) ? | 1803 | cmd->autoneg = (bp->flags & B44_FLAG_FORCE_LINK) ? |
1651 | AUTONEG_DISABLE : AUTONEG_ENABLE; | 1804 | AUTONEG_DISABLE : AUTONEG_ENABLE; |
1805 | if (cmd->autoneg == AUTONEG_ENABLE) | ||
1806 | cmd->advertising |= ADVERTISED_Autoneg; | ||
1807 | if (!netif_running(dev)){ | ||
1808 | cmd->speed = 0; | ||
1809 | cmd->duplex = 0xff; | ||
1810 | } | ||
1652 | cmd->maxtxpkt = 0; | 1811 | cmd->maxtxpkt = 0; |
1653 | cmd->maxrxpkt = 0; | 1812 | cmd->maxrxpkt = 0; |
1654 | return 0; | 1813 | return 0; |
@@ -1658,9 +1817,6 @@ static int b44_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) | |||
1658 | { | 1817 | { |
1659 | struct b44 *bp = netdev_priv(dev); | 1818 | struct b44 *bp = netdev_priv(dev); |
1660 | 1819 | ||
1661 | if (!netif_running(dev)) | ||
1662 | return -EAGAIN; | ||
1663 | |||
1664 | /* We do not support gigabit. */ | 1820 | /* We do not support gigabit. */ |
1665 | if (cmd->autoneg == AUTONEG_ENABLE) { | 1821 | if (cmd->autoneg == AUTONEG_ENABLE) { |
1666 | if (cmd->advertising & | 1822 | if (cmd->advertising & |
@@ -1677,28 +1833,39 @@ static int b44_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) | |||
1677 | spin_lock_irq(&bp->lock); | 1833 | spin_lock_irq(&bp->lock); |
1678 | 1834 | ||
1679 | if (cmd->autoneg == AUTONEG_ENABLE) { | 1835 | if (cmd->autoneg == AUTONEG_ENABLE) { |
1680 | bp->flags &= ~B44_FLAG_FORCE_LINK; | 1836 | bp->flags &= ~(B44_FLAG_FORCE_LINK | |
1681 | bp->flags &= ~(B44_FLAG_ADV_10HALF | | 1837 | B44_FLAG_100_BASE_T | |
1838 | B44_FLAG_FULL_DUPLEX | | ||
1839 | B44_FLAG_ADV_10HALF | | ||
1682 | B44_FLAG_ADV_10FULL | | 1840 | B44_FLAG_ADV_10FULL | |
1683 | B44_FLAG_ADV_100HALF | | 1841 | B44_FLAG_ADV_100HALF | |
1684 | B44_FLAG_ADV_100FULL); | 1842 | B44_FLAG_ADV_100FULL); |
1685 | if (cmd->advertising & ADVERTISE_10HALF) | 1843 | if (cmd->advertising == 0) { |
1686 | bp->flags |= B44_FLAG_ADV_10HALF; | 1844 | bp->flags |= (B44_FLAG_ADV_10HALF | |
1687 | if (cmd->advertising & ADVERTISE_10FULL) | 1845 | B44_FLAG_ADV_10FULL | |
1688 | bp->flags |= B44_FLAG_ADV_10FULL; | 1846 | B44_FLAG_ADV_100HALF | |
1689 | if (cmd->advertising & ADVERTISE_100HALF) | 1847 | B44_FLAG_ADV_100FULL); |
1690 | bp->flags |= B44_FLAG_ADV_100HALF; | 1848 | } else { |
1691 | if (cmd->advertising & ADVERTISE_100FULL) | 1849 | if (cmd->advertising & ADVERTISED_10baseT_Half) |
1692 | bp->flags |= B44_FLAG_ADV_100FULL; | 1850 | bp->flags |= B44_FLAG_ADV_10HALF; |
1851 | if (cmd->advertising & ADVERTISED_10baseT_Full) | ||
1852 | bp->flags |= B44_FLAG_ADV_10FULL; | ||
1853 | if (cmd->advertising & ADVERTISED_100baseT_Half) | ||
1854 | bp->flags |= B44_FLAG_ADV_100HALF; | ||
1855 | if (cmd->advertising & ADVERTISED_100baseT_Full) | ||
1856 | bp->flags |= B44_FLAG_ADV_100FULL; | ||
1857 | } | ||
1693 | } else { | 1858 | } else { |
1694 | bp->flags |= B44_FLAG_FORCE_LINK; | 1859 | bp->flags |= B44_FLAG_FORCE_LINK; |
1860 | bp->flags &= ~(B44_FLAG_100_BASE_T | B44_FLAG_FULL_DUPLEX); | ||
1695 | if (cmd->speed == SPEED_100) | 1861 | if (cmd->speed == SPEED_100) |
1696 | bp->flags |= B44_FLAG_100_BASE_T; | 1862 | bp->flags |= B44_FLAG_100_BASE_T; |
1697 | if (cmd->duplex == DUPLEX_FULL) | 1863 | if (cmd->duplex == DUPLEX_FULL) |
1698 | bp->flags |= B44_FLAG_FULL_DUPLEX; | 1864 | bp->flags |= B44_FLAG_FULL_DUPLEX; |
1699 | } | 1865 | } |
1700 | 1866 | ||
1701 | b44_setup_phy(bp); | 1867 | if (netif_running(dev)) |
1868 | b44_setup_phy(bp); | ||
1702 | 1869 | ||
1703 | spin_unlock_irq(&bp->lock); | 1870 | spin_unlock_irq(&bp->lock); |
1704 | 1871 | ||
@@ -1734,7 +1901,7 @@ static int b44_set_ringparam(struct net_device *dev, | |||
1734 | 1901 | ||
1735 | b44_halt(bp); | 1902 | b44_halt(bp); |
1736 | b44_init_rings(bp); | 1903 | b44_init_rings(bp); |
1737 | b44_init_hw(bp); | 1904 | b44_init_hw(bp, 1); |
1738 | netif_wake_queue(bp->dev); | 1905 | netif_wake_queue(bp->dev); |
1739 | spin_unlock_irq(&bp->lock); | 1906 | spin_unlock_irq(&bp->lock); |
1740 | 1907 | ||
@@ -1777,7 +1944,7 @@ static int b44_set_pauseparam(struct net_device *dev, | |||
1777 | if (bp->flags & B44_FLAG_PAUSE_AUTO) { | 1944 | if (bp->flags & B44_FLAG_PAUSE_AUTO) { |
1778 | b44_halt(bp); | 1945 | b44_halt(bp); |
1779 | b44_init_rings(bp); | 1946 | b44_init_rings(bp); |
1780 | b44_init_hw(bp); | 1947 | b44_init_hw(bp, 1); |
1781 | } else { | 1948 | } else { |
1782 | __b44_set_flow_ctrl(bp, bp->flags); | 1949 | __b44_set_flow_ctrl(bp, bp->flags); |
1783 | } | 1950 | } |
@@ -1819,12 +1986,40 @@ static void b44_get_ethtool_stats(struct net_device *dev, | |||
1819 | spin_unlock_irq(&bp->lock); | 1986 | spin_unlock_irq(&bp->lock); |
1820 | } | 1987 | } |
1821 | 1988 | ||
1989 | static void b44_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol) | ||
1990 | { | ||
1991 | struct b44 *bp = netdev_priv(dev); | ||
1992 | |||
1993 | wol->supported = WAKE_MAGIC; | ||
1994 | if (bp->flags & B44_FLAG_WOL_ENABLE) | ||
1995 | wol->wolopts = WAKE_MAGIC; | ||
1996 | else | ||
1997 | wol->wolopts = 0; | ||
1998 | memset(&wol->sopass, 0, sizeof(wol->sopass)); | ||
1999 | } | ||
2000 | |||
2001 | static int b44_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) | ||
2002 | { | ||
2003 | struct b44 *bp = netdev_priv(dev); | ||
2004 | |||
2005 | spin_lock_irq(&bp->lock); | ||
2006 | if (wol->wolopts & WAKE_MAGIC) | ||
2007 | bp->flags |= B44_FLAG_WOL_ENABLE; | ||
2008 | else | ||
2009 | bp->flags &= ~B44_FLAG_WOL_ENABLE; | ||
2010 | spin_unlock_irq(&bp->lock); | ||
2011 | |||
2012 | return 0; | ||
2013 | } | ||
2014 | |||
1822 | static struct ethtool_ops b44_ethtool_ops = { | 2015 | static struct ethtool_ops b44_ethtool_ops = { |
1823 | .get_drvinfo = b44_get_drvinfo, | 2016 | .get_drvinfo = b44_get_drvinfo, |
1824 | .get_settings = b44_get_settings, | 2017 | .get_settings = b44_get_settings, |
1825 | .set_settings = b44_set_settings, | 2018 | .set_settings = b44_set_settings, |
1826 | .nway_reset = b44_nway_reset, | 2019 | .nway_reset = b44_nway_reset, |
1827 | .get_link = ethtool_op_get_link, | 2020 | .get_link = ethtool_op_get_link, |
2021 | .get_wol = b44_get_wol, | ||
2022 | .set_wol = b44_set_wol, | ||
1828 | .get_ringparam = b44_get_ringparam, | 2023 | .get_ringparam = b44_get_ringparam, |
1829 | .set_ringparam = b44_set_ringparam, | 2024 | .set_ringparam = b44_set_ringparam, |
1830 | .get_pauseparam = b44_get_pauseparam, | 2025 | .get_pauseparam = b44_get_pauseparam, |
@@ -1903,6 +2098,10 @@ static int __devinit b44_get_invariants(struct b44 *bp) | |||
1903 | /* XXX - really required? | 2098 | /* XXX - really required? |
1904 | bp->flags |= B44_FLAG_BUGGY_TXPTR; | 2099 | bp->flags |= B44_FLAG_BUGGY_TXPTR; |
1905 | */ | 2100 | */ |
2101 | |||
2102 | if (ssb_get_core_rev(bp) >= 7) | ||
2103 | bp->flags |= B44_FLAG_B0_ANDLATER; | ||
2104 | |||
1906 | out: | 2105 | out: |
1907 | return err; | 2106 | return err; |
1908 | } | 2107 | } |
@@ -1921,13 +2120,14 @@ static int __devinit b44_init_one(struct pci_dev *pdev, | |||
1921 | 2120 | ||
1922 | err = pci_enable_device(pdev); | 2121 | err = pci_enable_device(pdev); |
1923 | if (err) { | 2122 | if (err) { |
1924 | printk(KERN_ERR PFX "Cannot enable PCI device, " | 2123 | dev_err(&pdev->dev, "Cannot enable PCI device, " |
1925 | "aborting.\n"); | 2124 | "aborting.\n"); |
1926 | return err; | 2125 | return err; |
1927 | } | 2126 | } |
1928 | 2127 | ||
1929 | if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)) { | 2128 | if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)) { |
1930 | printk(KERN_ERR PFX "Cannot find proper PCI device " | 2129 | dev_err(&pdev->dev, |
2130 | "Cannot find proper PCI device " | ||
1931 | "base address, aborting.\n"); | 2131 | "base address, aborting.\n"); |
1932 | err = -ENODEV; | 2132 | err = -ENODEV; |
1933 | goto err_out_disable_pdev; | 2133 | goto err_out_disable_pdev; |
@@ -1935,8 +2135,8 @@ static int __devinit b44_init_one(struct pci_dev *pdev, | |||
1935 | 2135 | ||
1936 | err = pci_request_regions(pdev, DRV_MODULE_NAME); | 2136 | err = pci_request_regions(pdev, DRV_MODULE_NAME); |
1937 | if (err) { | 2137 | if (err) { |
1938 | printk(KERN_ERR PFX "Cannot obtain PCI resources, " | 2138 | dev_err(&pdev->dev, |
1939 | "aborting.\n"); | 2139 | "Cannot obtain PCI resources, aborting.\n"); |
1940 | goto err_out_disable_pdev; | 2140 | goto err_out_disable_pdev; |
1941 | } | 2141 | } |
1942 | 2142 | ||
@@ -1944,15 +2144,13 @@ static int __devinit b44_init_one(struct pci_dev *pdev, | |||
1944 | 2144 | ||
1945 | err = pci_set_dma_mask(pdev, (u64) B44_DMA_MASK); | 2145 | err = pci_set_dma_mask(pdev, (u64) B44_DMA_MASK); |
1946 | if (err) { | 2146 | if (err) { |
1947 | printk(KERN_ERR PFX "No usable DMA configuration, " | 2147 | dev_err(&pdev->dev, "No usable DMA configuration, aborting.\n"); |
1948 | "aborting.\n"); | ||
1949 | goto err_out_free_res; | 2148 | goto err_out_free_res; |
1950 | } | 2149 | } |
1951 | 2150 | ||
1952 | err = pci_set_consistent_dma_mask(pdev, (u64) B44_DMA_MASK); | 2151 | err = pci_set_consistent_dma_mask(pdev, (u64) B44_DMA_MASK); |
1953 | if (err) { | 2152 | if (err) { |
1954 | printk(KERN_ERR PFX "No usable DMA configuration, " | 2153 | dev_err(&pdev->dev, "No usable DMA configuration, aborting.\n"); |
1955 | "aborting.\n"); | ||
1956 | goto err_out_free_res; | 2154 | goto err_out_free_res; |
1957 | } | 2155 | } |
1958 | 2156 | ||
@@ -1961,7 +2159,7 @@ static int __devinit b44_init_one(struct pci_dev *pdev, | |||
1961 | 2159 | ||
1962 | dev = alloc_etherdev(sizeof(*bp)); | 2160 | dev = alloc_etherdev(sizeof(*bp)); |
1963 | if (!dev) { | 2161 | if (!dev) { |
1964 | printk(KERN_ERR PFX "Etherdev alloc failed, aborting.\n"); | 2162 | dev_err(&pdev->dev, "Etherdev alloc failed, aborting.\n"); |
1965 | err = -ENOMEM; | 2163 | err = -ENOMEM; |
1966 | goto err_out_free_res; | 2164 | goto err_out_free_res; |
1967 | } | 2165 | } |
@@ -1982,8 +2180,7 @@ static int __devinit b44_init_one(struct pci_dev *pdev, | |||
1982 | 2180 | ||
1983 | bp->regs = ioremap(b44reg_base, b44reg_len); | 2181 | bp->regs = ioremap(b44reg_base, b44reg_len); |
1984 | if (bp->regs == 0UL) { | 2182 | if (bp->regs == 0UL) { |
1985 | printk(KERN_ERR PFX "Cannot map device registers, " | 2183 | dev_err(&pdev->dev, "Cannot map device registers, aborting.\n"); |
1986 | "aborting.\n"); | ||
1987 | err = -ENOMEM; | 2184 | err = -ENOMEM; |
1988 | goto err_out_free_dev; | 2185 | goto err_out_free_dev; |
1989 | } | 2186 | } |
@@ -2013,8 +2210,8 @@ static int __devinit b44_init_one(struct pci_dev *pdev, | |||
2013 | 2210 | ||
2014 | err = b44_get_invariants(bp); | 2211 | err = b44_get_invariants(bp); |
2015 | if (err) { | 2212 | if (err) { |
2016 | printk(KERN_ERR PFX "Problem fetching invariants of chip, " | 2213 | dev_err(&pdev->dev, |
2017 | "aborting.\n"); | 2214 | "Problem fetching invariants of chip, aborting.\n"); |
2018 | goto err_out_iounmap; | 2215 | goto err_out_iounmap; |
2019 | } | 2216 | } |
2020 | 2217 | ||
@@ -2034,8 +2231,7 @@ static int __devinit b44_init_one(struct pci_dev *pdev, | |||
2034 | 2231 | ||
2035 | err = register_netdev(dev); | 2232 | err = register_netdev(dev); |
2036 | if (err) { | 2233 | if (err) { |
2037 | printk(KERN_ERR PFX "Cannot register net device, " | 2234 | dev_err(&pdev->dev, "Cannot register net device, aborting.\n"); |
2038 | "aborting.\n"); | ||
2039 | goto err_out_iounmap; | 2235 | goto err_out_iounmap; |
2040 | } | 2236 | } |
2041 | 2237 | ||
@@ -2103,6 +2299,10 @@ static int b44_suspend(struct pci_dev *pdev, pm_message_t state) | |||
2103 | spin_unlock_irq(&bp->lock); | 2299 | spin_unlock_irq(&bp->lock); |
2104 | 2300 | ||
2105 | free_irq(dev->irq, dev); | 2301 | free_irq(dev->irq, dev); |
2302 | if (bp->flags & B44_FLAG_WOL_ENABLE) { | ||
2303 | b44_init_hw(bp, 0); | ||
2304 | b44_setup_wol(bp); | ||
2305 | } | ||
2106 | pci_disable_device(pdev); | 2306 | pci_disable_device(pdev); |
2107 | return 0; | 2307 | return 0; |
2108 | } | 2308 | } |
@@ -2119,13 +2319,13 @@ static int b44_resume(struct pci_dev *pdev) | |||
2119 | if (!netif_running(dev)) | 2319 | if (!netif_running(dev)) |
2120 | return 0; | 2320 | return 0; |
2121 | 2321 | ||
2122 | if (request_irq(dev->irq, b44_interrupt, SA_SHIRQ, dev->name, dev)) | 2322 | if (request_irq(dev->irq, b44_interrupt, IRQF_SHARED, dev->name, dev)) |
2123 | printk(KERN_ERR PFX "%s: request_irq failed\n", dev->name); | 2323 | printk(KERN_ERR PFX "%s: request_irq failed\n", dev->name); |
2124 | 2324 | ||
2125 | spin_lock_irq(&bp->lock); | 2325 | spin_lock_irq(&bp->lock); |
2126 | 2326 | ||
2127 | b44_init_rings(bp); | 2327 | b44_init_rings(bp); |
2128 | b44_init_hw(bp); | 2328 | b44_init_hw(bp, 1); |
2129 | netif_device_attach(bp->dev); | 2329 | netif_device_attach(bp->dev); |
2130 | spin_unlock_irq(&bp->lock); | 2330 | spin_unlock_irq(&bp->lock); |
2131 | 2331 | ||