Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wirel...
authorLuciano Coelho <coelho@ti.com>
Thu, 1 Dec 2011 10:14:48 +0000 (12:14 +0200)
committerLuciano Coelho <coelho@ti.com>
Thu, 1 Dec 2011 10:14:48 +0000 (12:14 +0200)
1  2 
drivers/net/wireless/wl12xx/boot.c
drivers/net/wireless/wl12xx/scan.c
drivers/net/wireless/wl12xx/spi.c

index 4ce634b925cb0ad5e16dadad4f1d654e54d37b54,6813379149767ea4c6236d6b43a0f1f0c219c8d1..6e140bf4e23666f8baf689320f2ab24e2c03482f
@@@ -23,8 -23,8 +23,9 @@@
  
  #include <linux/slab.h>
  #include <linux/wl12xx.h>
+ #include <linux/export.h>
  
 +#include "debug.h"
  #include "acx.h"
  #include "reg.h"
  #include "boot.h"
index a13c49e27a363912baff48d9476de8eee9434b89,fc29c671cf3b34db3fc695fbd70209720a3c52e8..330d6788a916d7b6689ebd96aa237b0a17c13bd7
@@@ -24,7 -24,6 +24,7 @@@
  #include <linux/ieee80211.h>
  
  #include "wl12xx.h"
 +#include "debug.h"
  #include "cmd.h"
  #include "scan.h"
  #include "acx.h"
