wl12xx: rename wl1251.c wl1251_ops.c
[pandora-kernel.git] / drivers / net / wireless / wl12xx / main.c
index 603d611..3fc48c7 100644 (file)
 #include "wl12xx.h"
 #include "wl12xx_80211.h"
 #include "reg.h"
-#include "wl1251.h"
+#include "wl1251_ops.h"
 #include "spi.h"
 #include "event.h"
-#include "tx.h"
+#include "wl1251_tx.h"
 #include "rx.h"
 #include "ps.h"
 #include "init.h"
@@ -157,8 +157,6 @@ static void wl12xx_fw_wakeup(struct wl12xx *wl)
 
        if (!(elp_reg & ELPCTRL_WLAN_READY)) {
                wl12xx_warning("WLAN not ready");
-               elp_reg = ELPCTRL_WAKE_UP_WLAN_READY;
-               wl12xx_write32(wl, HW_ACCESS_ELP_CTRL_REG_ADDR, elp_reg);
        }
 }
 
@@ -198,6 +196,13 @@ static int wl12xx_chip_wakeup(struct wl12xx *wl)
 
                break;
        case CHIP_ID_1271_PG10:
+               wl12xx_warning("chip id 0x%x (1271 PG10) support is obsolete",
+                              wl->chip.id);
+               break;
+       case CHIP_ID_1271_PG20:
+               wl12xx_debug(DEBUG_BOOT, "chip id 0x%x (1271 PG20)",
+                            wl->chip.id);
+               break;
        case CHIP_ID_1251_PG10:
        case CHIP_ID_1251_PG11:
        default:
@@ -234,10 +239,18 @@ static void wl12xx_filter_work(struct work_struct *work)
        if (wl->state == WL12XX_STATE_OFF)
                goto out;
 
-       ret = wl12xx_cmd_join(wl, wl->bss_type, 1, 100, 0);
+       ret = wl12xx_ps_elp_wakeup(wl);
        if (ret < 0)
                goto out;
 
+       /* FIXME: replace the magic numbers with proper definitions */
+       ret = wl->chip.op_cmd_join(wl, wl->bss_type, 1, 100, 0);
+       if (ret < 0)
+               goto out_sleep;
+
+out_sleep:
+       wl12xx_ps_elp_sleep(wl);
+
 out:
        mutex_unlock(&wl->mutex);
 }
@@ -298,6 +311,11 @@ static int wl12xx_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
 
        skb_queue_tail(&wl->tx_queue, skb);
 
+       /*
+        * The chip specific setup must run before the first TX packet -
+        * before that, the tx_work will not be initialized!
+        */
+
        schedule_work(&wl->tx_work);
 
        /*
@@ -395,8 +413,7 @@ static void wl12xx_op_stop(struct ieee80211_hw *hw)
        mutex_lock(&wl->mutex);
 
        /* let's notify MAC80211 about the remaining pending TX frames */
-       wl12xx_tx_flush(wl);
-
+       wl->chip.op_tx_flush(wl);
        wl12xx_power_off(wl);
 
        memset(wl->bssid, 0, ETH_ALEN);
@@ -512,18 +529,22 @@ static int wl12xx_op_config(struct ieee80211_hw *hw, u32 changed)
 
        mutex_lock(&wl->mutex);
 
+       ret = wl12xx_ps_elp_wakeup(wl);
+       if (ret < 0)
+               goto out;
+
        if (channel != wl->channel) {
                /* FIXME: use beacon interval provided by mac80211 */
-               ret = wl12xx_cmd_join(wl, wl->bss_type, 1, 100, 0);
+               ret = wl->chip.op_cmd_join(wl, wl->bss_type, 1, 100, 0);
                if (ret < 0)
-                       goto out;
+                       goto out_sleep;
 
                wl->channel = channel;
        }
 
        ret = wl12xx_build_null_data(wl);
        if (ret < 0)
