Auto merge with /home/aegl/GIT/linus
[powerpc.git] / drivers / net / skge.c
index f11e0e1..5cacc7a 100644 (file)
@@ -7,7 +7,7 @@
  * of the original driver such as link fail-over and link management because
  * those should be done at higher levels.
  *
- * Copyright (C) 2004, Stephen Hemminger <shemminger@osdl.org>
+ * Copyright (C) 2004, 2005 Stephen Hemminger <shemminger@osdl.org>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
 #include "skge.h"
 
 #define DRV_NAME               "skge"
-#define DRV_VERSION            "0.6"
+#define DRV_VERSION            "0.7"
 #define PFX                    DRV_NAME " "
 
 #define DEFAULT_TX_RING_SIZE   128
 #define DEFAULT_RX_RING_SIZE   512
 #define MAX_TX_RING_SIZE       1024
 #define MAX_RX_RING_SIZE       4096
+#define RX_COPY_THRESHOLD      128
+#define RX_BUF_SIZE            1536
 #define PHY_RETRIES            1000
 #define ETH_JUMBO_MTU          9000
 #define TX_WATCHDOG            (5 * HZ)
@@ -97,10 +99,12 @@ static void genesis_mac_init(struct skge_hw *hw, int port);
 static void genesis_reset(struct skge_hw *hw, int port);
 static void genesis_link_up(struct skge_port *skge);
 
+/* Avoid conditionals by using array */
 static const int txqaddr[] = { Q_XA1, Q_XA2 };
 static const int rxqaddr[] = { Q_R1, Q_R2 };
 static const u32 rxirqmask[] = { IS_R1_F, IS_R2_F };
 static const u32 txirqmask[] = { IS_XA1_F, IS_XA2_F };
