Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next
[pandora-kernel.git] / drivers / net / wireless / libertas / if_spi.c
index f6c2cd6..e0286cf 100644 (file)
  * (at your option) any later version.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/hardirq.h>
+#include <linux/interrupt.h>
 #include <linux/moduleparam.h>
 #include <linux/firmware.h>
 #include <linux/jiffies.h>
@@ -57,6 +61,7 @@ struct if_spi_card {
        /* Handles all SPI communication (except for FW load) */
        struct workqueue_struct         *workqueue;
        struct work_struct              packet_work;
+       struct work_struct              resume_work;
 
        u8                              cmd_buffer[IF_SPI_CMD_BUF_SIZE];
 
@@ -68,6 +73,9 @@ struct if_spi_card {
 
        /* Protects cmd_packet_list and data_packet_list */
        spinlock_t                      buffer_lock;
+
+       /* True is card suspended */
+       u8                              suspended;
 };
 
 static void free_if_spi_card(struct if_spi_card *card)
@@ -139,8 +147,10 @@ static void spu_transaction_finish(struct if_spi_card *card)
        card->prev_xfer_time = jiffies;
 }
 
-/* Write out a byte buffer to an SPI register,
- * using a series of 16-bit transfers. */
+/*
+ * Write out a byte buffer to an SPI register,
+ * using a series of 16-bit transfers.
+ */
 static int spu_write(struct if_spi_card *card, u16 reg, const u8 *buf, int len)
 {
        int err = 0;
@@ -204,8 +214,10 @@ static int spu_read(struct if_spi_card *card, u16 reg, u8 *buf, int len)
        struct spi_transfer dummy_trans;
        struct spi_transfer data_trans;
 
-       /* You must take an even number of bytes from the SPU, even if you
-        * don't care about the last one.  */
+       /*
+        * You must take an even number of bytes from the SPU, even if you
+        * don't care about the last one.
+        */
        BUG_ON(len & 0x1);
 
        spu_transaction_init(card);
@@ -254,8 +266,10 @@ static inline int spu_read_u16(struct if_spi_card *card, u16 reg, u16 *val)
        return ret;
 }
 
-/* Read 32 bits from an SPI register.
- * The low 16 bits are read first. */
+/*
+ * Read 32 bits from an SPI register.
+ * The low 16 bits are read first.
+ */
 static int spu_read_u32(struct if_spi_card *card, u16 reg, u32 *val)
 {
        __le32 buf;
@@ -267,13 +281,15 @@ static int spu_read_u32(struct if_spi_card *card, u16 reg, u32 *val)
        return err;
 }
 
-/* Keep reading 16 bits from an SPI register until you get the correct result.
+/*
+ * Keep reading 16 bits from an SPI register until you get the correct result.
  *
  * If mask = 0, the correct result is any non-zero number.
  * If mask != 0, the correct result is any number where
  * number & target_mask == target
  *
- * Returns -ETIMEDOUT if a second passes without the correct result. */
+ * Returns -ETIMEDOUT if a second passes without the correct result.
+ */
 static int spu_wait_for_u16(struct if_spi_card *card, u16 reg,
                        u16 target_mask, u16 target)
 {
@@ -293,16 +309,17 @@ static int spu_wait_for_u16(struct if_spi_card *card, u16 reg,
                }
                udelay(100);
                if (time_after(jiffies, timeout)) {
-                       lbs_pr_err("%s: timeout with val=%02x, "
-                              "target_mask=%02x, target=%02x\n",
+                       pr_err("%s: timeout with val=%02x, target_mask=%02x, target=%02x\n",
                               __func__, val, target_mask, target);
                        return -ETIMEDOUT;
                }
        }
 }
 
