diff options
Diffstat (limited to 'drivers/net/b44.c')
-rw-r--r-- | drivers/net/b44.c | 76 |
1 files changed, 76 insertions, 0 deletions
diff --git a/drivers/net/b44.c b/drivers/net/b44.c index 41b1618573c7..73ca729e4cd7 100644 --- a/drivers/net/b44.c +++ b/drivers/net/b44.c | |||
@@ -1450,6 +1450,41 @@ static void b44_poll_controller(struct net_device *dev) | |||
1450 | } | 1450 | } |
1451 | #endif | 1451 | #endif |
1452 | 1452 | ||
1453 | |||
1454 | static void b44_setup_wol(struct b44 *bp) | ||
1455 | { | ||
1456 | u32 val; | ||
1457 | u16 pmval; | ||
1458 | |||
1459 | bw32(bp, B44_RXCONFIG, RXCONFIG_ALLMULTI); | ||
1460 | |||
1461 | if (bp->flags & B44_FLAG_B0_ANDLATER) { | ||
1462 | |||
1463 | bw32(bp, B44_WKUP_LEN, WKUP_LEN_DISABLE); | ||
1464 | |||
1465 | val = bp->dev->dev_addr[2] << 24 | | ||
1466 | bp->dev->dev_addr[3] << 16 | | ||
1467 | bp->dev->dev_addr[4] << 8 | | ||
1468 | bp->dev->dev_addr[5]; | ||
1469 | bw32(bp, B44_ADDR_LO, val); | ||
1470 | |||
1471 | val = bp->dev->dev_addr[0] << 8 | | ||
1472 | bp->dev->dev_addr[1]; | ||
1473 | bw32(bp, B44_ADDR_HI, val); | ||
1474 | |||
1475 | val = br32(bp, B44_DEVCTRL); | ||
1476 | bw32(bp, B44_DEVCTRL, val | DEVCTRL_MPM | DEVCTRL_PFE); | ||
1477 | |||
1478 | } | ||
1479 | |||
1480 | val = br32(bp, B44_SBTMSLOW); | ||
1481 | bw32(bp, B44_SBTMSLOW, val | SBTMSLOW_PE); | ||
1482 | |||
1483 | pci_read_config_word(bp->pdev, SSB_PMCSR, &pmval); | ||
1484 | pci_write_config_word(bp->pdev, SSB_PMCSR, pmval | SSB_PE); | ||
1485 | |||
1486 | } | ||
1487 | |||
1453 | static int b44_close(struct net_device *dev) | 1488 | static int b44_close(struct net_device *dev) |
1454 | { | 1489 | { |
1455 | struct b44 *bp = netdev_priv(dev); | 1490 | struct b44 *bp = netdev_priv(dev); |
@@ -1475,6 +1510,11 @@ static int b44_close(struct net_device *dev) | |||
1475 | 1510 | ||
1476 | netif_poll_enable(dev); | 1511 | netif_poll_enable(dev); |
1477 | 1512 | ||
1513 | if (bp->flags & B44_FLAG_WOL_ENABLE) { | ||
1514 | b44_init_hw(bp); | ||
1515 | b44_setup_wol(bp); | ||
1516 | } | ||
1517 | |||
1478 | b44_free_consistent(bp); | 1518 | b44_free_consistent(bp); |
1479 | 1519 | ||
1480 | return 0; | 1520 | return 0; |
@@ -1831,12 +1871,40 @@ static void b44_get_ethtool_stats(struct net_device *dev, | |||
1831 | spin_unlock_irq(&bp->lock); | 1871 | spin_unlock_irq(&bp->lock); |
1832 | } | 1872 | } |
1833 | 1873 | ||
1874 | static void b44_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol) | ||
1875 | { | ||
1876 | struct b44 *bp = netdev_priv(dev); | ||
1877 | |||
1878 | wol->supported = WAKE_MAGIC; | ||
1879 | if (bp->flags & B44_FLAG_WOL_ENABLE) | ||
1880 | wol->wolopts = WAKE_MAGIC; | ||
1881 | else | ||
1882 | wol->wolopts = 0; | ||
1883 | memset(&wol->sopass, 0, sizeof(wol->sopass)); | ||
1884 | } | ||
1885 | |||
1886 | static int b44_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) | ||
1887 | { | ||
1888 | struct b44 *bp = netdev_priv(dev); | ||
1889 | |||
1890 | spin_lock_irq(&bp->lock); | ||
1891 | if (wol->wolopts & WAKE_MAGIC) | ||
1892 | bp->flags |= B44_FLAG_WOL_ENABLE; | ||
1893 | else | ||
1894 | bp->flags &= ~B44_FLAG_WOL_ENABLE; | ||
1895 | spin_unlock_irq(&bp->lock); | ||
1896 | |||
1897 | return 0; | ||
1898 | } | ||
1899 | |||
1834 | static struct ethtool_ops b44_ethtool_ops = { | 1900 | static struct ethtool_ops b44_ethtool_ops = { |
1835 | .get_drvinfo = b44_get_drvinfo, | 1901 | .get_drvinfo = b44_get_drvinfo, |
1836 | .get_settings = b44_get_settings, | 1902 | .get_settings = b44_get_settings, |
1837 | .set_settings = b44_set_settings, | 1903 | .set_settings = b44_set_settings, |
1838 | .nway_reset = b44_nway_reset, | 1904 | .nway_reset = b44_nway_reset, |
1839 | .get_link = ethtool_op_get_link, | 1905 | .get_link = ethtool_op_get_link, |
1906 | .get_wol = b44_get_wol, | ||
1907 | .set_wol = b44_set_wol, | ||
1840 | .get_ringparam = b44_get_ringparam, | 1908 | .get_ringparam = b44_get_ringparam, |
1841 | .set_ringparam = b44_set_ringparam, | 1909 | .set_ringparam = b44_set_ringparam, |
1842 | .get_pauseparam = b44_get_pauseparam, | 1910 | .get_pauseparam = b44_get_pauseparam, |
@@ -1915,6 +1983,10 @@ static int __devinit b44_get_invariants(struct b44 *bp) | |||
1915 | /* XXX - really required? | 1983 | /* XXX - really required? |
1916 | bp->flags |= B44_FLAG_BUGGY_TXPTR; | 1984 | bp->flags |= B44_FLAG_BUGGY_TXPTR; |
1917 | */ | 1985 | */ |
1986 | |||
1987 | if (ssb_get_core_rev(bp) >= 7) | ||
1988 | bp->flags |= B44_FLAG_B0_ANDLATER; | ||
1989 | |||
1918 | out: | 1990 | out: |
1919 | return err; | 1991 | return err; |
1920 | } | 1992 | } |
@@ -2115,6 +2187,10 @@ static int b44_suspend(struct pci_dev *pdev, pm_message_t state) | |||
2115 | spin_unlock_irq(&bp->lock); | 2187 | spin_unlock_irq(&bp->lock); |
2116 | 2188 | ||
2117 | free_irq(dev->irq, dev); | 2189 | free_irq(dev->irq, dev); |
2190 | if (bp->flags & B44_FLAG_WOL_ENABLE) { | ||
2191 | b44_init_hw(bp); | ||
2192 | b44_setup_wol(bp); | ||
2193 | } | ||
2118 | pci_disable_device(pdev); | 2194 | pci_disable_device(pdev); |
2119 | return 0; | 2195 | return 0; |
2120 | } | 2196 | } |