+static const u32 portirqmask[] = { IS_PORT_1, IS_PORT_2 };
 
 /* Don't need to look at whole 16K.
  * last interesting register is descriptor poll timer.
@@ -744,6 +748,7 @@ static int skge_ring_alloc(struct skge_ring *ring, void *vaddr, u64 base)
 
        for (i = 0, e = ring->start, d = vaddr; i < ring->count; i++, e++, d++) {
                e->desc = d;
+               e->skb = NULL;
                if (i == ring->count - 1) {
                        e->next = ring->start;
                        d->next_offset = base;
@@ -757,24 +762,23 @@ static int skge_ring_alloc(struct skge_ring *ring, void *vaddr, u64 base)
        return 0;
 }
 
-/* Setup buffer for receiving */
-static inline int skge_rx_alloc(struct skge_port *skge,
-                               struct skge_element *e)
+static struct sk_buff *skge_rx_alloc(struct net_device *dev, unsigned int size)
 {
-       unsigned long bufsize = skge->netdev->mtu + ETH_HLEN; /* VLAN? */
-       struct skge_rx_desc *rd = e->desc;
-       struct sk_buff *skb;
-       u64 map;
+       struct sk_buff *skb = dev_alloc_skb(size);
 
-       skb = dev_alloc_skb(bufsize + NET_IP_ALIGN);
-       if (unlikely(!skb)) {
-               printk(KERN_DEBUG PFX "%s: out of memory for receive\n",
-                      skge->netdev->name);
-               return -ENOMEM;
+       if (likely(skb)) {
+               skb->dev = dev;
+               skb_reserve(skb, NET_IP_ALIGN);
        }
+       return skb;
+}
 
-       skb->dev = skge->netdev;
-       skb_reserve(skb, NET_IP_ALIGN);
+/* Allocate and setup a new buffer for receiving */
+static void skge_rx_setup(struct skge_port *skge, struct skge_element *e,
+                         struct sk_buff *skb, unsigned int bufsize)
+{
+       struct skge_rx_desc *rd = e->desc;
+       u64 map;
 
        map = pci_map_single(skge->hw->pdev, skb->data, bufsize,
                             PCI_DMA_FROMDEVICE);
@@ -792,55 +796,69 @@ static inline int skge_rx_alloc(struct skge_port *skge,
        rd->control = BMU_OWN | BMU_STF | BMU_IRQ_EOF | BMU_TCP_CHECK | bufsize;
        pci_unmap_addr_set(e, mapaddr, map);
        pci_unmap_len_set(e, maplen, bufsize);
-       return 0;
 }
 
-/* Free all unused buffers in receive ring, assumes receiver stopped */
+/* Resume receiving using existing skb,
+ * Note: DMA address is not changed by chip.
+ *      MTU not changed while receiver active.
+ */
+static void skge_rx_reuse(struct skge_element *e, unsigned int size)
+{
+       struct skge_rx_desc *rd = e->desc;
+
+       rd->csum2 = 0;
+       rd->csum2_start = ETH_HLEN;
+
+       wmb();
+
+       rd->control = BMU_OWN | BMU_STF | BMU_IRQ_EOF | BMU_TCP_CHECK | size;
+}
+
+
+/* Free all  buffers in receive ring, assumes receiver stopped */
 static void skge_rx_clean(struct skge_port *skge)
 {
        struct skge_hw *hw = skge->hw;
        struct skge_ring *ring = &skge->rx_ring;
        struct skge_element *e;
 
-       for (e = ring->to_clean; e != ring->to_use; e = e->next) {
+       e = ring->start;
+       do {
                struct skge_rx_desc *rd = e->desc;
                rd->control = 0;
-
-               pci_unmap_single(hw->pdev,
-                                pci_unmap_addr(e, mapaddr),
-                                pci_unmap_len(e, maplen),
-                                PCI_DMA_FROMDEVICE);
-               dev_kfree_skb(e->skb);
-               e->skb = NULL;
-       }
-       ring->to_clean = e;
+               if (e->skb) {
+                       pci_unmap_single(hw->pdev,
+                                        pci_unmap_addr(e, mapaddr),
+                                        pci_unmap_len(e, maplen),
+                                        PCI_DMA_FROMDEVICE);
+                       dev_kfree_skb(e->skb);
+                       e->skb = NULL;
+               }
+       } while ((e = e->next) != ring->start);
 }
 
+
 /* Allocate buffers for receive ring
- * For receive: to_use   is refill location
- *              to_clean is next received frame.
- *
- * if (to_use == to_clean)
- *      then ring all frames in ring need buffers
- * if (to_use->next == to_clean)
- *      then ring all frames in ring have buffers
+ * For receive:  to_clean is next received frame.
  */
 static int skge_rx_fill(struct skge_port *skge)
 {
        struct skge_ring *ring = &skge->rx_ring;
        struct skge_element *e;
-       int ret = 0;
+       unsigned int bufsize = skge->rx_buf_size;
 
-       for (e = ring->to_use; e->next != ring->to_clean; e = e->next) {
-               if (skge_rx_alloc(skge, e)) {
-                       ret = 1;
-                       break;
-               }
+       e = ring->start;
+       do {
+               struct sk_buff *skb = skge_rx_alloc(skge->netdev, bufsize);
 
-       }
-       ring->to_use = e;
+               if (!skb)
+                       return -ENOMEM;
 
-       return ret;
+               skge_rx_setup(skge, e, skb, bufsize);
+       } while ( (e = e->next) != ring->start);
+
+       ring->to_clean = ring->start;
+       return 0;
 }
 
 static void skge_link_up(struct skge_port *skge)
@@ -1382,7 +1400,9 @@ static void genesis_mac_intr(struct skge_hw *hw, int port)
        struct skge_port *skge = netdev_priv(hw->dev[port]);
        u16 status = xm_read16(hw, port, XM_ISRC);
 
-       pr_debug("genesis_intr status %x\n", status);
+       if (netif_msg_intr(skge))
+               printk(KERN_DEBUG PFX "%s: mac interrupt status 0x%x\n",
+                      skge->netdev->name, status);
 
        if (status & XM_IS_TXF_UR) {
                xm_write32(hw, port, XM_MODE, XM_MD_FTF);
@@ -1446,6 +1466,7 @@ static void genesis_link_up(struct skge_port *skge)
         */
        if (skge->flow_control == FLOW_MODE_NONE ||
            skge->flow_control == FLOW_MODE_LOC_SEND)
+               /* Disable Pause Frame Reception */
                cmd |= XM_MMU_IGN_PF;
        else
                /* Enable Pause Frame Reception */
@@ -1519,7 +1540,9 @@ static inline void bcom_phy_intr(struct skge_port *skge)
        u16 isrc;
 
        isrc = xm_phy_read(hw, port, PHY_BCOM_INT_STAT);
-       pr_debug("bcom_phy_interrupt status=0x%x\n", isrc);
+       if (netif_msg_intr(skge))
+               printk(KERN_DEBUG PFX "%s: phy interrupt status 0x%x\n",
+                      skge->netdev->name, isrc);
 
        if (isrc & PHY_B_IS_PSE)
                printk(KERN_ERR PFX "%s: uncorrectable pair swap error\n",
@@ -1823,10 +1846,14 @@ static void yukon_get_stats(struct skge_port *skge, u64 *data)
 
 static void yukon_mac_intr(struct skge_hw *hw, int port)
 {
-       struct skge_port *skge = netdev_priv(hw->dev[port]);
+       struct net_device *dev = hw->dev[port];
+       struct skge_port *skge = netdev_priv(dev);
        u8 status = skge_read8(hw, SK_REG(port, GMAC_IRQ_SRC));
 
-       pr_debug("yukon_intr status %x\n", status);
+       if (netif_msg_intr(skge))
+               printk(KERN_DEBUG PFX "%s: mac interrupt status 0x%x\n",
+                      dev->name, status);
+
        if (status & GM_IS_RX_FF_OR) {
                ++skge->net_stats.rx_fifo_errors;
                gma_write8(hw, port, RX_GMF_CTRL_T, GMF_CLI_RX_FO);
@@ -1908,7 +1935,10 @@ static void yukon_phy_intr(struct skge_port *skge)
 
        istatus = gm_phy_read(hw, port, PHY_MARV_INT_STAT);
        phystat = gm_phy_read(hw, port, PHY_MARV_PHY_STAT);
-       pr_debug("yukon phy intr istat=%x phy_stat=%x\n", istatus, phystat);
+
+       if (netif_msg_intr(skge))
+               printk(KERN_DEBUG PFX "%s: phy interrupt status 0x%x 0x%x\n",
+                      skge->netdev->name, istatus, phystat);
 
        if (istatus & PHY_M_IS_AN_COMPL) {
                if (gm_phy_read(hw, port, PHY_MARV_AUNE_LP)
@@ -2034,6 +2064,12 @@ static int skge_up(struct net_device *dev)
        if (netif_msg_ifup(skge))
                printk(KERN_INFO PFX "%s: enabling interface\n", dev->name);
 
+       if (dev->mtu > RX_BUF_SIZE)
+               skge->rx_buf_size = dev->mtu + ETH_HLEN + NET_IP_ALIGN;
+       else
+               skge->rx_buf_size = RX_BUF_SIZE;
+
+
        rx_size = skge->rx_ring.count * sizeof(struct skge_rx_desc);
        tx_size = skge->tx_ring.count * sizeof(struct skge_tx_desc);
        skge->mem_size = tx_size + rx_size;
@@ -2046,7 +2082,8 @@ static int skge_up(struct net_device *dev)
        if ((err = skge_ring_alloc(&skge->rx_ring, skge->mem, skge->dma)))
                goto free_pci_mem;
 
-       if (skge_rx_fill(skge))
+       err = skge_rx_fill(skge);
+       if (err)
                goto free_rx_ring;
 
        if ((err = skge_ring_alloc(&skge->tx_ring, skge->mem + rx_size,
@@ -2055,6 +2092,10 @@ static int skge_up(struct net_device *dev)
 
        skge->tx_avail = skge->tx_ring.count - 1;
 
+       /* Enable IRQ from port */
+       hw->intr_mask |= portirqmask[port];
+       skge_write32(hw, B0_IMSK, hw->intr_mask);
+
        /* Initialze MAC */
        if (hw->chip_id == CHIP_ID_GENESIS)
                genesis_mac_init(hw, port);
@@ -2266,6 +2307,7 @@ static int skge_xmit_frame(struct sk_buff *skb, struct net_device *dev)
 
 static inline void skge_tx_free(struct skge_hw *hw, struct skge_element *e)
 {
+       /* This ring element can be skb or fragment */
        if (e->skb) {
                pci_unmap_single(hw->pdev,
                               pci_unmap_addr(e, mapaddr),
@@ -2310,16 +2352,17 @@ static void skge_tx_timeout(struct net_device *dev)
 static int skge_change_mtu(struct net_device *dev, int new_mtu)
 {
        int err = 0;
+       int running = netif_running(dev);
 
        if (new_mtu < ETH_ZLEN || new_mtu > ETH_JUMBO_MTU)
                return -EINVAL;
 
-       dev->mtu = new_mtu;
 
-       if (netif_running(dev)) {
+       if (running)
                skge_down(dev);
+       dev->mtu = new_mtu;
+       if (running)
                skge_up(dev);
-       }
 
        return err;
 }
@@ -2418,28 +2461,76 @@ static void skge_rx_error(struct skge_port *skge, int slot,
                printk(KERN_DEBUG PFX "%s: rx err, slot %d control 0x%x status 0x%x\n",
                       skge->netdev->name, slot, control, status);
 
-       if ((control & (BMU_EOF|BMU_STF)) != (BMU_STF|BMU_EOF)
-           || (control & BMU_BBC) > skge->netdev->mtu + VLAN_ETH_HLEN)
+       if ((control & (BMU_EOF|BMU_STF)) != (BMU_STF|BMU_EOF))
                skge->net_stats.rx_length_errors++;
-       else {
-               if (skge->hw->chip_id == CHIP_ID_GENESIS) {
-                       if (status & (XMR_FS_RUNT|XMR_FS_LNG_ERR))
-                               skge->net_stats.rx_length_errors++;
-                       if (status & XMR_FS_FRA_ERR)
-                               skge->net_stats.rx_frame_errors++;
-                       if (status & XMR_FS_FCS_ERR)
-                               skge->net_stats.rx_crc_errors++;
-               } else {
-                       if (status & (GMR_FS_LONG_ERR|GMR_FS_UN_SIZE))
-                               skge->net_stats.rx_length_errors++;
-                       if (status & GMR_FS_FRAGMENT)
-                               skge->net_stats.rx_frame_errors++;
-                       if (status & GMR_FS_CRC_ERR)
-                               skge->net_stats.rx_crc_errors++;
+       else if (skge->hw->chip_id == CHIP_ID_GENESIS) {
+               if (status & (XMR_FS_RUNT|XMR_FS_LNG_ERR))
+                       skge->net_stats.rx_length_errors++;
+               if (status & XMR_FS_FRA_ERR)
+                       skge->net_stats.rx_frame_errors++;
+               if (status & XMR_FS_FCS_ERR)
+                       skge->net_stats.rx_crc_errors++;
+       } else {
+               if (status & (GMR_FS_LONG_ERR|GMR_FS_UN_SIZE))
+                       skge->net_stats.rx_length_errors++;
+               if (status & GMR_FS_FRAGMENT)
+                       skge->net_stats.rx_frame_errors++;
+               if (status & GMR_FS_CRC_ERR)
+                       skge->net_stats.rx_crc_errors++;
+       }
+}
+
+/* Get receive buffer from descriptor.
+ * Handles copy of small buffers and reallocation failures
+ */
+static inline struct sk_buff *skge_rx_get(struct skge_port *skge,
+                                         struct skge_element *e,
+                                         unsigned int len)
+{
+       struct sk_buff *nskb, *skb;
+
+       if (len < RX_COPY_THRESHOLD) {
+               nskb = skge_rx_alloc(skge->netdev, len + NET_IP_ALIGN);
+               if (unlikely(!nskb))
+                       return NULL;
+
+               pci_dma_sync_single_for_cpu(skge->hw->pdev,
+                                           pci_unmap_addr(e, mapaddr),
+                                           len, PCI_DMA_FROMDEVICE);
+               memcpy(nskb->data, e->skb->data, len);
+               pci_dma_sync_single_for_device(skge->hw->pdev,
+                                              pci_unmap_addr(e, mapaddr),
+                                              len, PCI_DMA_FROMDEVICE);
+
+               if (skge->rx_csum) {
+                       struct skge_rx_desc *rd = e->desc;
+                       nskb->csum = le16_to_cpu(rd->csum2);
+                       nskb->ip_summed = CHECKSUM_HW;
+               }
+               skge_rx_reuse(e, skge->rx_buf_size);
+               return nskb;
+       } else {
+               nskb = skge_rx_alloc(skge->netdev, skge->rx_buf_size);
+               if (unlikely(!nskb))
+                       return NULL;
+
+               pci_unmap_single(skge->hw->pdev,
+                                pci_unmap_addr(e, mapaddr),
+                                pci_unmap_len(e, maplen),
+                                PCI_DMA_FROMDEVICE);
+               skb = e->skb;
+               if (skge->rx_csum) {
+                       struct skge_rx_desc *rd = e->desc;
+                       skb->csum = le16_to_cpu(rd->csum2);
+                       skb->ip_summed = CHECKSUM_HW;
                }
+
+               skge_rx_setup(skge, e, nskb, skge->rx_buf_size);
+               return skb;
        }
 }
 
+
 static int skge_poll(struct net_device *dev, int *budget)
 {
        struct skge_port *skge = netdev_priv(dev);
@@ -2448,13 +2539,12 @@ static int skge_poll(struct net_device *dev, int *budget)
        struct skge_element *e;
        unsigned int to_do = min(dev->quota, *budget);
        unsigned int work_done = 0;
-       int done;
-       static const u32 irqmask[] = { IS_PORT_1, IS_PORT_2 };
 
-       for (e = ring->to_clean; e != ring->to_use && work_done < to_do;
-            e = e->next) {
+       pr_debug("skge_poll\n");
+
+       for (e = ring->to_clean; work_done < to_do; e = e->next) {
                struct skge_rx_desc *rd = e->desc;
-               struct sk_buff *skb = e->skb;
+               struct sk_buff *skb;
                u32 control, len, status;
 
                rmb();
@@ -2463,19 +2553,12 @@ static int skge_poll(struct net_device *dev, int *budget)
                        break;
 
                len = control & BMU_BBC;
-               e->skb = NULL;
-
-               pci_unmap_single(hw->pdev,
-                                pci_unmap_addr(e, mapaddr),
-                                pci_unmap_len(e, maplen),
-                                PCI_DMA_FROMDEVICE);
-
                status = rd->status;
-               if ((control & (BMU_EOF|BMU_STF)) != (BMU_STF|BMU_EOF)
-                    || len > dev->mtu + VLAN_ETH_HLEN
-                    || bad_phy_status(hw, status)) {
+
+               if (unlikely((control & (BMU_EOF|BMU_STF)) != (BMU_STF|BMU_EOF)
+                            || bad_phy_status(hw, status))) {
                        skge_rx_error(skge, e - ring->start, control, status);
-                       dev_kfree_skb(skb);
+                       skge_rx_reuse(e, skge->rx_buf_size);
                        continue;
                }
 
@@ -2483,43 +2566,37 @@ static int skge_poll(struct net_device *dev, int *budget)
                    printk(KERN_DEBUG PFX "%s: rx slot %td status 0x%x len %d\n",
                           dev->name, e - ring->start, rd->status, len);
 
-               skb_put(skb, len);
-               skb->protocol = eth_type_trans(skb, dev);
-
-               if (skge->rx_csum) {
-                       skb->csum = le16_to_cpu(rd->csum2);
-                       skb->ip_summed = CHECKSUM_HW;
-               }
+               skb = skge_rx_get(skge, e, len);
+               if (likely(skb)) {
+                       skb_put(skb, len);
+                       skb->protocol = eth_type_trans(skb, dev);
 
-               dev->last_rx = jiffies;
-               netif_receive_skb(skb);
+                       dev->last_rx = jiffies;
+                       netif_receive_skb(skb);
 
-               ++work_done;
+                       ++work_done;
+               } else
+                       skge_rx_reuse(e, skge->rx_buf_size);
        }
        ring->to_clean = e;
 
-       *budget -= work_done;
-       dev->quota -= work_done;
-       done = work_done < to_do;
-
-       if (skge_rx_fill(skge))
-               done = 0;
-
        /* restart receiver */
        wmb();
        skge_write8(hw, Q_ADDR(rxqaddr[skge->port], Q_CSR),
                    CSR_START | CSR_IRQ_CL_F);
 
-       if (done) {
-               local_irq_disable();
-               hw->intr_mask |= irqmask[skge->port];
-               /* Order is important since data can get interrupted */
-               skge_write32(hw, B0_IMSK, hw->intr_mask);
-               __netif_rx_complete(dev);
-               local_irq_enable();
-       }
+       *budget -= work_done;
+       dev->quota -= work_done;
+
+       if (work_done >=  to_do)
+               return 1; /* not done */
 
-       return !done;
+       local_irq_disable();
+       __netif_rx_complete(dev);
+       hw->intr_mask |= portirqmask[skge->port];
+       skge_write32(hw, B0_IMSK, hw->intr_mask);
+       local_irq_enable();
+       return 0;
 }
 
 static inline void skge_tx_intr(struct net_device *dev)
@@ -2697,19 +2774,14 @@ static irqreturn_t skge_intr(int irq, void *dev_id, struct pt_regs *regs)
                return IRQ_NONE;
 
        status &= hw->intr_mask;
-
-       if ((status & IS_R1_F) && netif_rx_schedule_prep(hw->dev[0])) {
-               status &= ~IS_R1_F;
+       if (status & IS_R1_F) {
                hw->intr_mask &= ~IS_R1_F;
-               skge_write32(hw, B0_IMSK, hw->intr_mask);
-               __netif_rx_schedule(hw->dev[0]);
+               netif_rx_schedule(hw->dev[0]);
        }
 
-       if ((status & IS_R2_F) && netif_rx_schedule_prep(hw->dev[1])) {
-               status &= ~IS_R2_F;
+       if (status & IS_R2_F) {
                hw->intr_mask &= ~IS_R2_F;
-               skge_write32(hw, B0_IMSK, hw->intr_mask);
-               __netif_rx_schedule(hw->dev[1]);
+               netif_rx_schedule(hw->dev[1]);
        }
 
        if (status & IS_XA1_F)
@@ -2718,6 +2790,24 @@ static irqreturn_t skge_intr(int irq, void *dev_id, struct pt_regs *regs)
        if (status & IS_XA2_F)
                skge_tx_intr(hw->dev[1]);
 
+       if (status & IS_PA_TO_RX1) {
+               struct skge_port *skge = netdev_priv(hw->dev[0]);
+               ++skge->net_stats.rx_over_errors;
+               skge_write16(hw, B3_PA_CTRL, PA_CLR_TO_RX1);
+       }
+
+       if (status & IS_PA_TO_RX2) {
+               struct skge_port *skge = netdev_priv(hw->dev[1]);
+               ++skge->net_stats.rx_over_errors;
+               skge_write16(hw, B3_PA_CTRL, PA_CLR_TO_RX2);
+       }
+
+       if (status & IS_PA_TO_TX1)
+               skge_write16(hw, B3_PA_CTRL, PA_CLR_TO_TX1);
+
+       if (status & IS_PA_TO_TX2)
+               skge_write16(hw, B3_PA_CTRL, PA_CLR_TO_TX2);
+
        if (status & IS_MAC1)
                skge_mac_intr(hw, 0);
 
@@ -2732,8 +2822,7 @@ static irqreturn_t skge_intr(int irq, void *dev_id, struct pt_regs *regs)
                tasklet_schedule(&hw->ext_tasklet);
        }
 
-       if (status)
-               skge_write32(hw, B0_IMSK, hw->intr_mask);
+       skge_write32(hw, B0_IMSK, hw->intr_mask);
 
        return IRQ_HANDLED;
 }
@@ -2918,9 +3007,7 @@ static int skge_reset(struct skge_hw *hw)
        skge_write32(hw, B2_IRQM_INI, skge_usecs2clk(hw, 100));
        skge_write32(hw, B2_IRQM_CTRL, TIM_START);
 
-       hw->intr_mask = IS_HW_ERR | IS_EXT_REG | IS_PORT_1;
-       if (hw->ports > 1)
-               hw->intr_mask |= IS_PORT_2;
+       hw->intr_mask = IS_HW_ERR | IS_EXT_REG;
        skge_write32(hw, B0_IMSK, hw->intr_mask);
 
        if (hw->chip_id != CHIP_ID_GENESIS)
@@ -3172,7 +3259,7 @@ static void __devexit skge_remove(struct pci_dev *pdev)
 }
 
 #ifdef CONFIG_PM
-static int skge_suspend(struct pci_dev *pdev, u32 state)
+static int skge_suspend(struct pci_dev *pdev, pm_message_t state)
 {
        struct skge_hw *hw  = pci_get_drvdata(pdev);
        int i, wol = 0;
@@ -3192,7 +3279,7 @@ static int skge_suspend(struct pci_dev *pdev, u32 state)
        }
 
        pci_save_state(pdev);
-       pci_enable_wake(pdev, state, wol);
+       pci_enable_wake(pdev, pci_choose_state(pdev, state), wol);
        pci_disable_device(pdev);
        pci_set_power_state(pdev, pci_choose_state(pdev, state));