diff options
| author | Michael Hennerich <michael.hennerich@analog.com> | 2010-05-10 01:39:11 -0400 |
|---|---|---|
| committer | David S. Miller <davem@davemloft.net> | 2010-05-17 20:20:59 -0400 |
| commit | 53fd3f2829268703729a2db0e24c0e36360b68a2 (patch) | |
| tree | 748ffb62dd85169e42205a36c4b28efadbea2cef | |
| parent | 812a9de71512e5da6f3177f7249a2448b6a4322e (diff) | |
netdev: bfin_mac: add support for wake-on-lan magic packets
Note that WOL works only in PM Suspend Standby Mode (Sleep Mode).
Signed-off-by: Michael Hennerich <michael.hennerich@analog.com>
Signed-off-by: Mike Frysinger <vapier@gentoo.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
| -rw-r--r-- | drivers/net/bfin_mac.c | 76 | ||||
| -rw-r--r-- | drivers/net/bfin_mac.h | 3 |
2 files changed, 75 insertions, 4 deletions
diff --git a/drivers/net/bfin_mac.c b/drivers/net/bfin_mac.c index 5d962b86ee22..28f350711267 100644 --- a/drivers/net/bfin_mac.c +++ b/drivers/net/bfin_mac.c | |||
| @@ -464,6 +464,14 @@ static int mii_probe(struct net_device *dev) | |||
| 464 | * Ethtool support | 464 | * Ethtool support |
| 465 | */ | 465 | */ |
| 466 | 466 | ||
| 467 | /* | ||
| 468 | * interrupt routine for magic packet wakeup | ||
| 469 | */ | ||
| 470 | static irqreturn_t bfin_mac_wake_interrupt(int irq, void *dev_id) | ||
| 471 | { | ||
| 472 | return IRQ_HANDLED; | ||
| 473 | } | ||
| 474 | |||
| 467 | static int | 475 | static int |
| 468 | bfin_mac_ethtool_getsettings(struct net_device *dev, struct ethtool_cmd *cmd) | 476 | bfin_mac_ethtool_getsettings(struct net_device *dev, struct ethtool_cmd *cmd) |
| 469 | { | 477 | { |
| @@ -498,11 +506,57 @@ static void bfin_mac_ethtool_getdrvinfo(struct net_device *dev, | |||
| 498 | strcpy(info->bus_info, dev_name(&dev->dev)); | 506 | strcpy(info->bus_info, dev_name(&dev->dev)); |
| 499 | } | 507 | } |
| 500 | 508 | ||
| 509 | static void bfin_mac_ethtool_getwol(struct net_device *dev, | ||
| 510 | struct ethtool_wolinfo *wolinfo) | ||
| 511 | { | ||
| 512 | struct bfin_mac_local *lp = netdev_priv(dev); | ||
| 513 | |||
| 514 | wolinfo->supported = WAKE_MAGIC; | ||
| 515 | wolinfo->wolopts = lp->wol; | ||
| 516 | } | ||
| 517 | |||
| 518 | static int bfin_mac_ethtool_setwol(struct net_device *dev, | ||
| 519 | struct ethtool_wolinfo *wolinfo) | ||
| 520 | { | ||
| 521 | struct bfin_mac_local *lp = netdev_priv(dev); | ||
| 522 | int rc; | ||
| 523 | |||
| 524 | if (wolinfo->wolopts & (WAKE_MAGICSECURE | | ||
| 525 | WAKE_UCAST | | ||
| 526 | WAKE_MCAST | | ||
| 527 | WAKE_BCAST | | ||
| 528 | WAKE_ARP)) | ||
| 529 | return -EOPNOTSUPP; | ||
| 530 | |||
| 531 | lp->wol = wolinfo->wolopts; | ||
| 532 | |||
| 533 | if (lp->wol && !lp->irq_wake_requested) { | ||
| 534 | /* register wake irq handler */ | ||
| 535 | rc = request_irq(IRQ_MAC_WAKEDET, bfin_mac_wake_interrupt, | ||
| 536 | IRQF_DISABLED, "EMAC_WAKE", dev); | ||
| 537 | if (rc) | ||
| 538 | return rc; | ||
| 539 | lp->irq_wake_requested = true; | ||
| 540 | } | ||
| 541 | |||
| 542 | if (!lp->wol && lp->irq_wake_requested) { | ||
| 543 | free_irq(IRQ_MAC_WAKEDET, dev); | ||
| 544 | lp->irq_wake_requested = false; | ||
| 545 | } | ||
| 546 | |||
| 547 | /* Make sure the PHY driver doesn't suspend */ | ||
| 548 | device_init_wakeup(&dev->dev, lp->wol); | ||
| 549 | |||
| 550 | return 0; | ||
| 551 | } | ||
| 552 | |||
| 501 | static const struct ethtool_ops bfin_mac_ethtool_ops = { | 553 | static const struct ethtool_ops bfin_mac_ethtool_ops = { |
| 502 | .get_settings = bfin_mac_ethtool_getsettings, | 554 | .get_settings = bfin_mac_ethtool_getsettings, |
| 503 | .set_settings = bfin_mac_ethtool_setsettings, | 555 | .set_settings = bfin_mac_ethtool_setsettings, |
| 504 | .get_link = ethtool_op_get_link, | 556 | .get_link = ethtool_op_get_link, |
| 505 | .get_drvinfo = bfin_mac_ethtool_getdrvinfo, | 557 | .get_drvinfo = bfin_mac_ethtool_getdrvinfo, |
| 558 | .get_wol = bfin_mac_ethtool_getwol, | ||
| 559 | .set_wol = bfin_mac_ethtool_setwol, | ||
| 506 | }; | 560 | }; |
| 507 | 561 | ||
| 508 | /**************************************************************************/ | 562 | /**************************************************************************/ |
| @@ -1474,9 +1528,16 @@ static int __devexit bfin_mac_remove(struct platform_device *pdev) | |||
| 1474 | static int bfin_mac_suspend(struct platform_device *pdev, pm_message_t mesg) | 1528 | static int bfin_mac_suspend(struct platform_device *pdev, pm_message_t mesg) |
| 1475 | { | 1529 | { |
| 1476 | struct net_device *net_dev = platform_get_drvdata(pdev); | 1530 | struct net_device *net_dev = platform_get_drvdata(pdev); |
| 1531 | struct bfin_mac_local *lp = netdev_priv(net_dev); | ||
| 1477 | 1532 | ||
| 1478 | if (netif_running(net_dev)) | 1533 | if (lp->wol) { |
| 1479 | bfin_mac_close(net_dev); | 1534 | bfin_write_EMAC_OPMODE((bfin_read_EMAC_OPMODE() & ~TE) | RE); |
| 1535 | bfin_write_EMAC_WKUP_CTL(MPKE); | ||
| 1536 | enable_irq_wake(IRQ_MAC_WAKEDET); | ||
| 1537 | } else { | ||
| 1538 | if (netif_running(net_dev)) | ||
| 1539 | bfin_mac_close(net_dev); | ||
| 1540 | } | ||
| 1480 | 1541 | ||
| 1481 | return 0; | 1542 | return 0; |
| 1482 | } | 1543 | } |
| @@ -1484,9 +1545,16 @@ static int bfin_mac_suspend(struct platform_device *pdev, pm_message_t mesg) | |||
| 1484 | static int bfin_mac_resume(struct platform_device *pdev) | 1545 | static int bfin_mac_resume(struct platform_device *pdev) |
| 1485 | { | 1546 | { |
| 1486 | struct net_device *net_dev = platform_get_drvdata(pdev); | 1547 | struct net_device *net_dev = platform_get_drvdata(pdev); |
| 1548 | struct bfin_mac_local *lp = netdev_priv(net_dev); | ||
| 1487 | 1549 | ||
| 1488 | if (netif_running(net_dev)) | 1550 | if (lp->wol) { |
| 1489 | bfin_mac_open(net_dev); | 1551 | bfin_write_EMAC_OPMODE(bfin_read_EMAC_OPMODE() | TE); |
| 1552 | bfin_write_EMAC_WKUP_CTL(0); | ||
| 1553 | disable_irq_wake(IRQ_MAC_WAKEDET); | ||
| 1554 | } else { | ||
| 1555 | if (netif_running(net_dev)) | ||
| 1556 | bfin_mac_open(net_dev); | ||
| 1557 | } | ||
| 1490 | 1558 | ||
| 1491 | return 0; | 1559 | return 0; |
| 1492 | } | 1560 | } |
diff --git a/drivers/net/bfin_mac.h b/drivers/net/bfin_mac.h index 87c454fc0319..1ae7b82ceeee 100644 --- a/drivers/net/bfin_mac.h +++ b/drivers/net/bfin_mac.h | |||
| @@ -66,6 +66,9 @@ struct bfin_mac_local { | |||
| 66 | unsigned char Mac[6]; /* MAC address of the board */ | 66 | unsigned char Mac[6]; /* MAC address of the board */ |
| 67 | spinlock_t lock; | 67 | spinlock_t lock; |
| 68 | 68 | ||
| 69 | int wol; /* Wake On Lan */ | ||
| 70 | int irq_wake_requested; | ||
| 71 | |||
| 69 | /* MII and PHY stuffs */ | 72 | /* MII and PHY stuffs */ |
| 70 | int old_link; /* used by bf537_adjust_link */ | 73 | int old_link; /* used by bf537_adjust_link */ |
| 71 | int old_speed; | 74 | int old_speed; |
