ixgbe: Cleanup incorrect header comments
[safe/jmp/linux-2.6] / drivers / net / ucc_geth.c
index e474e57..a057202 100644 (file)
@@ -37,6 +37,7 @@
 #include <asm/qe.h>
 #include <asm/ucc.h>
 #include <asm/ucc_fast.h>
+#include <asm/machdep.h>
 
 #include "ucc_geth.h"
 #include "fsl_pq_mdio.h"
@@ -438,38 +439,6 @@ static void hw_add_addr_in_hash(struct ucc_geth_private *ugeth,
                     QE_CR_PROTOCOL_ETHERNET, 0);
 }
 
-#ifdef CONFIG_UGETH_MAGIC_PACKET
-static void magic_packet_detection_enable(struct ucc_geth_private *ugeth)
-{
-       struct ucc_fast_private *uccf;
-       struct ucc_geth __iomem *ug_regs;
-
-       uccf = ugeth->uccf;
-       ug_regs = ugeth->ug_regs;
-
-       /* Enable interrupts for magic packet detection */
-       setbits32(uccf->p_uccm, UCC_GETH_UCCE_MPD);
-
-       /* Enable magic packet detection */
-       setbits32(&ug_regs->maccfg2, MACCFG2_MPE);
-}
-
-static void magic_packet_detection_disable(struct ucc_geth_private *ugeth)
-{
-       struct ucc_fast_private *uccf;
-       struct ucc_geth __iomem *ug_regs;
-
-       uccf = ugeth->uccf;
-       ug_regs = ugeth->ug_regs;
-
-       /* Disable interrupts for magic packet detection */
-       clrbits32(uccf->p_uccm, UCC_GETH_UCCE_MPD);
-
-       /* Disable magic packet detection */
-       clrbits32(&ug_regs->maccfg2, MACCFG2_MPE);
-}
-#endif /* MAGIC_PACKET */
-
 static inline int compare_addr(u8 **addr1, u8 **addr2)
 {
        return memcmp(addr1, addr2, ENET_NUM_OCTETS_PER_ADDRESS);
@@ -1338,8 +1307,8 @@ static int init_max_rx_buff_len(u16 max_rx_buf_len,
                                u16 __iomem *mrblr_register)
 {
        /* max_rx_buf_len value must be a multiple of 128 */
-       if ((max_rx_buf_len == 0)
-           || (max_rx_buf_len % UCC_GETH_MRBLR_ALIGNMENT))
+       if ((max_rx_buf_len == 0) ||
+           (max_rx_buf_len % UCC_GETH_MRBLR_ALIGNMENT))
                return -EINVAL;
 
        out_be16(mrblr_register, max_rx_buf_len);
@@ -1366,7 +1335,7 @@ static int adjust_enet_interface(struct ucc_geth_private *ugeth)
        struct ucc_geth __iomem *ug_regs;
        struct ucc_fast __iomem *uf_regs;
        int ret_val;
-       u32 upsmr, maccfg2, tbiBaseAddress;
+       u32 upsmr, maccfg2;
        u16 value;
 
        ugeth_vdbg("%s: IN", __func__);
@@ -1421,14 +1390,20 @@ static int adjust_enet_interface(struct ucc_geth_private *ugeth)
        /* Note that this depends on proper setting in utbipar register. */
        if ((ugeth->phy_interface == PHY_INTERFACE_MODE_TBI) ||
            (ugeth->phy_interface == PHY_INTERFACE_MODE_RTBI)) {
-               tbiBaseAddress = in_be32(&ug_regs->utbipar);
-               tbiBaseAddress &= UTBIPAR_PHY_ADDRESS_MASK;
-               tbiBaseAddress >>= UTBIPAR_PHY_ADDRESS_SHIFT;
-               value = ugeth->phydev->bus->read(ugeth->phydev->bus,
-                               (u8) tbiBaseAddress, ENET_TBI_MII_CR);
+               struct ucc_geth_info *ug_info = ugeth->ug_info;
+               struct phy_device *tbiphy;
+
+               if (!ug_info->tbi_node)
+                       ugeth_warn("TBI mode requires that the device "
+                               "tree specify a tbi-handle\n");
+
+               tbiphy = of_phy_find_device(ug_info->tbi_node);
+               if (!tbiphy)
+                       ugeth_warn("Could not get TBI device\n");
+
+               value = phy_read(tbiphy, ENET_TBI_MII_CR);
                value &= ~0x1000;       /* Turn off autonegotiation */
-               ugeth->phydev->bus->write(ugeth->phydev->bus,
-                               (u8) tbiBaseAddress, ENET_TBI_MII_CR, value);
+               phy_write(tbiphy, ENET_TBI_MII_CR, value);
        }
 
        init_check_frame_length_mode(ug_info->lengthCheckRx, &ug_regs->maccfg2);
@@ -1444,6 +1419,177 @@ static int adjust_enet_interface(struct ucc_geth_private *ugeth)
        return 0;
 }
 
+static int ugeth_graceful_stop_tx(struct ucc_geth_private *ugeth)
+{
+       struct ucc_fast_private *uccf;
+       u32 cecr_subblock;
+       u32 temp;
+       int i = 10;
+
+       uccf = ugeth->uccf;
+
+       /* Mask GRACEFUL STOP TX interrupt bit and clear it */
+       clrbits32(uccf->p_uccm, UCC_GETH_UCCE_GRA);
+       out_be32(uccf->p_ucce, UCC_GETH_UCCE_GRA);  /* clear by writing 1 */
+
+       /* Issue host command */
+       cecr_subblock =
+           ucc_fast_get_qe_cr_subblock(ugeth->ug_info->uf_info.ucc_num);
+       qe_issue_cmd(QE_GRACEFUL_STOP_TX, cecr_subblock,
+                    QE_CR_PROTOCOL_ETHERNET, 0);
+
+       /* Wait for command to complete */
+       do {
+               msleep(10);
+               temp = in_be32(uccf->p_ucce);
+       } while (!(temp & UCC_GETH_UCCE_GRA) && --i);
+
+       uccf->stopped_tx = 1;
+
+       return 0;
+}
+
+static int ugeth_graceful_stop_rx(struct ucc_geth_private *ugeth)
+{
+       struct ucc_fast_private *uccf;
+       u32 cecr_subblock;
+       u8 temp;
+       int i = 10;
+
+       uccf = ugeth->uccf;
+
+       /* Clear acknowledge bit */
+       temp = in_8(&ugeth->p_rx_glbl_pram->rxgstpack);
+       temp &= ~GRACEFUL_STOP_ACKNOWLEDGE_RX;
+       out_8(&ugeth->p_rx_glbl_pram->rxgstpack, temp);
+
+       /* Keep issuing command and checking acknowledge bit until
+       it is asserted, according to spec */
+       do {
+               /* Issue host command */
+               cecr_subblock =
+                   ucc_fast_get_qe_cr_subblock(ugeth->ug_info->uf_info.
+                                               ucc_num);
+               qe_issue_cmd(QE_GRACEFUL_STOP_RX, cecr_subblock,
+                            QE_CR_PROTOCOL_ETHERNET, 0);
+               msleep(10);
+               temp = in_8(&ugeth->p_rx_glbl_pram->rxgstpack);
+       } while (!(temp & GRACEFUL_STOP_ACKNOWLEDGE_RX) && --i);
+
+       uccf->stopped_rx = 1;
+
+       return 0;
+}
+
+static int ugeth_restart_tx(struct ucc_geth_private *ugeth)
+{
+       struct ucc_fast_private *uccf;
+       u32 cecr_subblock;
+
+       uccf = ugeth->uccf;
+
+       cecr_subblock =
+           ucc_fast_get_qe_cr_subblock(ugeth->ug_info->uf_info.ucc_num);
+       qe_issue_cmd(QE_RESTART_TX, cecr_subblock, QE_CR_PROTOCOL_ETHERNET, 0);
+       uccf->stopped_tx = 0;
+
+       return 0;
+}
+
+static int ugeth_restart_rx(struct ucc_geth_private *ugeth)
+{
+       struct ucc_fast_private *uccf;
+       u32 cecr_subblock;
+
+       uccf = ugeth->uccf;
+
+       cecr_subblock =
+           ucc_fast_get_qe_cr_subblock(ugeth->ug_info->uf_info.ucc_num);
+       qe_issue_cmd(QE_RESTART_RX, cecr_subblock, QE_CR_PROTOCOL_ETHERNET,
+                    0);
+       uccf->stopped_rx = 0;
+
+       return 0;
+}
+
+static int ugeth_enable(struct ucc_geth_private *ugeth, enum comm_dir mode)
+{
+       struct ucc_fast_private *uccf;
+       int enabled_tx, enabled_rx;
+
+       uccf = ugeth->uccf;
+
+       /* check if the UCC number is in range. */
+       if (ugeth->ug_info->uf_info.ucc_num >= UCC_MAX_NUM) {
+               if (netif_msg_probe(ugeth))
+                       ugeth_err("%s: ucc_num out of range.", __func__);
+               return -EINVAL;
+       }
+
+       enabled_tx = uccf->enabled_tx;
+       enabled_rx = uccf->enabled_rx;
+
+       /* Get Tx and Rx going again, in case this channel was actively
+       disabled. */
+       if ((mode & COMM_DIR_TX) && (!enabled_tx) && uccf->stopped_tx)
+               ugeth_restart_tx(ugeth);
+       if ((mode & COMM_DIR_RX) && (!enabled_rx) && uccf->stopped_rx)
+               ugeth_restart_rx(ugeth);
+
+       ucc_fast_enable(uccf, mode);    /* OK to do even if not disabled */
+
+       return 0;
+
+}
+
+static int ugeth_disable(struct ucc_geth_private *ugeth, enum comm_dir mode)
+{
+       struct ucc_fast_private *uccf;
+
+       uccf = ugeth->uccf;
+
+       /* check if the UCC number is in range. */
+       if (ugeth->ug_info->uf_info.ucc_num >= UCC_MAX_NUM) {
+               if (netif_msg_probe(ugeth))
+                       ugeth_err("%s: ucc_num out of range.", __func__);
+               return -EINVAL;
+       }
+
+       /* Stop any transmissions */
+       if ((mode & COMM_DIR_TX) && uccf->enabled_tx && !uccf->stopped_tx)
+               ugeth_graceful_stop_tx(ugeth);
+
+       /* Stop any receptions */
+       if ((mode & COMM_DIR_RX) && uccf->enabled_rx && !uccf->stopped_rx)
+               ugeth_graceful_stop_rx(ugeth);
+
+       ucc_fast_disable(ugeth->uccf, mode); /* OK to do even if not enabled */
+
+       return 0;
+}
+
+static void ugeth_quiesce(struct ucc_geth_private *ugeth)
+{
+       /* Prevent any further xmits, plus detach the device. */
+       netif_device_detach(ugeth->ndev);
+
+       /* Wait for any current xmits to finish. */
+       netif_tx_disable(ugeth->ndev);
+
+       /* Disable the interrupt to avoid NAPI rescheduling. */
+       disable_irq(ugeth->ug_info->uf_info.irq);
+
+       /* Stop NAPI, and possibly wait for its completion. */
+       napi_disable(&ugeth->napi);
+}
+
+static void ugeth_activate(struct ucc_geth_private *ugeth)
+{
+       napi_enable(&ugeth->napi);
+       enable_irq(ugeth->ug_info->uf_info.irq);
+       netif_device_attach(ugeth->ndev);
+}
+
 /* Called every time the controller might need to be made
  * aware of new link state.  The PHY code conveys this
  * information through variables in the ugeth structure, and this
@@ -1457,14 +1603,11 @@ static void adjust_link(struct net_device *dev)
        struct ucc_geth __iomem *ug_regs;
        struct ucc_fast __iomem *uf_regs;
        struct phy_device *phydev = ugeth->phydev;
-       unsigned long flags;
        int new_state = 0;
 
        ug_regs = ugeth->ug_regs;
        uf_regs = ugeth->uccf->uf_regs;
 
-       spin_lock_irqsave(&ugeth->lock, flags);
-
        if (phydev->link) {
                u32 tempval = in_be32(&ug_regs->maccfg2);
                u32 upsmr = in_be32(&uf_regs->upsmr);
@@ -1515,13 +1658,28 @@ static void adjust_link(struct net_device *dev)
                        ugeth->oldspeed = phydev->speed;
                }
 
-               out_be32(&ug_regs->maccfg2, tempval);
-               out_be32(&uf_regs->upsmr, upsmr);
-
                if (!ugeth->oldlink) {
                        new_state = 1;
                        ugeth->oldlink = 1;
                }
+
+               if (new_state) {
+                       /*
+                        * To change the MAC configuration we need to disable
+                        * the controller. To do so, we have to either grab
+                        * ugeth->lock, which is a bad idea since 'graceful
+                        * stop' commands might take quite a while, or we can
+                        * quiesce driver's activity.
+                        */
+                       ugeth_quiesce(ugeth);
+                       ugeth_disable(ugeth, COMM_DIR_RX_AND_TX);
+
+                       out_be32(&ug_regs->maccfg2, tempval);
+                       out_be32(&uf_regs->upsmr, upsmr);
+
+                       ugeth_enable(ugeth, COMM_DIR_RX_AND_TX);
+                       ugeth_activate(ugeth);
+               }
        } else if (ugeth->oldlink) {
                        new_state = 1;
                        ugeth->oldlink = 0;
@@ -1531,8 +1689,6 @@ static void adjust_link(struct net_device *dev)
 
        if (new_state && netif_msg_link(ugeth))
                phy_print_status(phydev);
-
-       spin_unlock_irqrestore(&ugeth->lock, flags);
 }
 
 /* Initialize TBI PHY interface for communicating with the
@@ -1619,157 +1775,6 @@ static int init_phy(struct net_device *dev)
        return 0;
 }
 
-
-
-static int ugeth_graceful_stop_tx(struct ucc_geth_private *ugeth)
-{
-       struct ucc_fast_private *uccf;
-       u32 cecr_subblock;
-       u32 temp;
-       int i = 10;
-
-       uccf = ugeth->uccf;
-
-       /* Mask GRACEFUL STOP TX interrupt bit and clear it */
-       clrbits32(uccf->p_uccm, UCC_GETH_UCCE_GRA);
-       out_be32(uccf->p_ucce, UCC_GETH_UCCE_GRA);  /* clear by writing 1 */
-
-       /* Issue host command */
-       cecr_subblock =
-           ucc_fast_get_qe_cr_subblock(ugeth->ug_info->uf_info.ucc_num);
-       qe_issue_cmd(QE_GRACEFUL_STOP_TX, cecr_subblock,
-                    QE_CR_PROTOCOL_ETHERNET, 0);
-
-       /* Wait for command to complete */
-       do {
-               msleep(10);
-               temp = in_be32(uccf->p_ucce);
-       } while (!(temp & UCC_GETH_UCCE_GRA) && --i);
-
-       uccf->stopped_tx = 1;
-
-       return 0;
-}
-
-static int ugeth_graceful_stop_rx(struct ucc_geth_private * ugeth)
-{
-       struct ucc_fast_private *uccf;
-       u32 cecr_subblock;
-       u8 temp;
-       int i = 10;
-
-       uccf = ugeth->uccf;
-
-       /* Clear acknowledge bit */
-       temp = in_8(&ugeth->p_rx_glbl_pram->rxgstpack);
-       temp &= ~GRACEFUL_STOP_ACKNOWLEDGE_RX;
-       out_8(&ugeth->p_rx_glbl_pram->rxgstpack, temp);
-
-       /* Keep issuing command and checking acknowledge bit until
-       it is asserted, according to spec */
-       do {
-               /* Issue host command */
-               cecr_subblock =
-                   ucc_fast_get_qe_cr_subblock(ugeth->ug_info->uf_info.
-                                               ucc_num);
-               qe_issue_cmd(QE_GRACEFUL_STOP_RX, cecr_subblock,
-                            QE_CR_PROTOCOL_ETHERNET, 0);
-               msleep(10);
-               temp = in_8(&ugeth->p_rx_glbl_pram->rxgstpack);
-       } while (!(temp & GRACEFUL_STOP_ACKNOWLEDGE_RX) && --i);
-
-       uccf->stopped_rx = 1;
-
-       return 0;
-}
-
-static int ugeth_restart_tx(struct ucc_geth_private *ugeth)
-{
-       struct ucc_fast_private *uccf;
-       u32 cecr_subblock;
-
-       uccf = ugeth->uccf;
-
-       cecr_subblock =
-           ucc_fast_get_qe_cr_subblock(ugeth->ug_info->uf_info.ucc_num);
-       qe_issue_cmd(QE_RESTART_TX, cecr_subblock, QE_CR_PROTOCOL_ETHERNET, 0);
-       uccf->stopped_tx = 0;
-
-       return 0;
-}
-
-static int ugeth_restart_rx(struct ucc_geth_private *ugeth)
-{
-       struct ucc_fast_private *uccf;
-       u32 cecr_subblock;
-
-       uccf = ugeth->uccf;
-
-       cecr_subblock =
-           ucc_fast_get_qe_cr_subblock(ugeth->ug_info->uf_info.ucc_num);
-       qe_issue_cmd(QE_RESTART_RX, cecr_subblock, QE_CR_PROTOCOL_ETHERNET,
-                    0);
-       uccf->stopped_rx = 0;
-
-       return 0;
-}
-
-static int ugeth_enable(struct ucc_geth_private *ugeth, enum comm_dir mode)
-{
-       struct ucc_fast_private *uccf;
-       int enabled_tx, enabled_rx;
-
-       uccf = ugeth->uccf;
-
-       /* check if the UCC number is in range. */
-       if (ugeth->ug_info->uf_info.ucc_num >= UCC_MAX_NUM) {
-               if (netif_msg_probe(ugeth))
-                       ugeth_err("%s: ucc_num out of range.", __func__);
-               return -EINVAL;
-       }
-
-       enabled_tx = uccf->enabled_tx;
-       enabled_rx = uccf->enabled_rx;
-
-       /* Get Tx and Rx going again, in case this channel was actively
-       disabled. */
-       if ((mode & COMM_DIR_TX) && (!enabled_tx) && uccf->stopped_tx)
-               ugeth_restart_tx(ugeth);
-       if ((mode & COMM_DIR_RX) && (!enabled_rx) && uccf->stopped_rx)
-               ugeth_restart_rx(ugeth);
-
-       ucc_fast_enable(uccf, mode);    /* OK to do even if not disabled */
-
-       return 0;
-
-}
-
-static int ugeth_disable(struct ucc_geth_private * ugeth, enum comm_dir mode)
-{
-       struct ucc_fast_private *uccf;
-
-       uccf = ugeth->uccf;
-
-       /* check if the UCC number is in range. */
-       if (ugeth->ug_info->uf_info.ucc_num >= UCC_MAX_NUM) {
-               if (netif_msg_probe(ugeth))
-                       ugeth_err("%s: ucc_num out of range.", __func__);
-               return -EINVAL;
-       }
-
-       /* Stop any transmissions */
-       if ((mode & COMM_DIR_TX) && uccf->enabled_tx && !uccf->stopped_tx)
-               ugeth_graceful_stop_tx(ugeth);
-
-       /* Stop any receptions */
-       if ((mode & COMM_DIR_RX) && uccf->enabled_rx && !uccf->stopped_rx)
-               ugeth_graceful_stop_rx(ugeth);
-
-       ucc_fast_disable(ugeth->uccf, mode); /* OK to do even if not enabled */
-
-       return 0;
-}
-
 static void ugeth_dump_regs(struct ucc_geth_private *ugeth)
 {
 #ifdef DEBUG
@@ -2026,7 +2031,8 @@ static void ucc_geth_set_multi(struct net_device *dev)
 
                        dmi = dev->mc_list;
 
-                       for (i = 0; i < dev->mc_count; i++, dmi = dmi->next) {
+                       for (i = 0; i < netdev_mc_count(dev);
+                            i++, dmi = dmi->next) {
 
                                /* Only support group multicast for now.
                                 */
@@ -2167,8 +2173,8 @@ static int ucc_struct_init(struct ucc_geth_private *ugeth)
        }
 
        if ((ug_info->numStationAddresses !=
-            UCC_GETH_NUM_OF_STATION_ADDRESSES_1)
-           && ug_info->rxExtendedFiltering) {
+            UCC_GETH_NUM_OF_STATION_ADDRESSES_1) &&
+           ug_info->rxExtendedFiltering) {
                if (netif_msg_probe(ugeth))
                        ugeth_err("%s: Number of station addresses greater than 1 "
                                  "not allowed in extended parsing mode.",
@@ -2292,9 +2298,9 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth)
             UCC_GETH_NUM_OF_STATION_ADDRESSES_1);
 
        ugeth->rx_extended_features = ugeth->rx_non_dynamic_extended_features ||
-           (ug_info->vlanOperationTagged != UCC_GETH_VLAN_OPERATION_TAGGED_NOP)
-           || (ug_info->vlanOperationNonTagged !=
-               UCC_GETH_VLAN_OPERATION_NON_TAGGED_NOP);
+               (ug_info->vlanOperationTagged != UCC_GETH_VLAN_OPERATION_TAGGED_NOP) ||
+               (ug_info->vlanOperationNonTagged !=
+                UCC_GETH_VLAN_OPERATION_NON_TAGGED_NOP);
 
        init_default_reg_vals(&uf_regs->upsmr,
                              &ug_regs->maccfg1, &ug_regs->maccfg2);
@@ -2995,11 +3001,11 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth)
        ugeth->p_init_enet_param_shadow->rgftgfrxglobal |=
            ugeth->rx_glbl_pram_offset | ug_info->riscRx;
        if ((ug_info->largestexternallookupkeysize !=
-            QE_FLTR_LARGEST_EXTERNAL_TABLE_LOOKUP_KEY_SIZE_NONE)
-           && (ug_info->largestexternallookupkeysize !=
-               QE_FLTR_LARGEST_EXTERNAL_TABLE_LOOKUP_KEY_SIZE_8_BYTES)
-           && (ug_info->largestexternallookupkeysize !=
-               QE_FLTR_LARGEST_EXTERNAL_TABLE_LOOKUP_KEY_SIZE_16_BYTES)) {
+            QE_FLTR_LARGEST_EXTERNAL_TABLE_LOOKUP_KEY_SIZE_NONE) &&
+           (ug_info->largestexternallookupkeysize !=
+            QE_FLTR_LARGEST_EXTERNAL_TABLE_LOOKUP_KEY_SIZE_8_BYTES) &&
+           (ug_info->largestexternallookupkeysize !=
+            QE_FLTR_LARGEST_EXTERNAL_TABLE_LOOKUP_KEY_SIZE_16_BYTES)) {
                if (netif_msg_ifup(ugeth))
                        ugeth_err("%s: Invalid largest External Lookup Key Size.",
                                  __func__);
@@ -3116,10 +3122,11 @@ static int ucc_geth_start_xmit(struct sk_buff *skb, struct net_device *dev)
        u8 __iomem *bd;                 /* BD pointer */
        u32 bd_status;
        u8 txQ = 0;
+       unsigned long flags;
 
        ugeth_vdbg("%s: IN", __func__);
 
-       spin_lock_irq(&ugeth->lock);
+       spin_lock_irqsave(&ugeth->lock, flags);
 
        dev->stats.tx_bytes += skb->len;
 
@@ -3176,7 +3183,7 @@ static int ucc_geth_start_xmit(struct sk_buff *skb, struct net_device *dev)
        uccf = ugeth->uccf;
        out_be16(uccf->p_utodr, UCC_FAST_TOD);
 #endif
-       spin_unlock_irq(&ugeth->lock);
+       spin_unlock_irqrestore(&ugeth->lock, flags);
 
        return NETDEV_TX_OK;
 }