-               goto out;
+               goto out_sleep;
 
        if (conf->flags & IEEE80211_CONF_PS && !wl->psm_requested) {
                wl12xx_info("psm enabled");
@@ -554,8 +575,12 @@ static int wl12xx_op_config(struct ieee80211_hw *hw, u32 changed)
                wl->power_level = conf->power_level;
        }
 
+out_sleep:
+       wl12xx_ps_elp_sleep(wl);
+
 out:
        mutex_unlock(&wl->mutex);
+
        return ret;
 }
 
@@ -618,7 +643,8 @@ static void wl12xx_op_configure_filter(struct ieee80211_hw *hw,
 }
 
 /* HW encryption */
-static int wl12xx_set_key_type(struct wl12xx *wl, struct acx_set_key *key,
+static int wl12xx_set_key_type(struct wl12xx *wl,
+                              struct wl12xx_cmd_set_keys *key,
                               enum set_key_cmd cmd,
                               struct ieee80211_key_conf *mac80211_key,
                               const u8 *addr)
@@ -661,7 +687,7 @@ static int wl12xx_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
                             struct ieee80211_key_conf *key)
 {
        struct wl12xx *wl = hw->priv;
-       struct acx_set_key wl_key;
+       struct wl12xx_cmd_set_keys *wl_cmd;
        const u8 *addr;
        int ret;
 
@@ -670,7 +696,11 @@ static int wl12xx_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
 
        wl12xx_debug(DEBUG_MAC80211, "mac80211 set key");
 
-       memset(&wl_key, 0, sizeof(wl_key));
+       wl_cmd = kzalloc(sizeof(*wl_cmd), GFP_KERNEL);
+       if (!wl_cmd) {
+               ret = -ENOMEM;
+               goto out;
+       }
 
        addr = sta ? sta->addr : bcast_addr;
 
@@ -680,59 +710,76 @@ static int wl12xx_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
                     key->alg, key->keyidx, key->keylen, key->flags);
        wl12xx_dump(DEBUG_CRYPT, "KEY: ", key->key, key->keylen);
 
+       if (is_zero_ether_addr(addr)) {
+               /* We dont support TX only encryption */
+               ret = -EOPNOTSUPP;
+               goto out;
+       }
+
        mutex_lock(&wl->mutex);
 
+       ret = wl12xx_ps_elp_wakeup(wl);
+       if (ret < 0)
+               goto out_unlock;
+
        switch (cmd) {
        case SET_KEY:
-               wl_key.key_action = KEY_ADD_OR_REPLACE;
+               wl_cmd->key_action = KEY_ADD_OR_REPLACE;
                break;
        case DISABLE_KEY:
-               wl_key.key_action = KEY_REMOVE;
+               wl_cmd->key_action = KEY_REMOVE;
                break;
        default:
                wl12xx_error("Unsupported key cmd 0x%x", cmd);
                break;
        }
 
-       ret = wl12xx_set_key_type(wl, &wl_key, cmd, key, addr);
+       ret = wl12xx_set_key_type(wl, wl_cmd, cmd, key, addr);
        if (ret < 0) {
                wl12xx_error("Set KEY type failed");
-               goto out;
+               goto out_sleep;
        }
 
-       if (wl_key.key_type != KEY_WEP_DEFAULT)
-               memcpy(wl_key.addr, addr, ETH_ALEN);
+       if (wl_cmd->key_type != KEY_WEP_DEFAULT)
+               memcpy(wl_cmd->addr, addr, ETH_ALEN);
 