-/* Read 16 bits from an SPI register until you receive a specific value.
- * Returns -ETIMEDOUT if a 4 tries pass without success. */
+/*
+ * Read 16 bits from an SPI register until you receive a specific value.
+ * Returns -ETIMEDOUT if a 4 tries pass without success.
+ */
 static int spu_wait_for_u32(struct if_spi_card *card, u32 reg, u32 target)
 {
        int err, try;
@@ -324,8 +341,10 @@ static int spu_set_interrupt_mode(struct if_spi_card *card,
 {
        int err = 0;
 
-       /* We can suppress a host interrupt by clearing the appropriate
-        * bit in the "host interrupt status mask" register */
+       /*
+        * We can suppress a host interrupt by clearing the appropriate
+        * bit in the "host interrupt status mask" register
+        */
        if (suppress_host_int) {
                err = spu_write_u16(card, IF_SPI_HOST_INT_STATUS_MASK_REG, 0);
                if (err)
@@ -341,10 +360,12 @@ static int spu_set_interrupt_mode(struct if_spi_card *card,
                        return err;
        }
 
-       /* If auto-interrupts are on, the completion of certain transactions
+       /*
+        * If auto-interrupts are on, the completion of certain transactions
         * will trigger an interrupt automatically. If auto-interrupts
         * are off, we need to set the "Card Interrupt Cause" register to
-        * trigger a card interrupt. */
+        * trigger a card interrupt.
+        */
        if (auto_int) {
                err = spu_write_u16(card, IF_SPI_HOST_INT_CTRL_REG,
                                IF_SPI_HICT_TX_DOWNLOAD_OVER_AUTO |
@@ -387,7 +408,7 @@ static int spu_set_bus_mode(struct if_spi_card *card, u16 mode)
        if (err)
                return err;
        if ((rval & 0xF) != mode) {
-               lbs_pr_err("Can't read bus mode register.\n");
+               pr_err("Can't read bus mode register\n");
                return -EIO;
        }
        return 0;
@@ -398,8 +419,10 @@ static int spu_init(struct if_spi_card *card, int use_dummy_writes)
        int err = 0;
        u32 delay;
 
-       /* We have to start up in timed delay mode so that we can safely
-        * read the Delay Read Register. */
+       /*
+        * We have to start up in timed delay mode so that we can safely
+        * read the Delay Read Register.
+        */
        card->use_dummy_writes = 0;
        err = spu_set_bus_mode(card,
                                IF_SPI_BUS_MODE_SPI_CLOCK_PHASE_RISING |
@@ -455,8 +478,10 @@ static int if_spi_prog_helper_firmware(struct if_spi_card *card,
 
        /* Load helper firmware image */
        while (bytes_remaining > 0) {
-               /* Scratch pad 1 should contain the number of bytes we
-                * want to download to the firmware */
+               /*
+                * Scratch pad 1 should contain the number of bytes we
+                * want to download to the firmware
+                */
                err = spu_write_u16(card, IF_SPI_SCRATCH_1_REG,
                                        HELPER_FW_LOAD_CHUNK_SZ);
                if (err)
@@ -468,8 +493,10 @@ static int if_spi_prog_helper_firmware(struct if_spi_card *card,
                if (err)
                        goto out;
 
-               /* Feed the data into the command read/write port reg
-                * in chunks of 64 bytes */
+               /*
+                * Feed the data into the command read/write port reg
+                * in chunks of 64 bytes
+                */
                memset(temp, 0, sizeof(temp));
                memcpy(temp, fw,
                       min(bytes_remaining, HELPER_FW_LOAD_CHUNK_SZ));
@@ -491,9 +518,11 @@ static int if_spi_prog_helper_firmware(struct if_spi_card *card,
                fw += HELPER_FW_LOAD_CHUNK_SZ;
        }
 
-       /* Once the helper / single stage firmware download is complete,
+       /*
+        * Once the helper / single stage firmware download is complete,
         * write 0 to scratch pad 1 and interrupt the
-        * bootloader. This completes the helper download. */
+        * bootloader. This completes the helper download.
+        */
        err = spu_write_u16(card, IF_SPI_SCRATCH_1_REG, FIRMWARE_DNLD_OK);
        if (err)
                goto out;
@@ -508,26 +537,30 @@ static int if_spi_prog_helper_firmware(struct if_spi_card *card,
 
 out:
        if (err)
-               lbs_pr_err("failed to load helper firmware (err=%d)\n", err);
+               pr_err("failed to load helper firmware (err=%d)\n", err);
        lbs_deb_leave_args(LBS_DEB_SPI, "err %d", err);
        return err;
 }
 
-/* Returns the length of the next packet the firmware expects us to send
- * Sets crc_err if the previous transfer had a CRC error. */
+/*
+ * Returns the length of the next packet the firmware expects us to send.
+ * Sets crc_err if the previous transfer had a CRC error.
+ */
 static int if_spi_prog_main_firmware_check_len(struct if_spi_card *card,
                                                int *crc_err)
 {
        u16 len;
        int err = 0;
 
-       /* wait until the host interrupt status register indicates
-        * that we are ready to download */
+       /*
+        * wait until the host interrupt status register indicates
+        * that we are ready to download
+        */
        err = spu_wait_for_u16(card, IF_SPI_HOST_INT_STATUS_REG,
                                IF_SPI_HIST_CMD_DOWNLOAD_RDY,
                                IF_SPI_HIST_CMD_DOWNLOAD_RDY);
        if (err) {
-               lbs_pr_err("timed out waiting for host_int_status\n");
+               pr_err("timed out waiting for host_int_status\n");
                return err;
        }
 
@@ -537,9 +570,8 @@ static int if_spi_prog_main_firmware_check_len(struct if_spi_card *card,
                return err;
 
        if (len > IF_SPI_CMD_BUF_SIZE) {
-               lbs_pr_err("firmware load device requested a larger "
-                          "tranfer than we are prepared to "
-                          "handle. (len = %d)\n", len);
+               pr_err("firmware load device requested a larger transfer than we are prepared to handle (len = %d)\n",
+                      len);
                return -EIO;
        }
        if (len & 0x1) {
@@ -555,6 +587,7 @@ static int if_spi_prog_main_firmware_check_len(struct if_spi_card *card,
 static int if_spi_prog_main_firmware(struct if_spi_card *card,
                                        const struct firmware *firmware)
 {
+       struct lbs_private *priv = card->priv;
        int len, prev_len;
        int bytes, crc_err = 0, err = 0;
        const u8 *fw;
@@ -568,8 +601,9 @@ static int if_spi_prog_main_firmware(struct if_spi_card *card,
 
        err = spu_wait_for_u16(card, IF_SPI_SCRATCH_1_REG, 0, 0);
        if (err) {
-               lbs_pr_err("%s: timed out waiting for initial "
-                          "scratch reg = 0\n", __func__);
+               netdev_err(priv->dev,
+                          "%s: timed out waiting for initial scratch reg = 0\n",
+                          __func__);
                goto out;
        }
 
@@ -583,17 +617,18 @@ static int if_spi_prog_main_firmware(struct if_spi_card *card,
                        goto out;
                }
                if (bytes < 0) {
-                       /* If there are no more bytes left, we would normally
-                        * expect to have terminated with len = 0 */
-                       lbs_pr_err("Firmware load wants more bytes "
-                                  "than we have to offer.\n");
+                       /*
+                        * If there are no more bytes left, we would normally
+                        * expect to have terminated with len = 0
+                        */
+                       netdev_err(priv->dev,
+                                  "Firmware load wants more bytes than we have to offer.\n");
                        break;
                }
                if (crc_err) {
                        /* Previous transfer failed. */
                        if (++num_crc_errs > MAX_MAIN_FW_LOAD_CRC_ERR) {
-                               lbs_pr_err("Too many CRC errors encountered "
-                                          "in firmware load.\n");
+                               pr_err("Too many CRC errors encountered in firmware load.\n");
                                err = -EIO;
                                goto out;
                        }
@@ -622,21 +657,20 @@ static int if_spi_prog_main_firmware(struct if_spi_card *card,
                prev_len = len;
        }
        if (bytes > prev_len) {
-               lbs_pr_err("firmware load wants fewer bytes than "
-                          "we have to offer.\n");
+               pr_err("firmware load wants fewer bytes than we have to offer\n");
        }
 
        /* Confirm firmware download */
        err = spu_wait_for_u32(card, IF_SPI_SCRATCH_4_REG,
                                        SUCCESSFUL_FW_DOWNLOAD_MAGIC);
        if (err) {
-               lbs_pr_err("failed to confirm the firmware download\n");
+               pr_err("failed to confirm the firmware download\n");
                goto out;
        }
 
 out:
        if (err)
-               lbs_pr_err("failed to load firmware (err=%d)\n", err);
+               pr_err("failed to load firmware (err=%d)\n", err);
        lbs_deb_leave_args(LBS_DEB_SPI, "err %d", err);
        return err;
 }
@@ -656,14 +690,18 @@ static int if_spi_c2h_cmd(struct if_spi_card *card)
        u16 len;
        u8 i;
 
-       /* We need a buffer big enough to handle whatever people send to
-        * hw_host_to_card */
+       /*
+        * We need a buffer big enough to handle whatever people send to
+        * hw_host_to_card
+        */
        BUILD_BUG_ON(IF_SPI_CMD_BUF_SIZE < LBS_CMD_BUFFER_SIZE);
        BUILD_BUG_ON(IF_SPI_CMD_BUF_SIZE < LBS_UPLD_SIZE);
 
-       /* It's just annoying if the buffer size isn't a multiple of 4, because
-        * then we might have len <  IF_SPI_CMD_BUF_SIZE but
-        * ALIGN(len, 4) > IF_SPI_CMD_BUF_SIZE */
+       /*
+        * It's just annoying if the buffer size isn't a multiple of 4, because
+        * then we might have len < IF_SPI_CMD_BUF_SIZE but
+        * ALIGN(len, 4) > IF_SPI_CMD_BUF_SIZE
+        */
        BUILD_BUG_ON(IF_SPI_CMD_BUF_SIZE % 4 != 0);
 
        lbs_deb_enter(LBS_DEB_SPI);
@@ -673,13 +711,13 @@ static int if_spi_c2h_cmd(struct if_spi_card *card)
        if (err)
                goto out;
        if (!len) {
-               lbs_pr_err("%s: error: card has no data for host\n",
+               netdev_err(priv->dev, "%s: error: card has no data for host\n",
                           __func__);
                err = -EINVAL;
                goto out;
        } else if (len > IF_SPI_CMD_BUF_SIZE) {
-               lbs_pr_err("%s: error: response packet too large: "
-                          "%d bytes, but maximum is %d\n",
+               netdev_err(priv->dev,
+                          "%s: error: response packet too large: %d bytes, but maximum is %d\n",
                           __func__, len, IF_SPI_CMD_BUF_SIZE);
                err = -EINVAL;
                goto out;
@@ -701,7 +739,7 @@ static int if_spi_c2h_cmd(struct if_spi_card *card)
 
 out:
        if (err)
-               lbs_pr_err("%s: err=%d\n", __func__, err);
+               netdev_err(priv->dev, "%s: err=%d\n", __func__, err);
        lbs_deb_leave(LBS_DEB_SPI);
        return err;
 }
@@ -709,6 +747,7 @@ out:
 /* Move data from the card to the host */
 static int if_spi_c2h_data(struct if_spi_card *card)
 {
+       struct lbs_private *priv = card->priv;
        struct sk_buff *skb;
        char *data;
        u16 len;
@@ -721,13 +760,13 @@ static int if_spi_c2h_data(struct if_spi_card *card)
        if (err)
                goto out;
        if (!len) {
-               lbs_pr_err("%s: error: card has no data for host\n",
+               netdev_err(priv->dev, "%s: error: card has no data for host\n",
                           __func__);
                err = -EINVAL;
                goto out;
        } else if (len > MRVDRV_ETH_RX_PACKET_BUFFER_SIZE) {
-               lbs_pr_err("%s: error: card has %d bytes of data, but "
-                          "our maximum skb size is %zu\n",
+               netdev_err(priv->dev,
+                          "%s: error: card has %d bytes of data, but our maximum skb size is %zu\n",
                           __func__, len, MRVDRV_ETH_RX_PACKET_BUFFER_SIZE);
                err = -EINVAL;
                goto out;
@@ -759,7 +798,7 @@ free_skb:
        dev_kfree_skb(skb);
 out:
        if (err)
-               lbs_pr_err("%s: err=%d\n", __func__, err);
+               netdev_err(priv->dev, "%s: err=%d\n", __func__, err);
        lbs_deb_leave(LBS_DEB_SPI);
        return err;
 }
@@ -768,6 +807,7 @@ out:
 static void if_spi_h2c(struct if_spi_card *card,
                        struct if_spi_packet *packet, int type)
 {
+       struct lbs_private *priv = card->priv;
        int err = 0;
        u16 int_type, port_reg;
 
@@ -781,7 +821,8 @@ static void if_spi_h2c(struct if_spi_card *card,
                port_reg = IF_SPI_CMD_RDWRPORT_REG;
                break;
        default:
-               lbs_pr_err("can't transfer buffer of type %d\n", type);
+               netdev_err(priv->dev, "can't transfer buffer of type %d\n",
+                          type);
                err = -EINVAL;
                goto out;
        }
@@ -795,7 +836,7 @@ out:
        kfree(packet);
 
        if (err)
-               lbs_pr_err("%s: error %d\n", __func__, err);
+               netdev_err(priv->dev, "%s: error %d\n", __func__, err);
 }
 
 /* Inform the host about a card event */
@@ -819,7 +860,7 @@ static void if_spi_e2h(struct if_spi_card *card)
        lbs_queue_event(priv, cause & 0xff);
 out:
        if (err)
-               lbs_pr_err("%s: error %d\n", __func__, err);
+               netdev_err(priv->dev, "%s: error %d\n", __func__, err);
 }
 
 static void if_spi_host_to_card_worker(struct work_struct *work)
@@ -829,17 +870,21 @@ static void if_spi_host_to_card_worker(struct work_struct *work)
        u16 hiStatus;
        unsigned long flags;
        struct if_spi_packet *packet;
+       struct lbs_private *priv;
 
        card = container_of(work, struct if_spi_card, packet_work);
+       priv = card->priv;
 
        lbs_deb_enter(LBS_DEB_SPI);
 
-       /* Read the host interrupt status register to see what we
-        * can do. */
+       /*
+        * Read the host interrupt status register to see what we
+        * can do.
+        */
        err = spu_read_u16(card, IF_SPI_HOST_INT_STATUS_REG,
                                &hiStatus);
        if (err) {
-               lbs_pr_err("I/O error\n");
+               netdev_err(priv->dev, "I/O error\n");
                goto err;
        }
 
@@ -854,12 +899,15 @@ static void if_spi_host_to_card_worker(struct work_struct *work)
                        goto err;
        }
 
-       /* workaround: in PS mode, the card does not set the Command
-        * Download Ready bit, but it sets TX Download Ready. */
+       /*
+        * workaround: in PS mode, the card does not set the Command
+        * Download Ready bit, but it sets TX Download Ready.
+        */
        if (hiStatus & IF_SPI_HIST_CMD_DOWNLOAD_RDY ||
           (card->priv->psstate != PS_STATE_FULL_POWER &&
            (hiStatus & IF_SPI_HIST_TX_DOWNLOAD_RDY))) {
-               /* This means two things. First of all,
+               /*
+                * This means two things. First of all,
                 * if there was a previous command sent, the card has
                 * successfully received it.
                 * Secondly, it is now ready to download another
@@ -867,8 +915,7 @@ static void if_spi_host_to_card_worker(struct work_struct *work)
                 */
                lbs_host_to_card_done(card->priv);
 
-               /* Do we have any command packets from the host to
-                * send? */
+               /* Do we have any command packets from the host to send? */
                packet = NULL;
                spin_lock_irqsave(&card->buffer_lock, flags);
                if (!list_empty(&card->cmd_packet_list)) {
@@ -882,8 +929,7 @@ static void if_spi_host_to_card_worker(struct work_struct *work)
                        if_spi_h2c(card, packet, MVMS_CMD);
        }
        if (hiStatus & IF_SPI_HIST_TX_DOWNLOAD_RDY) {
-               /* Do we have any data packets from the host to
-                * send? */
+               /* Do we have any data packets from the host to send? */
                packet = NULL;
                spin_lock_irqsave(&card->buffer_lock, flags);
                if (!list_empty(&card->data_packet_list)) {
@@ -901,7 +947,7 @@ static void if_spi_host_to_card_worker(struct work_struct *work)
 
 err:
        if (err)
-               lbs_pr_err("%s: got error %d\n", __func__, err);
+               netdev_err(priv->dev, "%s: got error %d\n", __func__, err);
 
        lbs_deb_leave(LBS_DEB_SPI);
 }
@@ -910,7 +956,8 @@ err:
  * Host to Card
  *
  * Called from Libertas to transfer some data to the WLAN device
- * We can't sleep here. */
+ * We can't sleep here.
+ */
 static int if_spi_host_to_card(struct lbs_private *priv,
                                u8 type, u8 *buf, u16 nb)
 {
@@ -923,7 +970,8 @@ static int if_spi_host_to_card(struct lbs_private *priv,
        lbs_deb_enter_args(LBS_DEB_SPI, "type %d, bytes %d", type, nb);
 
        if (nb == 0) {
-               lbs_pr_err("%s: invalid size requested: %d\n", __func__, nb);
+               netdev_err(priv->dev, "%s: invalid size requested: %d\n",
+                          __func__, nb);
                err = -EINVAL;
                goto out;
        }
@@ -951,7 +999,8 @@ static int if_spi_host_to_card(struct lbs_private *priv,
                spin_unlock_irqrestore(&card->buffer_lock, flags);
                break;
        default:
-               lbs_pr_err("can't transfer buffer of type %d", type);
+               netdev_err(priv->dev, "can't transfer buffer of type %d\n",
+                          type);
                err = -EINVAL;
                break;
        }
@@ -984,7 +1033,7 @@ static irqreturn_t if_spi_host_interrupt(int irq, void *dev_id)
 
 static int if_spi_init_card(struct if_spi_card *card)
 {
-       struct spi_device *spi = card->spi;
+       struct lbs_private *priv = card->priv;
        int err, i;
        u32 scratch;
        const struct firmware *helper = NULL;
@@ -1012,8 +1061,8 @@ static int if_spi_init_card(struct if_spi_card *card)
                                break;
                }
                if (i == ARRAY_SIZE(fw_table)) {
-                       lbs_pr_err("Unsupported chip_id: 0x%02x\n",
-                                       card->card_id);
+                       netdev_err(priv->dev, "Unsupported chip_id: 0x%02x\n",
+                                  card->card_id);
                        err = -ENODEV;
                        goto out;
                }
@@ -1022,7 +1071,8 @@ static int if_spi_init_card(struct if_spi_card *card)
                                        card->card_id, &fw_table[0], &helper,
                                        &mainfw);
                if (err) {
-                       lbs_pr_err("failed to find firmware (%d)\n", err);
+                       netdev_err(priv->dev, "failed to find firmware (%d)\n",
+                                  err);
                        goto out;
                }
 
@@ -1031,8 +1081,9 @@ static int if_spi_init_card(struct if_spi_card *card)
                                "attached to SPI bus_num %d, chip_select %d. "
                                "spi->max_speed_hz=%d\n",
                                card->card_id, card->card_rev,
-                               spi->master->bus_num, spi->chip_select,
-                               spi->max_speed_hz);
+                               card->spi->master->bus_num,
+                               card->spi->chip_select,
+                               card->spi->max_speed_hz);
                err = if_spi_prog_helper_firmware(card, helper);
                if (err)
                        goto out;
@@ -1057,6 +1108,28 @@ out:
        return err;
 }
 
+static void if_spi_resume_worker(struct work_struct *work)
+{
+       struct if_spi_card *card;
+
+       card = container_of(work, struct if_spi_card, resume_work);
+
+       if (card->suspended) {
+               if (card->pdata->setup)
+                       card->pdata->setup(card->spi);
+
+               /* Init card ... */
+               if_spi_init_card(card);
+
+               enable_irq(card->spi->irq);
+
+               /* And resume it ... */
+               lbs_resume(card->priv);
+
+               card->suspended = 0;
+       }
+}
+
 static int __devinit if_spi_probe(struct spi_device *spi)
 {
        struct if_spi_card *card;
@@ -1099,14 +1172,17 @@ static int __devinit if_spi_probe(struct spi_device *spi)
        if (err)
                goto free_card;
 
-       /* Register our card with libertas.
-        * This will call alloc_etherdev */
+       /*
+        * Register our card with libertas.
+        * This will call alloc_etherdev.
+        */
        priv = lbs_add_card(card, &spi->dev);
        if (!priv) {
                err = -ENOMEM;
                goto free_card;
        }
        card->priv = priv;
+       priv->setup_fw_on_resume = 1;
        priv->card = card;
        priv->hw_host_to_card = if_spi_host_to_card;
        priv->enter_deep_sleep = NULL;
@@ -1117,17 +1193,20 @@ static int __devinit if_spi_probe(struct spi_device *spi)
        /* Initialize interrupt handling stuff. */
        card->workqueue = create_workqueue("libertas_spi");
        INIT_WORK(&card->packet_work, if_spi_host_to_card_worker);
+       INIT_WORK(&card->resume_work, if_spi_resume_worker);
 
        err = request_irq(spi->irq, if_spi_host_interrupt,
                        IRQF_TRIGGER_FALLING, "libertas_spi", card);
        if (err) {
-               lbs_pr_err("can't get host irq line-- request_irq failed\n");
+               pr_err("can't get host irq line-- request_irq failed\n");
                goto terminate_workqueue;
        }
 
-       /* Start the card.
+       /*
+        * Start the card.
         * This will call register_netdev, and we'll start
-        * getting interrupts... */
+        * getting interrupts...
+        */
        err = lbs_start_card(priv);
        if (err)
                goto release_irq;
@@ -1161,6 +1240,8 @@ static int __devexit libertas_spi_remove(struct spi_device *spi)
        lbs_deb_spi("libertas_spi_remove\n");
        lbs_deb_enter(LBS_DEB_SPI);
 
+       cancel_work_sync(&card->resume_work);
+
        lbs_stop_card(priv);
        lbs_remove_card(priv); /* will call free_netdev */
 
@@ -1174,6 +1255,40 @@ static int __devexit libertas_spi_remove(struct spi_device *spi)
        return 0;
 }
 
+static int if_spi_suspend(struct device *dev)
+{
+       struct spi_device *spi = to_spi_device(dev);
+       struct if_spi_card *card = spi_get_drvdata(spi);
+
+       if (!card->suspended) {
+               lbs_suspend(card->priv);
+               flush_workqueue(card->workqueue);
+               disable_irq(spi->irq);
+
+               if (card->pdata->teardown)
+                       card->pdata->teardown(spi);
+               card->suspended = 1;
+       }
+
+       return 0;
+}
+
+static int if_spi_resume(struct device *dev)
+{
+       struct spi_device *spi = to_spi_device(dev);
+       struct if_spi_card *card = spi_get_drvdata(spi);
+
+       /* Schedule delayed work */
+       schedule_work(&card->resume_work);
+
+       return 0;
+}
+
+static const struct dev_pm_ops if_spi_pm_ops = {
+       .suspend        = if_spi_suspend,
+       .resume         = if_spi_resume,
+};
+
 static struct spi_driver libertas_spi_driver = {
        .probe  = if_spi_probe,
        .remove = __devexit_p(libertas_spi_remove),
@@ -1181,6 +1296,7 @@ static struct spi_driver libertas_spi_driver = {
                .name   = "libertas_spi",
                .bus    = &spi_bus_type,
                .owner  = THIS_MODULE,
+               .pm     = &if_spi_pm_ops,
        },
 };