@@ -3280,13 +3287,12 @@ static int ucc_geth_tx(struct net_device *dev, u8 txQ)
                /* Handle the transmitted buffer and release */
                /* the BD to be used with the current frame  */
 
-               if ((bd == ugeth->txBd[txQ]) && (netif_queue_stopped(dev) == 0))
+               skb = ugeth->tx_skbuff[txQ][ugeth->skb_dirtytx[txQ]];
+               if (!skb)
                        break;
 
                dev->stats.tx_packets++;
 
-               skb = ugeth->tx_skbuff[txQ][ugeth->skb_dirtytx[txQ]];
-
                if (skb_queue_len(&ugeth->rx_recycle) < RX_BD_RING_LEN &&
                             skb_recycle_check(skb,
                                    ugeth->ug_info->uf_info.max_rx_buf_length +
@@ -3529,6 +3535,10 @@ static int ucc_geth_open(struct net_device *dev)
        napi_enable(&ugeth->napi);
        netif_start_queue(dev);
 
+       device_set_wakeup_capable(&dev->dev,
+                       qe_alive_during_sleep() || ugeth->phydev->irq);
+       device_set_wakeup_enable(&dev->dev, ugeth->wol_en);
+
        return err;
 
 err:
@@ -3593,6 +3603,86 @@ static void ucc_geth_timeout(struct net_device *dev)
        schedule_work(&ugeth->timeout_work);
 }
 
+
+#ifdef CONFIG_PM
+
+static int ucc_geth_suspend(struct of_device *ofdev, pm_message_t state)
+{
+       struct net_device *ndev = dev_get_drvdata(&ofdev->dev);
+       struct ucc_geth_private *ugeth = netdev_priv(ndev);
+
+       if (!netif_running(ndev))
+               return 0;
+
+       netif_device_detach(ndev);
+       napi_disable(&ugeth->napi);
+
+       /*
+        * Disable the controller, otherwise we'll wakeup on any network
+        * activity.
+        */
+       ugeth_disable(ugeth, COMM_DIR_RX_AND_TX);
+
+       if (ugeth->wol_en & WAKE_MAGIC) {
+               setbits32(ugeth->uccf->p_uccm, UCC_GETH_UCCE_MPD);
+               setbits32(&ugeth->ug_regs->maccfg2, MACCFG2_MPE);
+               ucc_fast_enable(ugeth->uccf, COMM_DIR_RX_AND_TX);
+       } else if (!(ugeth->wol_en & WAKE_PHY)) {
+               phy_stop(ugeth->phydev);
+       }
+
+       return 0;
+}
+
+static int ucc_geth_resume(struct of_device *ofdev)
+{
+       struct net_device *ndev = dev_get_drvdata(&ofdev->dev);
+       struct ucc_geth_private *ugeth = netdev_priv(ndev);
+       int err;
+
+       if (!netif_running(ndev))
+               return 0;
+
+       if (qe_alive_during_sleep()) {
+               if (ugeth->wol_en & WAKE_MAGIC) {
+                       ucc_fast_disable(ugeth->uccf, COMM_DIR_RX_AND_TX);
+                       clrbits32(&ugeth->ug_regs->maccfg2, MACCFG2_MPE);
+                       clrbits32(ugeth->uccf->p_uccm, UCC_GETH_UCCE_MPD);
+               }
+               ugeth_enable(ugeth, COMM_DIR_RX_AND_TX);
+       } else {
+               /*
+                * Full reinitialization is required if QE shuts down
+                * during sleep.
+                */
+               ucc_geth_memclean(ugeth);
+
+               err = ucc_geth_init_mac(ugeth);
+               if (err) {
+                       ugeth_err("%s: Cannot initialize MAC, aborting.",
+                                 ndev->name);
+                       return err;
+               }
+       }
+
+       ugeth->oldlink = 0;
+       ugeth->oldspeed = 0;
+       ugeth->oldduplex = -1;
+
+       phy_stop(ugeth->phydev);
+       phy_start(ugeth->phydev);
+
+       napi_enable(&ugeth->napi);
+       netif_device_attach(ndev);
+
+       return 0;
+}
+
+#else
+#define ucc_geth_suspend NULL
+#define ucc_geth_resume NULL
+#endif
+
 static phy_interface_t to_phy_interface(const char *phy_connection_type)
 {
        if (strcasecmp(phy_connection_type, "mii") == 0)
@@ -3722,7 +3812,7 @@ static int ucc_geth_probe(struct of_device* ofdev, const struct of_device_id *ma
                prop = of_get_property(np, "tx-clock", NULL);
                if (!prop) {
                        printk(KERN_ERR
-                               "ucc_geth: mising tx-clock-name property\n");
+                               "ucc_geth: missing tx-clock-name property\n");
                        return -EINVAL;
                }
                if ((*prop < QE_CLK_NONE) || (*prop > QE_CLK24)) {
@@ -3884,6 +3974,8 @@ static struct of_platform_driver ucc_geth_driver = {
        .match_table    = ucc_geth_match,
        .probe          = ucc_geth_probe,
        .remove         = ucc_geth_remove,
+       .suspend        = ucc_geth_suspend,
+       .resume         = ucc_geth_resume,
 };
 
 static int __init ucc_geth_init(void)