aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/ti/wl18xx
diff options
context:
space:
mode:
authorArik Nemtsov <arik@wizery.com>2012-05-18 07:46:40 +0300
committerLuciano Coelho <coelho@ti.com>2012-06-06 19:28:05 +0300
commita1c597f2b22cdc228de3c58784b00e80b9b53e03 (patch)
treeeac1d01f867fd3f8df77fae3b050dba94c95e5b9 /drivers/net/wireless/ti/wl18xx
parentwlcore: stop queues on Tx flush (diff)
downloadlinux-dev-a1c597f2b22cdc228de3c58784b00e80b9b53e03.tar.xz
linux-dev-a1c597f2b22cdc228de3c58784b00e80b9b53e03.zip
wlcore/wl12xx/wl18xx: implement op_set_key per HW arch
The 12xx set_key just calls the common wlcore_set_key function, in order to program the keys into the FW. The 18xx variant changes the spare block count when a GEM or TKIP key is set. Also modify the get_spare_blocks HW op for 18xx to return the correct numbers of spare blocks, according to what is currently set in FW. Signed-off-by: Arik Nemtsov <arik@wizery.com> Signed-off-by: Luciano Coelho <coelho@ti.com>
Diffstat (limited to 'drivers/net/wireless/ti/wl18xx')
-rw-r--r--drivers/net/wireless/ti/wl18xx/acx.c4
-rw-r--r--drivers/net/wireless/ti/wl18xx/main.c96
-rw-r--r--drivers/net/wireless/ti/wl18xx/wl18xx.h3
3 files changed, 91 insertions, 12 deletions
diff --git a/drivers/net/wireless/ti/wl18xx/acx.c b/drivers/net/wireless/ti/wl18xx/acx.c
index 3379db23a165..01ba40321435 100644
--- a/drivers/net/wireless/ti/wl18xx/acx.c
+++ b/drivers/net/wireless/ti/wl18xx/acx.c
@@ -32,6 +32,10 @@ int wl18xx_acx_host_if_cfg_bitmap(struct wl1271 *wl, u32 host_cfg_bitmap,
struct wl18xx_acx_host_config_bitmap *bitmap_conf;
int ret;
+ wl1271_debug(DEBUG_ACX, "acx cfg bitmap %d blk %d spare %d field %d",
+ host_cfg_bitmap, sdio_blk_size, extra_mem_blks,
+ len_field_size);
+
bitmap_conf = kzalloc(sizeof(*bitmap_conf), GFP_KERNEL);
if (!bitmap_conf) {
ret = -ENOMEM;
diff --git a/drivers/net/wireless/ti/wl18xx/main.c b/drivers/net/wireless/ti/wl18xx/main.c
index c651f872d7d5..9e5ce569f8da 100644
--- a/drivers/net/wireless/ti/wl18xx/main.c
+++ b/drivers/net/wireless/ti/wl18xx/main.c
@@ -848,17 +848,12 @@ static void wl18xx_tx_immediate_completion(struct wl1271 *wl)
wl18xx_tx_immediate_complete(wl);
}
-static int wl18xx_hw_init(struct wl1271 *wl)
+static int wl18xx_set_host_cfg_bitmap(struct wl1271 *wl, u32 extra_mem_blk)
{
int ret;
- struct wl18xx_priv *priv = wl->priv;
- u32 host_cfg_bitmap = HOST_IF_CFG_RX_FIFO_ENABLE |
- HOST_IF_CFG_ADD_RX_ALIGNMENT;
-
u32 sdio_align_size = 0;
-
- /* (re)init private structures. Relevant on recovery as well. */
- priv->last_fw_rls_idx = 0;
+ u32 host_cfg_bitmap = HOST_IF_CFG_RX_FIFO_ENABLE |
+ HOST_IF_CFG_ADD_RX_ALIGNMENT;
/* Enable Tx SDIO padding */
if (wl->quirks & WLCORE_QUIRK_TX_BLOCKSIZE_ALIGN) {
@@ -873,12 +868,28 @@ static int wl18xx_hw_init(struct wl1271 *wl)
}
ret = wl18xx_acx_host_if_cfg_bitmap(wl, host_cfg_bitmap,
- sdio_align_size,
- WL18XX_TX_HW_EXTRA_BLOCK_SPARE,
+ sdio_align_size, extra_mem_blk,
WL18XX_HOST_IF_LEN_SIZE_FIELD);
if (ret < 0)
return ret;
+ return 0;
+}
+
+static int wl18xx_hw_init(struct wl1271 *wl)
+{
+ int ret;
+ struct wl18xx_priv *priv = wl->priv;
+
+ /* (re)init private structures. Relevant on recovery as well. */
+ priv->last_fw_rls_idx = 0;
+ priv->extra_spare_vif_count = 0;
+
+ /* set the default amount of spare blocks in the bitmap */
+ ret = wl18xx_set_host_cfg_bitmap(wl, WL18XX_TX_HW_BLOCK_SPARE);
+ if (ret < 0)
+ return ret;
+
if (checksum_param) {
ret = wl18xx_acx_set_checksum_state(wl);
if (ret != 0)
@@ -1036,8 +1047,68 @@ static int wl18xx_handle_static_data(struct wl1271 *wl,
static int wl18xx_get_spare_blocks(struct wl1271 *wl, bool is_gem)
{
- /* TODO: dynamically change to extra only when we have GEM or TKIP */
- return WL18XX_TX_HW_EXTRA_BLOCK_SPARE;
+ struct wl18xx_priv *priv = wl->priv;
+
+ /* If we have VIFs requiring extra spare, indulge them */
+ if (priv->extra_spare_vif_count)
+ return WL18XX_TX_HW_EXTRA_BLOCK_SPARE;
+
+ return WL18XX_TX_HW_BLOCK_SPARE;
+}
+
+static int wl18xx_set_key(struct wl1271 *wl, enum set_key_cmd cmd,
+ struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta,
+ struct ieee80211_key_conf *key_conf)
+{
+ struct wl18xx_priv *priv = wl->priv;
+ bool change_spare = false;
+ int ret;
+
+ /*
+ * when adding the first or removing the last GEM/TKIP interface,
+ * we have to adjust the number of spare blocks.
+ */
+ change_spare = (key_conf->cipher == WL1271_CIPHER_SUITE_GEM ||
+ key_conf->cipher == WLAN_CIPHER_SUITE_TKIP) &&
+ ((priv->extra_spare_vif_count == 0 && cmd == SET_KEY) ||
+ (priv->extra_spare_vif_count == 1 && cmd == DISABLE_KEY));
+
+ /* no need to change spare - just regular set_key */
+ if (!change_spare)
+ return wlcore_set_key(wl, cmd, vif, sta, key_conf);
+
+ /*
+ * stop the queues and flush to ensure the next packets are
+ * in sync with FW spare block accounting
+ */
+ wlcore_stop_queues(wl, WLCORE_QUEUE_STOP_REASON_SPARE_BLK);
+ wl1271_tx_flush(wl);
+
+ ret = wlcore_set_key(wl, cmd, vif, sta, key_conf);
+ if (ret < 0)
+ goto out;
+
+ /* key is now set, change the spare blocks */
+ if (cmd == SET_KEY) {
+ ret = wl18xx_set_host_cfg_bitmap(wl,
+ WL18XX_TX_HW_EXTRA_BLOCK_SPARE);
+ if (ret < 0)
+ goto out;
+
+ priv->extra_spare_vif_count++;
+ } else {
+ ret = wl18xx_set_host_cfg_bitmap(wl,
+ WL18XX_TX_HW_BLOCK_SPARE);
+ if (ret < 0)
+ goto out;
+
+ priv->extra_spare_vif_count--;
+ }
+
+out:
+ wlcore_wake_queues(wl, WLCORE_QUEUE_STOP_REASON_SPARE_BLK);
+ return ret;
}
static struct wlcore_ops wl18xx_ops = {
@@ -1063,6 +1134,7 @@ static struct wlcore_ops wl18xx_ops = {
.debugfs_init = wl18xx_debugfs_add_files,
.handle_static_data = wl18xx_handle_static_data,
.get_spare_blocks = wl18xx_get_spare_blocks,
+ .set_key = wl18xx_set_key,
};
/* HT cap appropriate for wide channels */
diff --git a/drivers/net/wireless/ti/wl18xx/wl18xx.h b/drivers/net/wireless/ti/wl18xx/wl18xx.h
index 34e202bc2bb3..b9c43097d2f6 100644
--- a/drivers/net/wireless/ti/wl18xx/wl18xx.h
+++ b/drivers/net/wireless/ti/wl18xx/wl18xx.h
@@ -36,6 +36,9 @@ struct wl18xx_priv {
u8 last_fw_rls_idx;
u8 board_type;
+
+ /* number of VIFs requiring extra spare mem-blocks */
+ int extra_spare_vif_count;
};
#define WL18XX_FW_MAX_TX_STATUS_DESC 33