-       if ((wl_key.key_type == KEY_TKIP_MIC_GROUP) ||
-           (wl_key.key_type == KEY_TKIP_MIC_PAIRWISE)) {
+       if ((wl_cmd->key_type == KEY_TKIP_MIC_GROUP) ||
+           (wl_cmd->key_type == KEY_TKIP_MIC_PAIRWISE)) {
                /*
                 * We get the key in the following form:
                 * TKIP (16 bytes) - TX MIC (8 bytes) - RX MIC (8 bytes)
                 * but the target is expecting:
                 * TKIP - RX MIC - TX MIC
                 */
-               memcpy(wl_key.key, key->key, 16);
-               memcpy(wl_key.key + 16, key->key + 24, 8);
-               memcpy(wl_key.key + 24, key->key + 16, 8);
+               memcpy(wl_cmd->key, key->key, 16);
+               memcpy(wl_cmd->key + 16, key->key + 24, 8);
+               memcpy(wl_cmd->key + 24, key->key + 16, 8);
 
        } else {
-               memcpy(wl_key.key, key->key, key->keylen);
+               memcpy(wl_cmd->key, key->key, key->keylen);
        }
-       wl_key.key_size = key->keylen;
+       wl_cmd->key_size = key->keylen;
 
-       wl_key.id = key->keyidx;
-       wl_key.ssid_profile = 0;
+       wl_cmd->id = key->keyidx;
+       wl_cmd->ssid_profile = 0;
 
-       wl12xx_dump(DEBUG_CRYPT, "TARGET KEY: ", &wl_key, sizeof(wl_key));
+       wl12xx_dump(DEBUG_CRYPT, "TARGET KEY: ", wl_cmd, sizeof(*wl_cmd));
 
-       if (wl12xx_cmd_send(wl, CMD_SET_KEYS, &wl_key, sizeof(wl_key)) < 0) {
-               wl12xx_error("Set KEY failed");
-               ret = -EOPNOTSUPP;
-               goto out;
+       ret = wl12xx_cmd_send(wl, CMD_SET_KEYS, wl_cmd, sizeof(*wl_cmd));
+       if (ret < 0) {
+               wl12xx_warning("could not set keys");
+               goto out_sleep;
        }
 
-out:
+out_sleep:
+       wl12xx_ps_elp_sleep(wl);
+
+out_unlock:
        mutex_unlock(&wl->mutex);
+
+out:
+       kfree(wl_cmd);
+
        return ret;
 }
 
@@ -812,11 +859,10 @@ static int wl12xx_hw_scan(struct wl12xx *wl, u8 *ssid, size_t len,
                          u8 active_scan, u8 high_prio, u8 num_channels,
                          u8 probe_requests)
 {
+       struct wl12xx_cmd_trigger_scan_to *trigger = NULL;
+       struct cmd_scan *params = NULL;
        int i, ret;
-       u32 split_scan = 0;
        u16 scan_options = 0;
-       struct cmd_scan *params;
-       struct wl12xx_command *cmd_answer;
 
        if (wl->scanning)
                return -EINVAL;
@@ -870,10 +916,16 @@ static int wl12xx_hw_scan(struct wl12xx *wl, u8 *ssid, size_t len,
                goto out;
        }
 
-       ret = wl12xx_cmd_send(wl, CMD_TRIGGER_SCAN_TO, &split_scan,
-                             sizeof(u32));
+       trigger = kzalloc(sizeof(*trigger), GFP_KERNEL);
+       if (!trigger)
+               goto out;
+
+       trigger->timeout = 0;
+
+       ret = wl12xx_cmd_send(wl, CMD_TRIGGER_SCAN_TO, trigger,
+                             sizeof(*trigger));
        if (ret < 0) {
-               wl12xx_error("Split SCAN failed");
+               wl12xx_error("trigger scan to failed for hw scan");
                goto out;
        }
 
@@ -887,10 +939,9 @@ static int wl12xx_hw_scan(struct wl12xx *wl, u8 *ssid, size_t len,
 
        wl12xx_spi_mem_read(wl, wl->cmd_box_addr, params, sizeof(*params));
 
-       cmd_answer = (struct wl12xx_command *) params;
-       if (cmd_answer->status != CMD_STATUS_SUCCESS) {
+       if (params->header.status != CMD_STATUS_SUCCESS) {
                wl12xx_error("TEST command answer error: %d",
-                            cmd_answer->status);
+                            params->header.status);
                wl->scanning = false;
                ret = -EIO;
                goto out;
@@ -918,7 +969,16 @@ static int wl12xx_op_hw_scan(struct ieee80211_hw *hw,
        }
 
        mutex_lock(&wl->mutex);
+
+       ret = wl12xx_ps_elp_wakeup(wl);
+       if (ret < 0)
+               goto out;
+
        ret = wl12xx_hw_scan(hw->priv, ssid, ssid_len, 1, 0, 13, 3);
+
+       wl12xx_ps_elp_sleep(wl);
+
+out:
        mutex_unlock(&wl->mutex);
 
        return ret;
@@ -929,11 +989,21 @@ static int wl12xx_op_set_rts_threshold(struct ieee80211_hw *hw, u32 value)
        struct wl12xx *wl = hw->priv;
        int ret;
 
-       ret = wl12xx_acx_rts_threshold(wl, (u16) value);
+       mutex_lock(&wl->mutex);
 
+       ret = wl12xx_ps_elp_wakeup(wl);
+       if (ret < 0)
+               goto out;
+
+       ret = wl12xx_acx_rts_threshold(wl, (u16) value);
        if (ret < 0)
                wl12xx_warning("wl12xx_op_set_rts_threshold failed: %d", ret);
 
+       wl12xx_ps_elp_sleep(wl);
+
+out:
+       mutex_unlock(&wl->mutex);
+
        return ret;
 }
 
@@ -942,7 +1012,7 @@ static void wl12xx_op_bss_info_changed(struct ieee80211_hw *hw,
                                       struct ieee80211_bss_conf *bss_conf,
                                       u32 changed)
 {
-       enum acx_ps_mode mode;
+       enum wl12xx_cmd_ps_mode mode;
        struct wl12xx *wl = hw->priv;
        struct sk_buff *beacon;
        int ret;
@@ -951,24 +1021,28 @@ static void wl12xx_op_bss_info_changed(struct ieee80211_hw *hw,
 
        mutex_lock(&wl->mutex);
 
+       ret = wl12xx_ps_elp_wakeup(wl);
+       if (ret < 0)
+               goto out;
+
        if (changed & BSS_CHANGED_ASSOC) {
                if (bss_conf->assoc) {
                        wl->aid = bss_conf->aid;
 
                        ret = wl12xx_build_ps_poll(wl, wl->aid);
                        if (ret < 0)
-                               goto out;
+                               goto out_sleep;
 
                        ret = wl12xx_acx_aid(wl, wl->aid);
                        if (ret < 0)
-                               goto out;
+                               goto out_sleep;
 
                        /* If we want to go in PSM but we're not there yet */
                        if (wl->psm_requested && !wl->psm) {
                                mode = STATION_POWER_SAVE_MODE;
                                ret = wl12xx_ps_set_mode(wl, mode);
                                if (ret < 0)
-                                       goto out;
+                                       goto out_sleep;
                        }
                }
        }
@@ -979,7 +1053,7 @@ static void wl12xx_op_bss_info_changed(struct ieee80211_hw *hw,
                        ret = wl12xx_acx_slot(wl, SLOT_TIME_LONG);
                if (ret < 0) {
                        wl12xx_warning("Set slot time failed %d", ret);
-                       goto out;
+                       goto out_sleep;
                }
        }
 
@@ -997,7 +1071,7 @@ static void wl12xx_op_bss_info_changed(struct ieee80211_hw *hw,
                        ret = wl12xx_acx_cts_protect(wl, CTSPROTECT_DISABLE);
                if (ret < 0) {
                        wl12xx_warning("Set ctsprotect failed %d", ret);
-                       goto out;
+                       goto out_sleep;
                }
        }
 
@@ -1009,7 +1083,7 @@ static void wl12xx_op_bss_info_changed(struct ieee80211_hw *hw,
                        goto out;
 
                if (wl->bss_type != BSS_TYPE_IBSS) {
-                       ret = wl12xx_cmd_join(wl, wl->bss_type, 5, 100, 1);
+                       ret = wl->chip.op_cmd_join(wl, wl->bss_type, 5, 100, 1);
                        if (ret < 0)
                                goto out;
                }
@@ -1033,12 +1107,15 @@ static void wl12xx_op_bss_info_changed(struct ieee80211_hw *hw,
                if (ret < 0)
                        goto out;
 
-               ret = wl12xx_cmd_join(wl, wl->bss_type, 1, 100, 0);
+               ret = wl->chip.op_cmd_join(wl, wl->bss_type, 1, 100, 0);
 
                if (ret < 0)
                        goto out;
        }
 
+out_sleep:
+       wl12xx_ps_elp_sleep(wl);
+
 out:
        mutex_unlock(&wl->mutex);
 }
@@ -1152,7 +1229,7 @@ static int wl12xx_init_ieee80211(struct wl12xx *wl)
 {
        /* The tx descriptor buffer and the TKIP space */
        wl->hw->extra_tx_headroom = sizeof(struct tx_double_buffer_desc)
-               + WL12XX_TKIP_IV_SPACE;
+               + WL1251_TKIP_IV_SPACE;
 
        /* unit us */
        /* FIXME: find a proper value */
@@ -1202,7 +1279,6 @@ static int __devinit wl12xx_probe(struct spi_device *spi)
 
        skb_queue_head_init(&wl->tx_queue);
 
-       INIT_WORK(&wl->tx_work, wl12xx_tx_work);
        INIT_WORK(&wl->filter_work, wl12xx_filter_work);
        wl->channel = WL12XX_DEFAULT_CHANNEL;
        wl->scanning = false;
@@ -1242,6 +1318,13 @@ static int __devinit wl12xx_probe(struct spi_device *spi)
        wl->tx_mgmt_frm_rate = DEFAULT_HW_GEN_TX_RATE;
        wl->tx_mgmt_frm_mod = DEFAULT_HW_GEN_MODULATION_TYPE;
 
+       wl->rx_descriptor = kmalloc(sizeof(*wl->rx_descriptor), GFP_KERNEL);
+       if (!wl->rx_descriptor) {
+               wl12xx_error("could not allocate memory for rx descriptor");
+               ret = -ENOMEM;
+               goto out_free;
+       }
+
        /* This is the only SPI value that we need to set here, the rest
         * comes from the board-peripherals file */
        spi->bits_per_word = 32;
@@ -1255,13 +1338,15 @@ static int __devinit wl12xx_probe(struct spi_device *spi)
        wl->set_power = pdata->set_power;
        if (!wl->set_power) {
                wl12xx_error("set power function missing in platform data");
-               return -ENODEV;
+               ret = -ENODEV;
+               goto out_free;
        }
 
        wl->irq = spi->irq;
        if (wl->irq < 0) {
                wl12xx_error("irq missing in platform data");
-               return -ENODEV;
+               ret = -ENODEV;
+               goto out_free;
        }
 
        ret = request_irq(wl->irq, wl12xx_irq, 0, DRIVER_NAME, wl);
@@ -1292,6 +1377,9 @@ static int __devinit wl12xx_probe(struct spi_device *spi)
        free_irq(wl->irq, wl);
 
  out_free:
+       kfree(wl->rx_descriptor);
+       wl->rx_descriptor = NULL;
+
        ieee80211_free_hw(hw);
 
        return ret;
@@ -1312,6 +1400,10 @@ static int __devexit wl12xx_remove(struct spi_device *spi)
        wl->fw = NULL;
        kfree(wl->nvs);
        wl->nvs = NULL;
+
+       kfree(wl->rx_descriptor);
+       wl->rx_descriptor = NULL;
+
        ieee80211_free_hw(wl->hw);
 
        return 0;