aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/dm9000.c
diff options
context:
space:
mode:
authorAndrea Bastoni <bastoni@cs.unc.edu>2010-05-30 19:16:45 -0400
committerAndrea Bastoni <bastoni@cs.unc.edu>2010-05-30 19:16:45 -0400
commitada47b5fe13d89735805b566185f4885f5a3f750 (patch)
tree644b88f8a71896307d71438e9b3af49126ffb22b /drivers/net/dm9000.c
parent43e98717ad40a4ae64545b5ba047c7b86aa44f4f (diff)
parent3280f21d43ee541f97f8cda5792150d2dbec20d5 (diff)
Merge branch 'wip-2.6.34' into old-private-masterarchived-private-master
Diffstat (limited to 'drivers/net/dm9000.c')
-rw-r--r--drivers/net/dm9000.c157
1 files changed, 142 insertions, 15 deletions
diff --git a/drivers/net/dm9000.c b/drivers/net/dm9000.c
index 31b8bef49d2e..7f9960f718e3 100644
--- a/drivers/net/dm9000.c
+++ b/drivers/net/dm9000.c
@@ -33,6 +33,7 @@
33#include <linux/delay.h> 33#include <linux/delay.h>
34#include <linux/platform_device.h> 34#include <linux/platform_device.h>
35#include <linux/irq.h> 35#include <linux/irq.h>
36#include <linux/slab.h>
36 37
37#include <asm/delay.h> 38#include <asm/delay.h>
38#include <asm/irq.h> 39#include <asm/irq.h>
@@ -100,6 +101,7 @@ typedef struct board_info {
100 101
101 unsigned int flags; 102 unsigned int flags;
102 unsigned int in_suspend :1; 103 unsigned int in_suspend :1;
104 unsigned int wake_supported :1;
103 int debug_level; 105 int debug_level;
104 106
105 enum dm9000_type type; 107 enum dm9000_type type;
@@ -116,6 +118,8 @@ typedef struct board_info {
116 struct resource *data_req; 118 struct resource *data_req;
117 struct resource *irq_res; 119 struct resource *irq_res;
118 120
121 int irq_wake;
122
119 struct mutex addr_lock; /* phy and eeprom access lock */ 123 struct mutex addr_lock; /* phy and eeprom access lock */
120 124
121 struct delayed_work phy_poll; 125 struct delayed_work phy_poll;
@@ -125,6 +129,7 @@ typedef struct board_info {
125 129
126 struct mii_if_info mii; 130 struct mii_if_info mii;
127 u32 msg_enable; 131 u32 msg_enable;
132 u32 wake_state;
128 133
129 int rx_csum; 134 int rx_csum;
130 int can_csum; 135 int can_csum;
@@ -568,6 +573,54 @@ static int dm9000_set_eeprom(struct net_device *dev,
568 return 0; 573 return 0;
569} 574}
570 575
576static void dm9000_get_wol(struct net_device *dev, struct ethtool_wolinfo *w)
577{
578 board_info_t *dm = to_dm9000_board(dev);
579
580 memset(w, 0, sizeof(struct ethtool_wolinfo));
581
582 /* note, we could probably support wake-phy too */
583 w->supported = dm->wake_supported ? WAKE_MAGIC : 0;
584 w->wolopts = dm->wake_state;
585}
586
587static int dm9000_set_wol(struct net_device *dev, struct ethtool_wolinfo *w)
588{
589 board_info_t *dm = to_dm9000_board(dev);
590 unsigned long flags;
591 u32 opts = w->wolopts;
592 u32 wcr = 0;
593
594 if (!dm->wake_supported)
595 return -EOPNOTSUPP;
596
597 if (opts & ~WAKE_MAGIC)
598 return -EINVAL;
599
600 if (opts & WAKE_MAGIC)
601 wcr |= WCR_MAGICEN;
602
603 mutex_lock(&dm->addr_lock);
604
605 spin_lock_irqsave(&dm->lock, flags);
606 iow(dm, DM9000_WCR, wcr);
607 spin_unlock_irqrestore(&dm->lock, flags);
608
609 mutex_unlock(&dm->addr_lock);
610
611 if (dm->wake_state != opts) {
612 /* change in wol state, update IRQ state */
613
614 if (!dm->wake_state)
615 set_irq_wake(dm->irq_wake, 1);
616 else if (dm->wake_state & !opts)
617 set_irq_wake(dm->irq_wake, 0);
618 }
619
620 dm->wake_state = opts;
621 return 0;
622}
623
571static const struct ethtool_ops dm9000_ethtool_ops = { 624static const struct ethtool_ops dm9000_ethtool_ops = {
572 .get_drvinfo = dm9000_get_drvinfo, 625 .get_drvinfo = dm9000_get_drvinfo,
573 .get_settings = dm9000_get_settings, 626 .get_settings = dm9000_get_settings,
@@ -576,6 +629,8 @@ static const struct ethtool_ops dm9000_ethtool_ops = {
576 .set_msglevel = dm9000_set_msglevel, 629 .set_msglevel = dm9000_set_msglevel,
577 .nway_reset = dm9000_nway_reset, 630 .nway_reset = dm9000_nway_reset,
578 .get_link = dm9000_get_link, 631 .get_link = dm9000_get_link,
632 .get_wol = dm9000_get_wol,
633 .set_wol = dm9000_set_wol,
579 .get_eeprom_len = dm9000_get_eeprom_len, 634 .get_eeprom_len = dm9000_get_eeprom_len,
580 .get_eeprom = dm9000_get_eeprom, 635 .get_eeprom = dm9000_get_eeprom,
581 .set_eeprom = dm9000_set_eeprom, 636 .set_eeprom = dm9000_set_eeprom,
@@ -670,8 +725,7 @@ static void
670dm9000_hash_table(struct net_device *dev) 725dm9000_hash_table(struct net_device *dev)
671{ 726{
672 board_info_t *db = netdev_priv(dev); 727 board_info_t *db = netdev_priv(dev);
673 struct dev_mc_list *mcptr = dev->mc_list; 728 struct dev_mc_list *mcptr;
674 int mc_cnt = dev->mc_count;
675 int i, oft; 729 int i, oft;
676 u32 hash_val; 730 u32 hash_val;
677 u16 hash_table[4]; 731 u16 hash_table[4];
@@ -699,7 +753,7 @@ dm9000_hash_table(struct net_device *dev)
699 rcr |= RCR_ALL; 753 rcr |= RCR_ALL;
700 754
701 /* the multicast address in Hash Table : 64 bits */ 755 /* the multicast address in Hash Table : 64 bits */
702 for (i = 0; i < mc_cnt; i++, mcptr = mcptr->next) { 756 netdev_for_each_mc_addr(mcptr, dev) {
703 hash_val = ether_crc_le(6, mcptr->dmi_addr) & 0x3f; 757 hash_val = ether_crc_le(6, mcptr->dmi_addr) & 0x3f;
704 hash_table[hash_val / 16] |= (u16) 1 << (hash_val % 16); 758 hash_table[hash_val / 16] |= (u16) 1 << (hash_val % 16);
705 } 759 }
@@ -722,6 +776,7 @@ dm9000_init_dm9000(struct net_device *dev)
722{ 776{
723 board_info_t *db = netdev_priv(dev); 777 board_info_t *db = netdev_priv(dev);
724 unsigned int imr; 778 unsigned int imr;
779 unsigned int ncr;
725 780
726 dm9000_dbg(db, 1, "entering %s\n", __func__); 781 dm9000_dbg(db, 1, "entering %s\n", __func__);
727 782
@@ -736,8 +791,15 @@ dm9000_init_dm9000(struct net_device *dev)
736 iow(db, DM9000_GPCR, GPCR_GEP_CNTL); /* Let GPIO0 output */ 791 iow(db, DM9000_GPCR, GPCR_GEP_CNTL); /* Let GPIO0 output */
737 iow(db, DM9000_GPR, 0); /* Enable PHY */ 792 iow(db, DM9000_GPR, 0); /* Enable PHY */
738 793
739 if (db->flags & DM9000_PLATF_EXT_PHY) 794 ncr = (db->flags & DM9000_PLATF_EXT_PHY) ? NCR_EXT_PHY : 0;
740 iow(db, DM9000_NCR, NCR_EXT_PHY); 795
796 /* if wol is needed, then always set NCR_WAKEEN otherwise we end
797 * up dumping the wake events if we disable this. There is already
798 * a wake-mask in DM9000_WCR */
799 if (db->wake_supported)
800 ncr |= NCR_WAKEEN;
801
802 iow(db, DM9000_NCR, ncr);
741 803
742 /* Program operating register */ 804 /* Program operating register */
743 iow(db, DM9000_TCR, 0); /* TX Polling clear */ 805 iow(db, DM9000_TCR, 0); /* TX Polling clear */
@@ -962,8 +1024,8 @@ dm9000_rx(struct net_device *dev)
962 } 1024 }
963 1025
964 /* Move data from DM9000 */ 1026 /* Move data from DM9000 */
965 if (GoodPacket 1027 if (GoodPacket &&
966 && ((skb = dev_alloc_skb(RxLen + 4)) != NULL)) { 1028 ((skb = dev_alloc_skb(RxLen + 4)) != NULL)) {
967 skb_reserve(skb, 2); 1029 skb_reserve(skb, 2);
968 rdptr = (u8 *) skb_put(skb, RxLen - 4); 1030 rdptr = (u8 *) skb_put(skb, RxLen - 4);
969 1031
@@ -1045,6 +1107,41 @@ static irqreturn_t dm9000_interrupt(int irq, void *dev_id)
1045 return IRQ_HANDLED; 1107 return IRQ_HANDLED;
1046} 1108}
1047 1109
1110static irqreturn_t dm9000_wol_interrupt(int irq, void *dev_id)
1111{
1112 struct net_device *dev = dev_id;
1113 board_info_t *db = netdev_priv(dev);
1114 unsigned long flags;
1115 unsigned nsr, wcr;
1116
1117 spin_lock_irqsave(&db->lock, flags);
1118
1119 nsr = ior(db, DM9000_NSR);
1120 wcr = ior(db, DM9000_WCR);
1121
1122 dev_dbg(db->dev, "%s: NSR=0x%02x, WCR=0x%02x\n", __func__, nsr, wcr);
1123
1124 if (nsr & NSR_WAKEST) {
1125 /* clear, so we can avoid */
1126 iow(db, DM9000_NSR, NSR_WAKEST);
1127
1128 if (wcr & WCR_LINKST)
1129 dev_info(db->dev, "wake by link status change\n");
1130 if (wcr & WCR_SAMPLEST)
1131 dev_info(db->dev, "wake by sample packet\n");
1132 if (wcr & WCR_MAGICST )
1133 dev_info(db->dev, "wake by magic packet\n");
1134 if (!(wcr & (WCR_LINKST | WCR_SAMPLEST | WCR_MAGICST)))
1135 dev_err(db->dev, "wake signalled with no reason? "
1136 "NSR=0x%02x, WSR=0x%02x\n", nsr, wcr);
1137
1138 }
1139
1140 spin_unlock_irqrestore(&db->lock, flags);
1141
1142 return (nsr & NSR_WAKEST) ? IRQ_HANDLED : IRQ_NONE;
1143}
1144
1048#ifdef CONFIG_NET_POLL_CONTROLLER 1145#ifdef CONFIG_NET_POLL_CONTROLLER
1049/* 1146/*
1050 *Used by netconsole 1147 *Used by netconsole
@@ -1078,7 +1175,7 @@ dm9000_open(struct net_device *dev)
1078 1175
1079 irqflags |= IRQF_SHARED; 1176 irqflags |= IRQF_SHARED;
1080 1177
1081 if (request_irq(dev->irq, &dm9000_interrupt, irqflags, dev->name, dev)) 1178 if (request_irq(dev->irq, dm9000_interrupt, irqflags, dev->name, dev))
1082 return -EAGAIN; 1179 return -EAGAIN;
1083 1180
1084 /* Initialize DM9000 board */ 1181 /* Initialize DM9000 board */
@@ -1299,6 +1396,29 @@ dm9000_probe(struct platform_device *pdev)
1299 goto out; 1396 goto out;
1300 } 1397 }
1301 1398
1399 db->irq_wake = platform_get_irq(pdev, 1);
1400 if (db->irq_wake >= 0) {
1401 dev_dbg(db->dev, "wakeup irq %d\n", db->irq_wake);
1402
1403 ret = request_irq(db->irq_wake, dm9000_wol_interrupt,
1404 IRQF_SHARED, dev_name(db->dev), ndev);
1405 if (ret) {
1406 dev_err(db->dev, "cannot get wakeup irq (%d)\n", ret);
1407 } else {
1408
1409 /* test to see if irq is really wakeup capable */
1410 ret = set_irq_wake(db->irq_wake, 1);
1411 if (ret) {
1412 dev_err(db->dev, "irq %d cannot set wakeup (%d)\n",
1413 db->irq_wake, ret);
1414 ret = 0;
1415 } else {
1416 set_irq_wake(db->irq_wake, 0);
1417 db->wake_supported = 1;
1418 }
1419 }
1420 }
1421
1302 iosize = resource_size(db->addr_res); 1422 iosize = resource_size(db->addr_res);
1303 db->addr_req = request_mem_region(db->addr_res->start, iosize, 1423 db->addr_req = request_mem_region(db->addr_res->start, iosize,
1304 pdev->name); 1424 pdev->name);
@@ -1490,10 +1610,14 @@ dm9000_drv_suspend(struct device *dev)
1490 db = netdev_priv(ndev); 1610 db = netdev_priv(ndev);
1491 db->in_suspend = 1; 1611 db->in_suspend = 1;
1492 1612
1493 if (netif_running(ndev)) { 1613 if (!netif_running(ndev))
1494 netif_device_detach(ndev); 1614 return 0;
1615
1616 netif_device_detach(ndev);
1617
1618 /* only shutdown if not using WoL */
1619 if (!db->wake_state)
1495 dm9000_shutdown(ndev); 1620 dm9000_shutdown(ndev);
1496 }
1497 } 1621 }
1498 return 0; 1622 return 0;
1499} 1623}
@@ -1506,10 +1630,13 @@ dm9000_drv_resume(struct device *dev)
1506 board_info_t *db = netdev_priv(ndev); 1630 board_info_t *db = netdev_priv(ndev);
1507 1631
1508 if (ndev) { 1632 if (ndev) {
1509
1510 if (netif_running(ndev)) { 1633 if (netif_running(ndev)) {
1511 dm9000_reset(db); 1634 /* reset if we were not in wake mode to ensure if
1512 dm9000_init_dm9000(ndev); 1635 * the device was powered off it is in a known state */
1636 if (!db->wake_state) {
1637 dm9000_reset(db);
1638 dm9000_init_dm9000(ndev);
1639 }
1513 1640
1514 netif_device_attach(ndev); 1641 netif_device_attach(ndev);
1515 } 1642 }
@@ -1519,7 +1646,7 @@ dm9000_drv_resume(struct device *dev)
1519 return 0; 1646 return 0;
1520} 1647}
1521 1648
1522static struct dev_pm_ops dm9000_drv_pm_ops = { 1649static const struct dev_pm_ops dm9000_drv_pm_ops = {
1523 .suspend = dm9000_drv_suspend, 1650 .suspend = dm9000_drv_suspend,
1524 .resume = dm9000_drv_resume, 1651 .resume = dm9000_drv_resume,
1525}; 1652};