@@@ -35,8 -34,6 +35,8 @@@ void wl1271_scan_complete_work(struct w
  {
        struct delayed_work *dwork;
        struct wl1271 *wl;
 +      struct ieee80211_vif *vif;
 +      struct wl12xx_vif *wlvif;
        int ret;
        bool is_sta, is_ibss;
  
        if (wl->scan.state == WL1271_SCAN_STATE_IDLE)
                goto out;
  
 +      vif = wl->scan_vif;
 +      wlvif = wl12xx_vif_to_data(vif);
 +
        wl->scan.state = WL1271_SCAN_STATE_IDLE;
        memset(wl->scan.scanned_ch, 0, sizeof(wl->scan.scanned_ch));
        wl->scan.req = NULL;
 +      wl->scan_vif = NULL;
  
        ret = wl1271_ps_elp_wakeup(wl);
        if (ret < 0)
                goto out;
  
 -      if (test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) {
 +      if (test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags)) {
                /* restore hardware connection monitoring template */
 -              wl1271_cmd_build_ap_probe_req(wl, wl->probereq);
 +              wl1271_cmd_build_ap_probe_req(wl, wlvif, wlvif->probereq);
        }
  
        /* return to ROC if needed */
 -      is_sta = (wl->bss_type == BSS_TYPE_STA_BSS);
 -      is_ibss = (wl->bss_type == BSS_TYPE_IBSS);
 -      if (((is_sta && !test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) ||
 -           (is_ibss && !test_bit(WL1271_FLAG_IBSS_JOINED, &wl->flags))) &&
 -          !test_bit(wl->dev_role_id, wl->roc_map)) {
 +      is_sta = (wlvif->bss_type == BSS_TYPE_STA_BSS);
 +      is_ibss = (wlvif->bss_type == BSS_TYPE_IBSS);
 +      if (((is_sta && !test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags)) ||
 +           (is_ibss && !test_bit(WLVIF_FLAG_IBSS_JOINED, &wlvif->flags))) &&
 +          !test_bit(wlvif->dev_role_id, wl->roc_map)) {
                /* restore remain on channel */
 -              wl12xx_cmd_role_start_dev(wl);
 -              wl12xx_roc(wl, wl->dev_role_id);
 +              wl12xx_start_dev(wl, wlvif);
        }
        wl1271_ps_elp_sleep(wl);
  
@@@ -161,11 -155,9 +161,11 @@@ static int wl1271_get_scan_channels(str
  
  #define WL1271_NOTHING_TO_SCAN 1
  
 -static int wl1271_scan_send(struct wl1271 *wl, enum ieee80211_band band,
 -                           bool passive, u32 basic_rate)
 +static int wl1271_scan_send(struct wl1271 *wl, struct ieee80211_vif *vif,
 +                          enum ieee80211_band band,
 +                          bool passive, u32 basic_rate)
  {
 +      struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif);
        struct wl1271_cmd_scan *cmd;
        struct wl1271_cmd_trigger_scan_to *trigger;
        int ret;
        if (passive)
                scan_options |= WL1271_SCAN_OPT_PASSIVE;
  
 -      if (WARN_ON(wl->role_id == WL12XX_INVALID_ROLE_ID)) {
 +      if (WARN_ON(wlvif->role_id == WL12XX_INVALID_ROLE_ID)) {
                ret = -EINVAL;
                goto out;
        }
 -      cmd->params.role_id = wl->role_id;
 +      cmd->params.role_id = wlvif->role_id;
        cmd->params.scan_options = cpu_to_le16(scan_options);
  
        cmd->params.n_ch = wl1271_get_scan_channels(wl, wl->scan.req,
  
        cmd->params.tx_rate = cpu_to_le32(basic_rate);
        cmd->params.n_probe_reqs = wl->conf.scan.num_probe_reqs;
 -      cmd->params.tx_rate = cpu_to_le32(basic_rate);
        cmd->params.tid_trigger = 0;
        cmd->params.scan_tag = WL1271_SCAN_DEFAULT_TAG;
  
                memcpy(cmd->params.ssid, wl->scan.ssid, wl->scan.ssid_len);
        }
  
 -      memcpy(cmd->addr, wl->mac_addr, ETH_ALEN);
 +      memcpy(cmd->addr, vif->addr, ETH_ALEN);
  
 -      ret = wl1271_cmd_build_probe_req(wl, wl->scan.ssid, wl->scan.ssid_len,
 -                                       wl->scan.req->ie, wl->scan.req->ie_len,
 -                                       band);
 +      ret = wl1271_cmd_build_probe_req(wl, wlvif, wl->scan.ssid,
 +                                       wl->scan.ssid_len, wl->scan.req->ie,
 +                                       wl->scan.req->ie_len, band);
        if (ret < 0) {
                wl1271_error("PROBE request template failed");
                goto out;
@@@ -248,12 -241,11 +248,12 @@@ out
        return ret;
  }
  
 -void wl1271_scan_stm(struct wl1271 *wl)
 +void wl1271_scan_stm(struct wl1271 *wl, struct ieee80211_vif *vif)
  {
 +      struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif);
        int ret = 0;
        enum ieee80211_band band;
 -      u32 rate;
 +      u32 rate, mask;
  
        switch (wl->scan.state) {
        case WL1271_SCAN_STATE_IDLE:
  
        case WL1271_SCAN_STATE_2GHZ_ACTIVE:
                band = IEEE80211_BAND_2GHZ;
 -              rate = wl1271_tx_min_rate_get(wl, wl->bitrate_masks[band]);
 -              ret = wl1271_scan_send(wl, band, false, rate);
 +              mask = wlvif->bitrate_masks[band];
 +              if (wl->scan.req->no_cck) {
 +                      mask &= ~CONF_TX_CCK_RATES;
 +                      if (!mask)
 +                              mask = CONF_TX_RATE_MASK_BASIC_P2P;
 +              }
 +              rate = wl1271_tx_min_rate_get(wl, mask);
 +              ret = wl1271_scan_send(wl, vif, band, false, rate);
                if (ret == WL1271_NOTHING_TO_SCAN) {
                        wl->scan.state = WL1271_SCAN_STATE_2GHZ_PASSIVE;
 -                      wl1271_scan_stm(wl);
 +                      wl1271_scan_stm(wl, vif);
                }
  
                break;
  
        case WL1271_SCAN_STATE_2GHZ_PASSIVE:
                band = IEEE80211_BAND_2GHZ;
 -              rate = wl1271_tx_min_rate_get(wl, wl->bitrate_masks[band]);
 -              ret = wl1271_scan_send(wl, band, true, rate);
 +              mask = wlvif->bitrate_masks[band];
 +              if (wl->scan.req->no_cck) {
 +                      mask &= ~CONF_TX_CCK_RATES;
 +                      if (!mask)
 +                              mask = CONF_TX_RATE_MASK_BASIC_P2P;
 +              }
 +              rate = wl1271_tx_min_rate_get(wl, mask);
 +              ret = wl1271_scan_send(wl, vif, band, true, rate);
                if (ret == WL1271_NOTHING_TO_SCAN) {
                        if (wl->enable_11a)
                                wl->scan.state = WL1271_SCAN_STATE_5GHZ_ACTIVE;
                        else
                                wl->scan.state = WL1271_SCAN_STATE_DONE;
 -                      wl1271_scan_stm(wl);
 +                      wl1271_scan_stm(wl, vif);
                }
  
                break;
  
        case WL1271_SCAN_STATE_5GHZ_ACTIVE:
                band = IEEE80211_BAND_5GHZ;
 -              rate = wl1271_tx_min_rate_get(wl, wl->bitrate_masks[band]);
 -              ret = wl1271_scan_send(wl, band, false, rate);
 +              rate = wl1271_tx_min_rate_get(wl, wlvif->bitrate_masks[band]);
 +              ret = wl1271_scan_send(wl, vif, band, false, rate);
                if (ret == WL1271_NOTHING_TO_SCAN) {
                        wl->scan.state = WL1271_SCAN_STATE_5GHZ_PASSIVE;
 -                      wl1271_scan_stm(wl);
 +                      wl1271_scan_stm(wl, vif);
                }
  
                break;
  
        case WL1271_SCAN_STATE_5GHZ_PASSIVE:
                band = IEEE80211_BAND_5GHZ;
 -              rate = wl1271_tx_min_rate_get(wl, wl->bitrate_masks[band]);
 -              ret = wl1271_scan_send(wl, band, true, rate);
 +              rate = wl1271_tx_min_rate_get(wl, wlvif->bitrate_masks[band]);
 +              ret = wl1271_scan_send(wl, vif, band, true, rate);
                if (ret == WL1271_NOTHING_TO_SCAN) {
                        wl->scan.state = WL1271_SCAN_STATE_DONE;
 -                      wl1271_scan_stm(wl);
 +                      wl1271_scan_stm(wl, vif);
                }
  
                break;
        }
  }
  
 -int wl1271_scan(struct wl1271 *wl, const u8 *ssid, size_t ssid_len,
 +int wl1271_scan(struct wl1271 *wl, struct ieee80211_vif *vif,
 +              const u8 *ssid, size_t ssid_len,
                struct cfg80211_scan_request *req)
  {
        /*
                wl->scan.ssid_len = 0;
        }
  
 +      wl->scan_vif = vif;
        wl->scan.req = req;
        memset(wl->scan.scanned_ch, 0, sizeof(wl->scan.scanned_ch));
  
        ieee80211_queue_delayed_work(wl->hw, &wl->scan_complete_work,
                                     msecs_to_jiffies(WL1271_SCAN_TIMEOUT));
  
 -      wl1271_scan_stm(wl);
 +      wl1271_scan_stm(wl, vif);
  
        return 0;
  }
@@@ -581,7 -559,7 +581,7 @@@ wl12xx_scan_sched_scan_ssid_list(struc
                                                break;
                                        }
                                /* Fail if SSID isn't present in the filters */
-                               if (j == req->n_ssids) {
+                               if (j == cmd->n_ssids) {
                                        ret = -EINVAL;
                                        goto out_free;
                                }
@@@ -607,7 -585,6 +607,7 @@@ out
  }
  
  int wl1271_scan_sched_scan_config(struct wl1271 *wl,
 +                                struct wl12xx_vif *wlvif,
                                  struct cfg80211_sched_scan_request *req,
                                  struct ieee80211_sched_scan_ies *ies)
  {
        }
  
        if (!force_passive && cfg->active[0]) {
 -              ret = wl1271_cmd_build_probe_req(wl, req->ssids[0].ssid,
 +              ret = wl1271_cmd_build_probe_req(wl, wlvif, req->ssids[0].ssid,
                                                 req->ssids[0].ssid_len,
                                                 ies->ie[IEEE80211_BAND_2GHZ],
                                                 ies->len[IEEE80211_BAND_2GHZ],
        }
  
        if (!force_passive && cfg->active[1]) {
 -              ret = wl1271_cmd_build_probe_req(wl,  req->ssids[0].ssid,
 +              ret = wl1271_cmd_build_probe_req(wl, wlvif, req->ssids[0].ssid,
                                                 req->ssids[0].ssid_len,
                                                 ies->ie[IEEE80211_BAND_5GHZ],
                                                 ies->len[IEEE80211_BAND_5GHZ],
@@@ -690,14 -667,14 +690,14 @@@ out
        return ret;
  }
  
 -int wl1271_scan_sched_scan_start(struct wl1271 *wl)
 +int wl1271_scan_sched_scan_start(struct wl1271 *wl, struct wl12xx_vif *wlvif)
  {
        struct wl1271_cmd_sched_scan_start *start;
        int ret = 0;
  
        wl1271_debug(DEBUG_CMD, "cmd periodic scan start");
  
 -      if (wl->bss_type != BSS_TYPE_STA_BSS)
 +      if (wlvif->bss_type != BSS_TYPE_STA_BSS)
                return -EOPNOTSUPP;
  
        if (!test_bit(WL1271_FLAG_IDLE, &wl->flags))
index 9e6f7fa0f9a32cb18d5a22ffdf4e50d07936dee1,12421a64d891c185c20307ffd940b7b3ebfc2175..92caa7ce6053efc1c36227553b03b05e61844cbe
@@@ -27,7 -27,6 +27,7 @@@
  #include <linux/crc7.h>
  #include <linux/spi/spi.h>
  #include <linux/wl12xx.h>
 +#include <linux/platform_device.h>
  #include <linux/slab.h>
  
  #include "wl12xx.h"
  
  #define WSPI_MAX_NUM_OF_CHUNKS (WL1271_AGGR_BUFFER_SIZE / WSPI_MAX_CHUNK_SIZE)
  
 -static inline struct spi_device *wl_to_spi(struct wl1271 *wl)
 -{
 -      return wl->if_priv;
 -}
 -
 -static struct device *wl1271_spi_wl_to_dev(struct wl1271 *wl)
 -{
 -      return &(wl_to_spi(wl)->dev);
 -}
 -
 -static void wl1271_spi_disable_interrupts(struct wl1271 *wl)
 -{
 -      disable_irq(wl->irq);
 -}
 -
 -static void wl1271_spi_enable_interrupts(struct wl1271 *wl)
 -{
 -      enable_irq(wl->irq);
 -}
 +struct wl12xx_spi_glue {
 +      struct device *dev;
 +      struct platform_device *core;
 +};
  
 -static void wl1271_spi_reset(struct wl1271 *wl)
 +static void wl12xx_spi_reset(struct device *child)
  {
 +      struct wl12xx_spi_glue *glue = dev_get_drvdata(child->parent);
        u8 *cmd;
        struct spi_transfer t;
        struct spi_message m;
  
        cmd = kzalloc(WSPI_INIT_CMD_LEN, GFP_KERNEL);
        if (!cmd) {
 -              wl1271_error("could not allocate cmd for spi reset");
 +              dev_err(child->parent,
 +                      "could not allocate cmd for spi reset\n");
                return;
        }
  
        t.len = WSPI_INIT_CMD_LEN;
        spi_message_add_tail(&t, &m);
  
 -      spi_sync(wl_to_spi(wl), &m);
 +      spi_sync(to_spi_device(glue->dev), &m);
  
 -      wl1271_dump(DEBUG_SPI, "spi reset -> ", cmd, WSPI_INIT_CMD_LEN);
        kfree(cmd);
  }
  
 -static void wl1271_spi_init(struct wl1271 *wl)
 +static void wl12xx_spi_init(struct device *child)
  {
 +      struct wl12xx_spi_glue *glue = dev_get_drvdata(child->parent);
        u8 crc[WSPI_INIT_CMD_CRC_LEN], *cmd;
        struct spi_transfer t;
        struct spi_message m;
  
        cmd = kzalloc(WSPI_INIT_CMD_LEN, GFP_KERNEL);
        if (!cmd) {
 -              wl1271_error("could not allocate cmd for spi init");
 +              dev_err(child->parent,
 +                      "could not allocate cmd for spi init\n");
                return;
        }
  
        t.len = WSPI_INIT_CMD_LEN;
        spi_message_add_tail(&t, &m);
  
 -      spi_sync(wl_to_spi(wl), &m);
 -      wl1271_dump(DEBUG_SPI, "spi init -> ", cmd, WSPI_INIT_CMD_LEN);
 +      spi_sync(to_spi_device(glue->dev), &m);
        kfree(cmd);
  }
  
  #define WL1271_BUSY_WORD_TIMEOUT 1000
  
 -static int wl1271_spi_read_busy(struct wl1271 *wl)
 +static int wl12xx_spi_read_busy(struct device *child)
  {
 +      struct wl12xx_spi_glue *glue = dev_get_drvdata(child->parent);
 +      struct wl1271 *wl = dev_get_drvdata(child);
        struct spi_transfer t[1];
        struct spi_message m;
        u32 *busy_buf;
                t[0].len = sizeof(u32);
                t[0].cs_change = true;
                spi_message_add_tail(&t[0], &m);
 -              spi_sync(wl_to_spi(wl), &m);
 +              spi_sync(to_spi_device(glue->dev), &m);
  
                if (*busy_buf & 0x1)
                        return 0;
        }
  
        /* The SPI bus is unresponsive, the read failed. */
 -      wl1271_error("SPI read busy-word timeout!\n");
 +      dev_err(child->parent, "SPI read busy-word timeout!\n");
        return -ETIMEDOUT;
  }
  
 -static void wl1271_spi_raw_read(struct wl1271 *wl, int addr, void *buf,
 +static void wl12xx_spi_raw_read(struct device *child, int addr, void *buf,
                                size_t len, bool fixed)
  {
 +      struct wl12xx_spi_glue *glue = dev_get_drvdata(child->parent);
 +      struct wl1271 *wl = dev_get_drvdata(child);
        struct spi_transfer t[2];
        struct spi_message m;
        u32 *busy_buf;
                t[1].cs_change = true;
                spi_message_add_tail(&t[1], &m);
  
 -              spi_sync(wl_to_spi(wl), &m);
 +              spi_sync(to_spi_device(glue->dev), &m);
  
                if (!(busy_buf[WL1271_BUSY_WORD_CNT - 1] & 0x1) &&
 -                  wl1271_spi_read_busy(wl)) {
 +                  wl12xx_spi_read_busy(child)) {
                        memset(buf, 0, chunk_len);
                        return;
                }
                t[0].cs_change = true;
                spi_message_add_tail(&t[0], &m);
  
 -              spi_sync(wl_to_spi(wl), &m);
 -
 -              wl1271_dump(DEBUG_SPI, "spi_read cmd -> ", cmd, sizeof(*cmd));
 -              wl1271_dump(DEBUG_SPI, "spi_read buf <- ", buf, chunk_len);
 +              spi_sync(to_spi_device(glue->dev), &m);
  
                if (!fixed)
                        addr += chunk_len;
        }
  }
  
 -static void wl1271_spi_raw_write(struct wl1271 *wl, int addr, void *buf,
 -                        size_t len, bool fixed)
 +static void wl12xx_spi_raw_write(struct device *child, int addr, void *buf,
 +                               size_t len, bool fixed)
  {
 +      struct wl12xx_spi_glue *glue = dev_get_drvdata(child->parent);
        struct spi_transfer t[2 * WSPI_MAX_NUM_OF_CHUNKS];
        struct spi_message m;
        u32 commands[WSPI_MAX_NUM_OF_CHUNKS];
                t[i].len = chunk_len;
                spi_message_add_tail(&t[i++], &m);
  
 -              wl1271_dump(DEBUG_SPI, "spi_write cmd -> ", cmd, sizeof(*cmd));
 -              wl1271_dump(DEBUG_SPI, "spi_write buf -> ", buf, chunk_len);
 -
                if (!fixed)
                        addr += chunk_len;
                buf += chunk_len;
                cmd++;
        }
  
 -      spi_sync(wl_to_spi(wl), &m);
 -}
 -
 -static irqreturn_t wl1271_hardirq(int irq, void *cookie)
 -{
 -      struct wl1271 *wl = cookie;
 -      unsigned long flags;
 -
 -      wl1271_debug(DEBUG_IRQ, "IRQ");
 -
 -      /* complete the ELP completion */
 -      spin_lock_irqsave(&wl->wl_lock, flags);
 -      set_bit(WL1271_FLAG_IRQ_RUNNING, &wl->flags);
 -      if (wl->elp_compl) {
 -              complete(wl->elp_compl);
 -              wl->elp_compl = NULL;
 -      }
 -      spin_unlock_irqrestore(&wl->wl_lock, flags);
 -
 -      return IRQ_WAKE_THREAD;
 -}
 -
 -static int wl1271_spi_set_power(struct wl1271 *wl, bool enable)
 -{
 -      if (wl->set_power)
 -              wl->set_power(enable);
 -
 -      return 0;
 +      spi_sync(to_spi_device(glue->dev), &m);
  }
  
  static struct wl1271_if_operations spi_ops = {
 -      .read           = wl1271_spi_raw_read,
 -      .write          = wl1271_spi_raw_write,
 -      .reset          = wl1271_spi_reset,
 -      .init           = wl1271_spi_init,
 -      .power          = wl1271_spi_set_power,
 -      .dev            = wl1271_spi_wl_to_dev,
 -      .enable_irq     = wl1271_spi_enable_interrupts,
 -      .disable_irq    = wl1271_spi_disable_interrupts,
 +      .read           = wl12xx_spi_raw_read,
 +      .write          = wl12xx_spi_raw_write,
 +      .reset          = wl12xx_spi_reset,
 +      .init           = wl12xx_spi_init,
        .set_block_size = NULL,
  };
  
  static int __devinit wl1271_probe(struct spi_device *spi)
  {
 +      struct wl12xx_spi_glue *glue;
        struct wl12xx_platform_data *pdata;
 -      struct ieee80211_hw *hw;
 -      struct wl1271 *wl;
 -      unsigned long irqflags;
 -      int ret;
 +      struct resource res[1];
 +      int ret = -ENOMEM;
  
        pdata = spi->dev.platform_data;
        if (!pdata) {
 -              wl1271_error("no platform data");
 +              dev_err(&spi->dev, "no platform data\n");
                return -ENODEV;
        }
  
 -      hw = wl1271_alloc_hw();
 -      if (IS_ERR(hw))
 -              return PTR_ERR(hw);
 +      pdata->ops = &spi_ops;
  
 -      wl = hw->priv;
 +      glue = kzalloc(sizeof(*glue), GFP_KERNEL);
 +      if (!glue) {
 +              dev_err(&spi->dev, "can't allocate glue\n");
 +              goto out;
 +      }
  
 -      dev_set_drvdata(&spi->dev, wl);
 -      wl->if_priv = spi;
 +      glue->dev = &spi->dev;
  
 -      wl->if_ops = &spi_ops;
 +      spi_set_drvdata(spi, glue);
  
        /* This is the only SPI value that we need to set here, the rest
         * comes from the board-peripherals file */
  
        ret = spi_setup(spi);
        if (ret < 0) {
 -              wl1271_error("spi_setup failed");
 -              goto out_free;
 +              dev_err(glue->dev, "spi_setup failed\n");
 +              goto out_free_glue;
        }
  
 -      wl->set_power = pdata->set_power;
 -      if (!wl->set_power) {
 -              wl1271_error("set power function missing in platform data");
 -              ret = -ENODEV;
 -              goto out_free;
 +      glue->core = platform_device_alloc("wl12xx", -1);
 +      if (!glue->core) {
 +              dev_err(glue->dev, "can't allocate platform_device\n");
 +              ret = -ENOMEM;
 +              goto out_free_glue;
        }
  
 -      wl->ref_clock = pdata->board_ref_clock;
 -      wl->tcxo_clock = pdata->board_tcxo_clock;
 -      wl->platform_quirks = pdata->platform_quirks;
 +      glue->core->dev.parent = &spi->dev;
  
 -      if (wl->platform_quirks & WL12XX_PLATFORM_QUIRK_EDGE_IRQ)
 -              irqflags = IRQF_TRIGGER_RISING;
 -      else
 -              irqflags = IRQF_TRIGGER_HIGH | IRQF_ONESHOT;
 +      memset(res, 0x00, sizeof(res));
  
 -      wl->irq = spi->irq;
 -      if (wl->irq < 0) {
 -              wl1271_error("irq missing in platform data");
 -              ret = -ENODEV;
 -              goto out_free;
 -      }
 +      res[0].start = spi->irq;
 +      res[0].flags = IORESOURCE_IRQ;
 +      res[0].name = "irq";
  
 -      ret = request_threaded_irq(wl->irq, wl1271_hardirq, wl1271_irq,
 -                                 irqflags,
 -                                 DRIVER_NAME, wl);
 -      if (ret < 0) {
 -              wl1271_error("request_irq() failed: %d", ret);
 -              goto out_free;
 +      ret = platform_device_add_resources(glue->core, res, ARRAY_SIZE(res));
 +      if (ret) {
 +              dev_err(glue->dev, "can't add resources\n");
 +              goto out_dev_put;
        }
  
 -      disable_irq(wl->irq);
 -
 -      ret = wl1271_init_ieee80211(wl);
 -      if (ret)
 -              goto out_irq;
 +      ret = platform_device_add_data(glue->core, pdata, sizeof(*pdata));
 +      if (ret) {
 +              dev_err(glue->dev, "can't add platform data\n");
 +              goto out_dev_put;
 +      }
  
 -      ret = wl1271_register_hw(wl);
 -      if (ret)
 -              goto out_irq;
 +      ret = platform_device_add(glue->core);
 +      if (ret) {
 +              dev_err(glue->dev, "can't register platform device\n");
 +              goto out_dev_put;
 +      }
  
        return 0;
  
 - out_irq:
 -      free_irq(wl->irq, wl);
 -
 - out_free:
 -      wl1271_free_hw(wl);
 +out_dev_put:
 +      platform_device_put(glue->core);
  
 +out_free_glue:
 +      kfree(glue);
 +out:
        return ret;
  }
  
  static int __devexit wl1271_remove(struct spi_device *spi)
  {
 -      struct wl1271 *wl = dev_get_drvdata(&spi->dev);
 +      struct wl12xx_spi_glue *glue = spi_get_drvdata(spi);
  
 -      wl1271_unregister_hw(wl);
 -      free_irq(wl->irq, wl);
 -      wl1271_free_hw(wl);
 +      platform_device_del(glue->core);
 +      platform_device_put(glue->core);
 +      kfree(glue);
  
        return 0;
  }
  static struct spi_driver wl1271_spi_driver = {
        .driver = {
                .name           = "wl1271_spi",
-               .bus            = &spi_bus_type,
                .owner          = THIS_MODULE,
        },