#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"
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);
}
}
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:
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);
}
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);
/*
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);
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");
wl->power_level = conf->power_level;
}
+out_sleep:
+ wl12xx_ps_elp_sleep(wl);
+
out:
mutex_unlock(&wl->mutex);
+
return ret;
}
}
/* 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)
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;
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;
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;
}
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;
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;
}
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;
}
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;
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;
}
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;
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;
}
}
}
ret = wl12xx_acx_slot(wl, SLOT_TIME_LONG);
if (ret < 0) {
wl12xx_warning("Set slot time failed %d", ret);
- goto out;
+ goto out_sleep;
}
}
ret = wl12xx_acx_cts_protect(wl, CTSPROTECT_DISABLE);
if (ret < 0) {
wl12xx_warning("Set ctsprotect failed %d", ret);
- goto out;
+ goto out_sleep;
}
}
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;
}
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);
}
{
/* 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 */
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;
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;
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);
free_irq(wl->irq, wl);
out_free:
+ kfree(wl->rx_descriptor);
+ wl->rx_descriptor = NULL;
+
ieee80211_free_hw(hw);
return ret;
wl->fw = NULL;
kfree(wl->nvs);
wl->nvs = NULL;
+
+ kfree(wl->rx_descriptor);
+ wl->rx_descriptor = NULL;
+
ieee80211_free_hw(wl->hw);
return 0;